isa_parser.py (12109:f29e9c5418aa) isa_parser.py (12110:c24ee249b8ba)
1# Copyright (c) 2014, 2016 ARM Limited
2# All rights reserved
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license

--- 479 unchanged lines hidden (view full) ---

488 return 0
489
490 def isCCReg(self):
491 return 0
492
493 def isControlReg(self):
494 return 0
495
1# Copyright (c) 2014, 2016 ARM Limited
2# All rights reserved
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license

--- 479 unchanged lines hidden (view full) ---

488 return 0
489
490 def isCCReg(self):
491 return 0
492
493 def isControlReg(self):
494 return 0
495
496 def isVecReg(self):
497 return 0
498
499 def isVecElem(self):
500 return 0
501
496 def isPCState(self):
497 return 0
498
499 def isPCPart(self):
500 return self.isPCState() and self.reg_spec
501
502 def hasReadPred(self):
503 return self.read_predicate != None

--- 149 unchanged lines hidden (view full) ---

653 wb = '''
654 {
655 %s final_val = %s;
656 %s\n
657 if (traceData) { traceData->setData(final_val); }
658 }''' % (self.ctype, self.base_name, wp)
659 return wb
660
502 def isPCState(self):
503 return 0
504
505 def isPCPart(self):
506 return self.isPCState() and self.reg_spec
507
508 def hasReadPred(self):
509 return self.read_predicate != None

--- 149 unchanged lines hidden (view full) ---

