Added support for following SIMD instruction categories:
[dyninst.git] / instructionAPI / aarch64_manual_pareser.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3
4 """
5 Author: Steve Song
6 Email:  songxi.buaa@gmail.com
7 Date:   Sep 2015
8 """
9
10 import os, sys
11 from sets import Set
12 from array import *
13
14 #######################################
15 # a flag for vector and floating points
16 #######################################
17 #VEC_SIMD_SWITCH = False
18 VEC_SIMD_SWITCH = True
19
20 ####################################
21 # dir to store aarch64 ISA xml files
22 ####################################
23 ISA_dir = '/p/paradyn/arm/arm-download-1350222/AR100-DA-70000-r0p0-00rel10/AR100-DA-70000-r0p0-00rel10/ISA_xml/ISA_xml_v2_00rel11/'
24 files_dir = os.listdir(ISA_dir)
25
26 flagFieldsSet = set(['S', 'imm', 'option', 'opt', 'N', 'cond', 'sz', 'size', 'type'])
27 #forwardFieldsSet = set([ ])
28
29 insn_set = Set()
30 fp_insn_set = Set()
31
32 masksArray = list()
33 encodingsArray = list()
34
35 class Opcode:
36     def __init__(self, ISA_dir, vec_FP=True):
37         self.op_set = Set()
38         self.insn_set = Set()
39         self.fp_insn_set =Set()
40         self.vec_FP = vec_FP
41         self.base_insn_file = open(ISA_dir+'index.xml')
42         if self.vec_FP == True:
43             self.vec_FP_insn_file = open(ISA_dir+'fpsimdindex.xml')
44
45     # to get op IDs
46     def printP(self, op):
47         print '  aarch64_op_'+op+','
48
49     ##############################
50     # parse xml files
51     # get opcodes
52     ##############################
53     def getOpcodes(self):
54         for lines in self.base_insn_file:
55             if lines.startswith("    <iform"):
56                 self.op_set.add(lines.split('"')[1].split('.xml')[0].split('_')[0])
57                 self.insn_set.add(lines.split('"')[1].split('.xml')[0])
58
59         if self.vec_FP == True:
60             for lines in self.vec_FP_insn_file:
61                 if lines.startswith("    <iform"):
62                     self.op_set.add(lines.split('"')[1].split('.xml')[0].split('_')[0])
63                     self.insn_set.add(lines.split('"')[1].split('.xml')[0])
64                     self.fp_insn_set.add(lines.split('"')[1].split('.xml')[0])
65
66     def printOpcodes(self):
67         self.getOpcodes()
68         print('enum {')
69         self.printP('INVALID')
70         self.printP('extended')
71
72         for ele in sorted(self.insn_set):
73             self.printP(ele)
74
75         print('}')
76         print 'number of instructions: ', len(self.insn_set)
77
78     def get_insn_set(self):
79         return self.insn_set
80
81     def get_fp_insn_set(self):
82         return self.fp_insn_set
83
84 #################################
85 # to find all control field names
86 # discarded
87 #################################
88 '''
89 control_field_set = Set()
90 non_ctl_field_set = Set(['sf'] )
91
92 def getDecodeFieldNames():
93
94     decodeFile = open(ISA_dir + 'encodingindex.xml')
95
96     startReadDecodeField = False
97
98     for line in decodeFile:
99         if startReadDecodeField == True:
100             if line.find('\"bitfields\"') != -1:
101                 control_field_set.add(line.split('>')[1].split('<')[0])
102
103         if line.find('Decode fields') !=-1:
104             startReadDecodeField = True
105
106         if line.find('</thread>')!=-1 and startReadDecodeField == True:
107             startReadDecodeField = False
108
109         if line.find('funcgrouphearder') !=-1 and line.find('simd-dp')!=-1:
110             break
111
112     control_field_set.difference_update(non_ctl_field_set)
113     print sorted(control_field_set)
114     '''
115
116
117 def shifting(bitlist):
118     out = 0
119     for bit in bitlist:
120         out = (out<<1) | (bit=='1' )
121     return out
122
123 ##########################
124 # parse xml files and get
125 # opcodes and operands
126 ##########################
127
128 def getOperand_Insn(line):
129     '''
130     analyze one <box> line </box> to get operand
131     '''
132     for field in line.split(' '):
133         if field.find('name') != -1 and field.find('usename') == -1:
134             opname = field.split('\"')[1]
135             if opname.find('imm') !=-1:
136                 opname = 'imm'
137             return opname
138         # else continue do nothing
139
140 def isRnUpdated(line):
141     if line.find('post-idx') != -1 or line.find('pre-idx') !=-1:
142         return True;
143     return False;
144
145 def ifNeedToSetFlags(line):
146     if line.find('<iclass ') != -1 :
147         for field in line.split(' '):
148             if field.find('id=') !=-1:
149                 if field.split('\"')[1] == 's':
150                     return True
151
152     if line.find('<regdiagram') != -1:
153         if line.find('float/compare') != -1:
154             return True
155     return False
156
157
158 class OpTable:
159     global files_dir
160
161     def __init__(self):
162         self.masksArray = list()
163         self.encodingsArray = list()
164         self.insnArray = list()
165         self.operandsArray = list()
166         self.operandsSet = set()
167         self.insn_unallocated = (2**28+2**27)
168
169     def getTable(self):
170         return self.masksArray, self.encodingsArray, self.insnArray, self.operandsArray
171
172     def analyzeEncodeBit(self, encodeBit, maskBit, encodingArray, operands_pos_Insn, reserve_operand_pos, maskStartBit):
173         if encodeBit == '1' or encodeBit == '0':
174             maskBit[31-maskStartBit] = '1'
175             encodingArray[31-maskStartBit] = encodeBit
176
177         elif encodeBit == '(1)':
178             maskBit[31-maskStartBit] = '1'
179             encodingArray[31-maskStartBit] = '1'
180
181         elif encodeBit == '(0)':
182             maskBit[31-maskStartBit] = '1'
183             encodingArray[31-maskStartBit] = '0'
184
185         # if it is 'x', we set it as not a control field
186         # and append the reserved operand to the list
187         elif encodeBit == 'x':
188             maskBit[31-maskStartBit] = '0'
189             encodingArray[31-maskStartBit] = '0'
190
191             if len(operands_pos_Insn) == 0:
192                 operands_pos_Insn.append(reserve_operand_pos)
193             elif operands_pos_Insn[-1:][0] != reserve_operand_pos:
194                 operands_pos_Insn.append(reserve_operand_pos)
195             if reserve_operand_pos[0] not in self.operandsSet:
196                 self.operandsSet.add(reserve_operand_pos[0])
197
198         # if it is blank, same as 'x', do late operand appending
199         elif encodeBit == '' or encodeBit.startswith('!=') != -1:
200             operands_pos_Insn.append(reserve_operand_pos)
201             if reserve_operand_pos[0] not in self.operandsSet:
202                 self.operandsSet.add(reserve_operand_pos[0])
203
204         else:
205             #if not encodeBit.startswith('!='):
206             print '[WARN] something not has been analyzed:'+ encodeBit
207
208
209     # to get the encoding table
210     def printOpTable(self ):
211
212         self.masksArray.append(self.insn_unallocated)
213         self.encodingsArray.append(int(0))
214         self.insnArray.append('INVALID')
215         self.operandsArray.append('')
216
217         indexOfInsn = 1
218
219         print 0, '%22s'%'INVALID',  '%34s'%bin(self.insn_unallocated), '(', hex(self.insn_unallocated), ')'
220
221         for file in sorted(files_dir):
222
223             if file.endswith('.xml'):
224                 instruction = file.split('.xml')[0]
225
226                 if instruction in insn_set:
227                     #print file
228                     curFile = open(ISA_dir+file)
229
230                     startBox = False
231
232                     startDiagram = False
233                     maskBit = list('0'*32)
234                     encodingArray = list('0'*32)
235                     operands_pos_Insn = list()
236
237                     reserve_operand_pos = list()
238                     maskStartBit = 31
239                     isRnUp = False
240                     needToSetFlags = False
241
242                     # to analyze lines , do iterative passes#
243                     for line in curFile:
244
245                         if line.find('<iclass ') != -1 :
246                             needToSetFlags = ifNeedToSetFlags(line)
247
248                         # diagram starts #
249                         if line.find('<regdiagram')!=-1:
250                             isRnUp = isRnUpdated(line)
251                             if needToSetFlags == False:
252                                 needToSetFlags = ifNeedToSetFlags(line)
253                             startDiagram = True
254                             continue
255
256                         # end of diagram #
257                         if line.find('</regdiagram')!=-1:
258                             if needToSetFlags == True:
259                                 operands_pos_Insn.insert(0, ('setFlags',) )
260                             self.printInstnEntry(maskBit, encodingArray, indexOfInsn, instruction, operands_pos_Insn)
261
262                             startDiagram = False
263                             maskBit = list('0'*32)
264                             encodingArray = list('0'*32)
265                             operands_pos_Insn = list()
266
267                             indexOfInsn +=1
268                             continue
269
270                         # analyze each box #
271                         if startDiagram == True and line.find('<box') != -1:
272                             #name, start bit, length
273                             for x in line.split(' '):
274                                 if x.find('hibit') != -1:
275                                     maskStartBit = int(x.split('\"')[1])
276                                     break
277
278                             # reserve the operand and position information
279                             # it only will be appended if the encoding fields are not defined unique
280                             reserve_operand_pos = getOperandValues(line, instruction, isRnUp)
281                             startBox = True
282
283                         # end of box #
284                         if line.find('</box') != -1:
285                             startBox = False
286                             continue
287
288                         # read box content #
289                         if startBox == True:
290                             # start of <c>
291                             if line.find('<c') != -1:
292                                 encodeBit = line.split('>')[1].split('<')[0]
293                                 self.analyzeEncodeBit(encodeBit, maskBit, encodingArray, operands_pos_Insn, reserve_operand_pos, maskStartBit)
294                                 maskStartBit = maskStartBit - 1
295
296
297                     # end of each line #
298
299     ####################################
300     # generate instructions
301     ####################################
302     def printInstnEntry(self, maskBit, encodingArray, index, instruction, operands):
303
304         # print instruction and encoding mask per file
305         maskBitInt = int(''.join(maskBit), 2)
306         encodingBitInt = int( ''.join(encodingArray),2)
307
308         self.masksArray.append(maskBitInt)
309         self.encodingsArray.append(encodingBitInt)
310         self.insnArray.append(instruction)
311         self.operandsArray.append(operands)
312
313         print index, "%22s"%instruction, '\t', ''.join(maskBit),'(', hex(maskBitInt),')', '\t', ''.join(encodingArray), '(', hex(encodingBitInt), ')', operands
314
315
316     def isLDST(self, insn):
317         if insn.startswith('ld') or insn.startswith('st'):
318             return True
319         return False
320
321     def getRegWidth(self, insn):
322
323         insnMnemonic = insn.split('_')[0]
324         # ld/st register, do nothing
325         if insnMnemonic.endswith('b') and not insnMnemonic.endswith('sb'):
326             return 32
327         elif insnMnemonic.endswith('h') and not insnMnemonic.endswith('sh'):
328             return 32
329         elif insnMnemonic.endswith('sb'):
330             return 64
331         elif insnMnemonic.endswith('sh'):
332             return 64
333         elif insnMnemonic.endswith('sw'):
334             return 64
335         elif insnMnemonic.endswith('r'):
336             return 64
337         elif insnMnemonic.endswith('p'):
338             return 64
339         else :
340             return 128
341             #print '[WARN] not recognized instruction:', insn
342         return 64
343
344     def isSIMD(self, insn):
345         if insn.find('simd') != -1:
346             return True
347         return False
348
349
350     ####################################
351     # generate the c++ code
352     # which builds the instruction table
353     ####################################
354     def buildInsnTable(self):
355         assert len(self.masksArray) == len(self.encodingsArray) ==len(self.insnArray)
356         print len(self.insnArray)
357         print '*** instruction table ***'
358
359         for i in range(0, len(self.insnArray)):
360             instruction = self.insnArray[i]
361
362             if len(self.operandsArray[i]) == 0:
363                 operands = 'operandSpec()'
364             else:
365                 operands = 'list_of'
366
367                 # recognize FP and SIMD
368                 if instruction in fp_insn_set:
369                     if self.isSIMD(instruction) == False:
370                         self.operandsArray[i].insert(0, ('setFPMode',) )
371                     else:
372                         self.operandsArray[i].insert(0, ('setSIMDMode',) )
373
374                 if self.isLDST(instruction) == True:
375                     if self.getRegWidth(instruction) == 32 or self.getRegWidth(instruction) == 64:
376                         self.operandsArray[i].insert(0, ('setRegWidth',) )
377                     else:
378                         if self.getRegWidth(instruction) != 128:
379                             print '[WARN] unknown width'
380
381                 for index, operand in enumerate(self.operandsArray[i]):
382                     # this is solution to the compiler bug
383                     # if OPRimm<x, y> appears in the first place of the list
384                     if len(operand) != 1 and index == 0:
385                         operands += '( (operandFactory) fn('
386                     else:
387                         operands += '( fn('
388
389                     if len(operand) != 1:
390                         operands += 'OPR'+operand[0]+'<'+ str(operand[1][0])+' COMMA ' + str(operand[1][1])+'>'
391                     else:
392                         curOperandName = operand[0]
393                         if curOperandName.startswith('set'):
394                             operands += curOperandName
395                         else:
396                             operands += 'OPR'+ curOperandName
397
398                     operands += ') )'
399
400             #print '\tmain_insn_table.push_back(aarch64_insn_entry(aarch64_op_'+ self.insnArray[i]+', \t\"'+ self.insnArray[i].split('_')[0]+'\",\t'+ operands +' ));'
401             print '\tmain_insn_table.push_back(aarch64_insn_entry(aarch64_op_'+ self.insnArray[i]+', \t\"'+ self.insnArray[i].split('_')[0]+'\",\t'+ operands +', ' \
402                 + str(self.encodingsArray[i]) + ', ' + str(self.masksArray[i]) + ') );'
403
404 ##################
405 # a helper function
406 # clapse(1001, 1101) => (101 & 111) => 101 => 5
407 ##################
408 def clapseMask(encoding, curMask):
409     ret = 0
410     while curMask!=0:
411         if curMask & 0x80000000 != 0:
412             ret = (ret<<1)|((encoding & 0x80000000)>>31)
413         curMask = (curMask << 1)&0xffffffff
414         encoding = (encoding << 1)&0xffffffff
415     return ret
416
417 ####################################
418 # generate the c++ code
419 # which builds the decoding table
420 ####################################
421 def printDecodertable(entryToPlace, curMask=0, entryList=list(), index=-1 ):
422     entries = 'map_list_of'
423     if len(entryList) == 0:
424         entries = 'branchMap()'
425     else:
426         for ent in entryList:
427             entries += '('+str(ent[0])+','+str(ent[1])+')'
428
429     print '\tmain_decoder_table['+str(entryToPlace)+']=aarch64_mask_entry('+str(hex(curMask))+', '+entries+','+str(index)+');'
430
431 def printDecodertable_list(entryToPlace, curMask=0, entryList=list(), index=list() ):
432     entries = 'map_list_of'
433     if len(entryList) == 0:
434         entries = 'branchMap()'
435     else:
436         for ent in entryList:
437             entries += '('+str(ent[0])+','+str(ent[1])+')'
438
439     index_list = str()
440     for i in index:
441         index_list += '('+ str(i) +')'
442
443     print '\tmain_decoder_table['+str(entryToPlace)+']=aarch64_mask_entry('+str(hex(curMask))+', '+entries+', list_of'+ index_list+');'
444
445 def num1sInMask(x):
446     mask = masksArray[x]
447     num = 0
448     while mask != 0:
449         if mask &1 == 1:
450             num +=1
451         mask = mask>>1
452     return int(num)
453
454 def alias_comparator( x, y ):
455     return num1sInMask(x) - num1sInMask(y)
456
457 def alias_comparatorRev( x, y ):
458     return num1sInMask(y) - num1sInMask(x)
459
460 class DecodeTable:
461     global masksArray
462     global encodingsArray
463     global insnArray
464     global operandsArray
465
466     ##########################
467     # generate decoding tree #
468     ##########################
469     def __init__(self):
470         self.numOfLeafNodes=0
471         self.processedIndex = Set()
472         self.numNodes = 0
473         ####################################
474         # this is the init value that the instruction
475         # entry should start from. 0 is reserved for
476         # invalid insn.
477         ####################################
478         self.entryAvailable = 1
479         self.debug = False
480         self.aliasWeakSolution = True
481
482     # weak solution to aliases
483     def alias_weakSolution(self, inInsnIndex, entryToPlace):
484         inInsnIndex.sort( cmp=alias_comparator )
485         for i in inInsnIndex:
486             self.processedIndex.add(i)
487             #if self.debug == True:
488             print insnArray[i], '\t', bin( masksArray[i] ), '\t', bin(encodingsArray[i])
489
490         printDecodertable(entryToPlace, 0, list(), inInsnIndex[0]);
491
492     # strict solution to aliases
493     def alias_strictSolution(self, inInsnIndex, entryToPlace):
494         inInsnIndex.sort( cmp=alias_comparatorRev )
495
496         # for debuggging
497         for i in inInsnIndex:
498             self.processedIndex.add(i)
499             #if self.debug == True:
500             print insnArray[i], '\t', bin( masksArray[i] ), '\t', bin(encodingsArray[i])
501
502         printDecodertable_list(entryToPlace, 0, list(), inInsnIndex);
503
504
505
506     ###########################################
507     # arg-1 is self
508     # arg0 is the range of indexes in the instruction array
509     #   that you want to analyze
510     # arg1 is the bit mask that has been processed
511     # arg2 is the entry of the decoding table
512     #   where the current call should place for one decision node
513     ###########################################
514     def buildDecodeTable(self, inInsnIndex , processedMask, entryToPlace):
515
516         # guards, redundant
517         if entryToPlace > 2**32:
518             print '*** [WARN] should not reach here ***'
519             return
520
521         # terminated condition 1
522         if len(inInsnIndex) < 1:
523             print '*** [WARN] should not reach here ***'
524             return
525
526         # size of inInsnIndex is 1. This means we should generate a leaf node
527         if len(inInsnIndex) ==1:
528             if self.aliasWeakSolution == True:
529                 printDecodertable(entryToPlace, 0, list() , inInsnIndex[0]);
530             else:
531                 printDecodertable_list(entryToPlace, 0, list() , inInsnIndex[0:1]);
532             self.numNodes += 1
533             if self.debug == True:
534                 print insnArray[inInsnIndex[0]]
535             if inInsnIndex[0] in self.processedIndex:
536                 print '[WARN] index processed, repeated index is ', inInsnIndex[0]
537
538             self.processedIndex.add(inInsnIndex[0])
539             self.numOfLeafNodes +=1
540             return
541
542         validMaskBits = int(''.join('1'*32), 2)
543
544         # find the minimum common mask bit field
545         for i in inInsnIndex:
546             validMaskBits = validMaskBits & masksArray[i]
547
548         # eliminate the processed mask bit field
549         validMaskBits = validMaskBits&(~processedMask)
550         if self.debug == True:
551             print hex(validMaskBits), bin(validMaskBits)
552
553         #### ALIASING ####
554         # terminated condition 2
555         # if the mask we get is 0, this means we have a bunch of instructions
556         # sharing the same opcode. They are aliases actually.
557         # Group them together.
558         addMask = 0
559         if validMaskBits == 0:
560             # weak solution to aliases
561             self.alias_weakSolution( inInsnIndex, entryToPlace)
562             # strict solution to aliases
563             #self.alias_strictSolution(inInsnIndex, entryToPlace)
564
565             self.numOfLeafNodes += len(inInsnIndex)
566             self.numNodes += 1
567             return
568
569             '''
570             for i in inInsnIndex:
571                 #print '%3d'%i+'%22s'%insnArray[i]+'%34s'%bin(masksArray[i])+'%34s'%bin(encodingsArray[i])
572                 addMask |= masksArray[i] &(~processedMask)
573                 #addMask ^= encodingsArray[i] &(~processedMask)
574
575             # handle alias, merge them into one node
576             if addMask == 0:
577                 numOfLeafNodes += len(inInsnIndex)
578                 for i in inInsnIndex:
579                     processedIndex.add(i)
580                 printDecodertable(entryToPlace, 0, list(), inInsnIndex[0]);
581                 numNodes += 1
582                 return
583             # handle more mask bits
584             else:
585                 validMaskBits = addMask
586                 #print bin(addMask)
587                 '''
588
589         # till here we should have got the mask bits
590         MSBmask = 0x80000000
591         curMask = 0
592         numCurMaskBit = 0
593
594         #print hex(validMaskBits)
595
596         # get currrent valid mask
597         # check bit one by one from MSB
598         for bit in range(0, 32):
599             if (MSBmask & validMaskBits) == 0 :
600                 validMaskBits = (validMaskBits << 1)
601             else:
602                 curMask |= 1<<(31-bit)
603                 validMaskBits = (validMaskBits << 1)
604                 numCurMaskBit += 1
605
606         #print 'cur mask', hex(curMask)
607
608         # should not be 0
609         if curMask == 0:
610             print "[WARN] mask is 0"
611             if self.debug == True:
612                 print '%25s'%'processed mask'+'%35s'%bin(processedMask)
613             for i in inInsnIndex:
614                 print '%3d'%i+'%22s'%insnArray[i]+'%35s'%bin(masksArray[i])+'%35s'%bin(encodingsArray[i])
615             self.numOfLeafNodes+=len(inInsnIndex)
616             return
617
618
619         # update processed mask
620         processedMask = processedMask | curMask
621
622         indexList = [ ]
623         for i in range(0, 2**numCurMaskBit):
624             indexList.append([])
625
626         # generate the branches
627         # glue instructions to that branch
628         for index in inInsnIndex:
629             branchNo = clapseMask(encodingsArray[index] & curMask, curMask)
630             #print 'branchNo' ,branchNo
631             indexList[branchNo].append(index)
632
633         # get number of branches
634         # a trick to eliminate null branches
635         numBranch = 0
636         validIndexList = []
637         brNoinIndexList = 0
638         posToBrNo = list()
639         for i in indexList:
640             if len(i)!=0:
641                 numBranch+=1
642                 validIndexList.append(i)
643                 posToBrNo.append(brNoinIndexList)
644             brNoinIndexList += 1
645
646         # typedef mask_table vector<mask_entry>;
647         # assign entry number to that branch
648         entryList = []
649         for i in range(0, numBranch):
650             entryList.append( (posToBrNo[i], self.entryAvailable + i) )
651
652         # reserve room
653         self.entryAvailable += numBranch
654
655         if self.aliasWeakSolution == True:
656             printDecodertable(entryToPlace, curMask, entryList, -1);
657         else:
658             printDecodertable_list(entryToPlace, curMask, entryList, [-1]);
659         self.numNodes += 1
660
661         """
662         print '%34s'%bin(curMask)
663         for i in zeroIndexes:
664             print '%34s'%bin(encodingsArray[i])
665
666         for i in oneIndexes:
667             print '%34s'%bin(encodingsArray[i])
668         """
669         if self.debug == True:
670             print validIndexList
671         for i in range(0, numBranch):
672             self.buildDecodeTable( validIndexList[i], processedMask, entryList[i][1])
673
674 ###############################################################
675 # the following section is for parsing and generating operands.
676 ###############################################################
677
678 def getOperandValues(line, instruction, isRnUp):
679     multiOperandSet = flagFieldsSet
680
681     if line.find(' name') != -1:
682         width = 1
683         tokens = line.split(' ')
684         for token in tokens:
685             if token.find('name')!=-1 and token.find('usename')== -1:
686                 name = token.split('\"')[1]
687                 if name.find('imm') != -1:
688                     name = 'imm'
689             if token.find('hibit')!=-1:
690                 bit = int(token.split('\"')[1])
691             if token.find('width') != -1:
692                 width = int(token.split('\"')[1])
693     else:
694         #print '*** [WARN] Blank operand field ***'
695         return ('', [0, 0])
696
697     if name.find('Rt') != -1 or name.find('Rt2') != -1 or name.find('Rn') !=-1:
698         if instruction.startswith('ld'):
699             name += 'L'
700
701         if instruction.startswith('st'):
702             name += 'S'
703
704     if instruction.startswith('ld') or instruction.startswith('st'):
705         if name.startswith('Rn'):
706             if isRnUp == True:
707                 name += 'U'
708
709     endbit = bit - (width-1)
710     if name in multiOperandSet:
711         return (name, [bit, endbit])
712     else:
713         return (name,)
714
715
716 def printOperandFuncs(operandsSet):
717     print 'operand function declares'
718     for operand in operandsSet:
719         print 'void '+ 'OPR'+operand + '(){ }'
720
721
722 def main():
723
724     ######################################
725     # get opcodes of GP instructions
726     # and FP/VEC instructions respectively
727     ######################################
728     opcodes = Opcode(ISA_dir, True)
729     opcodes.printOpcodes()
730     global insn_set
731     global fp_insn_set
732     insn_set = opcodes.get_insn_set()
733     fp_insn_set = opcodes.get_fp_insn_set()
734
735     #################################################################
736     # get instructions, opcodes, lists of operands
737     # each set is stored in an array
738     # indexes in the arrays are used to find the instruction you want
739     #################################################################
740     opTable = OpTable()
741     opTable.printOpTable()
742
743     ###############################################
744     # instruction table
745     # generate C++ code to build instruction tables
746     ###############################################
747     opTable.buildInsnTable()
748
749     global masksArray
750     global encodingsArray
751     global insnArray
752     global operandsArray
753     masksArray, encodingsArray, insnArray, operandsArray = opTable.getTable()
754
755     #########################################
756     # generate C++ code of operands functions
757     #########################################
758     print '*** operands ***'
759     print sorted(opTable.operandsSet)
760     printOperandFuncs(opTable.operandsSet)
761
762     ###########################################
763     # Decoder table.
764     # Generate C++ code to build decoding table.
765     # Basically, the generated stuff is a decision tree, which is represented in a map.
766     #
767     # Each entry stands for a decision node in the decision tree with a few or zero
768     #   branches. One branch contains a {Key, Value} pair. Key is used to index. Value is
769     #   the next entry number in the map, like a pointer.
770     #
771     # Binaries are passed to the root node first, and compared with the decision mask in
772     #   that node. Instrution binary does bit operation AND over the mask. The result of it
773     #   will be compared with the Key of the branches. Once matched to the Key, the instruction
774     #   will be passed to next decision node pointed by the branch.
775     #   Recursively do this, until to the leaf node.
776     #
777     # Each leaf node contains the index of the instruction array in the last field,
778     #   which holds the instruction entry.
779     ###########################################
780     print '*** decoder table ***'
781     validInsnIndex = list( range(0, len(opTable.insnArray) ) )
782     decodeTable = DecodeTable()
783     decodeTable.buildDecodeTable(validInsnIndex, 0 , 0)
784
785     ###############################
786     # some statistics for debugging
787     ###############################
788     print 'num of vaild leaves', decodeTable.numOfLeafNodes
789     allIndex = Set(range(0, len(opTable.insnArray)) )
790     print 'processed indexex: ', decodeTable.processedIndex, len(decodeTable.processedIndex)
791     print 'missing indexes:', sorted(allIndex - decodeTable.processedIndex), len(allIndex-decodeTable.processedIndex)
792     print 'number of total nodes in the tree:', decodeTable.numNodes
793
794 if __name__ == '__main__':
795     main()
796
797
798
799