Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5

into  zizzer.eecs.umich.edu:/z/m5/Bitkeeper/multiarch

--HG--
extra : convert_revision : 427b5c957f91e66271444acebc01e1a861790363
This commit is contained in:
Gabe Black 2006-02-12 11:38:26 -05:00
commit 94590a4dba
15 changed files with 700 additions and 575 deletions

View file

@ -71,6 +71,15 @@ class Linux {
typedef uint32_t gid_t;
//@}
#if BSD_HOST
typedef struct stat hst_stat;
typedef struct stat hst_stat64;
#else
typedef struct stat hst_stat ;
typedef struct stat64 hst_stat64;
#endif
//@{
/// open(2) flag values.
static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
@ -139,7 +148,7 @@ class Linux {
uint64_t st_mtime_nsec;
uint64_t tgt_st_ctime;
uint64_t st_ctime_nsec;
int64_t __unused[3];
int64_t ___unused[3];
};
/// Length of strings in struct utsname (plus 1 for null char).
@ -170,18 +179,18 @@ class Linux {
/// Resource enumeration for getrlimit().
enum rlimit_resources {
RLIMIT_CPU = 0,
RLIMIT_FSIZE = 1,
RLIMIT_DATA = 2,
RLIMIT_STACK = 3,
RLIMIT_CORE = 4,
RLIMIT_RSS = 5,
RLIMIT_NOFILE = 6,
RLIMIT_AS = 7,
RLIMIT_VMEM = 7,
RLIMIT_NPROC = 8,
RLIMIT_MEMLOCK = 9,
RLIMIT_LOCKS = 10
TGT_RLIMIT_CPU = 0,
TGT_RLIMIT_FSIZE = 1,
TGT_RLIMIT_DATA = 2,
TGT_RLIMIT_STACK = 3,
TGT_RLIMIT_CORE = 4,
TGT_RLIMIT_RSS = 5,
TGT_RLIMIT_NOFILE = 6,
TGT_RLIMIT_AS = 7,
TGT_RLIMIT_VMEM = 7,
TGT_RLIMIT_NPROC = 8,
TGT_RLIMIT_MEMLOCK = 9,
TGT_RLIMIT_LOCKS = 10
};
/// Limit struct for getrlimit/setrlimit.
@ -208,9 +217,9 @@ class Linux {
//@{
/// For getrusage().
static const int RUSAGE_SELF = 0;
static const int RUSAGE_CHILDREN = -1;
static const int RUSAGE_BOTH = -2;
static const int TGT_RUSAGE_SELF = 0;
static const int TGT_RUSAGE_CHILDREN = -1;
static const int TGT_RUSAGE_BOTH = -2;
//@}
/// For getrusage().
@ -236,54 +245,81 @@ class Linux {
/// Helper function to convert a host stat buffer to a target stat
/// buffer. Also copies the target buffer out to the simulated
/// memory space. Used by stat(), fstat(), and lstat().
#if !BSD_HOST
static void
copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
{
TypedBufferArg<Linux::tgt_stat> tgt(addr);
tgt->st_dev = host->st_dev;
tgt->st_ino = host->st_ino;
tgt->st_mode = host->st_mode;
tgt->st_nlink = host->st_nlink;
tgt->st_uid = host->st_uid;
tgt->st_gid = host->st_gid;
tgt->st_rdev = host->st_rdev;
tgt->st_size = host->st_size;
tgt->st_atimeX = host->st_atime;
tgt->st_mtimeX = host->st_mtime;
tgt->st_ctimeX = host->st_ctime;
tgt->st_blksize = host->st_blksize;
tgt->st_blocks = host->st_blocks;
tgt->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);
}
#else
// Third version for bsd systems which no longer have any support for
// the old stat() call and stat() is actually a stat64()
static void
copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host)
{
TypedBufferArg<Linux::tgt_stat> tgt(addr);
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);
}
#endif
// Same for stat64
static void
copyOutStat64Buf(FunctionalMemory *mem, Addr addr, struct stat64 *host)
copyOutStat64Buf(FunctionalMemory *mem, Addr addr, hst_stat64 *host)
{
TypedBufferArg<Linux::tgt_stat64> tgt(addr);
// XXX byteswaps
tgt->st_dev = host->st_dev;
tgt->st_dev = htog(host->st_dev);
// XXX What about STAT64_HAS_BROKEN_ST_INO ???
tgt->st_ino = host->st_ino;
tgt->st_rdev = host->st_rdev;
tgt->st_size = host->st_size;
tgt->st_blocks = host->st_blocks;
tgt->st_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 = host->st_mode;
tgt->st_uid = host->st_uid;
tgt->st_gid = host->st_gid;
tgt->st_blksize = host->st_blksize;
tgt->st_nlink = host->st_nlink;
tgt->tgt_st_atime = host->st_atime;
tgt->tgt_st_mtime = host->st_mtime;
tgt->tgt_st_ctime = host->st_ctime;
#ifdef STAT_HAVE_NSEC
tgt->st_atime_nsec = host->st_atime_nsec;
tgt->st_mtime_nsec = host->st_mtime_nsec;
tgt->st_ctime_nsec = host->st_ctime_nsec;
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_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);
#else
tgt->st_atime_nsec = 0;
tgt->st_mtime_nsec = 0;
@ -356,7 +392,7 @@ class Linux {
// I don't think this exactly matches the HW FPCR
fpcr.copyIn(xc->mem);
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
" setting FPCR to 0x%x\n", *(uint64_t*)fpcr);
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
return 0;
}

View file