659 wb = '''
660 {
661 %s final_val = %s;
662 %s\n
663 if (traceData) { traceData->setData(final_val); }
664 }''' % (self.ctype, self.base_name, wp)
665 return wb
666
667class VecRegOperand(Operand):
668 reg_class = 'VecRegClass'
669
670 def __init__(self, parser, full_name, ext, is_src, is_dest):
671 Operand.__init__(self, parser, full_name, ext, is_src, is_dest)
672 self.elemExt = None
673 self.parser = parser
674
675 def isReg(self):
676 return 1
677
678 def isVecReg(self):
679 return 1
680
681 def makeDeclElem(self, elem_op):
682 (elem_name, elem_ext) = elem_op
683 (elem_spec, dflt_elem_ext, zeroing) = self.elems[elem_name]
684 if elem_ext:
685 ext = elem_ext
686 else:
687 ext = dflt_elem_ext
688 ctype = self.parser.operandTypeMap[ext]
689 return '\n\t%s %s = 0;' % (ctype, elem_name)
690
691 def makeDecl(self):
692 if not self.is_dest and self.is_src:
693 c_decl = '\t/* Vars for %s*/' % (self.base_name)
694 if hasattr(self, 'active_elems'):
695 if self.active_elems:
696 for elem in self.active_elems:
697 c_decl += self.makeDeclElem(elem)
698 return c_decl + '\t/* End vars for %s */\n' % (self.base_name)
699 else:
700 return ''
701
702 def makeConstructor(self, predRead, predWrite):
703 c_src = ''
704 c_dest = ''
705
706 numAccessNeeded = 1
707
708 if self.is_src:
709 c_src = src_reg_constructor % (self.reg_class, self.reg_spec)
710
711 if self.is_dest:
712 c_dest = dst_reg_constructor % (self.reg_class, self.reg_spec)
713 c_dest += '\n\t_numVecDestRegs++;'
714
715 return c_src + c_dest
716
717 # Read destination register to write
718 def makeReadWElem(self, elem_op):
719 (elem_name, elem_ext) = elem_op
720 (elem_spec, dflt_elem_ext, zeroing) = self.elems[elem_name]
721 if elem_ext:
722 ext = elem_ext
723 else:
724 ext = dflt_elem_ext
725 ctype = self.parser.operandTypeMap[ext]
726 c_read = '\t\t%s& %s = %s[%s];\n' % \
727 (ctype, elem_name, self.base_name, elem_spec)
728 return c_read
729
730 def makeReadW(self, predWrite):
731 func = 'getWritableVecRegOperand'
732 if self.read_code != None:
733 return self.buildReadCode(func)
734
735 if predWrite:
736 rindex = '_destIndex++'
737 else:
738 rindex = '%d' % self.dest_reg_idx
739
740 c_readw = '\t\t%s& tmp_d%s = xc->%s(this, %s);\n'\
741 % ('TheISA::VecRegContainer', rindex, func, rindex)
742 if self.elemExt:
743 c_readw += '\t\tauto %s = tmp_d%s.as<%s>();\n' % (self.base_name,
744 rindex, self.parser.operandTypeMap[self.elemExt])
745 if self.ext:
746 c_readw += '\t\tauto %s = tmp_d%s.as<%s>();\n' % (self.base_name,
747 rindex, self.parser.operandTypeMap[self.ext])
748 if hasattr(self, 'active_elems'):
749 if self.active_elems:
750 for elem in self.active_elems:
751 c_readw += self.makeReadWElem(elem)
752 return c_readw
753
754 # Normal source operand read
755 def makeReadElem(self, elem_op, name):
756 (elem_name, elem_ext) = elem_op
757 (elem_spec, dflt_elem_ext, zeroing) = self.elems[elem_name]
758
759 if elem_ext:
760 ext = elem_ext
761 else:
762 ext = dflt_elem_ext
763 ctype = self.parser.operandTypeMap[ext]
764 c_read = '\t\t%s = %s[%s];\n' % \
765 (elem_name, name, elem_spec)
766 return c_read
767
768 def makeRead(self, predRead):
769 func = 'readVecRegOperand'
770 if self.read_code != None:
771 return self.buildReadCode(func)
772
773 if predRead:
774 rindex = '_sourceIndex++'
775 else:
776 rindex = '%d' % self.src_reg_idx
777
778 name = self.base_name
779 if self.is_dest and self.is_src:
780 name += '_merger'
781
782 c_read = '\t\t%s& tmp_s%s = xc->%s(this, %s);\n' \
783 % ('const TheISA::VecRegContainer', rindex, func, rindex)
784 # If the parser has detected that elements are being access, create
785 # the appropriate view
786 if self.elemExt:
787 c_read += '\t\tauto %s = tmp_s%s.as<%s>();\n' % \
788 (name, rindex, self.parser.operandTypeMap[self.elemExt])
789 if self.ext:
790 c_read += '\t\tauto %s = tmp_s%s.as<%s>();\n' % \
791 (name, rindex, self.parser.operandTypeMap[self.ext])
792 if hasattr(self, 'active_elems'):
793 if self.active_elems:
794 for elem in self.active_elems:
795 c_read += self.makeReadElem(elem, name)
796 return c_read
797
798 def makeWrite(self, predWrite):
799 func = 'setVecRegOperand'
800 if self.write_code != None:
801 return self.buildWriteCode(func)
802
803 wb = '''
804 if (traceData) {
805 panic("Vectors not supported yet in tracedata");
806 /*traceData->setData(final_val);*/
807 }
808 '''
809 return wb
810
811 def finalize(self, predRead, predWrite):
812 super(VecRegOperand, self).finalize(predRead, predWrite)
813 if self.is_dest:
814 self.op_rd = self.makeReadW(predWrite) + self.op_rd
815
816class VecElemOperand(Operand):
817 reg_class = 'VectorElemClass'
818
819 def isReg(self):
820 return 1
821
822 def isVecElem(self):
823 return 1
824
825 def makeDecl(self):
826 if self.is_dest and not self.is_src:
827 return '\n\t%s %s;' % (self.ctype, self.base_name)
828 else:
829 return ''
830
831 def makeConstructor(self, predRead, predWrite):
832 c_src = ''
833 c_dest = ''
834
835 numAccessNeeded = 1
836 regId = 'RegId(%s, %s * numVecElemPerVecReg + elemIdx, %s)' % \
837 (self.reg_class, self.reg_spec)
838
839 if self.is_src:
840 c_src = ('\n\t_srcRegIdx[_numSrcRegs++] = RegId(%s, %s, %s);' %
841 (self.reg_class, self.reg_spec, self.elem_spec))
842
843 if self.is_dest:
844 c_dest = ('\n\t_destRegIdx[_numDestRegs++] = RegId(%s, %s, %s);' %
845 (self.reg_class, self.reg_spec, self.elem_spec))
846 c_dest += '\n\t_numVecElemDestRegs++;'
847 return c_src + c_dest
848
849 def makeRead(self, predRead):
850 c_read = ('\n/* Elem is kept inside the operand description */' +
851 '\n\tVecElem %s = xc->readVecElemOperand(this, %d);' %
852 (self.base_name, self.src_reg_idx))
853 return c_read
854
855 def makeWrite(self, predWrite):
856 c_write = ('\n/* Elem is kept inside the operand description */' +
857 '\n\txc->setVecElemOperand(this, %d, %s);' %
858 (self.dest_reg_idx, self.base_name))
859 return c_write
860
661class CCRegOperand(Operand):
662 reg_class = 'CCRegClass'
663
664 def isReg(self):
665 return 1
666
667 def isCCReg(self):
668 return 1

