12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667 |
- /* The IGEN simulator generator for GDB, the GNU Debugger.
- Copyright 2002-2022 Free Software Foundation, Inc.
- Contributed by Andrew Cagney.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "misc.h"
- #include "lf.h"
- #include "table.h"
- #include "filter.h"
- #include "igen.h"
- #include "ld-insn.h"
- #include "ld-decode.h"
- #include "gen.h"
- static insn_uint
- sub_val (insn_uint val, int val_last_pos, int first_pos, int last_pos)
- {
- return ((val >> (val_last_pos - last_pos))
- & (((insn_uint) 1 << (last_pos - first_pos + 1)) - 1));
- }
- static void
- update_depth (lf *file, gen_entry *entry, int depth, void *data)
- {
- int *max_depth = (int *) data;
- if (*max_depth < depth)
- *max_depth = depth;
- }
- int
- gen_entry_depth (gen_entry *table)
- {
- int depth = 0;
- gen_entry_traverse_tree (NULL, table, 1, NULL, /*start */
- update_depth, NULL, /*end */
- &depth); /* data */
- return depth;
- }
- static void
- print_gen_entry_path (line_ref *line, gen_entry *table, error_func *print)
- {
- if (table->parent == NULL)
- {
- if (table->top->model != NULL)
- print (line, "%s", table->top->model->name);
- else
- print (line, "");
- }
- else
- {
- print_gen_entry_path (line, table->parent, print);
- print (NULL, ".%d", table->opcode_nr);
- }
- }
- static void
- print_gen_entry_insns (gen_entry *table,
- error_func *print,
- char *first_message, char *next_message)
- {
- insn_list *i;
- char *message;
- message = first_message;
- for (i = table->insns; i != NULL; i = i->next)
- {
- insn_entry *insn = i->insn;
- print_gen_entry_path (insn->line, table, print);
- print (NULL, ": %s.%s %s\n", insn->format_name, insn->name, message);
- if (next_message != NULL)
- message = next_message;
- }
- }
- /* same as strcmp */
- static int
- insn_field_cmp (insn_word_entry *l, insn_word_entry *r)
- {
- while (1)
- {
- int bit_nr;
- if (l == NULL && r == NULL)
- return 0; /* all previous fields the same */
- if (l == NULL)
- return -1; /* left shorter than right */
- if (r == NULL)
- return +1; /* left longer than right */
- for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
- {
- if (l->bit[bit_nr]->field->type != insn_field_string)
- continue;
- if (r->bit[bit_nr]->field->type != insn_field_string)
- continue;
- if (l->bit[bit_nr]->field->conditions == NULL)
- continue;
- if (r->bit[bit_nr]->field->conditions == NULL)
- continue;
- if (0)
- printf ("%s%s%s VS %s%s%s\n",
- l->bit[bit_nr]->field->val_string,
- l->bit[bit_nr]->field->conditions->test ==
- insn_field_cond_eq ? "=" : "!",
- l->bit[bit_nr]->field->conditions->string,
- r->bit[bit_nr]->field->val_string,
- r->bit[bit_nr]->field->conditions->test ==
- insn_field_cond_eq ? "=" : "!",
- r->bit[bit_nr]->field->conditions->string);
- if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq
- && r->bit[bit_nr]->field->conditions->test ==
- insn_field_cond_eq)
- {
- if (l->bit[bit_nr]->field->conditions->type ==
- insn_field_cond_field
- && r->bit[bit_nr]->field->conditions->type ==
- insn_field_cond_field)
- /* somewhat arbitrary */
- {
- int cmp = strcmp (l->bit[bit_nr]->field->conditions->string,
- r->bit[bit_nr]->field->conditions->
- string);
- if (cmp != 0)
- return cmp;
- else
- continue;
- }
- if (l->bit[bit_nr]->field->conditions->type ==
- insn_field_cond_field)
- return +1;
- if (r->bit[bit_nr]->field->conditions->type ==
- insn_field_cond_field)
- return -1;
- /* The case of both fields having constant values should have
- already have been handled because such fields are converted
- into normal constant fields, but we must not make this
- an assert, as we wouldn't gracefully handle an (invalid)
- duplicate insn description. */
- continue;
- }
- if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
- return +1; /* left = only */
- if (r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
- return -1; /* right = only */
- /* FIXME: Need to some what arbitrarily order conditional lists */
- continue;
- }
- l = l->next;
- r = r->next;
- }
- }
- /* same as strcmp */
- static int
- insn_word_cmp (insn_word_entry *l, insn_word_entry *r)
- {
- while (1)
- {
- int bit_nr;
- if (l == NULL && r == NULL)
- return 0; /* all previous fields the same */
- if (l == NULL)
- return -1; /* left shorter than right */
- if (r == NULL)
- return +1; /* left longer than right */
- for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
- {
- if (l->bit[bit_nr]->mask < r->bit[bit_nr]->mask)
- return -1;
- if (l->bit[bit_nr]->mask > r->bit[bit_nr]->mask)
- return 1;
- if (l->bit[bit_nr]->value < r->bit[bit_nr]->value)
- return -1;
- if (l->bit[bit_nr]->value > r->bit[bit_nr]->value)
- return 1;
- }
- l = l->next;
- r = r->next;
- }
- }
- /* same as strcmp */
- static int
- opcode_bit_cmp (opcode_bits *l, opcode_bits *r)
- {
- if (l == NULL && r == NULL)
- return 0; /* all previous bits the same */
- if (l == NULL)
- return -1; /* left shorter than right */
- if (r == NULL)
- return +1; /* left longer than right */
- /* most significant word */
- if (l->field->word_nr < r->field->word_nr)
- return +1; /* left has more significant word */
- if (l->field->word_nr > r->field->word_nr)
- return -1; /* right has more significant word */
- /* most significant bit? */
- if (l->first < r->first)
- return +1; /* left as more significant bit */
- if (l->first > r->first)
- return -1; /* right as more significant bit */
- /* nr bits? */
- if (l->last < r->last)
- return +1; /* left as less bits */
- if (l->last > r->last)
- return -1; /* right as less bits */
- /* value? */
- if (l->value < r->value)
- return -1;
- if (l->value > r->value)
- return 1;
- return 0;
- }
- /* same as strcmp */
- static int
- opcode_bits_cmp (opcode_bits *l, opcode_bits *r)
- {
- while (1)
- {
- int cmp;
- if (l == NULL && r == NULL)
- return 0; /* all previous bits the same */
- cmp = opcode_bit_cmp (l, r);
- if (cmp != 0)
- return cmp;
- l = l->next;
- r = r->next;
- }
- }
- /* same as strcmp */
- static opcode_bits *
- new_opcode_bits (opcode_bits *old_bits,
- int value,
- int first,
- int last, insn_field_entry *field, opcode_field *opcode)
- {
- opcode_bits *new_bits = ZALLOC (opcode_bits);
- new_bits->field = field;
- new_bits->value = value;
- new_bits->first = first;
- new_bits->last = last;
- new_bits->opcode = opcode;
- if (old_bits != NULL)
- {
- opcode_bits *new_list;
- opcode_bits **last = &new_list;
- new_list = new_opcode_bits (old_bits->next,
- old_bits->value,
- old_bits->first,
- old_bits->last,
- old_bits->field, old_bits->opcode);
- while (*last != NULL)
- {
- int cmp = opcode_bit_cmp (new_bits, *last);
- if (cmp < 0) /* new < new_list */
- {
- break;
- }
- if (cmp == 0)
- {
- ERROR ("Duplicated insn bits in list");
- }
- last = &(*last)->next;
- }
- new_bits->next = *last;
- *last = new_bits;
- return new_list;
- }
- else
- {
- return new_bits;
- }
- }
- /* Same as strcmp(). */
- static int
- name_cmp (const char *l, const char *r)
- {
- if (l == NULL && r == NULL)
- return 0;
- if (l != NULL && r == NULL)
- return -1;
- if (l == NULL && r != NULL)
- return +1;
- return strcmp (l, r);
- }
- typedef enum
- {
- merge_duplicate_insns,
- report_duplicate_insns,
- }
- duplicate_insn_actions;
- static insn_list *
- insn_list_insert (insn_list **cur_insn_ptr,
- int *nr_insns,
- insn_entry * insn,
- opcode_bits *expanded_bits,
- opcode_field *opcodes,
- int nr_prefetched_words,
- duplicate_insn_actions duplicate_action)
- {
- /* insert it according to the order of the fields & bits */
- for (; (*cur_insn_ptr) != NULL; cur_insn_ptr = &(*cur_insn_ptr)->next)
- {
- int cmp;
- /* key#1 sort according to the constant fields of each instruction */
- cmp = insn_word_cmp (insn->words, (*cur_insn_ptr)->insn->words);
- if (cmp < 0)
- break;
- else if (cmp > 0)
- continue;
- /* key#2 sort according to the expanded bits of each instruction */
- cmp = opcode_bits_cmp (expanded_bits, (*cur_insn_ptr)->expanded_bits);
- if (cmp < 0)
- break;
- else if (cmp > 0)
- continue;
- /* key#3 sort according to the non-constant fields of each instruction */
- cmp = insn_field_cmp (insn->words, (*cur_insn_ptr)->insn->words);
- if (cmp < 0)
- break;
- else if (cmp > 0)
- continue;
- if (duplicate_action == merge_duplicate_insns)
- {
- /* key#4: If we're going to merge duplicates, also sort
- according to the format_name. Two instructions with
- identical decode patterns, but different names, are
- considered different when merging. Duplicates are only
- important when creating a decode table (implied by
- report_duplicate_insns) as such a table only has the
- instruction's bit code as a way of differentiating
- between instructions. */
- int cmp = name_cmp (insn->format_name,
- (*cur_insn_ptr)->insn->format_name);
- if (cmp < 0)
- break;
- else if (cmp > 0)
- continue;
- }
- if (duplicate_action == merge_duplicate_insns)
- {
- /* key#5: If we're going to merge duplicates, also sort
- according to the name. See comment above for
- format_name. */
- int cmp = name_cmp (insn->name, (*cur_insn_ptr)->insn->name);
- if (cmp < 0)
- break;
- else if (cmp > 0)
- continue;
- }
- /* duplicate keys, report problem */
- switch (duplicate_action)
- {
- case report_duplicate_insns:
- /* It would appear that we have two instructions with the
- same constant field values across all words and bits.
- This error can also occure when insn_field_cmp() is
- failing to differentiate between two instructions that
- differ only in their conditional fields. */
- warning (insn->line,
- "Two instructions with identical constant fields\n");
- error ((*cur_insn_ptr)->insn->line,
- "Location of duplicate instruction\n");
- case merge_duplicate_insns:
- /* Add the opcode path to the instructions list */
- if (options.trace.insn_insertion)
- {
- notify ((*cur_insn_ptr)->insn->line,
- "%s.%s: insert merge %s.%s\n",
- (*cur_insn_ptr)->insn->format_name,
- (*cur_insn_ptr)->insn->name,
- insn->format_name,
- insn->name);
- }
- if (opcodes != NULL)
- {
- insn_opcodes **last = &(*cur_insn_ptr)->opcodes;
- while (*last != NULL)
- {
- last = &(*last)->next;
- }
- (*last) = ZALLOC (insn_opcodes);
- (*last)->opcode = opcodes;
- }
- /* Use the larger nr_prefetched_words */
- if ((*cur_insn_ptr)->nr_prefetched_words < nr_prefetched_words)
- (*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words;
- return (*cur_insn_ptr);
- }
- }
- /* create a new list entry and insert it */
- {
- insn_list *new_insn = ZALLOC (insn_list);
- if (options.trace.insn_insertion)
- {
- notify (insn->line,
- "%s.%s: insert new\n",
- insn->format_name,
- insn->name);
- }
- new_insn->insn = insn;
- new_insn->expanded_bits = expanded_bits;
- new_insn->next = (*cur_insn_ptr);
- new_insn->nr_prefetched_words = nr_prefetched_words;
- if (opcodes != NULL)
- {
- new_insn->opcodes = ZALLOC (insn_opcodes);
- new_insn->opcodes->opcode = opcodes;
- }
- (*cur_insn_ptr) = new_insn;
- }
- *nr_insns += 1;
- return (*cur_insn_ptr);
- }
- extern void
- gen_entry_traverse_tree (lf *file,
- gen_entry *table,
- int depth,
- gen_entry_handler * start,
- gen_entry_handler * leaf,
- gen_entry_handler * end, void *data)
- {
- gen_entry *entry;
- ASSERT (table !=NULL);
- ASSERT (table->opcode != NULL);
- ASSERT (table->nr_entries > 0);
- ASSERT (table->entries != 0);
- /* prefix */
- if (start != NULL && depth >= 0)
- {
- start (file, table, depth, data);
- }
- /* infix leaves */
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- if (entry->entries != NULL && depth != 0)
- {
- gen_entry_traverse_tree (file, entry, depth + 1,
- start, leaf, end, data);
- }
- else if (depth >= 0)
- {
- if (leaf != NULL)
- {
- leaf (file, entry, depth, data);
- }
- }
- }
- /* postfix */
- if (end != NULL && depth >= 0)
- {
- end (file, table, depth, data);
- }
- }
- /* create a list element containing a single gen_table entry */
- static gen_list *
- make_table (insn_table *isa, decode_table *rules, model_entry *model)
- {
- insn_entry *insn;
- gen_list *entry = ZALLOC (gen_list);
- entry->table = ZALLOC (gen_entry);
- entry->table->top = entry;
- entry->model = model;
- entry->isa = isa;
- for (insn = isa->insns; insn != NULL; insn = insn->next)
- {
- if (model == NULL
- || insn->processors == NULL
- || filter_is_member (insn->processors, model->name))
- {
- insn_list_insert (&entry->table->insns, &entry->table->nr_insns, insn, NULL, /* expanded_bits - none yet */
- NULL, /* opcodes - none yet */
- 0, /* nr_prefetched_words - none yet */
- report_duplicate_insns);
- }
- }
- entry->table->opcode_rule = rules;
- return entry;
- }
- gen_table *
- make_gen_tables (insn_table *isa, decode_table *rules)
- {
- gen_table *gen = ZALLOC (gen_table);
- gen->isa = isa;
- gen->rules = rules;
- if (options.gen.multi_sim)
- {
- gen_list **last = &gen->tables;
- model_entry *model;
- filter *processors;
- if (options.model_filter != NULL)
- processors = options.model_filter;
- else
- processors = isa->model->processors;
- for (model = isa->model->models; model != NULL; model = model->next)
- {
- if (filter_is_member (processors, model->name))
- {
- *last = make_table (isa, rules, model);
- last = &(*last)->next;
- }
- }
- }
- else
- {
- gen->tables = make_table (isa, rules, NULL);
- }
- return gen;
- }
- /****************************************************************/
- /* Is the bit, according to the decode rule, identical across all the
- instructions? */
- static int
- insns_bit_useless (insn_list *insns, decode_table *rule, int bit_nr)
- {
- insn_list *entry;
- int value = -1;
- int is_useless = 1; /* cleared if something actually found */
- /* check the instructions for some constant value in at least one of
- the bit fields */
- for (entry = insns; entry != NULL; entry = entry->next)
- {
- insn_word_entry *word = entry->insn->word[rule->word_nr];
- insn_bit_entry *bit = word->bit[bit_nr];
- switch (bit->field->type)
- {
- case insn_field_invalid:
- ASSERT (0);
- break;
- case insn_field_wild:
- case insn_field_reserved:
- /* neither useless or useful - ignore */
- break;
- case insn_field_int:
- switch (rule->search)
- {
- case decode_find_strings:
- /* an integer isn't a string */
- return 1;
- case decode_find_constants:
- case decode_find_mixed:
- /* an integer is useful if its value isn't the same
- between all instructions. The first time through the
- value is saved, the second time through (if the
- values differ) it is marked as useful. */
- if (value < 0)
- value = bit->value;
- else if (value != bit->value)
- is_useless = 0;
- break;
- }
- break;
- case insn_field_string:
- switch (rule->search)
- {
- case decode_find_strings:
- /* at least one string, keep checking */
- is_useless = 0;
- break;
- case decode_find_constants:
- case decode_find_mixed:
- if (filter_is_member (rule->constant_field_names,
- bit->field->val_string))
- /* a string field forced to constant? */
- is_useless = 0;
- else if (bit->field->conditions != NULL
- && bit->field->conditions->test == insn_field_cond_eq
- && bit->field->conditions->type == insn_field_cond_value)
- {
- int shift = bit->field->last - bit_nr;
- int bitvalue = (bit->field->conditions->value >> shift) & 1;
- if (value < 0)
- value = bitvalue;
- else if (value != bitvalue)
- is_useless = 0;
- }
- else if (rule->search == decode_find_constants)
- /* the string field isn't constant */
- return 1;
- break;
- }
- }
- }
- /* Given only one constant value has been found, check through all
- the instructions to see if at least one conditional makes it
- usefull */
- if (value >= 0 && is_useless)
- {
- for (entry = insns; entry != NULL; entry = entry->next)
- {
- insn_word_entry *word = entry->insn->word[rule->word_nr];
- insn_bit_entry *bit = word->bit[bit_nr];
- switch (bit->field->type)
- {
- case insn_field_invalid:
- ASSERT (0);
- break;
- case insn_field_wild:
- case insn_field_reserved:
- case insn_field_int:
- /* already processed */
- break;
- case insn_field_string:
- switch (rule->search)
- {
- case decode_find_strings:
- case decode_find_constants:
- /* already processed */
- break;
- case decode_find_mixed:
- /* string field with conditions. If this condition
- eliminates the value then the compare is useful */
- if (bit->field->conditions != NULL)
- {
- insn_field_cond *condition;
- int shift = bit->field->last - bit_nr;
- for (condition = bit->field->conditions;
- condition != NULL; condition = condition->next)
- {
- switch (condition->type)
- {
- case insn_field_cond_value:
- switch (condition->test)
- {
- case insn_field_cond_ne:
- if (((condition->value >> shift) & 1)
- == (unsigned) value)
- /* conditional field excludes the
- current value */
- is_useless = 0;
- break;
- case insn_field_cond_eq:
- if (((condition->value >> shift) & 1)
- != (unsigned) value)
- /* conditional field requires the
- current value */
- is_useless = 0;
- break;
- }
- break;
- case insn_field_cond_field:
- /* are these handled separatly? */
- break;
- }
- }
- }
- }
- }
- }
- }
- return is_useless;
- }
- /* go through a gen-table's list of instruction formats looking for a
- range of bits that meet the decode table RULEs requirements */
- static opcode_field *
- gen_entry_find_opcode_field (insn_list *insns,
- decode_table *rule, int string_only)
- {
- opcode_field curr_opcode;
- ASSERT (rule != NULL);
- memset (&curr_opcode, 0, sizeof (curr_opcode));
- curr_opcode.word_nr = rule->word_nr;
- curr_opcode.first = rule->first;
- curr_opcode.last = rule->last;
- /* Try to reduce the size of first..last in accordance with the
- decode rules */
- while (curr_opcode.first <= rule->last)
- {
- if (insns_bit_useless (insns, rule, curr_opcode.first))
- curr_opcode.first++;
- else
- break;
- }
- while (curr_opcode.last >= rule->first)
- {
- if (insns_bit_useless (insns, rule, curr_opcode.last))
- curr_opcode.last--;
- else
- break;
- }
- /* did the final opcode field end up being empty? */
- if (curr_opcode.first > curr_opcode.last)
- {
- return NULL;
- }
- ASSERT (curr_opcode.last >= rule->first);
- ASSERT (curr_opcode.first <= rule->last);
- ASSERT (curr_opcode.first <= curr_opcode.last);
- /* Ensure that, for the non string only case, the opcode includes
- the range forced_first .. forced_last */
- if (!string_only && curr_opcode.first > rule->force_first)
- {
- curr_opcode.first = rule->force_first;
- }
- if (!string_only && curr_opcode.last < rule->force_last)
- {
- curr_opcode.last = rule->force_last;
- }
- /* For the string only case, force just the lower bound (so that the
- shift can be eliminated) */
- if (string_only && rule->force_last == options.insn_bit_size - 1)
- {
- curr_opcode.last = options.insn_bit_size - 1;
- }
- /* handle any special cases */
- switch (rule->type)
- {
- case normal_decode_rule:
- /* let the above apply */
- curr_opcode.nr_opcodes =
- (1 << (curr_opcode.last - curr_opcode.first + 1));
- break;
- case boolean_rule:
- curr_opcode.is_boolean = 1;
- curr_opcode.boolean_constant = rule->constant;
- curr_opcode.nr_opcodes = 2;
- break;
- }
- {
- opcode_field *new_field = ZALLOC (opcode_field);
- memcpy (new_field, &curr_opcode, sizeof (opcode_field));
- return new_field;
- }
- }
- static void
- gen_entry_insert_insn (gen_entry *table,
- insn_entry * old_insn,
- int new_word_nr,
- int new_nr_prefetched_words,
- int new_opcode_nr, opcode_bits *new_bits)
- {
- gen_entry **entry = &table->entries;
- /* find the new table for this entry */
- while ((*entry) != NULL && (*entry)->opcode_nr < new_opcode_nr)
- {
- entry = &(*entry)->sibling;
- }
- if ((*entry) == NULL || (*entry)->opcode_nr != new_opcode_nr)
- {
- /* insert the missing entry */
- gen_entry *new_entry = ZALLOC (gen_entry);
- new_entry->sibling = (*entry);
- (*entry) = new_entry;
- table->nr_entries++;
- /* fill it in */
- new_entry->top = table->top;
- new_entry->opcode_nr = new_opcode_nr;
- new_entry->word_nr = new_word_nr;
- new_entry->expanded_bits = new_bits;
- new_entry->opcode_rule = table->opcode_rule->next;
- new_entry->parent = table;
- new_entry->nr_prefetched_words = new_nr_prefetched_words;
- }
- /* ASSERT new_bits == cur_entry bits */
- ASSERT ((*entry) != NULL && (*entry)->opcode_nr == new_opcode_nr);
- insn_list_insert (&(*entry)->insns, &(*entry)->nr_insns, old_insn, NULL, /* expanded_bits - only in final list */
- NULL, /* opcodes - only in final list */
- new_nr_prefetched_words, /* for this table */
- report_duplicate_insns);
- }
- static void
- gen_entry_expand_opcode (gen_entry *table,
- insn_entry * instruction,
- int bit_nr, int opcode_nr, opcode_bits *bits)
- {
- if (bit_nr > table->opcode->last)
- {
- /* Only include the hardwired bit information with an entry IF
- that entry (and hence its functions) are being duplicated. */
- if (options.trace.insn_expansion)
- {
- print_gen_entry_path (table->opcode_rule->line, table, notify);
- notify (NULL, ": insert %d - %s.%s%s\n",
- opcode_nr,
- instruction->format_name,
- instruction->name,
- (table->opcode_rule->
- with_duplicates ? " (duplicated)" : ""));
- }
- if (table->opcode_rule->with_duplicates)
- {
- gen_entry_insert_insn (table, instruction,
- table->opcode->word_nr,
- table->nr_prefetched_words, opcode_nr, bits);
- }
- else
- {
- gen_entry_insert_insn (table, instruction,
- table->opcode->word_nr,
- table->nr_prefetched_words, opcode_nr, NULL);
- }
- }
- else
- {
- insn_word_entry *word = instruction->word[table->opcode->word_nr];
- insn_field_entry *field = word->bit[bit_nr]->field;
- int last_pos = ((field->last < table->opcode->last)
- ? field->last : table->opcode->last);
- int first_pos = ((field->first > table->opcode->first)
- ? field->first : table->opcode->first);
- int width = last_pos - first_pos + 1;
- switch (field->type)
- {
- case insn_field_int:
- {
- int val;
- val = sub_val (field->val_int, field->last, first_pos, last_pos);
- gen_entry_expand_opcode (table, instruction,
- last_pos + 1,
- ((opcode_nr << width) | val), bits);
- break;
- }
- default:
- {
- if (field->type == insn_field_reserved)
- gen_entry_expand_opcode (table, instruction,
- last_pos + 1,
- ((opcode_nr << width)), bits);
- else
- {
- int val;
- int last_val = (table->opcode->is_boolean ? 2 : (1 << width));
- for (val = 0; val < last_val; val++)
- {
- /* check to see if the value has been precluded
- (by a conditional) in some way */
- int is_precluded;
- insn_field_cond *condition;
- for (condition = field->conditions, is_precluded = 0;
- condition != NULL && !is_precluded;
- condition = condition->next)
- {
- switch (condition->type)
- {
- case insn_field_cond_value:
- {
- int value =
- sub_val (condition->value, field->last,
- first_pos, last_pos);
- switch (condition->test)
- {
- case insn_field_cond_ne:
- if (value == val)
- is_precluded = 1;
- break;
- case insn_field_cond_eq:
- if (value != val)
- is_precluded = 1;
- break;
- }
- break;
- }
- case insn_field_cond_field:
- {
- int value = -1;
- opcode_bits *bit;
- gen_entry *t = NULL;
- /* Try to find a value for the
- conditional by looking back through
- the previously defined bits for one
- that covers the designated
- conditional field */
- for (bit = bits; bit != NULL; bit = bit->next)
- {
- if (bit->field->word_nr ==
- condition->field->word_nr
- && bit->first <= condition->field->first
- && bit->last >= condition->field->last)
- {
- /* the bit field fully specified
- the conditional field's value */
- value = sub_val (bit->value, bit->last,
- condition->field->
- first,
- condition->field->
- last);
- }
- }
- /* Try to find a value by looking
- through this and previous tables */
- if (bit == NULL)
- {
- for (t = table;
- t->parent != NULL; t = t->parent)
- {
- if (t->parent->opcode->word_nr ==
- condition->field->word_nr
- && t->parent->opcode->first <=
- condition->field->first
- && t->parent->opcode->last >=
- condition->field->last)
- {
- /* the table entry fully
- specified the condition
- field's value */
- /* extract the field's value
- from the opcode */
- value =
- sub_val (t->opcode_nr,
- t->parent->opcode->last,
- condition->field->first,
- condition->field->last);
- /* this is a requirement of
- a conditonal field
- refering to another field */
- ASSERT ((condition->field->first -
- condition->field->last) ==
- (first_pos - last_pos));
- printf
- ("value=%d, opcode_nr=%d, last=%d, [%d..%d]\n",
- value, t->opcode_nr,
- t->parent->opcode->last,
- condition->field->first,
- condition->field->last);
- }
- }
- }
- if (bit == NULL && t == NULL)
- error (instruction->line,
- "Conditional `%s' of field `%s' isn't expanded",
- condition->string, field->val_string);
- switch (condition->test)
- {
- case insn_field_cond_ne:
- if (value == val)
- is_precluded = 1;
- break;
- case insn_field_cond_eq:
- if (value != val)
- is_precluded = 1;
- break;
- }
- break;
- }
- }
- }
- if (!is_precluded)
- {
- /* Only add additional hardwired bit
- information if the entry is not going to
- later be combined */
- if (table->opcode_rule->with_combine)
- {
- gen_entry_expand_opcode (table, instruction,
- last_pos + 1,
- ((opcode_nr << width) |
- val), bits);
- }
- else
- {
- opcode_bits *new_bits =
- new_opcode_bits (bits, val,
- first_pos, last_pos,
- field,
- table->opcode);
- gen_entry_expand_opcode (table, instruction,
- last_pos + 1,
- ((opcode_nr << width) |
- val), new_bits);
- }
- }
- }
- }
- }
- }
- }
- }
- static void
- gen_entry_insert_expanding (gen_entry *table, insn_entry * instruction)
- {
- gen_entry_expand_opcode (table,
- instruction,
- table->opcode->first, 0, table->expanded_bits);
- }
- static int
- insns_match_format_names (insn_list *insns, filter *format_names)
- {
- if (format_names != NULL)
- {
- insn_list *i;
- for (i = insns; i != NULL; i = i->next)
- {
- if (i->insn->format_name != NULL
- && !filter_is_member (format_names, i->insn->format_name))
- return 0;
- }
- }
- return 1;
- }
- static int
- table_matches_path (gen_entry *table, decode_path_list *paths)
- {
- if (paths == NULL)
- return 1;
- while (paths != NULL)
- {
- gen_entry *entry = table;
- decode_path *path = paths->path;
- while (1)
- {
- if (entry == NULL && path == NULL)
- return 1;
- if (entry == NULL || path == NULL)
- break;
- if (entry->opcode_nr != path->opcode_nr)
- break;
- entry = entry->parent;
- path = path->parent;
- }
- paths = paths->next;
- }
- return 0;
- }
- static int
- insns_match_conditions (insn_list *insns, decode_cond *conditions)
- {
- if (conditions != NULL)
- {
- insn_list *i;
- for (i = insns; i != NULL; i = i->next)
- {
- decode_cond *cond;
- for (cond = conditions; cond != NULL; cond = cond->next)
- {
- int bit_nr;
- if (i->insn->nr_words <= cond->word_nr)
- return 0;
- for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
- {
- if (!cond->mask[bit_nr])
- continue;
- if (!i->insn->word[cond->word_nr]->bit[bit_nr]->mask)
- return 0;
- if ((i->insn->word[cond->word_nr]->bit[bit_nr]->value
- == cond->value[bit_nr]) == !cond->is_equal)
- return 0;
- }
- }
- }
- }
- return 1;
- }
- static int
- insns_match_nr_words (insn_list *insns, int nr_words)
- {
- insn_list *i;
- for (i = insns; i != NULL; i = i->next)
- {
- if (i->insn->nr_words < nr_words)
- return 0;
- }
- return 1;
- }
- static int
- insn_list_cmp (insn_list *l, insn_list *r)
- {
- while (1)
- {
- insn_entry *insn;
- if (l == NULL && r == NULL)
- return 0;
- if (l == NULL)
- return -1;
- if (r == NULL)
- return 1;
- if (l->insn != r->insn)
- return -1; /* somewhat arbitrary at present */
- /* skip this insn */
- insn = l->insn;
- while (l != NULL && l->insn == insn)
- l = l->next;
- while (r != NULL && r->insn == insn)
- r = r->next;
- }
- }
- static void
- gen_entry_expand_insns (gen_entry *table)
- {
- decode_table *opcode_rule;
- ASSERT (table->nr_insns >= 1);
- /* determine a valid opcode */
- for (opcode_rule = table->opcode_rule;
- opcode_rule != NULL; opcode_rule = opcode_rule->next)
- {
- char *discard_reason;
- if (table->top->model != NULL
- && opcode_rule->model_names != NULL
- && !filter_is_member (opcode_rule->model_names,
- table->top->model->name))
- {
- /* the rule isn't applicable to this processor */
- discard_reason = "wrong model";
- }
- else if (table->nr_insns == 1 && opcode_rule->conditions == NULL)
- {
- /* for safety, require a pre-codition when attempting to
- apply a rule to a single instruction */
- discard_reason = "need pre-condition when nr-insn == 1";
- }
- else if (table->nr_insns == 1 && !opcode_rule->with_duplicates)
- {
- /* Little point in expanding a single instruction when we're
- not duplicating the semantic functions that this table
- calls */
- discard_reason = "need duplication with nr-insns == 1";
- }
- else
- if (!insns_match_format_names
- (table->insns, opcode_rule->format_names))
- {
- discard_reason = "wrong format name";
- }
- else if (!insns_match_nr_words (table->insns, opcode_rule->word_nr + 1))
- {
- discard_reason = "wrong nr words";
- }
- else if (!table_matches_path (table, opcode_rule->paths))
- {
- discard_reason = "path failed";
- }
- else
- if (!insns_match_conditions (table->insns, opcode_rule->conditions))
- {
- discard_reason = "condition failed";
- }
- else
- {
- discard_reason = "no opcode field";
- table->opcode = gen_entry_find_opcode_field (table->insns,
- opcode_rule,
- table->nr_insns == 1 /*string-only */
- );
- if (table->opcode != NULL)
- {
- table->opcode_rule = opcode_rule;
- break;
- }
- }
- if (options.trace.rule_rejection)
- {
- print_gen_entry_path (opcode_rule->line, table, notify);
- notify (NULL, ": rule discarded - %s\n", discard_reason);
- }
- }
- /* did we find anything */
- if (opcode_rule == NULL)
- {
- /* the decode table failed, this set of instructions haven't
- been uniquely identified */
- if (table->nr_insns > 1)
- {
- print_gen_entry_insns (table, warning,
- "was not uniquely decoded",
- "decodes to the same entry");
- error (NULL, "");
- }
- return;
- }
- /* Determine the number of words that must have been prefetched for
- this table to function */
- if (table->parent == NULL)
- table->nr_prefetched_words = table->opcode_rule->word_nr + 1;
- else if (table->opcode_rule->word_nr + 1 >
- table->parent->nr_prefetched_words)
- table->nr_prefetched_words = table->opcode_rule->word_nr + 1;
- else
- table->nr_prefetched_words = table->parent->nr_prefetched_words;
- /* back link what we found to its parent */
- if (table->parent != NULL)
- {
- ASSERT (table->parent->opcode != NULL);
- table->opcode->parent = table->parent->opcode;
- }
- /* report the rule being used to expand the instructions */
- if (options.trace.rule_selection)
- {
- print_gen_entry_path (table->opcode_rule->line, table, notify);
- notify (NULL,
- ": decode - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d\n",
- table->opcode->word_nr,
- i2target (options.hi_bit_nr, table->opcode->first),
- i2target (options.hi_bit_nr, table->opcode->last),
- i2target (options.hi_bit_nr, table->opcode_rule->first),
- i2target (options.hi_bit_nr, table->opcode_rule->last),
- table->opcode->nr_opcodes, table->nr_entries);
- }
- /* expand the raw instructions according to the opcode */
- {
- insn_list *entry;
- for (entry = table->insns; entry != NULL; entry = entry->next)
- {
- if (options.trace.insn_expansion)
- {
- print_gen_entry_path (table->opcode_rule->line, table, notify);
- notify (NULL, ": expand - %s.%s\n",
- entry->insn->format_name, entry->insn->name);
- }
- gen_entry_insert_expanding (table, entry->insn);
- }
- }
- /* dump the results */
- if (options.trace.entries)
- {
- gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- insn_list *l;
- print_gen_entry_path (table->opcode_rule->line, entry, notify);
- notify (NULL, ": %d - entries %d -",
- entry->opcode_nr, entry->nr_insns);
- for (l = entry->insns; l != NULL; l = l->next)
- notify (NULL, " %s.%s", l->insn->format_name, l->insn->name);
- notify (NULL, "\n");
- }
- }
- /* perform a combine pass if needed */
- if (table->opcode_rule->with_combine)
- {
- gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- if (entry->combined_parent == NULL)
- {
- gen_entry **last = &entry->combined_next;
- gen_entry *alt;
- for (alt = entry->sibling; alt != NULL; alt = alt->sibling)
- {
- if (alt->combined_parent == NULL
- && insn_list_cmp (entry->insns, alt->insns) == 0)
- {
- alt->combined_parent = entry;
- *last = alt;
- last = &alt->combined_next;
- }
- }
- }
- }
- if (options.trace.combine)
- {
- int nr_unique = 0;
- gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- if (entry->combined_parent == NULL)
- {
- insn_list *l;
- gen_entry *duplicate;
- nr_unique++;
- print_gen_entry_path (table->opcode_rule->line, entry,
- notify);
- for (duplicate = entry->combined_next; duplicate != NULL;
- duplicate = duplicate->combined_next)
- {
- notify (NULL, "+%d", duplicate->opcode_nr);
- }
- notify (NULL, ": entries %d -", entry->nr_insns);
- for (l = entry->insns; l != NULL; l = l->next)
- {
- notify (NULL, " %s.%s",
- l->insn->format_name, l->insn->name);
- }
- notify (NULL, "\n");
- }
- }
- print_gen_entry_path (table->opcode_rule->line, table, notify);
- notify (NULL,
- ": combine - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d, unique %d\n",
- table->opcode->word_nr, i2target (options.hi_bit_nr,
- table->opcode->first),
- i2target (options.hi_bit_nr, table->opcode->last),
- i2target (options.hi_bit_nr, table->opcode_rule->first),
- i2target (options.hi_bit_nr, table->opcode_rule->last),
- table->opcode->nr_opcodes, table->nr_entries, nr_unique);
- }
- }
- /* Check that the rule did more than re-arange the order of the
- instructions */
- {
- gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- if (entry->combined_parent == NULL)
- {
- if (insn_list_cmp (table->insns, entry->insns) == 0)
- {
- print_gen_entry_path (table->opcode_rule->line, table,
- warning);
- warning (NULL,
- ": Applying rule just copied all instructions\n");
- print_gen_entry_insns (entry, warning, "Copied", NULL);
- error (NULL, "");
- }
- }
- }
- }
- /* if some form of expanded table, fill in the missing dots */
- switch (table->opcode_rule->gen)
- {
- case padded_switch_gen:
- case array_gen:
- case goto_switch_gen:
- if (!table->opcode->is_boolean)
- {
- gen_entry **entry = &table->entries;
- gen_entry *illegals = NULL;
- gen_entry **last_illegal = &illegals;
- int opcode_nr = 0;
- while (opcode_nr < table->opcode->nr_opcodes)
- {
- if ((*entry) == NULL || (*entry)->opcode_nr != opcode_nr)
- {
- /* missing - insert it under our feet at *entry */
- gen_entry_insert_insn (table, table->top->isa->illegal_insn, table->opcode->word_nr, 0, /* nr_prefetched_words == 0 for invalid */
- opcode_nr, NULL);
- ASSERT ((*entry) != NULL);
- ASSERT ((*entry)->opcode_nr == opcode_nr);
- (*last_illegal) = *entry;
- (*last_illegal)->combined_parent = illegals;
- last_illegal = &(*last_illegal)->combined_next;
- }
- entry = &(*entry)->sibling;
- opcode_nr++;
- }
- /* oops, will have pointed the first illegal insn back to
- its self. Fix this */
- if (illegals != NULL)
- illegals->combined_parent = NULL;
- }
- break;
- case switch_gen:
- case invalid_gen:
- /* ignore */
- break;
- }
- /* and do the same for the newly created sub entries but *only*
- expand entries that haven't been combined. */
- {
- gen_entry *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling)
- {
- if (entry->combined_parent == NULL)
- {
- gen_entry_expand_insns (entry);
- }
- }
- }
- }
- void
- gen_tables_expand_insns (gen_table *gen)
- {
- gen_list *entry;
- for (entry = gen->tables; entry != NULL; entry = entry->next)
- {
- gen_entry_expand_insns (entry->table);
- }
- }
- /* create a list of all the semantic functions that need to be
- generated. Eliminate any duplicates. Verify that the decode stage
- worked. */
- static void
- make_gen_semantics_list (lf *file, gen_entry *entry, int depth, void *data)
- {
- gen_table *gen = (gen_table *) data;
- insn_list *insn;
- /* Not interested in an entrie that have been combined into some
- other entry at the same level */
- if (entry->combined_parent != NULL)
- return;
- /* a leaf should contain exactly one instruction. If not the decode
- stage failed. */
- ASSERT (entry->nr_insns == 1);
- /* Enter this instruction into the list of semantic functions. */
- insn = insn_list_insert (&gen->semantics, &gen->nr_semantics,
- entry->insns->insn,
- entry->expanded_bits,
- entry->parent->opcode,
- entry->insns->nr_prefetched_words,
- merge_duplicate_insns);
- /* point the table entry at the real semantic function */
- ASSERT (insn != NULL);
- entry->insns->semantic = insn;
- }
- void
- gen_tables_expand_semantics (gen_table *gen)
- {
- gen_list *entry;
- for (entry = gen->tables; entry != NULL; entry = entry->next)
- {
- gen_entry_traverse_tree (NULL, entry->table, 1, /* depth */
- NULL, /* start-handler */
- make_gen_semantics_list, /* leaf-handler */
- NULL, /* end-handler */
- gen); /* data */
- }
- }
- #ifdef MAIN
- static void
- dump_opcode_field (lf *file,
- char *prefix,
- opcode_field *field, char *suffix, int levels)
- {
- lf_printf (file, "%s(opcode_field *) 0x%lx", prefix, (long) field);
- if (levels && field != NULL)
- {
- lf_indent (file, +1);
- lf_printf (file, "\n(first %d)", field->first);
- lf_printf (file, "\n(last %d)", field->last);
- lf_printf (file, "\n(nr_opcodes %d)", field->nr_opcodes);
- lf_printf (file, "\n(is_boolean %d)", field->is_boolean);
- lf_printf (file, "\n(boolean_constant %d)", field->boolean_constant);
- dump_opcode_field (file, "\n(parent ", field->parent, ")", levels - 1);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_opcode_bits (lf *file,
- char *prefix, opcode_bits *bits, char *suffix, int levels)
- {
- lf_printf (file, "%s(opcode_bits *) 0x%lx", prefix, (long) bits);
- if (levels && bits != NULL)
- {
- lf_indent (file, +1);
- lf_printf (file, "\n(value %d)", bits->value);
- dump_opcode_field (file, "\n(opcode ", bits->opcode, ")", 0);
- dump_insn_field (file, "\n(field ", bits->field, ")");
- dump_opcode_bits (file, "\n(next ", bits->next, ")", levels - 1);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_list (lf *file, char *prefix, insn_list *entry, char *suffix)
- {
- lf_printf (file, "%s(insn_list *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- lf_indent (file, +1);
- dump_insn_entry (file, "\n(insn ", entry->insn, ")");
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_word_entry_list_entries (lf *file,
- char *prefix,
- insn_list *entry, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- while (entry != NULL)
- {
- dump_insn_list (file, "\n(", entry, ")");
- entry = entry->next;
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_gen_entry (lf *file,
- char *prefix, gen_entry *table, char *suffix, int levels)
- {
- lf_printf (file, "%s(gen_entry *) 0x%lx", prefix, (long) table);
- if (levels && table !=NULL)
- {
- lf_indent (file, +1);
- lf_printf (file, "\n(opcode_nr %d)", table->opcode_nr);
- lf_printf (file, "\n(word_nr %d)", table->word_nr);
- dump_opcode_bits (file, "\n(expanded_bits ", table->expanded_bits, ")",
- -1);
- lf_printf (file, "\n(nr_insns %d)", table->nr_insns);
- dump_insn_word_entry_list_entries (file, "\n(insns ", table->insns,
- ")");
- dump_decode_rule (file, "\n(opcode_rule ", table->opcode_rule, ")");
- dump_opcode_field (file, "\n(opcode ", table->opcode, ")", 0);
- lf_printf (file, "\n(nr_entries %d)", table->nr_entries);
- dump_gen_entry (file, "\n(entries ", table->entries, ")",
- table->nr_entries);
- dump_gen_entry (file, "\n(sibling ", table->sibling, ")", levels - 1);
- dump_gen_entry (file, "\n(parent ", table->parent, ")", 0);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_gen_list (lf *file,
- char *prefix, gen_list *entry, char *suffix, int levels)
- {
- while (entry != NULL)
- {
- lf_printf (file, "%s(gen_list *) 0x%lx", prefix, (long) entry);
- dump_gen_entry (file, "\n(", entry->table, ")", levels);
- lf_printf (file, "\n(next (gen_list *) 0x%lx)", (long) entry->next);
- lf_printf (file, "%s", suffix);
- }
- }
- static void
- dump_gen_table (lf *file,
- char *prefix, gen_table *gen, char *suffix, int levels)
- {
- lf_printf (file, "%s(gen_table *) 0x%lx", prefix, (long) gen);
- lf_printf (file, "\n(isa (insn_table *) 0x%lx)", (long) gen->isa);
- lf_printf (file, "\n(rules (decode_table *) 0x%lx)", (long) gen->rules);
- dump_gen_list (file, "\n(", gen->tables, ")", levels);
- lf_printf (file, "%s", suffix);
- }
- igen_options options;
- int
- main (int argc, char **argv)
- {
- decode_table *decode_rules;
- insn_table *instructions;
- gen_table *gen;
- lf *l;
- if (argc != 7)
- error (NULL,
- "Usage: insn <filter-in> <hi-bit-nr> <insn-bit-size> <widths> <decode-table> <insn-table>\n");
- INIT_OPTIONS ();
- filter_parse (&options.flags_filter, argv[1]);
- options.hi_bit_nr = a2i (argv[2]);
- options.insn_bit_size = a2i (argv[3]);
- options.insn_specifying_widths = a2i (argv[4]);
- ASSERT (options.hi_bit_nr < options.insn_bit_size);
- instructions = load_insn_table (argv[6], NULL);
- decode_rules = load_decode_table (argv[5]);
- gen = make_gen_tables (instructions, decode_rules);
- gen_tables_expand_insns (gen);
- l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn");
- dump_gen_table (l, "(", gen, ")\n", -1);
- return 0;
- }
- #endif
|