@ -28,7 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#if defined(__OpenBSD__)
#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/mount.h>
#else
@ -260,15 +260,15 @@ class Tru64 {
/// Resource enumeration for getrlimit().
enum rlimit_resources {
RLIMIT_CPU = 0,
RLIMIT_FSIZE = 1,
RLIMIT_DATA = 2,
RLIMIT_STACK = 3,
RLIMIT_CORE = 4,
RLIMIT_RSS = 5,
RLIMIT_NOFILE = 6,
RLIMIT_AS = 7,
RLIMIT_VMEM = 7
TGT_RLIMIT_CPU = 0,
TGT_RLIMIT_FSIZE = 1,
TGT_RLIMIT_DATA = 2,
TGT_RLIMIT_STACK = 3,
TGT_RLIMIT_CORE = 4,
TGT_RLIMIT_RSS = 5,
TGT_RLIMIT_NOFILE = 6,
TGT_RLIMIT_AS = 7,
TGT_RLIMIT_VMEM = 7
};
/// Limit struct for getrlimit/setrlimit.
@ -320,9 +320,9 @@ class Tru64 {
//@{
/// For getrusage().
static const int RUSAGE_THREAD = 1;
static const int RUSAGE_SELF = 0;
static const int RUSAGE_CHILDREN = -1;
static const int TGT_RUSAGE_THREAD = 1;
static const int TGT_RUSAGE_SELF = 0;
static const int TGT_RUSAGE_CHILDREN = -1;
//@}
/// For getrusage().
@ -568,7 +568,7 @@ class Tru64 {
{
TypedBufferArg<T> tgt(addr);
#if defined(__OpenBSD__)
#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
tgt->f_type = 0;
#else
tgt->f_type = host->f_type;

View file

@ -34,47 +34,47 @@ decode OPCODE default Unknown::unknown() {
}
format LoadOrNop {
0x0a: ldbu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.ub; }});
0x0c: ldwu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uw; }});
0x0b: ldq_u({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }});
0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x0a: ldbu({{ Ra.uq = Mem.ub; }});
0x0c: ldwu({{ Ra.uq = Mem.uw; }});
0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
0x23: ldt({{ Fa = Mem.df; }});
0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
{{ fault = xc->copySrcTranslate(EA); }},
IsMemRef, IsLoad, IsCopy);
inst_flags = [IsMemRef, IsLoad, IsCopy]);
}
format LoadOrPrefetch {
0x28: ldl({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }});
0x29: ldq({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, EVICT_NEXT);
0x28: ldl({{ Ra.sl = Mem.sl; }});
0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
// IsFloating flag on lds gets the prefetch to disassemble
// using f31 instead of r31... funcitonally it's unnecessary
0x22: lds({{ EA = Rb + disp; }}, {{ Fa.uq = s_to_t(Mem.ul); }},
PF_EXCLUSIVE, IsFloating);
0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
}
format Store {
0x0e: stb({{ EA = Rb + disp; }}, {{ Mem.ub = Ra<7:0>; }});
0x0d: stw({{ EA = Rb + disp; }}, {{ Mem.uw = Ra<15:0>; }});
0x2c: stl({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }});
0x2d: stq({{ EA = Rb + disp; }}, {{ Mem.uq = Ra.uq; }});
0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x0e: stb({{ Mem.ub = Ra<7:0>; }});
0x0d: stw({{ Mem.uw = Ra<15:0>; }});
0x2c: stl({{ Mem.ul = Ra<31:0>; }});
0x2d: stq({{ Mem.uq = Ra.uq; }});
0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ Mem.df = Fa; }});
0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
{{ fault = xc->copy(EA); }},
IsMemRef, IsStore, IsCopy);
inst_flags = [IsMemRef, IsStore, IsCopy]);
}
format StoreCond {
0x2e: stl_c({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }},
0x2e: stl_c({{ Mem.ul = Ra<31:0>; }},
{{
uint64_t tmp = write_result;
// see stq_c
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
}}, LOCKED);
0x2f: stq_c({{ EA = Rb + disp; }}, {{ Mem.uq = Ra; }},
}}, mem_flags = LOCKED);
0x2f: stq_c({{ Mem.uq = Ra; }},
{{
uint64_t tmp = write_result;
// If the write operation returns 0 or 1, then
@ -85,7 +85,7 @@ decode OPCODE default Unknown::unknown() {
// mailbox access, and we don't update the
// result register at all.
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
}}, LOCKED);
}}, mem_flags = LOCKED);
}
format IntegerOperate {
@ -607,8 +607,9 @@ decode OPCODE default Unknown::unknown() {
format MiscPrefetch {
0xf800: wh64({{ EA = Rb & ~ULL(63); }},
{{ xc->writeHint(EA, 64, memAccessFlags); }},
IsMemRef, IsDataPrefetch, IsStore, MemWriteOp,
NO_FAULT);
mem_flags = NO_FAULT,
inst_flags = [IsMemRef, IsDataPrefetch,
IsStore, MemWriteOp]);
}
format BasicOperate {

View file

@ -148,20 +148,19 @@ def operands {{
# Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should
# explicitly specify '.uq'.
'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
'Mem': MemOperandTraits('uq', None,
('IsMemRef', 'IsLoad', 'IsStore'), 4),
'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
'Ra': ('IntReg', 'uq', 'RA', 'IsInteger', 1),
'Rb': ('IntReg', 'uq', 'RB', 'IsInteger', 2),
'Rc': ('IntReg', 'uq', 'RC', 'IsInteger', 3),
'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
'FPCR': (' ControlReg', 'uq', 'Fpcr', None, 1),
# The next two are hacks for non-full-system call-pal emulation
'R0': IntRegOperandTraits('uq', '0', None, 1),
'R16': IntRegOperandTraits('uq', '16', None, 1)
'R0': ('IntReg', 'uq', '0', None, 1),
'R16': ('IntReg', 'uq', '16', None, 1)
}};
////////////////////////////////////////////////////////////////////

View file

@ -407,16 +407,12 @@ def template LoadPrefetchCheckDecode {{
let {{
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
base_class = 'MemoryDisp32', flags = [],
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
postacc_code = '', base_class = 'MemoryDisp32',
decode_template = BasicDecode, exec_template_base = ''):
# Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here).
# Would be nice to autogenerate this list, but oh well.
valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
mem_flags = [f for f in flags if f in valid_mem_flags]
inst_flags = [f for f in flags if f not in valid_mem_flags]
# Make sure flags are in lists (convert to lists if not).
mem_flags = makeList(mem_flags)
inst_flags = makeList(inst_flags)
# add hook to get effective addresses into execution trace output.
ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
@ -469,31 +465,39 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
}};
def format LoadOrNop(ea_code, memacc_code, *flags) {{
def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
exec_template_base = 'Load')
}};
// Note that the flags passed in apply only to the prefetch version
def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], pf_flags = [], inst_flags = []) {{
# declare the load instruction object and generate the decode block
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadPrefetchCheckDecode,
exec_template_base = 'Load')
# Declare the prefetch instruction object.
# convert flags from tuple to list to make them mutable
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
# Make sure flag args are lists so we can mess with them.
mem_flags = makeList(mem_flags)
pf_flags = makeList(pf_flags)
inst_flags = makeList(inst_flags)
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
'IsDataPrefetch', 'MemReadOp']
(pf_header_output, pf_decoder_output, _, pf_exec_output) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code,
'xc->prefetch(EA, memAccessFlags);',
flags = pf_flags, exec_template_base = 'Misc')
pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
header_output += pf_header_output
decoder_output += pf_decoder_output
@ -501,24 +505,28 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
}};
def format Store(ea_code, memacc_code, *flags) {{
def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
exec_template_base = 'Store')
}};
def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
def format StoreCond(memacc_code, postacc_code,
ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
flags = flags, exec_template_base = 'Store')
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
postacc_code, exec_template_base = 'Store')
}};
// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
def format MiscPrefetch(ea_code, memacc_code, *flags) {{
def format MiscPrefetch(ea_code, memacc_code,
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
}};

View file

@ -198,23 +198,25 @@ output decoder {{
def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
flags = flags, base_class = 'HwLoadStore',
exec_template_base = 'Load')
mem_flags = [], inst_flags = flags,
base_class = 'HwLoadStore', exec_template_base = 'Load')
}};
def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
flags = flags, base_class = 'HwLoadStore',
exec_template_base = 'Store')
mem_flags = [], inst_flags = flags,
base_class = 'HwLoadStore', exec_template_base = 'Store')
}};
def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, *flags) {{
def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext,
*flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
postacc_code, flags = flags, base_class = 'HwLoadStore')
postacc_code, mem_flags = [], inst_flags = flags,
base_class = 'HwLoadStore')
}};

