12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820 |
- /* 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"
- static insn_word_entry *
- parse_insn_word (line_ref *line, char *string, int word_nr)
- {
- char *chp;
- insn_word_entry *word = ZALLOC (insn_word_entry);
- /* create a leading sentinal */
- word->first = ZALLOC (insn_field_entry);
- word->first->first = -1;
- word->first->last = -1;
- word->first->width = 0;
- /* and a trailing sentinal */
- word->last = ZALLOC (insn_field_entry);
- word->last->first = options.insn_bit_size;
- word->last->last = options.insn_bit_size;
- word->last->width = 0;
- /* link them together */
- word->first->next = word->last;
- word->last->prev = word->first;
- /* now work through the formats */
- chp = skip_spaces (string);
- while (*chp != '\0')
- {
- char *start_pos;
- int strlen_pos;
- char *start_val;
- int strlen_val;
- insn_field_entry *new_field;
- /* create / link in the new field */
- new_field = ZALLOC (insn_field_entry);
- new_field->next = word->last;
- new_field->prev = word->last->prev;
- new_field->next->prev = new_field;
- new_field->prev->next = new_field;
- new_field->word_nr = word_nr;
- /* break out the first field (if present) */
- start_pos = chp;
- chp = skip_to_separator (chp, ".,!");
- strlen_pos = back_spaces (start_pos, chp) - start_pos;
- /* break out the second field (if present) */
- if (*chp != '.')
- {
- /* assume what was specified was the value (and not the start
- position). Assume the value length implicitly specifies
- the number of bits */
- start_val = start_pos;
- strlen_val = strlen_pos;
- start_pos = "";
- strlen_pos = 0;
- }
- else
- {
- chp++; /* skip `.' */
- chp = skip_spaces (chp);
- start_val = chp;
- if (*chp == '/' || *chp == '*')
- {
- do
- {
- chp++;
- }
- while (*chp == '/' || *chp == '*');
- }
- else if (isalpha (*start_val))
- {
- do
- {
- chp++;
- }
- while (isalnum (*chp) || *chp == '_');
- }
- else if (isdigit (*start_val))
- {
- do
- {
- chp++;
- }
- while (isalnum (*chp));
- }
- strlen_val = chp - start_val;
- chp = skip_spaces (chp);
- }
- if (strlen_val == 0)
- error (line, "Empty value field\n");
- /* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */
- while (*chp == '!' || *chp == '=')
- {
- char *start;
- char *end;
- int len;
- insn_field_cond *new_cond = ZALLOC (insn_field_cond);
- /* determine the conditional test */
- switch (*chp)
- {
- case '=':
- new_cond->test = insn_field_cond_eq;
- break;
- case '!':
- new_cond->test = insn_field_cond_ne;
- break;
- default:
- ASSERT (0);
- }
- /* save the value */
- chp++;
- chp = skip_spaces (chp);
- start = chp;
- chp = skip_to_separator (chp, "+,:!=");
- end = back_spaces (start, chp);
- len = end - start;
- if (len == 0)
- error (line, "Missing or invalid conditional value\n");
- new_cond->string = NZALLOC (char, len + 1);
- strncpy (new_cond->string, start, len);
- /* determine the conditional type */
- if (isdigit (*start))
- {
- /* [ "!" | "=" ] <value> */
- new_cond->type = insn_field_cond_value;
- new_cond->value = a2i (new_cond->string);
- }
- else
- {
- /* [ "!" | "=" ] <field> - check field valid */
- new_cond->type = insn_field_cond_field;
- /* new_cond->field is determined in later */
- }
- /* Only a single `=' is permitted. */
- if ((new_cond->test == insn_field_cond_eq
- && new_field->conditions != NULL)
- || (new_field->conditions != NULL
- && new_field->conditions->test == insn_field_cond_eq))
- error (line, "Only single conditional when `=' allowed\n");
- /* insert it */
- {
- insn_field_cond **last = &new_field->conditions;
- while (*last != NULL)
- last = &(*last)->next;
- *last = new_cond;
- }
- }
- /* NOW verify that the field was finished */
- if (*chp == ',')
- {
- chp = skip_spaces (chp + 1);
- if (*chp == '\0')
- error (line, "empty field\n");
- }
- else if (*chp != '\0')
- {
- error (line, "Missing field separator\n");
- }
- /* copy the value */
- new_field->val_string = NZALLOC (char, strlen_val + 1);
- strncpy (new_field->val_string, start_val, strlen_val);
- if (isdigit (new_field->val_string[0]))
- {
- if (strlen_pos == 0)
- {
- /* when the length/pos field is omited, an integer field
- is always binary */
- uint64_t val = 0;
- int i;
- for (i = 0; i < strlen_val; i++)
- {
- if (new_field->val_string[i] != '0'
- && new_field->val_string[i] != '1')
- error (line, "invalid binary field %s\n",
- new_field->val_string);
- val = (val << 1) + (new_field->val_string[i] == '1');
- }
- new_field->val_int = val;
- new_field->type = insn_field_int;
- }
- else
- {
- new_field->val_int = a2i (new_field->val_string);
- new_field->type = insn_field_int;
- }
- }
- else if (new_field->val_string[0] == '/')
- {
- new_field->type = insn_field_reserved;
- }
- else if (new_field->val_string[0] == '*')
- {
- new_field->type = insn_field_wild;
- }
- else
- {
- new_field->type = insn_field_string;
- if (filter_is_member (word->field_names, new_field->val_string))
- error (line, "Field name %s is duplicated\n",
- new_field->val_string);
- filter_parse (&word->field_names, new_field->val_string);
- }
- if (new_field->type != insn_field_string
- && new_field->conditions != NULL)
- error (line, "Conditionals can only be applied to named fields\n");
- /* the copy the position */
- new_field->pos_string = NZALLOC (char, strlen_pos + 1);
- strncpy (new_field->pos_string, start_pos, strlen_pos);
- if (strlen_pos == 0)
- {
- new_field->first = new_field->prev->last + 1;
- if (new_field->first == 0 /* first field */
- && *chp == '\0' /* no further fields */
- && new_field->type == insn_field_string)
- {
- /* A single string without any position, assume that it
- represents the entire instruction word */
- new_field->width = options.insn_bit_size;
- }
- else
- {
- /* No explicit width/position, assume value implicitly
- supplies the width */
- new_field->width = strlen_val;
- }
- new_field->last = new_field->first + new_field->width - 1;
- if (new_field->last >= options.insn_bit_size)
- error (line, "Bit position %d exceed instruction bit size (%d)\n",
- new_field->last, options.insn_bit_size);
- }
- else if (options.insn_specifying_widths)
- {
- new_field->first = new_field->prev->last + 1;
- new_field->width = a2i (new_field->pos_string);
- new_field->last = new_field->first + new_field->width - 1;
- if (new_field->last >= options.insn_bit_size)
- error (line, "Bit position %d exceed instruction bit size (%d)\n",
- new_field->last, options.insn_bit_size);
- }
- else
- {
- new_field->first = target_a2i (options.hi_bit_nr,
- new_field->pos_string);
- new_field->last = new_field->next->first - 1; /* guess */
- new_field->width = new_field->last - new_field->first + 1; /* guess */
- new_field->prev->last = new_field->first - 1; /*fix */
- new_field->prev->width = new_field->first - new_field->prev->first; /*fix */
- }
- }
- /* fiddle first/last so that the sentinals disapear */
- ASSERT (word->first->last < 0);
- ASSERT (word->last->first >= options.insn_bit_size);
- word->first = word->first->next;
- word->last = word->last->prev;
- /* check that the last field goes all the way to the last bit */
- if (word->last->last != options.insn_bit_size - 1)
- {
- if (options.warn.width)
- options.warning (line, "Instruction format is not %d bits wide\n",
- options.insn_bit_size);
- word->last->last = options.insn_bit_size - 1;
- }
- /* now go over this again, pointing each bit position at a field
- record */
- {
- insn_field_entry *field;
- for (field = word->first;
- field->last < options.insn_bit_size; field = field->next)
- {
- int i;
- for (i = field->first; i <= field->last; i++)
- {
- word->bit[i] = ZALLOC (insn_bit_entry);
- word->bit[i]->field = field;
- switch (field->type)
- {
- case insn_field_invalid:
- ASSERT (0);
- break;
- case insn_field_int:
- word->bit[i]->mask = 1;
- word->bit[i]->value = ((field->val_int
- & ((insn_uint) 1 <<
- (field->last - i))) != 0);
- case insn_field_reserved:
- case insn_field_wild:
- case insn_field_string:
- /* if we encounter a constant conditional, encode
- their bit value. */
- if (field->conditions != NULL
- && field->conditions->test == insn_field_cond_eq
- && field->conditions->type == insn_field_cond_value)
- {
- word->bit[i]->mask = 1;
- word->bit[i]->value = ((field->conditions->value
- & ((insn_uint) 1 <<
- (field->last - i))) != 0);
- }
- break;
- }
- }
- }
- }
- return word;
- }
- static void
- parse_insn_words (insn_entry * insn, char *formats)
- {
- insn_word_entry **last_word = &insn->words;
- char *chp;
- /* now work through the formats */
- insn->nr_words = 0;
- chp = formats;
- while (1)
- {
- char *start_pos;
- char *end_pos;
- int strlen_pos;
- char *format;
- insn_word_entry *new_word;
- /* skip leading spaces */
- chp = skip_spaces (chp);
- /* break out the format */
- start_pos = chp;
- chp = skip_to_separator (chp, "+");
- end_pos = back_spaces (start_pos, chp);
- strlen_pos = end_pos - start_pos;
- /* check that something was there */
- if (strlen_pos == 0)
- error (insn->line, "missing or empty instruction format\n");
- /* parse the field */
- format = NZALLOC (char, strlen_pos + 1);
- strncpy (format, start_pos, strlen_pos);
- new_word = parse_insn_word (insn->line, format, insn->nr_words);
- insn->nr_words++;
- if (filter_is_common (insn->field_names, new_word->field_names))
- error (insn->line, "Field name duplicated between two words\n");
- filter_add (&insn->field_names, new_word->field_names);
- /* insert it */
- *last_word = new_word;
- last_word = &new_word->next;
- /* last format? */
- if (*chp == '\0')
- break;
- ASSERT (*chp == '+');
- chp++;
- }
- /* create a quick access array (indexed by word) of the same structure */
- {
- int i;
- insn_word_entry *word;
- insn->word = NZALLOC (insn_word_entry *, insn->nr_words + 1);
- for (i = 0, word = insn->words;
- i < insn->nr_words; i++, word = word->next)
- insn->word[i] = word;
- }
- /* Go over all fields that have conditionals refering to other
- fields. Link the fields up. Verify that the two fields have the
- same size. Verify that the two fields are different */
- {
- int i;
- for (i = 0; i < insn->nr_words; i++)
- {
- insn_word_entry *word = insn->word[i];
- insn_field_entry *f;
- for (f = word->first; f->last < options.insn_bit_size; f = f->next)
- {
- insn_field_cond *cond;
- for (cond = f->conditions; cond != NULL; cond = cond->next)
- {
- if (cond->type == insn_field_cond_field)
- {
- int j;
- if (strcmp (cond->string, f->val_string) == 0)
- error (insn->line,
- "Conditional `%s' of field `%s' refers to its self\n",
- cond->string, f->val_string);
- for (j = 0; j <= i && cond->field == NULL; j++)
- {
- insn_word_entry *refered_word = insn->word[j];
- insn_field_entry *refered_field;
- for (refered_field = refered_word->first;
- refered_field != NULL && cond->field == NULL;
- refered_field = refered_field->next)
- {
- if (refered_field->type == insn_field_string
- && strcmp (refered_field->val_string,
- cond->string) == 0)
- {
- /* found field being refered to by conditonal */
- cond->field = refered_field;
- /* check refered to and this field are
- the same size */
- if (f->width != refered_field->width)
- error (insn->line,
- "Conditional `%s' of field `%s' should be of size %s\n",
- cond->string, f->val_string,
- refered_field->width);
- }
- }
- }
- if (cond->field == NULL)
- error (insn->line,
- "Conditional `%s' of field `%s' not yet defined\n",
- cond->string, f->val_string);
- }
- }
- }
- }
- }
- }
- typedef enum
- {
- unknown_record = 0,
- insn_record, /* default */
- code_record,
- cache_record,
- compute_record,
- scratch_record,
- option_record,
- string_function_record,
- function_record,
- internal_record,
- define_record,
- include_record,
- model_processor_record,
- model_macro_record,
- model_data_record,
- model_static_record,
- model_function_record,
- model_internal_record,
- }
- insn_record_type;
- static const name_map insn_type_map[] = {
- {"option", option_record},
- {"cache", cache_record},
- {"compute", compute_record},
- {"scratch", scratch_record},
- {"define", define_record},
- {"include", include_record},
- {"%s", string_function_record},
- {"function", function_record},
- {"internal", internal_record},
- {"model", model_processor_record},
- {"model-macro", model_macro_record},
- {"model-data", model_data_record},
- {"model-static", model_static_record},
- {"model-internal", model_internal_record},
- {"model-function", model_function_record},
- {NULL, insn_record},
- };
- static int
- record_is_old (table_entry *entry)
- {
- if (entry->nr_fields > record_type_field
- && strlen (entry->field[record_type_field]) == 0)
- return 1;
- return 0;
- }
- static insn_record_type
- record_type (table_entry *entry)
- {
- switch (entry->type)
- {
- case table_code_entry:
- return code_record;
- case table_colon_entry:
- if (record_is_old (entry))
- {
- /* old-format? */
- if (entry->nr_fields > old_record_type_field)
- {
- int i = name2i (entry->field[old_record_type_field],
- insn_type_map);
- return i;
- }
- else
- {
- return unknown_record;
- }
- }
- else if (entry->nr_fields > record_type_field
- && entry->field[0][0] == '\0')
- {
- /* new-format? */
- int i = name2i (entry->field[record_type_field],
- insn_type_map);
- return i;
- }
- else
- return insn_record; /* default */
- }
- return unknown_record;
- }
- static int
- record_prefix_is (table_entry *entry, char ch, int nr_fields)
- {
- if (entry->type != table_colon_entry)
- return 0;
- if (entry->nr_fields < nr_fields)
- return 0;
- if (entry->field[0][0] != ch && ch != '\0')
- return 0;
- return 1;
- }
- static table_entry *
- parse_model_data_record (insn_table *isa,
- table *file,
- table_entry *record,
- int nr_fields, model_data **list)
- {
- table_entry *model_record = record;
- table_entry *code_record = NULL;
- model_data *new_data;
- if (record->nr_fields < nr_fields)
- error (record->line, "Incorrect number of fields\n");
- record = table_read (file);
- if (record->type == table_code_entry)
- {
- code_record = record;
- record = table_read (file);
- }
- /* create the new data record */
- new_data = ZALLOC (model_data);
- new_data->line = model_record->line;
- filter_parse (&new_data->flags,
- model_record->field[record_filter_flags_field]);
- new_data->entry = model_record;
- new_data->code = code_record;
- /* append it if not filtered out */
- if (!is_filtered_out (options.flags_filter,
- model_record->field[record_filter_flags_field])
- && !is_filtered_out (options.model_filter,
- model_record->field[record_filter_models_field]))
- {
- while (*list != NULL)
- list = &(*list)->next;
- *list = new_data;
- }
- return record;
- }
- typedef enum
- {
- insn_bit_size_option = 1,
- insn_specifying_widths_option,
- hi_bit_nr_option,
- flags_filter_option,
- model_filter_option,
- multi_sim_option,
- format_names_option,
- gen_delayed_branch,
- unknown_option,
- }
- option_names;
- static const name_map option_map[] = {
- {"insn-bit-size", insn_bit_size_option},
- {"insn-specifying-widths", insn_specifying_widths_option},
- {"hi-bit-nr", hi_bit_nr_option},
- {"flags-filter", flags_filter_option},
- {"model-filter", model_filter_option},
- {"multi-sim", multi_sim_option},
- {"format-names", format_names_option},
- {"gen-delayed-branch", gen_delayed_branch},
- {NULL, unknown_option},
- };
- static table_entry *
- parse_include_record (table *file, table_entry *record)
- {
- /* parse the include record */
- if (record->nr_fields < nr_include_fields)
- error (record->line, "Incorrect nr fields for include record\n");
- /* process it */
- if (!is_filtered_out (options.flags_filter,
- record->field[record_filter_flags_field])
- && !is_filtered_out (options.model_filter,
- record->field[record_filter_models_field]))
- {
- table_push (file, record->line, options.include,
- record->field[include_filename_field]);
- }
- /* nb: can't read next record until after the file has been pushed */
- record = table_read (file);
- return record;
- }
- static table_entry *
- parse_option_record (table *file, table_entry *record)
- {
- table_entry *option_record;
- /* parse the option record */
- option_record = record;
- if (record->nr_fields < nr_option_fields)
- error (record->line, "Incorrect nr of fields for option record\n");
- record = table_read (file);
- /* process it */
- if (!is_filtered_out (options.flags_filter,
- option_record->field[record_filter_flags_field])
- && !is_filtered_out (options.model_filter,
- option_record->field[record_filter_models_field]))
- {
- char *name = option_record->field[option_name_field];
- option_names option = name2i (name, option_map);
- char *value = option_record->field[option_value_field];
- switch (option)
- {
- case insn_bit_size_option:
- {
- options.insn_bit_size = a2i (value);
- if (options.insn_bit_size < 0
- || options.insn_bit_size > max_insn_bit_size)
- error (option_record->line,
- "Instruction bit size out of range\n");
- if (options.hi_bit_nr != options.insn_bit_size - 1
- && options.hi_bit_nr != 0)
- error (option_record->line,
- "insn-bit-size / hi-bit-nr conflict\n");
- break;
- }
- case insn_specifying_widths_option:
- {
- options.insn_specifying_widths = a2i (value);
- break;
- }
- case hi_bit_nr_option:
- {
- options.hi_bit_nr = a2i (value);
- if (options.hi_bit_nr != 0
- && options.hi_bit_nr != options.insn_bit_size - 1)
- error (option_record->line,
- "hi-bit-nr / insn-bit-size conflict\n");
- break;
- }
- case flags_filter_option:
- {
- filter_parse (&options.flags_filter, value);
- break;
- }
- case model_filter_option:
- {
- filter_parse (&options.model_filter, value);
- break;
- }
- case multi_sim_option:
- {
- options.gen.multi_sim = a2i (value);
- break;
- }
- case format_names_option:
- {
- filter_parse (&options.format_name_filter, value);
- break;
- }
- case gen_delayed_branch:
- {
- options.gen.delayed_branch = a2i (value);
- break;
- }
- case unknown_option:
- {
- error (option_record->line, "Unknown option - %s\n", name);
- break;
- }
- }
- }
- return record;
- }
- static table_entry *
- parse_function_record (table *file,
- table_entry *record,
- function_entry ** list,
- function_entry ** list_entry,
- int is_internal, model_table *model)
- {
- function_entry *new_function;
- new_function = ZALLOC (function_entry);
- new_function->line = record->line;
- new_function->is_internal = is_internal;
- /* parse the function header */
- if (record_is_old (record))
- {
- if (record->nr_fields < nr_old_function_fields)
- error (record->line, "Missing fields from (old) function record\n");
- new_function->type = record->field[old_function_typedef_field];
- new_function->type = record->field[old_function_typedef_field];
- if (record->nr_fields > old_function_param_field)
- new_function->param = record->field[old_function_param_field];
- new_function->name = record->field[old_function_name_field];
- }
- else
- {
- if (record->nr_fields < nr_function_fields)
- error (record->line, "Missing fields from function record\n");
- filter_parse (&new_function->flags,
- record->field[record_filter_flags_field]);
- filter_parse (&new_function->models,
- record->field[record_filter_models_field]);
- new_function->type = record->field[function_typedef_field];
- new_function->param = record->field[function_param_field];
- new_function->name = record->field[function_name_field];
- }
- record = table_read (file);
- /* parse any function-model records */
- while (record != NULL
- && record_prefix_is (record, '*', nr_function_model_fields))
- {
- char *model_name = record->field[function_model_name_field] + 1; /*skip `*' */
- filter_parse (&new_function->models, model_name);
- if (!filter_is_subset (model->processors, new_function->models))
- {
- error (record->line, "machine model `%s' undefined\n", model_name);
- }
- record = table_read (file);
- }
- /* parse the function body */
- if (record->type == table_code_entry)
- {
- new_function->code = record;
- record = table_read (file);
- }
- /* insert it */
- if (!filter_is_subset (options.flags_filter, new_function->flags))
- {
- if (options.warn.discard)
- notify (new_function->line, "Discarding function %s - filter flags\n",
- new_function->name);
- }
- else if (new_function->models != NULL
- && !filter_is_common (options.model_filter, new_function->models))
- {
- if (options.warn.discard)
- notify (new_function->line,
- "Discarding function %s - filter models\n",
- new_function->name);
- }
- else
- {
- while (*list != NULL)
- list = &(*list)->next;
- *list = new_function;
- if (list_entry != NULL)
- *list_entry = new_function;
- }
- /* done */
- return record;
- }
- static void
- parse_insn_model_record (table *file,
- table_entry *record,
- insn_entry * insn, model_table *model)
- {
- insn_model_entry **last_insn_model;
- insn_model_entry *new_insn_model = ZALLOC (insn_model_entry);
- /* parse it */
- new_insn_model->line = record->line;
- if (record->nr_fields > insn_model_unit_data_field)
- new_insn_model->unit_data = record->field[insn_model_unit_data_field];
- new_insn_model->insn = insn;
- /* parse the model names, verify that all were defined */
- new_insn_model->names = NULL;
- filter_parse (&new_insn_model->names,
- record->field[insn_model_name_field] + 1 /*skip `*' */ );
- if (new_insn_model->names == NULL)
- {
- /* No processor names - a generic model entry, enter it into all
- the non-empty fields */
- int index;
- for (index = 0; index < model->nr_models; index++)
- if (insn->model[index] == 0)
- {
- insn->model[index] = new_insn_model;
- }
- /* also add the complete processor set to this processor's set */
- filter_add (&insn->processors, model->processors);
- }
- else
- {
- /* Find the corresponding master model record for each name so
- that they can be linked in. */
- int index;
- char *name = "";
- while (1)
- {
- name = filter_next (new_insn_model->names, name);
- if (name == NULL)
- break;
- index = filter_is_member (model->processors, name) - 1;
- if (index < 0)
- {
- error (new_insn_model->line,
- "machine model `%s' undefined\n", name);
- }
- /* store it in the corresponding model array entry */
- if (insn->model[index] != NULL && insn->model[index]->names != NULL)
- {
- warning (new_insn_model->line,
- "machine model `%s' previously defined\n", name);
- error (insn->model[index]->line, "earlier definition\n");
- }
- insn->model[index] = new_insn_model;
- /* also add the name to the instructions processor set as an
- alternative lookup mechanism */
- filter_parse (&insn->processors, name);
- }
- }
- /* link it in */
- last_insn_model = &insn->models;
- while ((*last_insn_model) != NULL)
- last_insn_model = &(*last_insn_model)->next;
- *last_insn_model = new_insn_model;
- }
- static void
- parse_insn_mnemonic_record (table *file,
- table_entry *record, insn_entry * insn)
- {
- insn_mnemonic_entry **last_insn_mnemonic;
- insn_mnemonic_entry *new_insn_mnemonic = ZALLOC (insn_mnemonic_entry);
- /* parse it */
- new_insn_mnemonic->line = record->line;
- ASSERT (record->nr_fields > insn_mnemonic_format_field);
- new_insn_mnemonic->format = record->field[insn_mnemonic_format_field];
- ASSERT (new_insn_mnemonic->format[0] == '"');
- if (new_insn_mnemonic->format[strlen (new_insn_mnemonic->format) - 1] !=
- '"')
- error (new_insn_mnemonic->line,
- "Missing closing double quote in mnemonic field\n");
- if (record->nr_fields > insn_mnemonic_condition_field)
- new_insn_mnemonic->condition =
- record->field[insn_mnemonic_condition_field];
- new_insn_mnemonic->insn = insn;
- /* insert it */
- last_insn_mnemonic = &insn->mnemonics;
- while ((*last_insn_mnemonic) != NULL)
- last_insn_mnemonic = &(*last_insn_mnemonic)->next;
- insn->nr_mnemonics++;
- *last_insn_mnemonic = new_insn_mnemonic;
- }
- static table_entry *
- parse_macro_record (table *file, table_entry *record)
- {
- #if 1
- error (record->line, "Macros are not implemented");
- #else
- /* parse the define record */
- if (record->nr_fields < nr_define_fields)
- error (record->line, "Incorrect nr fields for define record\n");
- /* process it */
- if (!is_filtered_out (options.flags_filter,
- record->field[record_filter_flags_field])
- && !is_filtered_out (options.model_filter,
- record->field[record_filter_models_field]))
- {
- table_define (file,
- record->line,
- record->field[macro_name_field],
- record->field[macro_args_field],
- record->field[macro_expr_field]);
- }
- record = table_read (file);
- #endif
- return record;
- }
- insn_table *
- load_insn_table (char *file_name, cache_entry *cache)
- {
- table *file = table_open (file_name);
- table_entry *record = table_read (file);
- insn_table *isa = ZALLOC (insn_table);
- model_table *model = ZALLOC (model_table);
- isa->model = model;
- isa->caches = cache;
- while (record != NULL)
- {
- switch (record_type (record))
- {
- case include_record:
- {
- record = parse_include_record (file, record);
- break;
- }
- case option_record:
- {
- if (isa->insns != NULL)
- error (record->line, "Option after first instruction\n");
- record = parse_option_record (file, record);
- break;
- }
- case string_function_record:
- {
- function_entry *function = NULL;
- record = parse_function_record (file, record,
- &isa->functions,
- &function, 0 /*is-internal */ ,
- model);
- /* convert a string function record into an internal function */
- if (function != NULL)
- {
- char *name = NZALLOC (char,
- (strlen ("str_")
- + strlen (function->name) + 1));
- strcat (name, "str_");
- strcat (name, function->name);
- function->name = name;
- function->type = "const char *";
- }
- break;
- }
- case function_record: /* function record */
- {
- record = parse_function_record (file, record,
- &isa->functions,
- NULL, 0 /*is-internal */ ,
- model);
- break;
- }
- case internal_record:
- {
- /* only insert it into the function list if it is unknown */
- function_entry *function = NULL;
- record = parse_function_record (file, record,
- &isa->functions,
- &function, 1 /*is-internal */ ,
- model);
- /* check what was inserted to see if a pseudo-instruction
- entry also needs to be created */
- if (function != NULL)
- {
- insn_entry **insn = NULL;
- if (strcmp (function->name, "illegal") == 0)
- {
- /* illegal function save it away */
- if (isa->illegal_insn != NULL)
- {
- warning (function->line,
- "Multiple illegal instruction definitions\n");
- error (isa->illegal_insn->line,
- "Location of first illegal instruction\n");
- }
- else
- insn = &isa->illegal_insn;
- }
- if (insn != NULL)
- {
- *insn = ZALLOC (insn_entry);
- (*insn)->line = function->line;
- (*insn)->name = function->name;
- (*insn)->code = function->code;
- }
- }
- break;
- }
- case scratch_record: /* cache macro records */
- case cache_record:
- case compute_record:
- {
- cache_entry *new_cache;
- /* parse the cache record */
- if (record->nr_fields < nr_cache_fields)
- error (record->line,
- "Incorrect nr of fields for scratch/cache/compute record\n");
- /* create it */
- new_cache = ZALLOC (cache_entry);
- new_cache->line = record->line;
- filter_parse (&new_cache->flags,
- record->field[record_filter_flags_field]);
- filter_parse (&new_cache->models,
- record->field[record_filter_models_field]);
- new_cache->type = record->field[cache_typedef_field];
- new_cache->name = record->field[cache_name_field];
- filter_parse (&new_cache->original_fields,
- record->field[cache_original_fields_field]);
- new_cache->expression = record->field[cache_expression_field];
- /* insert it but only if not filtered out */
- if (!filter_is_subset (options.flags_filter, new_cache->flags))
- {
- notify (new_cache->line,
- "Discarding cache entry %s - filter flags\n",
- new_cache->name);
- }
- else if (is_filtered_out (options.model_filter,
- record->
- field[record_filter_models_field]))
- {
- notify (new_cache->line,
- "Discarding cache entry %s - filter models\n",
- new_cache->name);
- }
- else
- {
- cache_entry **last;
- last = &isa->caches;
- while (*last != NULL)
- last = &(*last)->next;
- *last = new_cache;
- }
- /* advance things */
- record = table_read (file);
- break;
- }
- /* model records */
- case model_processor_record:
- {
- model_entry *new_model;
- /* parse the model */
- if (record->nr_fields < nr_model_processor_fields)
- error (record->line,
- "Incorrect nr of fields for model record\n");
- if (isa->insns != NULL)
- error (record->line, "Model appears after first instruction\n");
- new_model = ZALLOC (model_entry);
- filter_parse (&new_model->flags,
- record->field[record_filter_flags_field]);
- new_model->line = record->line;
- new_model->name = record->field[model_name_field];
- new_model->full_name = record->field[model_full_name_field];
- new_model->unit_data = record->field[model_unit_data_field];
- /* only insert it if not filtered out */
- if (!filter_is_subset (options.flags_filter, new_model->flags))
- {
- notify (new_model->line,
- "Discarding processor model %s - filter flags\n",
- new_model->name);
- }
- else if (is_filtered_out (options.model_filter,
- record->
- field[record_filter_models_field]))
- {
- notify (new_model->line,
- "Discarding processor model %s - filter models\n",
- new_model->name);
- }
- else if (filter_is_member (model->processors, new_model->name))
- {
- error (new_model->line, "Duplicate processor model %s\n",
- new_model->name);
- }
- else
- {
- model_entry **last;
- last = &model->models;
- while (*last != NULL)
- last = &(*last)->next;
- *last = new_model;
- /* count it */
- model->nr_models++;
- filter_parse (&model->processors, new_model->name);
- }
- /* advance things */
- record = table_read (file);
- }
- break;
- case model_macro_record:
- record = parse_model_data_record (isa, file, record,
- nr_model_macro_fields,
- &model->macros);
- break;
- case model_data_record:
- record = parse_model_data_record (isa, file, record,
- nr_model_data_fields,
- &model->data);
- break;
- case model_static_record:
- record = parse_function_record (file, record,
- &model->statics,
- NULL, 0 /*is internal */ ,
- model);
- break;
- case model_internal_record:
- record = parse_function_record (file, record,
- &model->internals,
- NULL, 1 /*is internal */ ,
- model);
- break;
- case model_function_record:
- record = parse_function_record (file, record,
- &model->functions,
- NULL, 0 /*is internal */ ,
- model);
- break;
- case insn_record: /* instruction records */
- {
- insn_entry *new_insn;
- char *format;
- /* parse the instruction */
- if (record->nr_fields < nr_insn_fields)
- error (record->line,
- "Incorrect nr of fields for insn record\n");
- new_insn = ZALLOC (insn_entry);
- new_insn->line = record->line;
- filter_parse (&new_insn->flags,
- record->field[record_filter_flags_field]);
- /* save the format field. Can't parse it until after the
- filter-out checks. Could be filtered out because the
- format is invalid */
- format = record->field[insn_word_field];
- new_insn->format_name = record->field[insn_format_name_field];
- if (options.format_name_filter != NULL
- && !filter_is_member (options.format_name_filter,
- new_insn->format_name))
- error (new_insn->line,
- "Unreconized instruction format name `%s'\n",
- new_insn->format_name);
- filter_parse (&new_insn->options,
- record->field[insn_options_field]);
- new_insn->name = record->field[insn_name_field];
- record = table_read (file);
- /* Parse any model/assember records */
- new_insn->nr_models = model->nr_models;
- new_insn->model =
- NZALLOC (insn_model_entry *, model->nr_models + 1);
- while (record != NULL)
- {
- if (record_prefix_is (record, '*', nr_insn_model_fields))
- parse_insn_model_record (file, record, new_insn, model);
- else
- if (record_prefix_is (record, '"', nr_insn_mnemonic_fields))
- parse_insn_mnemonic_record (file, record, new_insn);
- else
- break;
- /* advance */
- record = table_read (file);
- }
- /* Parse the code record */
- if (record != NULL && record->type == table_code_entry)
- {
- new_insn->code = record;
- record = table_read (file);
- }
- else if (options.warn.unimplemented)
- notify (new_insn->line, "unimplemented\n");
- /* insert it */
- if (!filter_is_subset (options.flags_filter, new_insn->flags))
- {
- if (options.warn.discard)
- notify (new_insn->line,
- "Discarding instruction %s (flags-filter)\n",
- new_insn->name);
- }
- else if (new_insn->processors != NULL
- && options.model_filter != NULL
- && !filter_is_common (options.model_filter,
- new_insn->processors))
- {
- /* only discard an instruction based in the processor
- model when both the instruction and the options are
- nonempty */
- if (options.warn.discard)
- notify (new_insn->line,
- "Discarding instruction %s (processor-model)\n",
- new_insn->name);
- }
- else
- {
- insn_entry **last;
- /* finish the parsing */
- parse_insn_words (new_insn, format);
- /* append it */
- last = &isa->insns;
- while (*last)
- last = &(*last)->next;
- *last = new_insn;
- /* update global isa counters */
- isa->nr_insns++;
- if (isa->max_nr_words < new_insn->nr_words)
- isa->max_nr_words = new_insn->nr_words;
- filter_add (&isa->flags, new_insn->flags);
- filter_add (&isa->options, new_insn->options);
- }
- break;
- }
- case define_record:
- record = parse_macro_record (file, record);
- break;
- case unknown_record:
- case code_record:
- error (record->line, "Unknown or unexpected entry\n");
- }
- }
- return isa;
- }
- void
- print_insn_words (lf *file, insn_entry * insn)
- {
- insn_word_entry *word = insn->words;
- if (word != NULL)
- {
- while (1)
- {
- insn_field_entry *field = word->first;
- while (1)
- {
- insn_field_cond *cond;
- if (options.insn_specifying_widths)
- lf_printf (file, "%d.", field->width);
- else
- lf_printf (file, "%d.",
- i2target (options.hi_bit_nr, field->first));
- switch (field->type)
- {
- case insn_field_invalid:
- ASSERT (0);
- break;
- case insn_field_int:
- lf_printf (file, "0x%lx", (long) field->val_int);
- break;
- case insn_field_reserved:
- lf_printf (file, "/");
- break;
- case insn_field_wild:
- lf_printf (file, "*");
- break;
- case insn_field_string:
- lf_printf (file, "%s", field->val_string);
- if (field->conditions == NULL)
- break;
- if (field->conditions->test == insn_field_cond_eq)
- {
- if (field->conditions->type == insn_field_cond_value)
- lf_printf (file, "=%ld",
- (long) field->conditions->value);
- else
- lf_printf (file, "=%s", field->conditions->string);
- /* There can be only one equality condition. */
- ASSERT (field->conditions->next == NULL);
- break;
- }
- for (cond = field->conditions;
- cond != NULL;
- cond = cond->next)
- {
- ASSERT (cond->test == insn_field_cond_ne);
- if (cond->type == insn_field_cond_value)
- lf_printf (file, "!%ld", (long) cond->value);
- else
- lf_printf (file, "!%s", cond->string);
- }
- break;
- }
- if (field == word->last)
- break;
- field = field->next;
- lf_printf (file, ",");
- }
- word = word->next;
- if (word == NULL)
- break;
- lf_printf (file, "+");
- }
- }
- }
- void
- function_entry_traverse (lf *file,
- function_entry * functions,
- function_entry_handler * handler, void *data)
- {
- function_entry *function;
- for (function = functions; function != NULL; function = function->next)
- {
- handler (file, function, data);
- }
- }
- void
- insn_table_traverse_insn (lf *file,
- insn_table *isa,
- insn_entry_handler * handler, void *data)
- {
- insn_entry *insn;
- for (insn = isa->insns; insn != NULL; insn = insn->next)
- {
- handler (file, isa, insn, data);
- }
- }
- static void
- dump_function_entry (lf *file,
- char *prefix, function_entry * entry, char *suffix)
- {
- lf_printf (file, "%s(function_entry *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- dump_line_ref (file, "\n(line ", entry->line, ")");
- dump_filter (file, "\n(flags ", entry->flags, ")");
- lf_printf (file, "\n(type \"%s\")", entry->type);
- lf_printf (file, "\n(name \"%s\")", entry->name);
- lf_printf (file, "\n(param \"%s\")", entry->param);
- dump_table_entry (file, "\n(code ", entry->code, ")");
- lf_printf (file, "\n(is_internal %d)", entry->is_internal);
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_function_entries (lf *file,
- char *prefix, function_entry * entry, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- lf_indent (file, +1);
- while (entry != NULL)
- {
- dump_function_entry (file, "\n(", entry, ")");
- entry = entry->next;
- }
- lf_indent (file, -1);
- lf_printf (file, "%s", suffix);
- }
- static char *
- cache_entry_type_to_str (cache_entry_type type)
- {
- switch (type)
- {
- case scratch_value:
- return "scratch";
- case cache_value:
- return "cache";
- case compute_value:
- return "compute";
- }
- ERROR ("Bad switch");
- return 0;
- }
- static void
- dump_cache_entry (lf *file, char *prefix, cache_entry *entry, char *suffix)
- {
- lf_printf (file, "%s(cache_entry *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- dump_line_ref (file, "\n(line ", entry->line, ")");
- dump_filter (file, "\n(flags ", entry->flags, ")");
- lf_printf (file, "\n(entry_type \"%s\")",
- cache_entry_type_to_str (entry->entry_type));
- lf_printf (file, "\n(name \"%s\")", entry->name);
- dump_filter (file, "\n(original_fields ", entry->original_fields, ")");
- lf_printf (file, "\n(type \"%s\")", entry->type);
- lf_printf (file, "\n(expression \"%s\")", entry->expression);
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- }
- lf_printf (file, "%s", suffix);
- }
- void
- dump_cache_entries (lf *file, char *prefix, cache_entry *entry, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- lf_indent (file, +1);
- while (entry != NULL)
- {
- dump_cache_entry (file, "\n(", entry, ")");
- entry = entry->next;
- }
- lf_indent (file, -1);
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_model_data (lf *file, char *prefix, model_data *entry, char *suffix)
- {
- lf_printf (file, "%s(model_data *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- lf_indent (file, +1);
- dump_line_ref (file, "\n(line ", entry->line, ")");
- dump_filter (file, "\n(flags ", entry->flags, ")");
- dump_table_entry (file, "\n(entry ", entry->entry, ")");
- dump_table_entry (file, "\n(code ", entry->code, ")");
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", prefix);
- }
- static void
- dump_model_datas (lf *file, char *prefix, model_data *entry, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- lf_indent (file, +1);
- while (entry != NULL)
- {
- dump_model_data (file, "\n(", entry, ")");
- entry = entry->next;
- }
- lf_indent (file, -1);
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_model_entry (lf *file, char *prefix, model_entry *entry, char *suffix)
- {
- lf_printf (file, "%s(model_entry *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- lf_indent (file, +1);
- dump_line_ref (file, "\n(line ", entry->line, ")");
- dump_filter (file, "\n(flags ", entry->flags, ")");
- lf_printf (file, "\n(name \"%s\")", entry->name);
- lf_printf (file, "\n(full_name \"%s\")", entry->full_name);
- lf_printf (file, "\n(unit_data \"%s\")", entry->unit_data);
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", prefix);
- }
- static void
- dump_model_entries (lf *file, char *prefix, model_entry *entry, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- lf_indent (file, +1);
- while (entry != NULL)
- {
- dump_model_entry (file, "\n(", entry, ")");
- entry = entry->next;
- }
- lf_indent (file, -1);
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_model_table (lf *file, char *prefix, model_table *entry, char *suffix)
- {
- lf_printf (file, "%s(model_table *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- lf_indent (file, +1);
- dump_filter (file, "\n(processors ", entry->processors, ")");
- lf_printf (file, "\n(nr_models %d)", entry->nr_models);
- dump_model_entries (file, "\n(models ", entry->models, ")");
- dump_model_datas (file, "\n(macros ", entry->macros, ")");
- dump_model_datas (file, "\n(data ", entry->data, ")");
- dump_function_entries (file, "\n(statics ", entry->statics, ")");
- dump_function_entries (file, "\n(internals ", entry->functions, ")");
- dump_function_entries (file, "\n(functions ", entry->functions, ")");
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static char *
- insn_field_type_to_str (insn_field_type type)
- {
- switch (type)
- {
- case insn_field_invalid:
- ASSERT (0);
- return "(invalid)";
- case insn_field_int:
- return "int";
- case insn_field_reserved:
- return "reserved";
- case insn_field_wild:
- return "wild";
- case insn_field_string:
- return "string";
- }
- ERROR ("bad switch");
- return 0;
- }
- void
- dump_insn_field (lf *file,
- char *prefix, insn_field_entry *field, char *suffix)
- {
- char *sep = " ";
- lf_printf (file, "%s(insn_field_entry *) 0x%lx", prefix, (long) field);
- if (field != NULL)
- {
- lf_indent (file, +1);
- lf_printf (file, "%s(first %d)", sep, field->first);
- lf_printf (file, "%s(last %d)", sep, field->last);
- lf_printf (file, "%s(width %d)", sep, field->width);
- lf_printf (file, "%s(type %s)", sep,
- insn_field_type_to_str (field->type));
- switch (field->type)
- {
- case insn_field_invalid:
- ASSERT (0);
- break;
- case insn_field_int:
- lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
- break;
- case insn_field_reserved:
- /* nothing output */
- break;
- case insn_field_wild:
- /* nothing output */
- break;
- case insn_field_string:
- lf_printf (file, "%s(val \"%s\")", sep, field->val_string);
- break;
- }
- lf_printf (file, "%s(next 0x%lx)", sep, (long) field->next);
- lf_printf (file, "%s(prev 0x%lx)", sep, (long) field->prev);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- void
- dump_insn_word_entry (lf *file,
- char *prefix, insn_word_entry *word, char *suffix)
- {
- lf_printf (file, "%s(insn_word_entry *) 0x%lx", prefix, (long) word);
- if (word != NULL)
- {
- int i;
- insn_field_entry *field;
- lf_indent (file, +1);
- lf_printf (file, "\n(first 0x%lx)", (long) word->first);
- lf_printf (file, "\n(last 0x%lx)", (long) word->last);
- lf_printf (file, "\n(bit");
- for (i = 0; i < options.insn_bit_size; i++)
- lf_printf (file, "\n ((value %d) (mask %d) (field 0x%lx))",
- word->bit[i]->value, word->bit[i]->mask,
- (long) word->bit[i]->field);
- lf_printf (file, ")");
- for (field = word->first; field != NULL; field = field->next)
- dump_insn_field (file, "\n(", field, ")");
- dump_filter (file, "\n(field_names ", word->field_names, ")");
- lf_printf (file, "\n(next 0x%lx)", (long) word->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_word_entries (lf *file,
- char *prefix, insn_word_entry *word, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- while (word != NULL)
- {
- dump_insn_word_entry (file, "\n(", word, ")");
- word = word->next;
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_model_entry (lf *file,
- char *prefix, insn_model_entry *model, char *suffix)
- {
- lf_printf (file, "%s(insn_model_entry *) 0x%lx", prefix, (long) model);
- if (model != NULL)
- {
- lf_indent (file, +1);
- dump_line_ref (file, "\n(line ", model->line, ")");
- dump_filter (file, "\n(names ", model->names, ")");
- lf_printf (file, "\n(full_name \"%s\")", model->full_name);
- lf_printf (file, "\n(unit_data \"%s\")", model->unit_data);
- lf_printf (file, "\n(insn (insn_entry *) 0x%lx)", (long) model->insn);
- lf_printf (file, "\n(next (insn_model_entry *) 0x%lx)",
- (long) model->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_model_entries (lf *file,
- char *prefix, insn_model_entry *model, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- while (model != NULL)
- {
- dump_insn_model_entry (file, "\n", model, "");
- model = model->next;
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_mnemonic_entry (lf *file,
- char *prefix,
- insn_mnemonic_entry *mnemonic, char *suffix)
- {
- lf_printf (file, "%s(insn_mnemonic_entry *) 0x%lx", prefix,
- (long) mnemonic);
- if (mnemonic != NULL)
- {
- lf_indent (file, +1);
- dump_line_ref (file, "\n(line ", mnemonic->line, ")");
- lf_printf (file, "\n(format \"%s\")", mnemonic->format);
- lf_printf (file, "\n(condition \"%s\")", mnemonic->condition);
- lf_printf (file, "\n(insn (insn_entry *) 0x%lx)",
- (long) mnemonic->insn);
- lf_printf (file, "\n(next (insn_mnemonic_entry *) 0x%lx)",
- (long) mnemonic->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_mnemonic_entries (lf *file,
- char *prefix,
- insn_mnemonic_entry *mnemonic, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- while (mnemonic != NULL)
- {
- dump_insn_mnemonic_entry (file, "\n", mnemonic, "");
- mnemonic = mnemonic->next;
- }
- lf_printf (file, "%s", suffix);
- }
- void
- dump_insn_entry (lf *file, char *prefix, insn_entry * entry, char *suffix)
- {
- lf_printf (file, "%s(insn_entry *) 0x%lx", prefix, (long) entry);
- if (entry != NULL)
- {
- int i;
- lf_indent (file, +1);
- dump_line_ref (file, "\n(line ", entry->line, ")");
- dump_filter (file, "\n(flags ", entry->flags, ")");
- lf_printf (file, "\n(nr_words %d)", entry->nr_words);
- dump_insn_word_entries (file, "\n(words ", entry->words, ")");
- lf_printf (file, "\n(word");
- for (i = 0; i < entry->nr_models; i++)
- lf_printf (file, " 0x%lx", (long) entry->word[i]);
- lf_printf (file, ")");
- dump_filter (file, "\n(field_names ", entry->field_names, ")");
- lf_printf (file, "\n(format_name \"%s\")", entry->format_name);
- dump_filter (file, "\n(options ", entry->options, ")");
- lf_printf (file, "\n(name \"%s\")", entry->name);
- lf_printf (file, "\n(nr_models %d)", entry->nr_models);
- dump_insn_model_entries (file, "\n(models ", entry->models, ")");
- lf_printf (file, "\n(model");
- for (i = 0; i < entry->nr_models; i++)
- lf_printf (file, " 0x%lx", (long) entry->model[i]);
- lf_printf (file, ")");
- dump_filter (file, "\n(processors ", entry->processors, ")");
- dump_insn_mnemonic_entries (file, "\n(mnemonics ", entry->mnemonics,
- ")");
- dump_table_entry (file, "\n(code ", entry->code, ")");
- lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- static void
- dump_insn_entries (lf *file, char *prefix, insn_entry * entry, char *suffix)
- {
- lf_printf (file, "%s", prefix);
- lf_indent (file, +1);
- while (entry != NULL)
- {
- dump_insn_entry (file, "\n(", entry, ")");
- entry = entry->next;
- }
- lf_indent (file, -1);
- lf_printf (file, "%s", suffix);
- }
- void
- dump_insn_table (lf *file, char *prefix, insn_table *isa, char *suffix)
- {
- lf_printf (file, "%s(insn_table *) 0x%lx", prefix, (long) isa);
- if (isa != NULL)
- {
- lf_indent (file, +1);
- dump_cache_entries (file, "\n(caches ", isa->caches, ")");
- lf_printf (file, "\n(nr_insns %d)", isa->nr_insns);
- lf_printf (file, "\n(max_nr_words %d)", isa->max_nr_words);
- dump_insn_entries (file, "\n(insns ", isa->insns, ")");
- dump_function_entries (file, "\n(functions ", isa->functions, ")");
- dump_insn_entry (file, "\n(illegal_insn ", isa->illegal_insn, ")");
- dump_model_table (file, "\n(model ", isa->model, ")");
- dump_filter (file, "\n(flags ", isa->flags, ")");
- dump_filter (file, "\n(options ", isa->options, ")");
- lf_indent (file, -1);
- }
- lf_printf (file, "%s", suffix);
- }
- #ifdef MAIN
- igen_options options;
- int
- main (int argc, char **argv)
- {
- insn_table *isa;
- lf *l;
- INIT_OPTIONS ();
- if (argc == 3)
- filter_parse (&options.flags_filter, argv[2]);
- else if (argc != 2)
- error (NULL, "Usage: insn <insn-table> [ <filter-in> ]\n");
- isa = load_insn_table (argv[1], NULL);
- l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn");
- dump_insn_table (l, "(isa ", isa, ")\n");
- return 0;
- }
- #endif
|