--- 183 unchanged lines hidden (view full) ---

852 while 1:
853 match = parser.operandsRE.search(code, next_pos)
854 if not match:
855 # no more matches: we're done
856 break
857 op = match.groups()
858 # regexp groups are operand full name, base, and extension
859 (op_full, op_base, op_ext) = op
861class CCRegOperand(Operand):
862 reg_class = 'CCRegClass'
863
864 def isReg(self):
865 return 1
866
867 def isCCReg(self):
868 return 1

--- 183 unchanged lines hidden (view full) ---

1052 while 1:
1053 match = parser.operandsRE.search(code, next_pos)
1054 if not match:
1055 # no more matches: we're done
1056 break
1057 op = match.groups()
1058 # regexp groups are operand full name, base, and extension
1059 (op_full, op_base, op_ext) = op
1060 # If is a elem operand, define or update the corresponding
1061 # vector operand
1062 isElem = False
1063 if op_base in parser.elemToVector:
1064 isElem = True
1065 elem_op = (op_base, op_ext)
1066 op_base = parser.elemToVector[op_base]
1067 op_ext = '' # use the default one
860 # if the token following the operand is an assignment, this is
861 # a destination (LHS), else it's a source (RHS)
862 is_dest = (assignRE.match(code, match.end()) != None)
863 is_src = not is_dest
1068 # if the token following the operand is an assignment, this is
1069 # a destination (LHS), else it's a source (RHS)
1070 is_dest = (assignRE.match(code, match.end()) != None)
1071 is_src = not is_dest
1072
864 # see if we've already seen this one
865 op_desc = self.find_base(op_base)
866 if op_desc:
1073 # see if we've already seen this one
1074 op_desc = self.find_base(op_base)
1075 if op_desc:
867 if op_desc.ext != op_ext:
868 error ('Inconsistent extensions for operand %s' % \
869 op_base)
1076 if op_ext and op_ext != '' and op_desc.ext != op_ext:
1077 error ('Inconsistent extensions for operand %s: %s - %s' \
1078 % (op_base, op_desc.ext, op_ext))
870 op_desc.is_src = op_desc.is_src or is_src
871 op_desc.is_dest = op_desc.is_dest or is_dest
1079 op_desc.is_src = op_desc.is_src or is_src
1080 op_desc.is_dest = op_desc.is_dest or is_dest
1081 if isElem:
1082 (elem_base, elem_ext) = elem_op
1083 found = False
1084 for ae in op_desc.active_elems:
1085 (ae_base, ae_ext) = ae
1086 if ae_base == elem_base:
1087 if ae_ext != elem_ext:
1088 error('Inconsistent extensions for elem'
1089 ' operand %s' % elem_base)
1090 else:
1091 found = True
1092 if not found:
1093 op_desc.active_elems.append(elem_op)
872 else:
873 # new operand: create new descriptor
874 op_desc = parser.operandNameMap[op_base](parser,
875 op_full, op_ext, is_src, is_dest)
1094 else:
1095 # new operand: create new descriptor
1096 op_desc = parser.operandNameMap[op_base](parser,
1097 op_full, op_ext, is_src, is_dest)
1098 # if operand is a vector elem, add the corresponding vector
1099 # operand if not already done
1100 if isElem:
1101 op_desc.elemExt = elem_op[1]
1102 op_desc.active_elems = [elem_op]
876 self.append(op_desc)
877 # start next search after end of current match
878 next_pos = match.end()
879 self.sort()
880 # enumerate source & dest register operands... used in building
881 # constructor later
882 self.numSrcRegs = 0
883 self.numDestRegs = 0
884 self.numFPDestRegs = 0
885 self.numIntDestRegs = 0
1103 self.append(op_desc)
1104 # start next search after end of current match
1105 next_pos = match.end()
1106 self.sort()
1107 # enumerate source & dest register operands... used in building
1108 # constructor later
1109 self.numSrcRegs = 0
1110 self.numDestRegs = 0
1111 self.numFPDestRegs = 0
1112 self.numIntDestRegs = 0
1113 self.numVecDestRegs = 0
886 self.numCCDestRegs = 0
887 self.numMiscDestRegs = 0
888 self.memOperand = None
889
890 # Flags to keep track if one or more operands are to be read/written
891 # conditionally.
892 self.predRead = False
893 self.predWrite = False