View file

@ -82,10 +82,9 @@ tokens = reserved + (
# ( ) [ ] { } < > , ; : :: *
'LPAREN', 'RPAREN',
# not used any more... commented out to suppress PLY warning
# 'LBRACKET', 'RBRACKET',
'LBRACKET', 'RBRACKET',
'LBRACE', 'RBRACE',
'LESS', 'GREATER',
'LESS', 'GREATER', 'EQUALS',
'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
'ASTERISK',
@ -104,13 +103,13 @@ tokens = reserved + (
# Regular expressions for token matching
t_LPAREN = r'\('
t_RPAREN = r'\)'
# not used any more... commented out to suppress PLY warning
# t_LBRACKET = r'\['
# t_RBRACKET = r'\]'
t_LBRACKET = r'\['
t_RBRACKET = r'\]'
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LESS = r'\<'
t_GREATER = r'\>'
t_EQUALS = r'='
t_COMMA = r','
t_SEMI = r';'
t_COLON = r':'
@ -321,25 +320,27 @@ def p_global_let(t):
# widths (stored in operandTypeMap).
def p_def_operand_types(t):
'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
s = 'global operandTypeMap; operandTypeMap = {' + t[3] + '}'
try:
exec s
userDict = eval('{' + t[3] + '}')
except Exception, exc:
error(t.lineno(1),
'error: %s in def operand_types block "%s".' % (exc, t[3]))
buildOperandTypeMap(userDict, t.lineno(1))
t[0] = GenCode() # contributes nothing to the output C++ file
# Define the mapping from operand names to operand classes and other
# traits. Stored in operandTraitsMap.
# traits. Stored in operandNameMap.
def p_def_operands(t):
'def_operands : DEF OPERANDS CODELIT SEMI'
s = 'global operandTraitsMap; operandTraitsMap = {' + t[3] + '}'
if not globals().has_key('operandTypeMap'):
error(t.lineno(1),
'error: operand types must be defined before operands')
try:
exec s
userDict = eval('{' + t[3] + '}')
except Exception, exc:
error(t.lineno(1),
'error: %s in def operands block "%s".' % (exc, t[3]))
defineDerivedOperandVars()
buildOperandNameMap(userDict, t.lineno(1))
t[0] = GenCode() # contributes nothing to the output C++ file
# A bitfield definition looks like:
@ -387,32 +388,66 @@ def p_def_format(t):
t[0] = GenCode()
# The formal parameter list for an instruction format is a possibly
# empty list of comma-separated parameters.
# empty list of comma-separated parameters. Positional (standard,
# non-keyword) parameters must come first, followed by keyword
# parameters, followed by a '*foo' parameter that gets excess
# positional arguments (as in Python). Each of these three parameter
# categories is optional.
#
# Note that we do not support the '**foo' parameter for collecting
# otherwise undefined keyword args. Otherwise the parameter list is
# (I believe) identical to what is supported in Python.
#
# The param list generates a tuple, where the first element is a list of
# the positional params and the second element is a dict containing the
# keyword params.
def p_param_list_0(t):
'param_list : empty'
t[0] = [ ]
'param_list : positional_param_list COMMA nonpositional_param_list'
t[0] = t[1] + t[3]
def p_param_list_1(t):
'param_list : param'
'''param_list : positional_param_list
| nonpositional_param_list'''
t[0] = t[1]
def p_positional_param_list_0(t):
'positional_param_list : empty'
t[0] = []
def p_positional_param_list_1(t):
'positional_param_list : ID'
t[0] = [t[1]]
def p_param_list_2(t):
'param_list : param_list COMMA param'
t[0] = t[1]
t[0].append(t[3])
def p_positional_param_list_2(t):
'positional_param_list : positional_param_list COMMA ID'
t[0] = t[1] + [t[3]]
# Each formal parameter is either an identifier or an identifier
# preceded by an asterisk. As in Python, the latter (if present) gets
# a tuple containing all the excess positional arguments, allowing
# varargs functions.
def p_param_0(t):
'param : ID'
def p_nonpositional_param_list_0(t):
'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
t[0] = t[1] + t[3]
def p_nonpositional_param_list_1(t):
'''nonpositional_param_list : keyword_param_list
| excess_args_param'''
t[0] = t[1]
def p_param_1(t):
'param : ASTERISK ID'
# just concatenate them: '*ID'
t[0] = t[1] + t[2]
def p_keyword_param_list_0(t):
'keyword_param_list : keyword_param'
t[0] = [t[1]]
def p_keyword_param_list_1(t):
'keyword_param_list : keyword_param_list COMMA keyword_param'
t[0] = t[1] + [t[3]]
def p_keyword_param(t):
'keyword_param : ID EQUALS expr'
t[0] = t[1] + ' = ' + t[3].__repr__()
def p_excess_args_param(t):
'excess_args_param : ASTERISK ID'
# Just concatenate them: '*ID'. Wrap in list to be consistent
# with positional_param_list and keyword_param_list.
t[0] = [t[1] + t[2]]
# End of format definition-related rules.
##############
@ -577,26 +612,79 @@ def p_inst_1(t):
codeObj.prepend_all(comment)
t[0] = codeObj
# The arg list generates a tuple, where the first element is a list of
# the positional args and the second element is a dict containing the
# keyword args.
def p_arg_list_0(t):
'arg_list : empty'
t[0] = [ ]
'arg_list : positional_arg_list COMMA keyword_arg_list'
t[0] = ( t[1], t[3] )
def p_arg_list_1(t):
'arg_list : arg'
t[0] = [t[1]]
'arg_list : positional_arg_list'
t[0] = ( t[1], {} )
def p_arg_list_2(t):
'arg_list : arg_list COMMA arg'
t[0] = t[1]
t[0].append(t[3])
'arg_list : keyword_arg_list'
t[0] = ( [], t[1] )
def p_arg(t):
'''arg : ID
| INTLIT
| STRLIT
| CODELIT'''
def p_positional_arg_list_0(t):
'positional_arg_list : empty'
t[0] = []
def p_positional_arg_list_1(t):
'positional_arg_list : expr'
t[0] = [t[1]]
def p_positional_arg_list_2(t):
'positional_arg_list : positional_arg_list COMMA expr'
t[0] = t[1] + [t[3]]
def p_keyword_arg_list_0(t):
'keyword_arg_list : keyword_arg'
t[0] = t[1]
def p_keyword_arg_list_1(t):
'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
t[0] = t[1]
t[0].update(t[3])
def p_keyword_arg(t):
'keyword_arg : ID EQUALS expr'
t[0] = { t[1] : t[3] }
#
# Basic expressions. These constitute the argument values of
# "function calls" (i.e. instruction definitions in the decode block)
# and default values for formal parameters of format functions.
#
# Right now, these are either strings, integers, or (recursively)
# lists of exprs (using Python square-bracket list syntax). Note that
# bare identifiers are trated as string constants here (since there
# isn't really a variable namespace to refer to).
#
def p_expr_0(t):
'''expr : ID
| INTLIT
| STRLIT
| CODELIT'''
t[0] = t[1]
def p_expr_1(t):
'''expr : LBRACKET list_expr RBRACKET'''
t[0] = t[2]
def p_list_expr_0(t):
'list_expr : expr'
t[0] = [t[1]]
def p_list_expr_1(t):
'list_expr : list_expr COMMA expr'
t[0] = t[1] + [t[3]]
def p_list_expr_2(t):
'list_expr : empty'
t[0] = []
#
# Empty production... use in other rules for readability.
#
@ -757,6 +845,19 @@ class GenCode:
# a defineInst() method that generates the code for an instruction
# definition.
exportContextSymbols = ('InstObjParams', 'CodeBlock',
'makeList', 're', 'string')
exportContext = {}
def updateExportContext():
exportContext.update(exportDict(*exportContextSymbols))
exportContext.update(templateMap)
def exportDict(*symNames):
return dict([(s, eval(s)) for s in symNames])
class Format:
def __init__(self, id, params, code):
# constructor: just save away arguments
@ -779,7 +880,7 @@ class Format:
context.update(exportContext)
context.update({ 'name': name, 'Name': string.capitalize(name) })
try:
vars = self.func(self.user_code, context, *args)
vars = self.func(self.user_code, context, *args[0], **args[1])
except Exception, exc:
error(lineno, 'error defining "%s": %s.' % (name, exc))
for k in vars.keys():
@ -974,53 +1075,294 @@ class Template:
#
#####################################################################
# Force the argument to be a list
def makeList(list_or_item):
if not list_or_item:
# Force the argument to be a list. Useful for flags, where a caller
# can specify a singleton flag or a list of flags. Also usful for
# converting tuples to lists so they can be modified.
def makeList(arg):
if isinstance(arg, list):
return arg
elif isinstance(arg, tuple):
return list(arg)
elif not arg:
return []
elif type(list_or_item) == ListType:
return list_or_item
else:
return [ list_or_item ]
return [ arg ]
# generate operandSizeMap based on provided operandTypeMap:
# basically generate equiv. C++ type and make is_signed flag
def buildOperandSizeMap():
global operandSizeMap
operandSizeMap = {}
for ext in operandTypeMap.keys():
(desc, size) = operandTypeMap[ext]
# Generate operandTypeMap from the user's 'def operand_types'
# statement.
def buildOperandTypeMap(userDict, lineno):
global operandTypeMap
operandTypeMap = {}
for (ext, (desc, size)) in userDict.iteritems():
if desc == 'signed int':
type = 'int%d_t' % size
ctype = 'int%d_t' % size
is_signed = 1
elif desc == 'unsigned int':
type = 'uint%d_t' % size
ctype = 'uint%d_t' % size
is_signed = 0
elif desc == 'float':
is_signed = 1 # shouldn't really matter
if size == 32:
type = 'float'
ctype = 'float'
elif size == 64:
type = 'double'
if type == '':
error(0, 'Unrecognized type description "%s" in operandTypeMap')
operandSizeMap[ext] = (size, type, is_signed)
ctype = 'double'
if ctype == '':
error(0, 'Unrecognized type description "%s" in userDict')
operandTypeMap[ext] = (size, ctype, is_signed)
#
# Base class for operand traits. An instance of this class (or actually
# a class derived from this one) encapsulates the traits of a particular
# operand type (e.g., "32-bit integer register").
#
class OperandTraits:
def __init__(self, dflt_ext, reg_spec, flags, sort_pri):
# Force construction of operandSizeMap from operandTypeMap
# if it hasn't happened yet
if not globals().has_key('operandSizeMap'):
buildOperandSizeMap()
self.dflt_ext = dflt_ext
(self.dflt_size, self.dflt_type, self.dflt_is_signed) = \
operandSizeMap[dflt_ext]
self.reg_spec = reg_spec
#
# Base class for operand descriptors. An instance of this class (or
# actually a class derived from this one) represents a specific
# operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
# derived classes encapsulates the traits of a particular operand type
# (e.g., "32-bit integer register").
#
class Operand(object):
def __init__(self, full_name, ext, is_src, is_dest):
self.full_name = full_name
self.ext = ext
self.is_src = is_src
self.is_dest = is_dest
# The 'effective extension' (eff_ext) is either the actual
# extension, if one was explicitly provided, or the default.
if ext:
self.eff_ext = ext
else:
self.eff_ext = self.dflt_ext
(self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
# note that mem_acc_size is undefined for non-mem operands...
# template must be careful not to use it if it doesn't apply.
if self.isMem():
self.mem_acc_size = self.makeAccSize()
# Finalize additional fields (primarily code fields). This step
# is done separately since some of these fields may depend on the
# register index enumeration that hasn't been performed yet at the
# time of __init__().
def finalize(self):
self.flags = self.getFlags()
self.constructor = self.makeConstructor()
self.op_decl = self.makeDecl()
if self.is_src:
self.op_rd = self.makeRead()
else:
self.op_rd = ''
if self.is_dest:
self.op_wb = self.makeWrite()
else:
self.op_wb = ''
def isMem(self):
return 0
def isReg(self):
return 0
def isFloatReg(self):
return 0
def isIntReg(self):
return 0
def isControlReg(self):
return 0
def getFlags(self):
# note the empty slice '[:]' gives us a copy of self.flags[0]
# instead of a reference to it
my_flags = self.flags[0][:]
if self.is_src:
my_flags += self.flags[1]
if self.is_dest:
my_flags += self.flags[2]
return my_flags
def makeDecl(self):
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
return self.ctype + ' ' + self.base_name + ' = 0;\n';
class IntRegOperand(Operand):
def isReg(self):
return 1
def isIntReg(self):
return 1
def makeConstructor(self):
c = ''
if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s;' % \
(self.src_reg_idx, self.reg_spec)
if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s;' % \
(self.dest_reg_idx, self.reg_spec)
return c
def makeRead(self):
if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read integer register as FP')
if (self.size == self.dflt_size):
return '%s = xc->readIntReg(this, %d);\n' % \
(self.base_name, self.src_reg_idx)
else:
return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
(self.base_name, self.src_reg_idx, self.size-1)
def makeWrite(self):
if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write integer register as FP')
if (self.size != self.dflt_size and self.is_signed):
final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
else:
final_val = self.base_name
wb = '''
{
%s final_val = %s;
xc->setIntReg(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
}''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
return wb
class FloatRegOperand(Operand):
def isReg(self):
return 1
def isFloatReg(self):
return 1
def makeConstructor(self):
c = ''
if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
(self.src_reg_idx, self.reg_spec)
if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
(self.dest_reg_idx, self.reg_spec)
return c
def makeRead(self):
bit_select = 0
if (self.ctype == 'float'):
func = 'readFloatRegSingle'
elif (self.ctype == 'double'):
func = 'readFloatRegDouble'
else:
func = 'readFloatRegInt'
if (self.size != self.dflt_size):
bit_select = 1
base = 'xc->%s(this, %d)' % \
(func, self.src_reg_idx)
if bit_select:
return '%s = bits(%s, %d, 0);\n' % \
(self.base_name, base, self.size-1)
else:
return '%s = %s;\n' % (self.base_name, base)
def makeWrite(self):
final_val = self.base_name
final_ctype = self.ctype
if (self.ctype == 'float'):
func = 'setFloatRegSingle'
elif (self.ctype == 'double'):
func = 'setFloatRegDouble'
else:
func = 'setFloatRegInt'
final_ctype = 'uint%d_t' % self.dflt_size
if (self.size != self.dflt_size and self.is_signed):
final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
wb = '''
{
%s final_val = %s;
xc->%s(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
}''' % (final_ctype, final_val, func, self.dest_reg_idx)
return wb
class ControlRegOperand(Operand):
def isReg(self):
return 1
def isControlReg(self):
return 1
def makeConstructor(self):
c = ''
if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
(self.src_reg_idx, self.reg_spec)
if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \
(self.dest_reg_idx, self.reg_spec)
return c
def makeRead(self):
bit_select = 0
if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read control register as FP')
base = 'xc->read%s()' % self.reg_spec
if self.size == self.dflt_size:
return '%s = %s;\n' % (self.base_name, base)
else:
return '%s = bits(%s, %d, 0);\n' % \
(self.base_name, base, self.size-1)
def makeWrite(self):
if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write control register as FP')
wb = 'xc->set%s(%s);\n' % (self.reg_spec, self.base_name)
wb += 'if (traceData) { traceData->setData(%s); }' % \
self.base_name
return wb
class MemOperand(Operand):
def isMem(self):
return 1
def makeConstructor(self):
return ''
def makeDecl(self):
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
# Declare memory data variable.
c = '%s %s = 0;\n' % (self.ctype, self.base_name)
return c
def makeRead(self):
return ''
def makeWrite(self):
return ''
# Return the memory access size *in bits*, suitable for
# forming a type via "uint%d_t". Divide by 8 if you want bytes.
def makeAccSize(self):
return self.size
class NPCOperand(Operand):
def makeConstructor(self):
return ''
def makeRead(self):
return '%s = xc->readPC() + 4;\n' % self.base_name
def makeWrite(self):
return 'xc->setNextPC(%s);\n' % self.base_name
def buildOperandNameMap(userDict, lineno):
global operandNameMap
operandNameMap = {}
for (op_name, val) in userDict.iteritems():
(base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val
(dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
# Canonical flag structure is a triple of lists, where each list
# indicates the set of flags implied by this operand always, when
# used as a source, and when used as a dest, respectively.
@ -1028,253 +1370,42 @@ class OperandTraits:
# obvious shortcuts; we convert these to canonical form here.
if not flags:
# no flags specified (e.g., 'None')
self.flags = ( [], [], [] )
elif type(flags) == StringType:
flags = ( [], [], [] )
elif isinstance(flags, str):
# a single flag: assumed to be unconditional
self.flags = ( [ flags ], [], [] )
elif type(flags) == ListType:
flags = ( [ flags ], [], [] )
elif isinstance(flags, list):
# a list of flags: also assumed to be unconditional
self.flags = ( flags, [], [] )
elif type(flags) == TupleType:
flags = ( flags, [], [] )
elif isinstance(flags, tuple):
# it's a tuple: it should be a triple,
# but each item could be a single string or a list
(uncond_flags, src_flags, dest_flags) = flags
self.flags = (makeList(uncond_flags),
makeList(src_flags), makeList(dest_flags))
self.sort_pri = sort_pri
flags = (makeList(uncond_flags),
makeList(src_flags), makeList(dest_flags))
# Accumulate attributes of new operand class in tmp_dict
tmp_dict = {}
for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
'dflt_size', 'dflt_ctype', 'dflt_is_signed'):
tmp_dict[attr] = eval(attr)
tmp_dict['base_name'] = op_name
# New class name will be e.g. "IntReg_Ra"
cls_name = base_cls_name + '_' + op_name
# Evaluate string arg to get class object. Note that the
# actual base class for "IntReg" is "IntRegOperand", i.e. we
# have to append "Operand".
try:
base_cls = eval(base_cls_name + 'Operand')
except NameError:
error(lineno,
'error: unknown operand base class "%s"' % base_cls_name)
# The following statement creates a new class called
# <cls_name> as a subclass of <base_cls> with the attributes
# in tmp_dict, just as if we evaluated a class declaration.
operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
def isMem(self):
return 0
def isReg(self):
return 0
def isFloatReg(self):
return 0
def isIntReg(self):
return 0
def isControlReg(self):
return 0
def getFlags(self, op_desc):
# note the empty slice '[:]' gives us a copy of self.flags[0]
# instead of a reference to it
my_flags = self.flags[0][:]
if op_desc.is_src:
my_flags += self.flags[1]
if op_desc.is_dest:
my_flags += self.flags[2]
return my_flags
def makeDecl(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
return type + ' ' + op_desc.base_name + ' = 0;\n';
class IntRegOperandTraits(OperandTraits):
def isReg(self):
return 1
def isIntReg(self):
return 1
def makeConstructor(self, op_desc):
c = ''
if op_desc.is_src:
c += '\n\t_srcRegIdx[%d] = %s;' % \
(op_desc.src_reg_idx, self.reg_spec)
if op_desc.is_dest:
c += '\n\t_destRegIdx[%d] = %s;' % \
(op_desc.dest_reg_idx, self.reg_spec)
return c
def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'):
error(0, 'Attempt to read integer register as FP')
if (size == self.dflt_size):
return '%s = xc->readIntReg(this, %d);\n' % \
(op_desc.base_name, op_desc.src_reg_idx)
else:
return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
(op_desc.base_name, op_desc.src_reg_idx, size-1)
def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'):
error(0, 'Attempt to write integer register as FP')
if (size != self.dflt_size and is_signed):
final_val = 'sext<%d>(%s)' % (size, op_desc.base_name)
else:
final_val = op_desc.base_name
wb = '''
{
%s final_val = %s;
xc->setIntReg(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
}''' % (self.dflt_type, final_val, op_desc.dest_reg_idx)
return wb
class FloatRegOperandTraits(OperandTraits):
def isReg(self):
return 1
def isFloatReg(self):
return 1
def makeConstructor(self, op_desc):
c = ''
if op_desc.is_src:
c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
(op_desc.src_reg_idx, self.reg_spec)
if op_desc.is_dest:
c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
(op_desc.dest_reg_idx, self.reg_spec)
return c
def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
bit_select = 0
if (type == 'float'):
func = 'readFloatRegSingle'
elif (type == 'double'):
func = 'readFloatRegDouble'
else:
func = 'readFloatRegInt'
if (size != self.dflt_size):
bit_select = 1
base = 'xc->%s(this, %d)' % \
(func, op_desc.src_reg_idx)
if bit_select:
return '%s = bits(%s, %d, 0);\n' % \
(op_desc.base_name, base, size-1)
else:
return '%s = %s;\n' % (op_desc.base_name, base)
def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
final_val = op_desc.base_name
if (type == 'float'):
func = 'setFloatRegSingle'
elif (type == 'double'):
func = 'setFloatRegDouble'
else:
func = 'setFloatRegInt'
type = 'uint%d_t' % self.dflt_size
if (size != self.dflt_size and is_signed):
final_val = 'sext<%d>(%s)' % (size, op_desc.base_name)
wb = '''
{
%s final_val = %s;
xc->%s(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
}''' % (type, final_val, func, op_desc.dest_reg_idx)
return wb
class ControlRegOperandTraits(OperandTraits):
def isReg(self):
return 1
def isControlReg(self):
return 1
def makeConstructor(self, op_desc):
c = ''
if op_desc.is_src:
c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
(op_desc.src_reg_idx, self.reg_spec)
if op_desc.is_dest:
c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \
(op_desc.dest_reg_idx, self.reg_spec)
return c
def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
bit_select = 0
if (type == 'float' or type == 'double'):
error(0, 'Attempt to read control register as FP')
base = 'xc->read%s()' % self.reg_spec
if size == self.dflt_size:
return '%s = %s;\n' % (op_desc.base_name, base)
else:
return '%s = bits(%s, %d, 0);\n' % \
(op_desc.base_name, base, size-1)
def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'):
error(0, 'Attempt to write control register as FP')
wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.base_name)
wb += 'if (traceData) { traceData->setData(%s); }' % \
op_desc.base_name
return wb
class MemOperandTraits(OperandTraits):
def isMem(self):
return 1
def makeConstructor(self, op_desc):
return ''
def makeDecl(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
# Declare memory data variable.
c = '%s %s = 0;\n' % (type, op_desc.base_name)
return c
def makeRead(self, op_desc):
return ''
def makeWrite(self, op_desc):
return ''
# Return the memory access size *in bits*, suitable for
# forming a type via "uint%d_t". Divide by 8 if you want bytes.
def makeAccSize(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
return size
class NPCOperandTraits(OperandTraits):
def makeConstructor(self, op_desc):
return ''
def makeRead(self, op_desc):
return '%s = xc->readPC() + 4;\n' % op_desc.base_name
def makeWrite(self, op_desc):
return 'xc->setNextPC(%s);\n' % op_desc.base_name
exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
'ControlRegOperandTraits', 'MemOperandTraits',
'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
're', 'string')
exportContext = {}
def updateExportContext():
exportContext.update(exportDict(*exportContextSymbols))
exportContext.update(templateMap)
def exportDict(*symNames):
return dict([(s, eval(s)) for s in symNames])
#
# Define operand variables that get derived from the basic declaration
# of ISA-specific operands in operandTraitsMap. This function must be
# called by the ISA description file explicitly after defining
# operandTraitsMap (in a 'let' block).
#
def defineDerivedOperandVars():
global operands
operands = operandTraitsMap.keys()
# Define operand variables.
operands = userDict.keys()
operandsREString = (r'''
(?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
@ -1296,54 +1427,10 @@ def defineDerivedOperandVars():
operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
#
# Operand descriptor class. An instance of this class represents
# a specific operand for a code block.
#
class OperandDescriptor:
def __init__(self, full_name, base_name, ext, is_src, is_dest):
self.full_name = full_name
self.base_name = base_name
self.ext = ext
self.is_src = is_src
self.is_dest = is_dest
self.traits = operandTraitsMap[base_name]
# The 'effective extension' (eff_ext) is either the actual
# extension, if one was explicitly provided, or the default.
if ext:
self.eff_ext = ext
else:
self.eff_ext = self.traits.dflt_ext
# note that mem_acc_size is undefined for non-mem operands...
# template must be careful not to use it if it doesn't apply.
if self.traits.isMem():
self.mem_acc_size = self.traits.makeAccSize(self)
# Finalize additional fields (primarily code fields). This step
# is done separately since some of these fields may depend on the
# register index enumeration that hasn't been performed yet at the
# time of __init__().
def finalize(self):
self.flags = self.traits.getFlags(self)
self.constructor = self.traits.makeConstructor(self)
self.op_decl = self.traits.makeDecl(self)
if self.is_src:
self.op_rd = self.traits.makeRead(self)
else:
self.op_rd = ''
if self.is_dest:
self.op_wb = self.traits.makeWrite(self)
else:
self.op_wb = ''
class OperandDescriptorList:
class OperandList:
# Find all the operands in the given code block. Returns an operand
# descriptor list (instance of class OperandDescriptorList).
# descriptor list (instance of class OperandList).
def __init__(self, code):
self.items = []
self.bases = {}
@ -1373,8 +1460,8 @@ class OperandDescriptorList:
op_desc.is_dest = op_desc.is_dest or is_dest
else:
# new operand: create new descriptor
op_desc = OperandDescriptor(op_full, op_base, op_ext,
is_src, is_dest)
op_desc = operandNameMap[op_base](op_full, op_ext,
is_src, is_dest)
self.append(op_desc)
# start next search after end of current match
next_pos = match.end()
@ -1387,18 +1474,18 @@ class OperandDescriptorList:
self.numIntDestRegs = 0
self.memOperand = None
for op_desc in self.items:
if op_desc.traits.isReg():
if op_desc.isReg():
if op_desc.is_src:
op_desc.src_reg_idx = self.numSrcRegs
self.numSrcRegs += 1
if op_desc.is_dest:
op_desc.dest_reg_idx = self.numDestRegs
self.numDestRegs += 1
if op_desc.traits.isFloatReg():
if op_desc.isFloatReg():
self.numFPDestRegs += 1
elif op_desc.traits.isIntReg():
elif op_desc.isIntReg():
self.numIntDestRegs += 1
elif op_desc.traits.isMem():
elif op_desc.isMem():
if self.memOperand:
error(0, "Code block has more than one memory operand.")
self.memOperand = op_desc
@ -1450,7 +1537,7 @@ class OperandDescriptorList:
return self.__internalConcatAttrs(attr_name, filter, [])
def sort(self):
self.items.sort(lambda a, b: a.traits.sort_pri - b.traits.sort_pri)
self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
# Regular expression object to match C++ comments
# (used in findOperands())
@ -1462,7 +1549,7 @@ assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
# Munge operand names in code string to make legal C++ variable names.
# This means getting rid of the type extension if any.
# (Will match base_name attribute of OperandDescriptor object.)
# (Will match base_name attribute of Operand object.)
def substMungedOpNames(code):
return operandsWithExtRE.sub(r'\1', code)
@ -1488,7 +1575,7 @@ def makeFlagConstructor(flag_list):
class CodeBlock:
def __init__(self, code):
self.orig_code = code
self.operands = OperandDescriptorList(code)
self.operands = OperandList(code)
self.code = substMungedOpNames(substBitOps(code))
self.constructor = self.operands.concatAttrStrings('constructor')
self.constructor += \

View file

@ -13,24 +13,23 @@ def operand_types {{
}};
def operands {{
'Rd': IntRegOperandTraits('uw', 'RD', 'IsInteger', 1),
'Rs': IntRegOperandTraits('uw', 'RS', 'IsInteger', 2),
'Rt': IntRegOperandTraits('uw', 'RT', 'IsInteger', 3),
'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1),
'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2),
'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3),
'IntImm': IntRegOperandTraits('uw', 'INTIMM', 'IsInteger', 3),
'Sa': IntRegOperandTraits('uw', 'SA', 'IsInteger', 4),
'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
'Sa': ('IntReg', 'uw', 'SA', 'IsInteger', 4),
'Fd': FloatRegOperandTraits('sf', 'FD', 'IsFloating', 1),
'Fs': FloatRegOperandTraits('sf', 'FS', 'IsFloating', 2),
'Ft': FloatRegOperandTraits('sf', 'FT', 'IsFloating', 3),
'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1),
'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2),
'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3),
'Mem': MemOperandTraits('udw', None,
('IsMemRef', 'IsLoad', 'IsStore'), 4)
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4)
#'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
#'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
#'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
#'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
#'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
#'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
# The next two are hacks for non-full-system call-pal emulation
#'R0': IntRegOperandTraits('uq', '0', None, 1),
#'R16': IntRegOperandTraits('uq', '16', None, 1)
#'R0': ('IntReg', 'uq', '0', None, 1),
#'R16': ('IntReg', 'uq', '16', None, 1)
}};

View file

@ -16,18 +16,17 @@ def operands {{
# Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should
# explicitly specify '.uq'.
'Rd': IntRegOperandTraits('udw', 'RD', 'IsInteger', 1),
'Rs1': IntRegOperandTraits('udw', 'RS1', 'IsInteger', 2),
'Rs2': IntRegOperandTraits('udw', 'RS2', 'IsInteger', 3),
#'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
#'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
#'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
'Mem': MemOperandTraits('udw', None,
('IsMemRef', 'IsLoad', 'IsStore'), 4)
#'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
#'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
#'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 2),
'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 3),
#'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
#'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
#'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4)
#'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
#'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
#'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
# The next two are hacks for non-full-system call-pal emulation
#'R0': IntRegOperandTraits('uq', '0', None, 1),
#'R16': IntRegOperandTraits('uq', '16', None, 1)
#'R0': ('IntReg', 'uq', '0', None, 1),
#'R16': ('IntReg', 'uq', '16', None, 1)
}};

View file

@ -145,22 +145,6 @@ floorLog2(long long x)
return floorLog2((unsigned long long)x);
}
#if defined(__APPLE__)
inline int
floorLog2(size_t x)
{
assert(x > 0);
assert(sizeof(size_t) == 4 || sizeof(size_t) == 8);
// It's my hope that this is optimized away?
if (sizeof(size_t) == 4)
return floorLog2((uint32_t)x);
else if (sizeof(size_t) == 8)
return floorLog2((uint64_t)x);
}
#endif
template <class T>
inline int
ceilLog2(T n)

View file

@ -93,9 +93,6 @@ ListenSocket::listen(int port, bool reuse)
return true;
}
#if defined(__APPLE__)
typedef int socklen_t;
#endif
// Open a connection. Accept will block, so if you don't want it to,
// make sure a connection is ready before you call accept.

View file

@ -32,7 +32,7 @@
// inst sequence type, used to order instructions in the ready list,
// if this rolls over the ready list order temporarily will get messed
// up, but execution will continue and complete correctly
typedef unsigned long long InstSeqNum;
typedef uint64_t InstSeqNum;
// inst tag type, used to tag an operation instance in the IQ
typedef unsigned int InstTag;

View file

@ -34,6 +34,7 @@
// but probably is more flexible to actually add in a delay parameter than
// just running it backwards.
#include <limits>
#include <vector>
#include "sim/root.hh"
@ -42,7 +43,7 @@
// Either compile error or max int due to sign extension.
// Hack to avoid compile warnings.
const InstSeqNum MaxInstSeqNum = 0 - 1;
const InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max();
template <class Impl>
InstructionQueue<Impl>::InstructionQueue(Params &params)

View file

@ -75,15 +75,16 @@ swap_byte16(uint16_t x)
//This lets the compiler figure out how to call the swap_byte functions above
//for different data types.
static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);} \
static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);} \
static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);} \
static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);} \
static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);} \
static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);} \
static inline uint8_t swap_byte(uint8_t x) {return x;} \
static inline int8_t swap_byte(int8_t x) {return x;} \
static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);} \
static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);}
static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);}
static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);}
static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);}
static inline int32_t swap_byte(long x) {return swap_byte32((long)x);}
static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);}
static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);}
static inline uint8_t swap_byte(uint8_t x) {return x;}
static inline int8_t swap_byte(int8_t x) {return x;}
static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);}
static inline float swap_byte(float x) {return swap_byte32((uint32_t)x);}
//The conversion functions with fixed endianness on both ends don't need to

