From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dave Brolley To: cgen@sources.redhat.com, binutils@sources.redhat.com Subject: Re: [patch][rfa] Ordering insns in hash chain for cgen disassemblers -- committed. Date: Wed, 14 Nov 2001 12:09:00 -0000 Message-ID: <3BF2CFA4.2070707@redhat.com> References: <3BF178A6.F12C7023@redhat.com> X-SW-Source: 2001-q4/msg00029.html Message-ID: <20011114120900.DZlwG96JrWm_27eVbb1Dna2_tscF6iZ8tQvuJ2pkFn8@z> Approved by fche and committed. Let me know if there are any problems. Dave Dave Brolley wrote: >Hi, > >Currently insns are added to the chains of the hash table in the >disassembler in the order in which they appear in the .cpu file. Thus, >resolution of insns which are a special case of another must be >managed by carefully defining then in the correct order. The insns are >also parsed in the order in which they appear and this is important in >cases where an operand in the assembler input might be successfully >parsed as more than on ecgen operand (e.g. register names are >successfully parsed as immediates). There is an impass, however, when >the order in which insns need to be parsed is not the same as the >order in which decoding must be attempted. > >I have run into such a case where an operand of an insn may be a >register name or an immediate. One particular register is forbidden, >however, and when the bits representing that register appear in the >field of the insn, it signifies that the operand is really an >immediate value which follows the insn. Thus the operand must be >parsed as a register name first, but decoding must attempt it as an >immediate first. > >The problem may be solved by automating the order in which the insns >are placed into the hash chains in the disassembler. By ordering insns >iby the number of decoding bits in decreasing order, we can assure >that an insn which is a special case of another wil be attempted >first, regardless of the order in which they appear in the .cpu file. >This is the same ordering which would have been required manually up >until now, so no existing ports should be affected. > >I have tested the attached patch on m32r (sid), fr30 and two internal >ports. Requesting approval to commit. > >Dave > > >------------------------------------------------------------------------ > >Index: opcodes/cgen-dis.c >=================================================================== >RCS file: /cvs/src/src/opcodes/cgen-dis.c,v >retrieving revision 1.5 >diff -c -p -r1.5 cgen-dis.c >*** opcodes/cgen-dis.c 2001/09/19 17:40:28 1.5 >--- opcodes/cgen-dis.c 2001/11/12 20:10:55 >*************** >*** 30,36 **** > static CGEN_INSN_LIST * hash_insn_array PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, int, int, CGEN_INSN_LIST **, CGEN_INSN_LIST *)); > static CGEN_INSN_LIST * hash_insn_list PARAMS ((CGEN_CPU_DESC, const CGEN_INSN_LIST *, CGEN_INSN_LIST **, CGEN_INSN_LIST *)); > static void build_dis_hash_table PARAMS ((CGEN_CPU_DESC)); >! > /* Subroutine of build_dis_hash_table to add INSNS to the hash table. > > COUNT is the number of elements in INSNS. >--- 30,87 ---- > static CGEN_INSN_LIST * hash_insn_array PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, int, int, CGEN_INSN_LIST **, CGEN_INSN_LIST *)); > static CGEN_INSN_LIST * hash_insn_list PARAMS ((CGEN_CPU_DESC, const CGEN_INSN_LIST *, CGEN_INSN_LIST **, CGEN_INSN_LIST *)); > static void build_dis_hash_table PARAMS ((CGEN_CPU_DESC)); >! >! /* Return the number of decodable bits in this insn. */ >! static int >! count_decodable_bits (insn) >! const CGEN_INSN *insn; >! { >! unsigned mask = CGEN_INSN_BASE_MASK (insn); >! int bits = 0; >! int m; >! for (m = 1; m != 0; m <<= 1) >! { >! if (mask & m) >! ++bits; >! } >! return bits; >! } >! >! /* Add an instruction to the hash chain. */ >! static void >! add_insn_to_hash_chain (hentbuf, insn, htable, hash) >! CGEN_INSN_LIST *hentbuf; >! const CGEN_INSN *insn; >! CGEN_INSN_LIST **htable; >! unsigned int hash; >! { >! CGEN_INSN_LIST *current_buf; >! CGEN_INSN_LIST *previous_buf; >! int insn_decodable_bits; >! >! /* Add insns sorted by the number of decodable bits, in decreasing order. >! This ensures that any insn which is a special case of another will be >! checked first. */ >! insn_decodable_bits = count_decodable_bits (insn); >! previous_buf = NULL; >! for (current_buf = htable[hash]; current_buf != NULL; >! current_buf = current_buf->next) >! { >! int current_decodable_bits = count_decodable_bits (current_buf->insn); >! if (insn_decodable_bits >= current_decodable_bits) >! break; >! previous_buf = current_buf; >! } >! >! /* Now insert the new insn. */ >! hentbuf->insn = insn; >! hentbuf->next = current_buf; >! if (previous_buf == NULL) >! htable[hash] = hentbuf; >! else >! previous_buf->next = hentbuf; >! } >! > /* Subroutine of build_dis_hash_table to add INSNS to the hash table. > > COUNT is the number of elements in INSNS. >*************** hash_insn_array (cd, insns, count, entsi >*** 74,82 **** > CGEN_INSN_MASK_BITSIZE (insn), > big_p); > hash = (* cd->dis_hash) (buf, value); >! hentbuf->next = htable[hash]; >! hentbuf->insn = insn; >! htable[hash] = hentbuf; > } > > return hentbuf; >--- 125,131 ---- > CGEN_INSN_MASK_BITSIZE (insn), > big_p); > hash = (* cd->dis_hash) (buf, value); >! add_insn_to_hash_chain (hentbuf, insn, htable, hash); > } > > return hentbuf; >*************** hash_insn_list (cd, insns, htable, hentb >*** 114,122 **** > CGEN_INSN_MASK_BITSIZE (ilist->insn), > big_p); > hash = (* cd->dis_hash) (buf, value); >! hentbuf->next = htable [hash]; >! hentbuf->insn = ilist->insn; >! htable [hash] = hentbuf; > } > > return hentbuf; >--- 163,169 ---- > CGEN_INSN_MASK_BITSIZE (ilist->insn), > big_p); > hash = (* cd->dis_hash) (buf, value); >! add_insn_to_hash_chain (hentbuf, ilist->insn, htable, hash); > } > > return hentbuf; > > dis-sort.patch.txt > > Content-Type: > > text/plain > Content-Encoding: > > 7bit > >