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:
commit
94590a4dba
15 changed files with 700 additions and 575 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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')
|
||||
}};
|
||||
|
||||
|
|
|
@ -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')
|
||||
}};
|
||||
|
||||
|
||||
|
|
|
@ -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 += \
|
||||
|
|
|
@ -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)
|
||||
}};
|
||||
|
|
|
@ -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)
|
||||
}};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ¶ms)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.",
|
||||
|
|
Loading…
Reference in a new issue