View file

@ -29,6 +29,9 @@
#ifndef __SIM_SYSCALL_EMUL_HH__
#define __SIM_SYSCALL_EMUL_HH__
#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
defined(__FreeBSD__))
///
/// @file syscall_emul.hh
///
@ -441,8 +444,13 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process,
return -EBADF;
}
struct stat64 hostBuf;
#if BSD_HOST
struct stat hostBuf;
int result = fstat(process->sim_fd(fd), &hostBuf);
#else
struct stat64 hostBuf;
int result = fstat64(process->sim_fd(fd), &hostBuf);
#endif
if (result < 0)
return errno;
@ -486,8 +494,13 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
return -EFAULT;
#if BSD_HOST
struct stat hostBuf;
int result = lstat(path.c_str(), &hostBuf);
#else
struct stat64 hostBuf;
int result = lstat64(path.c_str(), &hostBuf);
#endif
if (result < 0)
return -errno;
@ -517,7 +530,6 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
return -errno;
OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@ -653,22 +665,22 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
template <class OS>
SyscallReturn
getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
ExecContext *xc)
{
unsigned resource = xc->getSyscallArg(0);
TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
switch (resource) {
case OS::RLIMIT_STACK:
// max stack size in bytes: make up a number (2MB for now)
rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
break;
case OS::TGT_RLIMIT_STACK:
// max stack size in bytes: make up a number (2MB for now)
rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
break;
default:
std::cerr << "getrlimitFunc: unimplemented resource " << resource
<< std::endl;
abort();
break;
default:
std::cerr << "getrlimitFunc: unimplemented resource " << resource
<< std::endl;
abort();
break;
}
rlp.copyOut(xc->mem);
@ -679,7 +691,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
template <class OS>
SyscallReturn
gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
ExecContext *xc)
{
TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
@ -719,7 +731,6 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
return 0;
}
/// Target getrusage() function.
template <class OS>
SyscallReturn
@ -729,7 +740,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
if (who != OS::RUSAGE_SELF) {
if (who != OS::TGT_RUSAGE_SELF) {
// don't really handle THREAD or CHILDREN, but just warn and
// plow ahead
warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",