--- 5 unchanged lines hidden (view full) ---

899 self.numSrcRegs += 1
900 if op_desc.is_dest:
901 op_desc.dest_reg_idx = self.numDestRegs
902 self.numDestRegs += 1
903 if op_desc.isFloatReg():
904 self.numFPDestRegs += 1
905 elif op_desc.isIntReg():
906 self.numIntDestRegs += 1
1114 self.numCCDestRegs = 0
1115 self.numMiscDestRegs = 0
1116 self.memOperand = None
1117
1118 # Flags to keep track if one or more operands are to be read/written
1119 # conditionally.
1120 self.predRead = False
1121 self.predWrite = False

--- 5 unchanged lines hidden (view full) ---

1127 self.numSrcRegs += 1
1128 if op_desc.is_dest:
1129 op_desc.dest_reg_idx = self.numDestRegs
1130 self.numDestRegs += 1
1131 if op_desc.isFloatReg():
1132 self.numFPDestRegs += 1
1133 elif op_desc.isIntReg():
1134 self.numIntDestRegs += 1
1135 elif op_desc.isVecReg():
1136 self.numVecDestRegs += 1
907 elif op_desc.isCCReg():
908 self.numCCDestRegs += 1
909 elif op_desc.isControlReg():
910 self.numMiscDestRegs += 1
911 elif op_desc.isMem():
912 if self.memOperand:
913 error("Code block has more than one memory operand.")
914 self.memOperand = op_desc

--- 74 unchanged lines hidden (view full) ---

989 while 1:
990 match = parser.operandsRE.search(code, next_pos)
991 if not match:
992 # no more matches: we're done
993 break
994 op = match.groups()
995 # regexp groups are operand full name, base, and extension
996 (op_full, op_base, op_ext) = op
1137 elif op_desc.isCCReg():
1138 self.numCCDestRegs += 1
1139 elif op_desc.isControlReg():
1140 self.numMiscDestRegs += 1
1141 elif op_desc.isMem():
1142 if self.memOperand:
1143 error("Code block has more than one memory operand.")
1144 self.memOperand = op_desc

--- 74 unchanged lines hidden (view full) ---

1219 while 1:
1220 match = parser.operandsRE.search(code, next_pos)
1221 if not match:
1222 # no more matches: we're done
1223 break
1224 op = match.groups()
1225 # regexp groups are operand full name, base, and extension
1226 (op_full, op_base, op_ext) = op
1227 # If is a elem operand, define or update the corresponding
1228 # vector operand
1229 if op_base in parser.elemToVector:
1230 elem_op = op_base
1231 op_base = parser.elemToVector[elem_op]
997 # find this op in the master list
998 op_desc = master_list.find_base(op_base)
999 if not op_desc:
1000 error('Found operand %s which is not in the master list!'
1001 % op_base)
1002 else:
1003 # See if we've already found this operand
1004 op_desc = self.find_base(op_base)

--- 95 unchanged lines hidden (view full) ---

