summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/isa/decoder.isa20
-rw-r--r--arch/alpha/isa/mem.isa132
-rw-r--r--arch/alpha/isa/pal.isa13
-rwxr-xr-xarch/isa_parser.py183
4 files changed, 217 insertions, 131 deletions
diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa
index 6a35fa229..c21465928 100644
--- a/arch/alpha/isa/decoder.isa
+++ b/arch/alpha/isa/decoder.isa
@@ -40,9 +40,9 @@ decode OPCODE default Unknown::unknown() {
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);
- 0x20: copy_load({{EA = Ra;}},
- {{fault = xc->copySrcTranslate(EA);}},
- IsMemRef, IsLoad, IsCopy);
+ 0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
+ {{ fault = xc->copySrcTranslate(EA); }},
+ IsMemRef, IsLoad, IsCopy);
}
format LoadOrPrefetch {
@@ -62,21 +62,21 @@ decode OPCODE default Unknown::unknown() {
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; }});
- 0x24: copy_store({{EA = Rb;}},
- {{fault = xc->copy(EA);}},
- IsMemRef, IsStore, IsCopy);
+ 0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
+ {{ fault = xc->copy(EA); }},
+ IsMemRef, IsStore, IsCopy);
}
format StoreCond {
0x2e: stl_c({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }},
{{
- uint64_t tmp = Mem_write_result;
+ 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; }},
{{
- uint64_t tmp = Mem_write_result;
+ uint64_t tmp = write_result;
// If the write operation returns 0 or 1, then
// this was a conventional store conditional,
// and the value indicates the success/failure
@@ -704,12 +704,14 @@ decode OPCODE default Unknown::unknown() {
#endif
#if FULL_SYSTEM
- format HwLoadStore {
+ format HwLoad {
0x1b: decode HW_LDST_QUAD {
0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
}
+ }
+ format HwStore {
0x1f: decode HW_LDST_COND {
0: decode HW_LDST_QUAD {
0: hw_st({{ EA = (Rb + disp) & ~3; }},
diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa
index 89296626c..0d9d59cee 100644
--- a/arch/alpha/isa/mem.isa
+++ b/arch/alpha/isa/mem.isa
@@ -214,7 +214,7 @@ def template EACompExecute {{
}
}};
-def template MemAccExecute {{
+def template LoadMemAccExecute {{
Fault
%(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
@@ -224,16 +224,71 @@ def template MemAccExecute {{
%(fp_enable_check)s;
%(op_decl)s;
- %(op_nonmem_rd)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == No_Fault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(code)s;
+ }
+
+ if (fault == No_Fault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == No_Fault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(memacc_code)s;
+ }
+
+ if (fault == No_Fault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
EA = xc->getEA();
if (fault == No_Fault) {
- %(op_mem_rd)s;
%(code)s;
}
if (fault == No_Fault) {
- %(op_mem_wb)s;
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
}
if (fault == No_Fault) {
@@ -241,7 +296,7 @@ def template MemAccExecute {{
}
if (fault == No_Fault) {
- %(op_nonmem_wb)s;
+ %(op_wb)s;
}
return fault;
@@ -249,25 +304,27 @@ def template MemAccExecute {{
}};
-def template LoadStoreExecute {{
+def template StoreExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = No_Fault;
+ uint64_t write_result = 0;
%(fp_enable_check)s;
%(op_decl)s;
- %(op_nonmem_rd)s;
+ %(op_rd)s;
%(ea_code)s;
if (fault == No_Fault) {
- %(op_mem_rd)s;
%(memacc_code)s;
}
if (fault == No_Fault) {
- %(op_mem_wb)s;
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
}
if (fault == No_Fault) {
@@ -275,7 +332,7 @@ def template LoadStoreExecute {{
}
if (fault == No_Fault) {
- %(op_nonmem_wb)s;
+ %(op_wb)s;
}
return fault;
@@ -283,7 +340,27 @@ def template LoadStoreExecute {{
}};
-def template PrefetchExecute {{
+def template MiscMemAccExecute {{
+ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == No_Fault) {
+ %(code)s;
+ }
+
+ return No_Fault;
+ }
+}};
+
+def template MiscExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
@@ -292,11 +369,11 @@ def template PrefetchExecute {{
%(fp_enable_check)s;
%(op_decl)s;
- %(op_nonmem_rd)s;
+ %(op_rd)s;
%(ea_code)s;
if (fault == No_Fault) {
- xc->prefetch(EA, memAccessFlags);
+ %(memacc_code)s;
}
return No_Fault;
@@ -332,8 +409,7 @@ def template LoadPrefetchCheckDecode {{
let {{
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
base_class = 'MemoryDisp32', flags = [],
- decode_template = BasicDecode,
- exec_template = LoadStoreExecute):
+ decode_template = BasicDecode, exec_template_base = ''):
# Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here).
@@ -380,19 +456,24 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
iop.constructor += s
memacc_iop.constructor += s
+ # select templates
+ memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
+ fullExecTemplate = eval(exec_template_base + 'Execute')
+
# (header_output, decoder_output, decode_block, exec_output)
return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
decode_template.subst(iop),
EACompExecute.subst(ea_iop)
- + MemAccExecute.subst(memacc_iop)
- + exec_template.subst(iop))
+ + memAccExecTemplate.subst(memacc_iop)
+ + fullExecTemplate.subst(iop))
}};
def format LoadOrNop(ea_code, memacc_code, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
- decode_template = LoadNopCheckDecode)
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Load')
}};
@@ -401,7 +482,8 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_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,
- decode_template = LoadPrefetchCheckDecode)
+ decode_template = LoadPrefetchCheckDecode,
+ exec_template_base = 'Load')
# Declare the prefetch instruction object.
@@ -409,8 +491,9 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
(pf_header_output, pf_decoder_output, _, pf_exec_output) = \
- LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
- flags = pf_flags, exec_template = PrefetchExecute)
+ LoadStoreBase(name, Name + 'Prefetch', ea_code,
+ 'xc->prefetch(EA, memAccessFlags);',
+ flags = pf_flags, exec_template_base = 'Misc')
header_output += pf_header_output
decoder_output += pf_decoder_output
@@ -420,14 +503,15 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
def format Store(ea_code, memacc_code, *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, flags = flags,
+ exec_template_base = 'Store')
}};
def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
- flags = flags)
+ flags = flags, exec_template_base = 'Store')
}};
@@ -435,7 +519,7 @@ def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
def format MiscPrefetch(ea_code, memacc_code, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
- base_class = 'MemoryNoDisp')
+ base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
}};
diff --git a/arch/alpha/isa/pal.isa b/arch/alpha/isa/pal.isa
index 9debffa38..552dde2d7 100644
--- a/arch/alpha/isa/pal.isa
+++ b/arch/alpha/isa/pal.isa
@@ -195,10 +195,19 @@ output decoder {{
}
}};
-def format HwLoadStore(ea_code, memacc_code, class_ext, *flags) {{
+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')
+ 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')
}};
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index b12329ebb..fffcc33e5 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -868,16 +868,21 @@ def fixPythonIndentation(s):
return s
# Error handler. Just call exit. Output formatted to work under
-# Emacs compile-mode.
+# Emacs compile-mode. This function should be called when errors due
+# to user input are detected (as opposed to parser bugs).
def error(lineno, string):
spaces = ""
for (filename, line) in fileNameStack[0:-1]:
print spaces + "In file included from " + filename
spaces += " "
+ # Uncomment the following line to get a Python stack backtrace for
+ # these errors too. Can be handy when trying to debug the parser.
+ # traceback.print_exc()
sys.exit(spaces + "%s:%d: %s" % (fileNameStack[-1][0], lineno, string))
# Like error(), but include a Python stack backtrace (for processing
-# Python exceptions).
+# Python exceptions). This function should be called for errors that
+# appear to be bugs in the parser itself.
def error_bt(lineno, string):
traceback.print_exc()
print >> sys.stderr, "%s:%d: %s" % (input_filename, lineno, string)
@@ -1220,30 +1225,19 @@ class MemOperandTraits(OperandTraits):
# to avoid 'uninitialized variable' errors from the compiler.
# Declare memory data variable.
c = '%s %s = 0;\n' % (type, op_desc.base_name)
- # Declare var to hold memory access flags.
- c += 'unsigned %s_flags = memAccessFlags;\n' % op_desc.base_name
- # If this operand is a dest (i.e., it's a store operation),
- # then we need to declare a variable for the write result code
- # as well.
- if op_desc.is_dest:
- c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name
return c
def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- eff_type = 'uint%d_t' % size
- return 'fault = xc->read(EA, (%s&)%s, %s_flags);\n' \
- % (eff_type, op_desc.base_name, op_desc.base_name)
+ 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]
- eff_type = 'uint%d_t' % size
- wb = 'fault = xc->write((%s&)%s, EA, %s_flags, &%s_write_result);\n' \
- % (eff_type, op_desc.base_name, op_desc.base_name,
- op_desc.base_name)
- wb += 'if (traceData) { traceData->setData(%s); }' % \
- op_desc.base_name
- return wb
+ return size
class NPCOperandTraits(OperandTraits):
def makeConstructor(self, op_desc):
@@ -1321,6 +1315,11 @@ class OperandDescriptor:
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
@@ -1340,10 +1339,73 @@ class OperandDescriptor:
else:
self.op_wb = ''
+
class OperandDescriptorList:
- def __init__(self):
+
+ # Find all the operands in the given code block. Returns an operand
+ # descriptor list (instance of class OperandDescriptorList).
+ def __init__(self, code):
self.items = []
self.bases = {}
+ # delete comments so we don't match on reg specifiers inside
+ code = commentRE.sub('', code)
+ # search for operands
+ next_pos = 0
+ while 1:
+ match = operandsRE.search(code, next_pos)
+ if not match:
+ # no more matches: we're done
+ break
+ op = match.groups()
+ # regexp groups are operand full name, base, and extension
+ (op_full, op_base, op_ext) = op
+ # if the token following the operand is an assignment, this is
+ # a destination (LHS), else it's a source (RHS)
+ is_dest = (assignRE.match(code, match.end()) != None)
+ is_src = not is_dest
+ # see if we've already seen this one
+ op_desc = self.find_base(op_base)
+ if op_desc:
+ if op_desc.ext != op_ext:
+ error(0, 'Inconsistent extensions for operand %s' % \
+ op_base)
+ op_desc.is_src = op_desc.is_src or is_src
+ 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)
+ self.append(op_desc)
+ # start next search after end of current match
+ next_pos = match.end()
+ self.sort()
+ # enumerate source & dest register operands... used in building
+ # constructor later
+ self.numSrcRegs = 0
+ self.numDestRegs = 0
+ self.numFPDestRegs = 0
+ self.numIntDestRegs = 0
+ self.memOperand = None
+ for op_desc in self.items:
+ if op_desc.traits.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():
+ self.numFPDestRegs += 1
+ elif op_desc.traits.isIntReg():
+ self.numIntDestRegs += 1
+ elif op_desc.traits.isMem():
+ if self.memOperand:
+ error(0, "Code block has more than one memory operand.")
+ self.memOperand = op_desc
+ # now make a final pass to finalize op_desc fields that may depend
+ # on the register enumeration
+ for op_desc in self.items:
+ op_desc.finalize()
def __len__(self):
return len(self.items)
@@ -1398,69 +1460,6 @@ commentRE = re.compile(r'//.*\n')
# (used in findOperands())
assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
-#
-# Find all the operands in the given code block. Returns an operand
-# descriptor list (instance of class OperandDescriptorList).
-#
-def findOperands(code):
- operands = OperandDescriptorList()
- # delete comments so we don't accidentally match on reg specifiers inside
- code = commentRE.sub('', code)
- # search for operands
- next_pos = 0
- while 1:
- match = operandsRE.search(code, next_pos)
- if not match:
- # no more matches: we're done
- break
- op = match.groups()
- # regexp groups are operand full name, base, and extension
- (op_full, op_base, op_ext) = op
- # if the token following the operand is an assignment, this is
- # a destination (LHS), else it's a source (RHS)
- is_dest = (assignRE.match(code, match.end()) != None)
- is_src = not is_dest
- # see if we've already seen this one
- op_desc = operands.find_base(op_base)
- if op_desc:
- if op_desc.ext != op_ext:
- error(0, 'Inconsistent extensions for operand %s' % op_base)
- op_desc.is_src = op_desc.is_src or is_src
- 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)
- operands.append(op_desc)
- # start next search after end of current match
- next_pos = match.end()
- operands.sort()
- # enumerate source & dest register operands... used in building
- # constructor later
- srcRegs = 0
- destRegs = 0
- operands.numFPDestRegs = 0
- operands.numIntDestRegs = 0
- for op_desc in operands:
- if op_desc.traits.isReg():
- if op_desc.is_src:
- op_desc.src_reg_idx = srcRegs
- srcRegs += 1
- if op_desc.is_dest:
- op_desc.dest_reg_idx = destRegs
- destRegs += 1
- if op_desc.traits.isFloatReg():
- operands.numFPDestRegs += 1
- elif op_desc.traits.isIntReg():
- operands.numIntDestRegs += 1
- operands.numSrcRegs = srcRegs
- operands.numDestRegs = destRegs
- # now make a final pass to finalize op_desc fields that may depend
- # on the register enumeration
- for op_desc in operands:
- op_desc.finalize()
- return operands
-
# 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.)
@@ -1489,7 +1488,7 @@ def makeFlagConstructor(flag_list):
class CodeBlock:
def __init__(self, code):
self.orig_code = code
- self.operands = findOperands(code)
+ self.operands = OperandDescriptorList(code)
self.code = substMungedOpNames(substBitOps(code))
self.constructor = self.operands.concatAttrStrings('constructor')
self.constructor += \
@@ -1503,22 +1502,14 @@ class CodeBlock:
self.op_decl = self.operands.concatAttrStrings('op_decl')
- is_mem = lambda op: op.traits.isMem()
- not_mem = lambda op: not op.traits.isMem()
-
self.op_rd = self.operands.concatAttrStrings('op_rd')
self.op_wb = self.operands.concatAttrStrings('op_wb')
- self.op_mem_rd = \
- self.operands.concatSomeAttrStrings(is_mem, 'op_rd')
- self.op_mem_wb = \
- self.operands.concatSomeAttrStrings(is_mem, 'op_wb')
- self.op_nonmem_rd = \
- self.operands.concatSomeAttrStrings(not_mem, 'op_rd')
- self.op_nonmem_wb = \
- self.operands.concatSomeAttrStrings(not_mem, 'op_wb')
self.flags = self.operands.concatAttrLists('flags')
+ if self.operands.memOperand:
+ self.mem_acc_size = self.operands.memOperand.mem_acc_size
+
# Make a basic guess on the operand class (function unit type).
# These are good enough for most cases, and will be overridden
# later otherwise.