133965Sjdp/* itbl-ops.c 2218822Sdim Copyright 1997, 1999, 2000, 2001, 2002, 2003, 2005, 2006 3218822Sdim Free Software Foundation, Inc. 433965Sjdp 533965Sjdp This file is part of GAS, the GNU Assembler. 633965Sjdp 733965Sjdp GAS is free software; you can redistribute it and/or modify 833965Sjdp it under the terms of the GNU General Public License as published by 933965Sjdp the Free Software Foundation; either version 2, or (at your option) 1033965Sjdp any later version. 1133965Sjdp 1233965Sjdp GAS is distributed in the hope that it will be useful, 1333965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1433965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965Sjdp GNU General Public License for more details. 1633965Sjdp 1733965Sjdp You should have received a copy of the GNU General Public License 1833965Sjdp along with GAS; see the file COPYING. If not, write to the Free 19218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim 02110-1301, USA. */ 2133965Sjdp 2233965Sjdp/*======================================================================*/ 2333965Sjdp/* 2433965Sjdp * Herein lies the support for dynamic specification of processor 2533965Sjdp * instructions and registers. Mnemonics, values, and formats for each 2633965Sjdp * instruction and register are specified in an ascii file consisting of 2733965Sjdp * table entries. The grammar for the table is defined in the document 2833965Sjdp * "Processor instruction table specification". 2933965Sjdp * 3033965Sjdp * Instructions use the gnu assembler syntax, with the addition of 3133965Sjdp * allowing mnemonics for register. 3233965Sjdp * Eg. "func $2,reg3,0x100,symbol ; comment" 3333965Sjdp * func - opcode name 3433965Sjdp * $n - register n 3533965Sjdp * reg3 - mnemonic for processor's register defined in table 3633965Sjdp * 0xddd..d - immediate value 3733965Sjdp * symbol - address of label or external symbol 3833965Sjdp * 3933965Sjdp * First, itbl_parse reads in the table of register and instruction 4033965Sjdp * names and formats, and builds a list of entries for each 4133965Sjdp * processor/type combination. lex and yacc are used to parse 4233965Sjdp * the entries in the table and call functions defined here to 4333965Sjdp * add each entry to our list. 4433965Sjdp * 4533965Sjdp * Then, when assembling or disassembling, these functions are called to 4633965Sjdp * 1) get information on a processor's registers and 4733965Sjdp * 2) assemble/disassemble an instruction. 4833965Sjdp * To assemble(disassemble) an instruction, the function 4933965Sjdp * itbl_assemble(itbl_disassemble) is called to search the list of 5033965Sjdp * instruction entries, and if a match is found, uses the format 5133965Sjdp * described in the instruction entry structure to complete the action. 5233965Sjdp * 5333965Sjdp * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2" 5433965Sjdp * and we want to define function "pig" which takes two operands. 5533965Sjdp * 5633965Sjdp * Given the table entries: 5733965Sjdp * "p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0" 5833965Sjdp * "p3 dreg d2 0x2" 5933965Sjdp * and that the instruction encoding for coprocessor pz has encoding: 6033965Sjdp * #define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25) 6133965Sjdp * #define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum) 6233965Sjdp * 6333965Sjdp * a structure to describe the instruction might look something like: 6433965Sjdp * struct itbl_entry = { 6533965Sjdp * e_processor processor = e_p3 6633965Sjdp * e_type type = e_insn 6733965Sjdp * char *name = "pig" 6833965Sjdp * uint value = 0x1 6933965Sjdp * uint flags = 0 7033965Sjdp * struct itbl_range range = 24-21 7133965Sjdp * struct itbl_field *field = { 7233965Sjdp * e_type type = e_dreg 7333965Sjdp * struct itbl_range range = 20-16 7433965Sjdp * struct itbl_field *next = { 7533965Sjdp * e_type type = e_immed 7633965Sjdp * struct itbl_range range = 15-0 7733965Sjdp * struct itbl_field *next = 0 7833965Sjdp * }; 7933965Sjdp * }; 8033965Sjdp * struct itbl_entry *next = 0 8133965Sjdp * }; 8233965Sjdp * 8333965Sjdp * And the assembler instructions: 8433965Sjdp * "pig d2,0x100" 8533965Sjdp * "pig $2,0x100" 8633965Sjdp * 8733965Sjdp * would both assemble to the hex value: 8833965Sjdp * "0x4e220100" 8933965Sjdp * 9033965Sjdp */ 9133965Sjdp 92218822Sdim#include "as.h" 9333965Sjdp#include "itbl-ops.h" 94107492Sobrien#include <itbl-parse.h> 9533965Sjdp 9633965Sjdp/* #define DEBUG */ 9733965Sjdp 9833965Sjdp#ifdef DEBUG 9933965Sjdp#include <assert.h> 10033965Sjdp#define ASSERT(x) assert(x) 10133965Sjdp#define DBG(x) printf x 10233965Sjdp#else 10333965Sjdp#define ASSERT(x) 10433965Sjdp#define DBG(x) 10533965Sjdp#endif 10633965Sjdp 10733965Sjdp#ifndef min 10833965Sjdp#define min(a,b) (a<b?a:b) 10933965Sjdp#endif 11033965Sjdp 11133965Sjdpint itbl_have_entries = 0; 11233965Sjdp 11333965Sjdp/*======================================================================*/ 11433965Sjdp/* structures for keeping itbl format entries */ 11533965Sjdp 11677298Sobrienstruct itbl_range { 11777298Sobrien int sbit; /* mask starting bit position */ 11877298Sobrien int ebit; /* mask ending bit position */ 11977298Sobrien}; 12033965Sjdp 12177298Sobrienstruct itbl_field { 12277298Sobrien e_type type; /* dreg/creg/greg/immed/symb */ 12377298Sobrien struct itbl_range range; /* field's bitfield range within instruction */ 12477298Sobrien unsigned long flags; /* field flags */ 12577298Sobrien struct itbl_field *next; /* next field in list */ 12677298Sobrien}; 12733965Sjdp 12833965Sjdp/* These structures define the instructions and registers for a processor. 12933965Sjdp * If the type is an instruction, the structure defines the format of an 13033965Sjdp * instruction where the fields are the list of operands. 13133965Sjdp * The flags field below uses the same values as those defined in the 13277298Sobrien * gnu assembler and are machine specific. */ 13377298Sobrienstruct itbl_entry { 13477298Sobrien e_processor processor; /* processor number */ 13577298Sobrien e_type type; /* dreg/creg/greg/insn */ 13677298Sobrien char *name; /* mnemionic name for insn/register */ 13777298Sobrien unsigned long value; /* opcode/instruction mask/register number */ 13877298Sobrien unsigned long flags; /* effects of the instruction */ 13977298Sobrien struct itbl_range range; /* bit range within instruction for value */ 14077298Sobrien struct itbl_field *fields; /* list of operand definitions (if any) */ 14177298Sobrien struct itbl_entry *next; /* next entry */ 14277298Sobrien}; 14333965Sjdp 14433965Sjdp/* local data and structures */ 14533965Sjdp 14633965Sjdpstatic int itbl_num_opcodes = 0; 14733965Sjdp/* Array of entries for each processor and entry type */ 148218822Sdimstatic struct itbl_entry *entries[e_nprocs][e_ntypes]; 14933965Sjdp 15033965Sjdp/* local prototypes */ 151130561Sobrienstatic unsigned long build_opcode (struct itbl_entry *e); 152130561Sobrienstatic e_type get_type (int yytype); 153130561Sobrienstatic e_processor get_processor (int yyproc); 154130561Sobrienstatic struct itbl_entry **get_entries (e_processor processor, 155130561Sobrien e_type type); 156130561Sobrienstatic struct itbl_entry *find_entry_byname (e_processor processor, 157130561Sobrien e_type type, char *name); 158130561Sobrienstatic struct itbl_entry *find_entry_byval (e_processor processor, 159130561Sobrien e_type type, unsigned long val, struct itbl_range *r); 160130561Sobrienstatic struct itbl_entry *alloc_entry (e_processor processor, 161130561Sobrien e_type type, char *name, unsigned long value); 162130561Sobrienstatic unsigned long apply_range (unsigned long value, struct itbl_range r); 163130561Sobrienstatic unsigned long extract_range (unsigned long value, struct itbl_range r); 164130561Sobrienstatic struct itbl_field *alloc_field (e_type type, int sbit, 165130561Sobrien int ebit, unsigned long flags); 16633965Sjdp 16733965Sjdp/*======================================================================*/ 16833965Sjdp/* Interfaces to the parser */ 16933965Sjdp 17033965Sjdp/* Open the table and use lex and yacc to parse the entries. 17133965Sjdp * Return 1 for failure; 0 for success. */ 17233965Sjdp 17377298Sobrienint 17433965Sjdpitbl_parse (char *insntbl) 17533965Sjdp{ 17633965Sjdp extern FILE *yyin; 17733965Sjdp extern int yyparse (void); 17889857Sobrien 17989857Sobrien yyin = fopen (insntbl, FOPEN_RT); 18033965Sjdp if (yyin == 0) 18133965Sjdp { 18233965Sjdp printf ("Can't open processor instruction specification file \"%s\"\n", 18333965Sjdp insntbl); 18433965Sjdp return 1; 18533965Sjdp } 18689857Sobrien 18789857Sobrien while (yyparse ()) 18889857Sobrien ; 18989857Sobrien 19033965Sjdp fclose (yyin); 19133965Sjdp itbl_have_entries = 1; 19233965Sjdp return 0; 19333965Sjdp} 19433965Sjdp 19533965Sjdp/* Add a register entry */ 19633965Sjdp 19733965Sjdpstruct itbl_entry * 19833965Sjdpitbl_add_reg (int yyprocessor, int yytype, char *regname, 19933965Sjdp int regnum) 20033965Sjdp{ 20133965Sjdp return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname, 20233965Sjdp (unsigned long) regnum); 20333965Sjdp} 20433965Sjdp 20533965Sjdp/* Add an instruction entry */ 20633965Sjdp 20733965Sjdpstruct itbl_entry * 20833965Sjdpitbl_add_insn (int yyprocessor, char *name, unsigned long value, 20933965Sjdp int sbit, int ebit, unsigned long flags) 21033965Sjdp{ 21133965Sjdp struct itbl_entry *e; 21233965Sjdp e = alloc_entry (get_processor (yyprocessor), e_insn, name, value); 21333965Sjdp if (e) 21433965Sjdp { 21533965Sjdp e->range.sbit = sbit; 21633965Sjdp e->range.ebit = ebit; 21733965Sjdp e->flags = flags; 21833965Sjdp itbl_num_opcodes++; 21933965Sjdp } 22033965Sjdp return e; 22133965Sjdp} 22233965Sjdp 22333965Sjdp/* Add an operand to an instruction entry */ 22433965Sjdp 22533965Sjdpstruct itbl_field * 22633965Sjdpitbl_add_operand (struct itbl_entry *e, int yytype, int sbit, 22733965Sjdp int ebit, unsigned long flags) 22833965Sjdp{ 22933965Sjdp struct itbl_field *f, **last_f; 23033965Sjdp if (!e) 23133965Sjdp return 0; 23277298Sobrien /* Add to end of fields' list. */ 23333965Sjdp f = alloc_field (get_type (yytype), sbit, ebit, flags); 23433965Sjdp if (f) 23533965Sjdp { 23633965Sjdp last_f = &e->fields; 23733965Sjdp while (*last_f) 23833965Sjdp last_f = &(*last_f)->next; 23933965Sjdp *last_f = f; 24033965Sjdp f->next = 0; 24133965Sjdp } 24233965Sjdp return f; 24333965Sjdp} 24433965Sjdp 24533965Sjdp/*======================================================================*/ 24633965Sjdp/* Interfaces for assembler and disassembler */ 24733965Sjdp 24833965Sjdp#ifndef STAND_ALONE 24933965Sjdpstatic void append_insns_as_macros (void); 25033965Sjdp 25177298Sobrien/* Initialize for gas. */ 25277298Sobrien 25377298Sobrienvoid 25433965Sjdpitbl_init (void) 25533965Sjdp{ 25633965Sjdp struct itbl_entry *e, **es; 25733965Sjdp e_processor procn; 25833965Sjdp e_type type; 25933965Sjdp 26033965Sjdp if (!itbl_have_entries) 26177298Sobrien return; 26233965Sjdp 26333965Sjdp /* Since register names don't have a prefix, put them in the symbol table so 26433965Sjdp they can't be used as symbols. This simplifies argument parsing as 26577298Sobrien we can let gas parse registers for us. */ 26633965Sjdp /* Use symbol_create instead of symbol_new so we don't try to 26733965Sjdp output registers into the object file's symbol table. */ 26833965Sjdp 26933965Sjdp for (type = e_regtype0; type < e_nregtypes; type++) 27033965Sjdp for (procn = e_p0; procn < e_nprocs; procn++) 27133965Sjdp { 27233965Sjdp es = get_entries (procn, type); 27333965Sjdp for (e = *es; e; e = e->next) 27433965Sjdp { 27533965Sjdp symbol_table_insert (symbol_create (e->name, reg_section, 27677298Sobrien e->value, &zero_address_frag)); 27733965Sjdp } 27833965Sjdp } 27933965Sjdp append_insns_as_macros (); 28033965Sjdp} 28133965Sjdp 28277298Sobrien/* Append insns to opcodes table and increase number of opcodes 28377298Sobrien * Structure of opcodes table: 28433965Sjdp * struct itbl_opcode 28533965Sjdp * { 28633965Sjdp * const char *name; 28777298Sobrien * const char *args; - string describing the arguments. 28877298Sobrien * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO 28977298Sobrien * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO 29077298Sobrien * unsigned long pinfo; - insn flags, or INSN_MACRO 29133965Sjdp * }; 29233965Sjdp * examples: 29333965Sjdp * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, 29433965Sjdp * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, 29533965Sjdp */ 29633965Sjdp 29733965Sjdpstatic char *form_args (struct itbl_entry *e); 29877298Sobrienstatic void 29933965Sjdpappend_insns_as_macros (void) 30033965Sjdp{ 30133965Sjdp struct ITBL_OPCODE_STRUCT *new_opcodes, *o; 30233965Sjdp struct itbl_entry *e, **es; 30333965Sjdp int n, id, size, new_size, new_num_opcodes; 30433965Sjdp 30533965Sjdp if (!itbl_have_entries) 30677298Sobrien return; 30733965Sjdp 30833965Sjdp if (!itbl_num_opcodes) /* no new instructions to add! */ 30933965Sjdp { 31033965Sjdp return; 31133965Sjdp } 31233965Sjdp DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES)); 31333965Sjdp 31433965Sjdp new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes; 31533965Sjdp ASSERT (new_num_opcodes >= itbl_num_opcodes); 31633965Sjdp 31733965Sjdp size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES; 31833965Sjdp ASSERT (size >= 0); 31933965Sjdp DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0]))); 32033965Sjdp 32133965Sjdp new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes; 32233965Sjdp ASSERT (new_size > size); 32333965Sjdp 32433965Sjdp /* FIXME since ITBL_OPCODES culd be a static table, 32577298Sobrien we can't realloc or delete the old memory. */ 32633965Sjdp new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size); 32733965Sjdp if (!new_opcodes) 32833965Sjdp { 32960484Sobrien printf (_("Unable to allocate memory for new instructions\n")); 33033965Sjdp return; 33133965Sjdp } 332130561Sobrien if (size) /* copy preexisting opcodes table */ 33333965Sjdp memcpy (new_opcodes, ITBL_OPCODES, size); 33433965Sjdp 33533965Sjdp /* FIXME! some NUMOPCODES are calculated expressions. 33677298Sobrien These need to be changed before itbls can be supported. */ 33733965Sjdp 33833965Sjdp id = ITBL_NUM_MACROS; /* begin the next macro id after the last */ 33933965Sjdp o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */ 34033965Sjdp for (n = e_p0; n < e_nprocs; n++) 34133965Sjdp { 34233965Sjdp es = get_entries (n, e_insn); 34333965Sjdp for (e = *es; e; e = e->next) 34433965Sjdp { 34533965Sjdp /* name, args, mask, match, pinfo 34633965Sjdp * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, 34733965Sjdp * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, 34833965Sjdp * Construct args from itbl_fields. 34933965Sjdp */ 35033965Sjdp o->name = e->name; 35133965Sjdp o->args = strdup (form_args (e)); 35233965Sjdp o->mask = apply_range (e->value, e->range); 353130561Sobrien /* FIXME how to catch during assembly? */ 35433965Sjdp /* mask to identify this insn */ 35533965Sjdp o->match = apply_range (e->value, e->range); 35633965Sjdp o->pinfo = 0; 35733965Sjdp 35833965Sjdp#ifdef USE_MACROS 359130561Sobrien o->mask = id++; /* FIXME how to catch during assembly? */ 36033965Sjdp o->match = 0; /* for macros, the insn_isa number */ 36133965Sjdp o->pinfo = INSN_MACRO; 36233965Sjdp#endif 36333965Sjdp 36433965Sjdp /* Don't add instructions which caused an error */ 36533965Sjdp if (o->args) 36633965Sjdp o++; 36733965Sjdp else 36833965Sjdp new_num_opcodes--; 36933965Sjdp } 37033965Sjdp } 37133965Sjdp ITBL_OPCODES = new_opcodes; 37233965Sjdp ITBL_NUM_OPCODES = new_num_opcodes; 37333965Sjdp 37433965Sjdp /* FIXME 37533965Sjdp At this point, we can free the entries, as they should have 37633965Sjdp been added to the assembler's tables. 37733965Sjdp Don't free name though, since name is being used by the new 37833965Sjdp opcodes table. 37933965Sjdp 38077298Sobrien Eventually, we should also free the new opcodes table itself 38133965Sjdp on exit. 38233965Sjdp */ 38333965Sjdp} 38433965Sjdp 38533965Sjdpstatic char * 38633965Sjdpform_args (struct itbl_entry *e) 38733965Sjdp{ 38833965Sjdp static char s[31]; 38933965Sjdp char c = 0, *p = s; 39033965Sjdp struct itbl_field *f; 39133965Sjdp 39233965Sjdp ASSERT (e); 39333965Sjdp for (f = e->fields; f; f = f->next) 39433965Sjdp { 39533965Sjdp switch (f->type) 39633965Sjdp { 39733965Sjdp case e_dreg: 39833965Sjdp c = 'd'; 39933965Sjdp break; 40033965Sjdp case e_creg: 40133965Sjdp c = 't'; 40233965Sjdp break; 40333965Sjdp case e_greg: 40433965Sjdp c = 's'; 40533965Sjdp break; 40633965Sjdp case e_immed: 40733965Sjdp c = 'i'; 40833965Sjdp break; 40933965Sjdp case e_addr: 41033965Sjdp c = 'a'; 41133965Sjdp break; 41233965Sjdp default: 41333965Sjdp c = 0; /* ignore; unknown field type */ 41433965Sjdp } 41533965Sjdp if (c) 41633965Sjdp { 41733965Sjdp if (p != s) 41833965Sjdp *p++ = ','; 41933965Sjdp *p++ = c; 42033965Sjdp } 42133965Sjdp } 42233965Sjdp *p = 0; 42333965Sjdp return s; 42433965Sjdp} 42533965Sjdp#endif /* !STAND_ALONE */ 42633965Sjdp 42733965Sjdp/* Get processor's register name from val */ 42833965Sjdp 42960484Sobrienint 43060484Sobrienitbl_get_reg_val (char *name, unsigned long *pval) 43133965Sjdp{ 43233965Sjdp e_type t; 43333965Sjdp e_processor p; 43460484Sobrien 43533965Sjdp for (p = e_p0; p < e_nprocs; p++) 43660484Sobrien { 43760484Sobrien for (t = e_regtype0; t < e_nregtypes; t++) 43860484Sobrien { 43960484Sobrien if (itbl_get_val (p, t, name, pval)) 44060484Sobrien return 1; 44160484Sobrien } 44260484Sobrien } 44333965Sjdp return 0; 44433965Sjdp} 44533965Sjdp 44633965Sjdpchar * 44733965Sjdpitbl_get_name (e_processor processor, e_type type, unsigned long val) 44833965Sjdp{ 44933965Sjdp struct itbl_entry *r; 45033965Sjdp /* type depends on instruction passed */ 45133965Sjdp r = find_entry_byval (processor, type, val, 0); 45233965Sjdp if (r) 45333965Sjdp return r->name; 45433965Sjdp else 45533965Sjdp return 0; /* error; invalid operand */ 45633965Sjdp} 45733965Sjdp 45833965Sjdp/* Get processor's register value from name */ 45933965Sjdp 46060484Sobrienint 46160484Sobrienitbl_get_val (e_processor processor, e_type type, char *name, 46260484Sobrien unsigned long *pval) 46333965Sjdp{ 46433965Sjdp struct itbl_entry *r; 46533965Sjdp /* type depends on instruction passed */ 46633965Sjdp r = find_entry_byname (processor, type, name); 46760484Sobrien if (r == NULL) 46860484Sobrien return 0; 46960484Sobrien *pval = r->value; 47060484Sobrien return 1; 47133965Sjdp} 47233965Sjdp 47333965Sjdp/* Assemble instruction "name" with operands "s". 47433965Sjdp * name - name of instruction 47533965Sjdp * s - operands 47633965Sjdp * returns - long word for assembled instruction */ 47733965Sjdp 47877298Sobrienunsigned long 47933965Sjdpitbl_assemble (char *name, char *s) 48033965Sjdp{ 48133965Sjdp unsigned long opcode; 48278828Sobrien struct itbl_entry *e = NULL; 48333965Sjdp struct itbl_field *f; 48433965Sjdp char *n; 48533965Sjdp int processor; 48633965Sjdp 48733965Sjdp if (!name || !*name) 48889857Sobrien return 0; /* error! must have an opcode name/expr */ 48933965Sjdp 49033965Sjdp /* find entry in list of instructions for all processors */ 49133965Sjdp for (processor = 0; processor < e_nprocs; processor++) 49233965Sjdp { 49333965Sjdp e = find_entry_byname (processor, e_insn, name); 49433965Sjdp if (e) 49533965Sjdp break; 49633965Sjdp } 49733965Sjdp if (!e) 49877298Sobrien return 0; /* opcode not in table; invalid instruction */ 49933965Sjdp opcode = build_opcode (e); 50033965Sjdp 50133965Sjdp /* parse opcode's args (if any) */ 50277298Sobrien for (f = e->fields; f; f = f->next) /* for each arg, ... */ 50333965Sjdp { 50433965Sjdp struct itbl_entry *r; 50533965Sjdp unsigned long value; 50633965Sjdp if (!s || !*s) 50733965Sjdp return 0; /* error - not enough operands */ 50833965Sjdp n = itbl_get_field (&s); 50933965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 51033965Sjdp switch (f->type) 51133965Sjdp { 51233965Sjdp case e_dreg: 51333965Sjdp case e_creg: 51433965Sjdp case e_greg: 51533965Sjdp /* Accept either a string name 51633965Sjdp * or '$' followed by the register number */ 51733965Sjdp if (*n == '$') 51833965Sjdp { 51933965Sjdp n++; 52033965Sjdp value = strtol (n, 0, 10); 52133965Sjdp /* FIXME! could have "0l"... then what?? */ 52233965Sjdp if (value == 0 && *n != '0') 52333965Sjdp return 0; /* error; invalid operand */ 52433965Sjdp } 52533965Sjdp else 52633965Sjdp { 52733965Sjdp r = find_entry_byname (e->processor, f->type, n); 52833965Sjdp if (r) 52933965Sjdp value = r->value; 53033965Sjdp else 53133965Sjdp return 0; /* error; invalid operand */ 53233965Sjdp } 53333965Sjdp break; 53433965Sjdp case e_addr: 53533965Sjdp /* use assembler's symbol table to find symbol */ 53633965Sjdp /* FIXME!! Do we need this? 53733965Sjdp if so, what about relocs?? 53833965Sjdp my_getExpression (&imm_expr, s); 53933965Sjdp return 0; /-* error; invalid operand *-/ 54033965Sjdp break; 54133965Sjdp */ 54233965Sjdp /* If not a symbol, fall thru to IMMED */ 54333965Sjdp case e_immed: 54477298Sobrien if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ 54533965Sjdp { 54633965Sjdp n += 2; 54733965Sjdp value = strtol (n, 0, 16); 54833965Sjdp /* FIXME! could have "0xl"... then what?? */ 54933965Sjdp } 55033965Sjdp else 55133965Sjdp { 55233965Sjdp value = strtol (n, 0, 10); 55333965Sjdp /* FIXME! could have "0l"... then what?? */ 55433965Sjdp if (value == 0 && *n != '0') 55533965Sjdp return 0; /* error; invalid operand */ 55633965Sjdp } 55733965Sjdp break; 55833965Sjdp default: 55933965Sjdp return 0; /* error; invalid field spec */ 56033965Sjdp } 56133965Sjdp opcode |= apply_range (value, f->range); 56233965Sjdp } 56333965Sjdp if (s && *s) 56433965Sjdp return 0; /* error - too many operands */ 56533965Sjdp return opcode; /* done! */ 56633965Sjdp} 56733965Sjdp 56833965Sjdp/* Disassemble instruction "insn". 56933965Sjdp * insn - instruction 57033965Sjdp * s - buffer to hold disassembled instruction 57133965Sjdp * returns - 1 if succeeded; 0 if failed 57233965Sjdp */ 57333965Sjdp 57477298Sobrienint 57533965Sjdpitbl_disassemble (char *s, unsigned long insn) 57633965Sjdp{ 57733965Sjdp e_processor processor; 57833965Sjdp struct itbl_entry *e; 57933965Sjdp struct itbl_field *f; 58033965Sjdp 58133965Sjdp if (!ITBL_IS_INSN (insn)) 58277298Sobrien return 0; /* error */ 58333965Sjdp processor = get_processor (ITBL_DECODE_PNUM (insn)); 58433965Sjdp 58533965Sjdp /* find entry in list */ 58633965Sjdp e = find_entry_byval (processor, e_insn, insn, 0); 58733965Sjdp if (!e) 58877298Sobrien return 0; /* opcode not in table; invalid instruction */ 58933965Sjdp strcpy (s, e->name); 59033965Sjdp 59177298Sobrien /* Parse insn's args (if any). */ 59277298Sobrien for (f = e->fields; f; f = f->next) /* for each arg, ... */ 59333965Sjdp { 59433965Sjdp struct itbl_entry *r; 59533965Sjdp unsigned long value; 59633965Sjdp 597130561Sobrien if (f == e->fields) /* First operand is preceded by tab. */ 59833965Sjdp strcat (s, "\t"); 59977298Sobrien else /* ','s separate following operands. */ 60033965Sjdp strcat (s, ","); 60133965Sjdp value = extract_range (insn, f->range); 60233965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 60333965Sjdp switch (f->type) 60433965Sjdp { 60533965Sjdp case e_dreg: 60633965Sjdp case e_creg: 60733965Sjdp case e_greg: 60833965Sjdp /* Accept either a string name 60977298Sobrien or '$' followed by the register number. */ 61033965Sjdp r = find_entry_byval (e->processor, f->type, value, &f->range); 61133965Sjdp if (r) 61233965Sjdp strcat (s, r->name); 61333965Sjdp else 61460484Sobrien sprintf (s, "%s$%lu", s, value); 61533965Sjdp break; 61633965Sjdp case e_addr: 61777298Sobrien /* Use assembler's symbol table to find symbol. */ 61877298Sobrien /* FIXME!! Do we need this? If so, what about relocs?? */ 61977298Sobrien /* If not a symbol, fall through to IMMED. */ 62033965Sjdp case e_immed: 62160484Sobrien sprintf (s, "%s0x%lx", s, value); 62233965Sjdp break; 62333965Sjdp default: 62433965Sjdp return 0; /* error; invalid field spec */ 62533965Sjdp } 62633965Sjdp } 62777298Sobrien return 1; /* Done! */ 62833965Sjdp} 62933965Sjdp 63033965Sjdp/*======================================================================*/ 63133965Sjdp/* 63233965Sjdp * Local functions for manipulating private structures containing 63333965Sjdp * the names and format for the new instructions and registers 63433965Sjdp * for each processor. 63533965Sjdp */ 63633965Sjdp 63733965Sjdp/* Calculate instruction's opcode and function values from entry */ 63833965Sjdp 63977298Sobrienstatic unsigned long 64033965Sjdpbuild_opcode (struct itbl_entry *e) 64133965Sjdp{ 64233965Sjdp unsigned long opcode; 64333965Sjdp 64433965Sjdp opcode = apply_range (e->value, e->range); 64533965Sjdp opcode |= ITBL_ENCODE_PNUM (e->processor); 64633965Sjdp return opcode; 64733965Sjdp} 64833965Sjdp 64933965Sjdp/* Calculate absolute value given the relative value and bit position range 65033965Sjdp * within the instruction. 65133965Sjdp * The range is inclusive where 0 is least significant bit. 65233965Sjdp * A range of { 24, 20 } will have a mask of 65333965Sjdp * bit 3 2 1 65433965Sjdp * pos: 1098 7654 3210 9876 5432 1098 7654 3210 65533965Sjdp * bin: 0000 0001 1111 0000 0000 0000 0000 0000 65633965Sjdp * hex: 0 1 f 0 0 0 0 0 65733965Sjdp * mask: 0x01f00000. 65833965Sjdp */ 65933965Sjdp 66077298Sobrienstatic unsigned long 66133965Sjdpapply_range (unsigned long rval, struct itbl_range r) 66233965Sjdp{ 66333965Sjdp unsigned long mask; 66433965Sjdp unsigned long aval; 66533965Sjdp int len = MAX_BITPOS - r.sbit; 66633965Sjdp 66733965Sjdp ASSERT (r.sbit >= r.ebit); 66833965Sjdp ASSERT (MAX_BITPOS >= r.sbit); 66933965Sjdp ASSERT (r.ebit >= 0); 67033965Sjdp 67133965Sjdp /* create mask by truncating 1s by shifting */ 67233965Sjdp mask = 0xffffffff << len; 67333965Sjdp mask = mask >> len; 67433965Sjdp mask = mask >> r.ebit; 67533965Sjdp mask = mask << r.ebit; 67633965Sjdp 67733965Sjdp aval = (rval << r.ebit) & mask; 67833965Sjdp return aval; 67933965Sjdp} 68033965Sjdp 68133965Sjdp/* Calculate relative value given the absolute value and bit position range 68233965Sjdp * within the instruction. */ 68333965Sjdp 68477298Sobrienstatic unsigned long 68533965Sjdpextract_range (unsigned long aval, struct itbl_range r) 68633965Sjdp{ 68733965Sjdp unsigned long mask; 68833965Sjdp unsigned long rval; 68933965Sjdp int len = MAX_BITPOS - r.sbit; 69033965Sjdp 69133965Sjdp /* create mask by truncating 1s by shifting */ 69233965Sjdp mask = 0xffffffff << len; 69333965Sjdp mask = mask >> len; 69433965Sjdp mask = mask >> r.ebit; 69533965Sjdp mask = mask << r.ebit; 69633965Sjdp 69733965Sjdp rval = (aval & mask) >> r.ebit; 69833965Sjdp return rval; 69933965Sjdp} 70033965Sjdp 70133965Sjdp/* Extract processor's assembly instruction field name from s; 70233965Sjdp * forms are "n args" "n,args" or "n" */ 70333965Sjdp/* Return next argument from string pointer "s" and advance s. 70460484Sobrien * delimiters are " ,()" */ 70533965Sjdp 70633965Sjdpchar * 70733965Sjdpitbl_get_field (char **S) 70833965Sjdp{ 70933965Sjdp static char n[128]; 71060484Sobrien char *s; 71133965Sjdp int len; 71233965Sjdp 71333965Sjdp s = *S; 71433965Sjdp if (!s || !*s) 71533965Sjdp return 0; 71660484Sobrien /* FIXME: This is a weird set of delimiters. */ 71760484Sobrien len = strcspn (s, " \t,()"); 71833965Sjdp ASSERT (128 > len + 1); 71933965Sjdp strncpy (n, s, len); 72033965Sjdp n[len] = 0; 72133965Sjdp if (s[len] == '\0') 72233965Sjdp s = 0; /* no more args */ 72333965Sjdp else 72433965Sjdp s += len + 1; /* advance to next arg */ 72533965Sjdp 72633965Sjdp *S = s; 72733965Sjdp return n; 72833965Sjdp} 72933965Sjdp 73033965Sjdp/* Search entries for a given processor and type 73133965Sjdp * to find one matching the name "n". 73233965Sjdp * Return a pointer to the entry */ 73333965Sjdp 73433965Sjdpstatic struct itbl_entry * 73533965Sjdpfind_entry_byname (e_processor processor, 73633965Sjdp e_type type, char *n) 73733965Sjdp{ 73833965Sjdp struct itbl_entry *e, **es; 73933965Sjdp 74033965Sjdp es = get_entries (processor, type); 74177298Sobrien for (e = *es; e; e = e->next) /* for each entry, ... */ 74233965Sjdp { 74333965Sjdp if (!strcmp (e->name, n)) 74433965Sjdp return e; 74533965Sjdp } 74633965Sjdp return 0; 74733965Sjdp} 74833965Sjdp 74933965Sjdp/* Search entries for a given processor and type 75033965Sjdp * to find one matching the value "val" for the range "r". 75133965Sjdp * Return a pointer to the entry. 75233965Sjdp * This function is used for disassembling fields of an instruction. 75333965Sjdp */ 75433965Sjdp 75533965Sjdpstatic struct itbl_entry * 75633965Sjdpfind_entry_byval (e_processor processor, e_type type, 75733965Sjdp unsigned long val, struct itbl_range *r) 75833965Sjdp{ 75933965Sjdp struct itbl_entry *e, **es; 76033965Sjdp unsigned long eval; 76133965Sjdp 76233965Sjdp es = get_entries (processor, type); 76377298Sobrien for (e = *es; e; e = e->next) /* for each entry, ... */ 76433965Sjdp { 76533965Sjdp if (processor != e->processor) 76633965Sjdp continue; 76733965Sjdp /* For insns, we might not know the range of the opcode, 76833965Sjdp * so a range of 0 will allow this routine to match against 76933965Sjdp * the range of the entry to be compared with. 77033965Sjdp * This could cause ambiguities. 77133965Sjdp * For operands, we get an extracted value and a range. 77233965Sjdp */ 77377298Sobrien /* if range is 0, mask val against the range of the compared entry. */ 77433965Sjdp if (r == 0) /* if no range passed, must be whole 32-bits 77533965Sjdp * so create 32-bit value from entry's range */ 77633965Sjdp { 77733965Sjdp eval = apply_range (e->value, e->range); 77833965Sjdp val &= apply_range (0xffffffff, e->range); 77933965Sjdp } 78060484Sobrien else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit) 78160484Sobrien || (e->range.sbit == 0 && e->range.ebit == 0)) 78233965Sjdp { 78333965Sjdp eval = apply_range (e->value, *r); 78433965Sjdp val = apply_range (val, *r); 78533965Sjdp } 78633965Sjdp else 78733965Sjdp continue; 78833965Sjdp if (val == eval) 78933965Sjdp return e; 79033965Sjdp } 79133965Sjdp return 0; 79233965Sjdp} 79333965Sjdp 79477298Sobrien/* Return a pointer to the list of entries for a given processor and type. */ 79533965Sjdp 79633965Sjdpstatic struct itbl_entry ** 79733965Sjdpget_entries (e_processor processor, e_type type) 79833965Sjdp{ 79933965Sjdp return &entries[processor][type]; 80033965Sjdp} 80133965Sjdp 80277298Sobrien/* Return an integral value for the processor passed from yyparse. */ 80333965Sjdp 80477298Sobrienstatic e_processor 80533965Sjdpget_processor (int yyproc) 80633965Sjdp{ 80733965Sjdp /* translate from yacc's processor to enum */ 80833965Sjdp if (yyproc >= e_p0 && yyproc < e_nprocs) 80933965Sjdp return (e_processor) yyproc; 81033965Sjdp return e_invproc; /* error; invalid processor */ 81133965Sjdp} 81233965Sjdp 81377298Sobrien/* Return an integral value for the entry type passed from yyparse. */ 81433965Sjdp 81577298Sobrienstatic e_type 81633965Sjdpget_type (int yytype) 81733965Sjdp{ 81833965Sjdp switch (yytype) 81933965Sjdp { 82033965Sjdp /* translate from yacc's type to enum */ 82133965Sjdp case INSN: 82233965Sjdp return e_insn; 82333965Sjdp case DREG: 82433965Sjdp return e_dreg; 82533965Sjdp case CREG: 82633965Sjdp return e_creg; 82733965Sjdp case GREG: 82833965Sjdp return e_greg; 82933965Sjdp case ADDR: 83033965Sjdp return e_addr; 83133965Sjdp case IMMED: 83233965Sjdp return e_immed; 83333965Sjdp default: 83433965Sjdp return e_invtype; /* error; invalid type */ 83533965Sjdp } 83633965Sjdp} 83733965Sjdp 83833965Sjdp/* Allocate and initialize an entry */ 83933965Sjdp 84033965Sjdpstatic struct itbl_entry * 84133965Sjdpalloc_entry (e_processor processor, e_type type, 84233965Sjdp char *name, unsigned long value) 84333965Sjdp{ 84433965Sjdp struct itbl_entry *e, **es; 84533965Sjdp if (!name) 84633965Sjdp return 0; 84733965Sjdp e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry)); 84833965Sjdp if (e) 84933965Sjdp { 85033965Sjdp memset (e, 0, sizeof (struct itbl_entry)); 85133965Sjdp e->name = (char *) malloc (sizeof (strlen (name)) + 1); 85233965Sjdp if (e->name) 85333965Sjdp strcpy (e->name, name); 85433965Sjdp e->processor = processor; 85533965Sjdp e->type = type; 85633965Sjdp e->value = value; 85733965Sjdp es = get_entries (e->processor, e->type); 85833965Sjdp e->next = *es; 85933965Sjdp *es = e; 86033965Sjdp } 86133965Sjdp return e; 86233965Sjdp} 86333965Sjdp 86433965Sjdp/* Allocate and initialize an entry's field */ 86533965Sjdp 86633965Sjdpstatic struct itbl_field * 86733965Sjdpalloc_field (e_type type, int sbit, int ebit, 86833965Sjdp unsigned long flags) 86933965Sjdp{ 87033965Sjdp struct itbl_field *f; 87133965Sjdp f = (struct itbl_field *) malloc (sizeof (struct itbl_field)); 87233965Sjdp if (f) 87333965Sjdp { 87433965Sjdp memset (f, 0, sizeof (struct itbl_field)); 87533965Sjdp f->type = type; 87633965Sjdp f->range.sbit = sbit; 87733965Sjdp f->range.ebit = ebit; 87833965Sjdp f->flags = flags; 87933965Sjdp } 88033965Sjdp return f; 88133965Sjdp} 882