1100 self.operands = OperandList(parser, compositeCode)
1101
1102 # The header of the constructor declares the variables to be used
1103 # in the body of the constructor.
1104 header = ''
1105 header += '\n\t_numSrcRegs = 0;'
1106 header += '\n\t_numDestRegs = 0;'
1107 header += '\n\t_numFPDestRegs = 0;'
1232 # find this op in the master list
1233 op_desc = master_list.find_base(op_base)
1234 if not op_desc:
1235 error('Found operand %s which is not in the master list!'
1236 % op_base)
1237 else:
1238 # See if we've already found this operand
1239 op_desc = self.find_base(op_base)

--- 95 unchanged lines hidden (view full) ---

1335 self.operands = OperandList(parser, compositeCode)
1336
1337 # The header of the constructor declares the variables to be used
1338 # in the body of the constructor.
1339 header = ''
1340 header += '\n\t_numSrcRegs = 0;'
1341 header += '\n\t_numDestRegs = 0;'
1342 header += '\n\t_numFPDestRegs = 0;'
1343 header += '\n\t_numVecDestRegs = 0;'
1344 header += '\n\t_numVecElemDestRegs = 0;'
1108 header += '\n\t_numIntDestRegs = 0;'
1109 header += '\n\t_numCCDestRegs = 0;'
1110
1111 self.constructor = header + \
1112 self.operands.concatAttrStrings('constructor')
1113
1114 self.flags = self.operands.concatAttrLists('flags')
1115

--- 28 unchanged lines hidden (view full) ---

1144 # usually set in FP instructions because of the base
1145 # register
1146 if 'IsFloating' in self.flags:
1147 self.op_class = 'FloatMemReadOp'
1148 else:
1149 self.op_class = 'MemReadOp'
1150 elif 'IsFloating' in self.flags:
1151 self.op_class = 'FloatAddOp'
1345 header += '\n\t_numIntDestRegs = 0;'
1346 header += '\n\t_numCCDestRegs = 0;'
1347
1348 self.constructor = header + \
1349 self.operands.concatAttrStrings('constructor')
1350
1351 self.flags = self.operands.concatAttrLists('flags')
1352

--- 28 unchanged lines hidden (view full) ---

1381 # usually set in FP instructions because of the base
1382 # register
1383 if 'IsFloating' in self.flags:
1384 self.op_class = 'FloatMemReadOp'
1385 else:
1386 self.op_class = 'MemReadOp'
1387 elif 'IsFloating' in self.flags:
1388 self.op_class = 'FloatAddOp'
1389 elif 'IsVector' in self.flags:
1390 self.op_class = 'SimdAddOp'
1152 else:
1153 self.op_class = 'IntAluOp'
1154
1155 # add flag initialization to contructor here to include
1156 # any flags added via opt_args
1157 self.constructor += makeFlagConstructor(self.flags)
1158
1159 # if 'IsFloating' is set, add call to the FP enable check
1160 # function (which should be provided by isa_desc via a declare)
1391 else:
1392 self.op_class = 'IntAluOp'
1393
1394 # add flag initialization to contructor here to include
1395 # any flags added via opt_args
1396 self.constructor += makeFlagConstructor(self.flags)
1397
1398 # if 'IsFloating' is set, add call to the FP enable check
1399 # function (which should be provided by isa_desc via a declare)
1400 # if 'IsVector' is set, add call to the Vector enable check
1401 # function (which should be provided by isa_desc via a declare)
1161 if 'IsFloating' in self.flags:
1162 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
1402 if 'IsFloating' in self.flags:
1403 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
1404 elif 'IsVector' in self.flags:
1405 self.fp_enable_check = 'fault = checkVecEnableFault(xc);'
1163 else:
1164 self.fp_enable_check = ''
1165
1166##############
1167# Stack: a simple stack object. Used for both formats (formatStack)
1168# and default cases (defaultStack). Simply wraps a list to give more
1169# stack-like syntax and enable initialization with an argument list
1170# (as opposed to an argument that's a list).

--- 1124 unchanged lines hidden (view full) ---

2295 # Accumulate attributes of new operand class in tmp_dict
2296 tmp_dict = {}
2297 attrList = ['reg_spec', 'flags', 'sort_pri',
2298 'read_code', 'write_code',
2299 'read_predicate', 'write_predicate']
2300 if dflt_ext:
2301 dflt_ctype = self.operandTypeMap[dflt_ext]
2302 attrList.extend(['dflt_ctype', 'dflt_ext'])
1406 else:
1407 self.fp_enable_check = ''
1408
1409##############
1410# Stack: a simple stack object. Used for both formats (formatStack)
1411# and default cases (defaultStack). Simply wraps a list to give more
1412# stack-like syntax and enable initialization with an argument list
1413# (as opposed to an argument that's a list).

--- 1124 unchanged lines hidden (view full) ---

2538 # Accumulate attributes of new operand class in tmp_dict
2539 tmp_dict = {}
2540 attrList = ['reg_spec', 'flags', 'sort_pri',
2541 'read_code', 'write_code',
2542 'read_predicate', 'write_predicate']
2543 if dflt_ext:
2544 dflt_ctype = self.operandTypeMap[dflt_ext]
2545 attrList.extend(['dflt_ctype', 'dflt_ext'])
2546 # reg_spec is either just a string or a dictionary
2547 # (for elems of vector)
2548 if isinstance(reg_spec, tuple):
2549 (reg_spec, elem_spec) = reg_spec
2550 if isinstance(elem_spec, str):
2551 attrList.append('elem_spec')
2552 else:
2553 assert(isinstance(elem_spec, dict))
2554 elems = elem_spec
2555 attrList.append('elems')
2303 for attr in attrList:
2304 tmp_dict[attr] = eval(attr)
2305 tmp_dict['base_name'] = op_name
2306
2307 # New class name will be e.g. "IntReg_Ra"
2308 cls_name = base_cls_name + '_' + op_name
2309 # Evaluate string arg to get class object. Note that the
2310 # actual base class for "IntReg" is "IntRegOperand", i.e. we

--- 7 unchanged lines hidden (view full) ---

2318 # <cls_name> as a subclass of <base_cls> with the attributes
2319 # in tmp_dict, just as if we evaluated a class declaration.
2320 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict)
2321
2322 self.operandNameMap = operand_name
2323
2324 # Define operand variables.
2325 operands = user_dict.keys()
2556 for attr in attrList:
2557 tmp_dict[attr] = eval(attr)
2558 tmp_dict['base_name'] = op_name
2559
2560 # New class name will be e.g. "IntReg_Ra"
2561 cls_name = base_cls_name + '_' + op_name
2562 # Evaluate string arg to get class object. Note that the
2563 # actual base class for "IntReg" is "IntRegOperand", i.e. we

--- 7 unchanged lines hidden (view full) ---

2571 # <cls_name> as a subclass of <base_cls> with the attributes
2572 # in tmp_dict, just as if we evaluated a class declaration.
2573 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict)
2574
2575 self.operandNameMap = operand_name
2576
2577 # Define operand variables.
2578 operands = user_dict.keys()
2579 # Add the elems defined in the vector operands and
2580 # build a map elem -> vector (used in OperandList)
2581 elem_to_vec = {}
2582 for op in user_dict.keys():
2583 if hasattr(self.operandNameMap[op], 'elems'):
2584 for elem in self.operandNameMap[op].elems.keys():
2585 operands.append(elem)
2586 elem_to_vec[elem] = op
2587 self.elemToVector = elem_to_vec
2326 extensions = self.operandTypeMap.keys()
2327
2328 operandsREString = r'''
2329 (?<!\w) # neg. lookbehind assertion: prevent partial matches
2330 ((%s)(?:_(%s))?) # match: operand with optional '_' then suffix
2331 (?!\w) # neg. lookahead assertion: prevent partial matches
2332 ''' % (string.join(operands, '|'), string.join(extensions, '|'))
2333

--- 121 unchanged lines hidden ---
2588 extensions = self.operandTypeMap.keys()
2589
2590 operandsREString = r'''
2591 (?<!\w) # neg. lookbehind assertion: prevent partial matches
2592 ((%s)(?:_(%s))?) # match: operand with optional '_' then suffix
2593 (?!\w) # neg. lookahead assertion: prevent partial matches
2594 ''' % (string.join(operands, '|'), string.join(extensions, '|'))
2595

--- 121 unchanged lines hidden ---