itbl-ops.c revision 60484
133965Sjdp/* itbl-ops.c 260484Sobrien Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. 333965Sjdp 433965Sjdp This file is part of GAS, the GNU Assembler. 533965Sjdp 633965Sjdp GAS is free software; you can redistribute it and/or modify 733965Sjdp it under the terms of the GNU General Public License as published by 833965Sjdp the Free Software Foundation; either version 2, or (at your option) 933965Sjdp any later version. 1033965Sjdp 1133965Sjdp GAS is distributed in the hope that it will be useful, 1233965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1333965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1433965Sjdp GNU General Public License for more details. 1533965Sjdp 1633965Sjdp You should have received a copy of the GNU General Public License 1733965Sjdp along with GAS; see the file COPYING. If not, write to the Free 1833965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 1933965Sjdp 02111-1307, USA. */ 2033965Sjdp 2133965Sjdp/*======================================================================*/ 2233965Sjdp/* 2333965Sjdp * Herein lies the support for dynamic specification of processor 2433965Sjdp * instructions and registers. Mnemonics, values, and formats for each 2533965Sjdp * instruction and register are specified in an ascii file consisting of 2633965Sjdp * table entries. The grammar for the table is defined in the document 2733965Sjdp * "Processor instruction table specification". 2833965Sjdp * 2933965Sjdp * Instructions use the gnu assembler syntax, with the addition of 3033965Sjdp * allowing mnemonics for register. 3133965Sjdp * Eg. "func $2,reg3,0x100,symbol ; comment" 3233965Sjdp * func - opcode name 3333965Sjdp * $n - register n 3433965Sjdp * reg3 - mnemonic for processor's register defined in table 3533965Sjdp * 0xddd..d - immediate value 3633965Sjdp * symbol - address of label or external symbol 3733965Sjdp * 3833965Sjdp * First, itbl_parse reads in the table of register and instruction 3933965Sjdp * names and formats, and builds a list of entries for each 4033965Sjdp * processor/type combination. lex and yacc are used to parse 4133965Sjdp * the entries in the table and call functions defined here to 4233965Sjdp * add each entry to our list. 4333965Sjdp * 4433965Sjdp * Then, when assembling or disassembling, these functions are called to 4533965Sjdp * 1) get information on a processor's registers and 4633965Sjdp * 2) assemble/disassemble an instruction. 4733965Sjdp * To assemble(disassemble) an instruction, the function 4833965Sjdp * itbl_assemble(itbl_disassemble) is called to search the list of 4933965Sjdp * instruction entries, and if a match is found, uses the format 5033965Sjdp * described in the instruction entry structure to complete the action. 5133965Sjdp * 5233965Sjdp * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2" 5333965Sjdp * and we want to define function "pig" which takes two operands. 5433965Sjdp * 5533965Sjdp * Given the table entries: 5633965Sjdp * "p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0" 5733965Sjdp * "p3 dreg d2 0x2" 5833965Sjdp * and that the instruction encoding for coprocessor pz has encoding: 5933965Sjdp * #define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25) 6033965Sjdp * #define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum) 6133965Sjdp * 6233965Sjdp * a structure to describe the instruction might look something like: 6333965Sjdp * struct itbl_entry = { 6433965Sjdp * e_processor processor = e_p3 6533965Sjdp * e_type type = e_insn 6633965Sjdp * char *name = "pig" 6733965Sjdp * uint value = 0x1 6833965Sjdp * uint flags = 0 6933965Sjdp * struct itbl_range range = 24-21 7033965Sjdp * struct itbl_field *field = { 7133965Sjdp * e_type type = e_dreg 7233965Sjdp * struct itbl_range range = 20-16 7333965Sjdp * struct itbl_field *next = { 7433965Sjdp * e_type type = e_immed 7533965Sjdp * struct itbl_range range = 15-0 7633965Sjdp * struct itbl_field *next = 0 7733965Sjdp * }; 7833965Sjdp * }; 7933965Sjdp * struct itbl_entry *next = 0 8033965Sjdp * }; 8133965Sjdp * 8233965Sjdp * And the assembler instructions: 8333965Sjdp * "pig d2,0x100" 8433965Sjdp * "pig $2,0x100" 8533965Sjdp * 8633965Sjdp * would both assemble to the hex value: 8733965Sjdp * "0x4e220100" 8833965Sjdp * 8933965Sjdp */ 9033965Sjdp 9133965Sjdp#include <stdio.h> 9233965Sjdp#include <stdlib.h> 9333965Sjdp#include <string.h> 9433965Sjdp#include "itbl-ops.h" 9533965Sjdp#include "itbl-parse.h" 9633965Sjdp 9733965Sjdp/* #define DEBUG */ 9833965Sjdp 9933965Sjdp#ifdef DEBUG 10033965Sjdp#include <assert.h> 10133965Sjdp#define ASSERT(x) assert(x) 10233965Sjdp#define DBG(x) printf x 10333965Sjdp#else 10433965Sjdp#define ASSERT(x) 10533965Sjdp#define DBG(x) 10633965Sjdp#endif 10733965Sjdp 10833965Sjdp#ifndef min 10933965Sjdp#define min(a,b) (a<b?a:b) 11033965Sjdp#endif 11133965Sjdp 11233965Sjdpint itbl_have_entries = 0; 11333965Sjdp 11433965Sjdp/*======================================================================*/ 11533965Sjdp/* structures for keeping itbl format entries */ 11633965Sjdp 11733965Sjdpstruct itbl_range 11833965Sjdp { 11933965Sjdp int sbit; /* mask starting bit position */ 12033965Sjdp int ebit; /* mask ending bit position */ 12133965Sjdp }; 12233965Sjdp 12333965Sjdpstruct itbl_field 12433965Sjdp { 12533965Sjdp e_type type; /* dreg/creg/greg/immed/symb */ 12633965Sjdp struct itbl_range range; /* field's bitfield range within instruction */ 12733965Sjdp unsigned long flags; /* field flags */ 12833965Sjdp struct itbl_field *next; /* next field in list */ 12933965Sjdp }; 13033965Sjdp 13133965Sjdp 13233965Sjdp/* These structures define the instructions and registers for a processor. 13333965Sjdp * If the type is an instruction, the structure defines the format of an 13433965Sjdp * instruction where the fields are the list of operands. 13533965Sjdp * The flags field below uses the same values as those defined in the 13633965Sjdp * gnu assembler and are machine specific. */ 13733965Sjdpstruct itbl_entry 13833965Sjdp { 13933965Sjdp e_processor processor; /* processor number */ 14033965Sjdp e_type type; /* dreg/creg/greg/insn */ 14133965Sjdp char *name; /* mnemionic name for insn/register */ 14233965Sjdp unsigned long value; /* opcode/instruction mask/register number */ 14333965Sjdp unsigned long flags; /* effects of the instruction */ 14433965Sjdp struct itbl_range range; /* bit range within instruction for value */ 14533965Sjdp struct itbl_field *fields; /* list of operand definitions (if any) */ 14633965Sjdp struct itbl_entry *next; /* next entry */ 14733965Sjdp }; 14833965Sjdp 14933965Sjdp 15033965Sjdp/* local data and structures */ 15133965Sjdp 15233965Sjdpstatic int itbl_num_opcodes = 0; 15333965Sjdp/* Array of entries for each processor and entry type */ 15433965Sjdpstatic struct itbl_entry *entries[e_nprocs][e_ntypes] = 15533965Sjdp{ 15633965Sjdp {0, 0, 0, 0, 0, 0}, 15733965Sjdp {0, 0, 0, 0, 0, 0}, 15833965Sjdp {0, 0, 0, 0, 0, 0}, 15933965Sjdp {0, 0, 0, 0, 0, 0} 16033965Sjdp}; 16133965Sjdp 16233965Sjdp/* local prototypes */ 16333965Sjdpstatic unsigned long build_opcode PARAMS ((struct itbl_entry *e)); 16433965Sjdpstatic e_type get_type PARAMS ((int yytype)); 16533965Sjdpstatic e_processor get_processor PARAMS ((int yyproc)); 16633965Sjdpstatic struct itbl_entry **get_entries PARAMS ((e_processor processor, 16733965Sjdp e_type type)); 16833965Sjdpstatic struct itbl_entry *find_entry_byname PARAMS ((e_processor processor, 16933965Sjdp e_type type, char *name)); 17033965Sjdpstatic struct itbl_entry *find_entry_byval PARAMS ((e_processor processor, 17133965Sjdp e_type type, unsigned long val, struct itbl_range *r)); 17233965Sjdpstatic struct itbl_entry *alloc_entry PARAMS ((e_processor processor, 17333965Sjdp e_type type, char *name, unsigned long value)); 17433965Sjdpstatic unsigned long apply_range PARAMS ((unsigned long value, 17533965Sjdp struct itbl_range r)); 17633965Sjdpstatic unsigned long extract_range PARAMS ((unsigned long value, 17733965Sjdp struct itbl_range r)); 17833965Sjdpstatic struct itbl_field *alloc_field PARAMS ((e_type type, int sbit, 17933965Sjdp int ebit, unsigned long flags)); 18033965Sjdp 18133965Sjdp 18233965Sjdp/*======================================================================*/ 18333965Sjdp/* Interfaces to the parser */ 18433965Sjdp 18533965Sjdp 18633965Sjdp/* Open the table and use lex and yacc to parse the entries. 18733965Sjdp * Return 1 for failure; 0 for success. */ 18833965Sjdp 18933965Sjdpint 19033965Sjdpitbl_parse (char *insntbl) 19133965Sjdp{ 19233965Sjdp extern FILE *yyin; 19333965Sjdp extern int yyparse (void); 19433965Sjdp yyin = fopen (insntbl, "r"); 19533965Sjdp if (yyin == 0) 19633965Sjdp { 19733965Sjdp printf ("Can't open processor instruction specification file \"%s\"\n", 19833965Sjdp insntbl); 19933965Sjdp return 1; 20033965Sjdp } 20133965Sjdp else 20233965Sjdp { 20333965Sjdp while (yyparse ()); 20433965Sjdp } 20533965Sjdp fclose (yyin); 20633965Sjdp itbl_have_entries = 1; 20733965Sjdp return 0; 20833965Sjdp} 20933965Sjdp 21033965Sjdp/* Add a register entry */ 21133965Sjdp 21233965Sjdpstruct itbl_entry * 21333965Sjdpitbl_add_reg (int yyprocessor, int yytype, char *regname, 21433965Sjdp int regnum) 21533965Sjdp{ 21633965Sjdp#if 0 21733965Sjdp#include "as.h" 21833965Sjdp#include "symbols.h" 21933965Sjdp /* Since register names don't have a prefix, we put them in the symbol table so 22033965Sjdp they can't be used as symbols. This also simplifies argument parsing as 22133965Sjdp we can let gas parse registers for us. The recorded register number is 22233965Sjdp regnum. */ 22333965Sjdp /* Use symbol_create here instead of symbol_new so we don't try to 22433965Sjdp output registers into the object file's symbol table. */ 22533965Sjdp symbol_table_insert (symbol_create (regname, reg_section, 22633965Sjdp regnum, &zero_address_frag)); 22733965Sjdp#endif 22833965Sjdp return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname, 22933965Sjdp (unsigned long) regnum); 23033965Sjdp} 23133965Sjdp 23233965Sjdp/* Add an instruction entry */ 23333965Sjdp 23433965Sjdpstruct itbl_entry * 23533965Sjdpitbl_add_insn (int yyprocessor, char *name, unsigned long value, 23633965Sjdp int sbit, int ebit, unsigned long flags) 23733965Sjdp{ 23833965Sjdp struct itbl_entry *e; 23933965Sjdp e = alloc_entry (get_processor (yyprocessor), e_insn, name, value); 24033965Sjdp if (e) 24133965Sjdp { 24233965Sjdp e->range.sbit = sbit; 24333965Sjdp e->range.ebit = ebit; 24433965Sjdp e->flags = flags; 24533965Sjdp itbl_num_opcodes++; 24633965Sjdp } 24733965Sjdp return e; 24833965Sjdp} 24933965Sjdp 25033965Sjdp/* Add an operand to an instruction entry */ 25133965Sjdp 25233965Sjdpstruct itbl_field * 25333965Sjdpitbl_add_operand (struct itbl_entry *e, int yytype, int sbit, 25433965Sjdp int ebit, unsigned long flags) 25533965Sjdp{ 25633965Sjdp struct itbl_field *f, **last_f; 25733965Sjdp if (!e) 25833965Sjdp return 0; 25933965Sjdp /* Add to end of fields' list. */ 26033965Sjdp f = alloc_field (get_type (yytype), sbit, ebit, flags); 26133965Sjdp if (f) 26233965Sjdp { 26333965Sjdp last_f = &e->fields; 26433965Sjdp while (*last_f) 26533965Sjdp last_f = &(*last_f)->next; 26633965Sjdp *last_f = f; 26733965Sjdp f->next = 0; 26833965Sjdp } 26933965Sjdp return f; 27033965Sjdp} 27133965Sjdp 27233965Sjdp 27333965Sjdp/*======================================================================*/ 27433965Sjdp/* Interfaces for assembler and disassembler */ 27533965Sjdp 27633965Sjdp#ifndef STAND_ALONE 27733965Sjdp#include "as.h" 27833965Sjdp#include "symbols.h" 27933965Sjdpstatic void append_insns_as_macros (void); 28033965Sjdp 28133965Sjdp/* initialize for gas */ 28233965Sjdpvoid 28333965Sjdpitbl_init (void) 28433965Sjdp{ 28533965Sjdp struct itbl_entry *e, **es; 28633965Sjdp e_processor procn; 28733965Sjdp e_type type; 28833965Sjdp 28933965Sjdp if (!itbl_have_entries) 29033965Sjdp return; 29133965Sjdp 29233965Sjdp /* Since register names don't have a prefix, put them in the symbol table so 29333965Sjdp they can't be used as symbols. This simplifies argument parsing as 29433965Sjdp we can let gas parse registers for us. */ 29533965Sjdp /* Use symbol_create instead of symbol_new so we don't try to 29633965Sjdp output registers into the object file's symbol table. */ 29733965Sjdp 29833965Sjdp for (type = e_regtype0; type < e_nregtypes; type++) 29933965Sjdp for (procn = e_p0; procn < e_nprocs; procn++) 30033965Sjdp { 30133965Sjdp es = get_entries (procn, type); 30233965Sjdp for (e = *es; e; e = e->next) 30333965Sjdp { 30433965Sjdp symbol_table_insert (symbol_create (e->name, reg_section, 30533965Sjdp e->value, &zero_address_frag)); 30633965Sjdp } 30733965Sjdp } 30833965Sjdp append_insns_as_macros (); 30933965Sjdp} 31033965Sjdp 31133965Sjdp 31233965Sjdp/* Append insns to opcodes table and increase number of opcodes 31333965Sjdp * Structure of opcodes table: 31433965Sjdp * struct itbl_opcode 31533965Sjdp * { 31633965Sjdp * const char *name; 31733965Sjdp * const char *args; - string describing the arguments. 31833965Sjdp * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO 31933965Sjdp * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO 32033965Sjdp * unsigned long pinfo; - insn flags, or INSN_MACRO 32133965Sjdp * }; 32233965Sjdp * examples: 32333965Sjdp * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, 32433965Sjdp * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, 32533965Sjdp */ 32633965Sjdp 32733965Sjdpstatic char *form_args (struct itbl_entry *e); 32833965Sjdpstatic void 32933965Sjdpappend_insns_as_macros (void) 33033965Sjdp{ 33133965Sjdp struct ITBL_OPCODE_STRUCT *new_opcodes, *o; 33233965Sjdp struct itbl_entry *e, **es; 33333965Sjdp int n, id, size, new_size, new_num_opcodes; 33433965Sjdp 33533965Sjdp if (!itbl_have_entries) 33633965Sjdp return; 33733965Sjdp 33833965Sjdp if (!itbl_num_opcodes) /* no new instructions to add! */ 33933965Sjdp { 34033965Sjdp return; 34133965Sjdp } 34233965Sjdp DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES)); 34333965Sjdp 34433965Sjdp new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes; 34533965Sjdp ASSERT (new_num_opcodes >= itbl_num_opcodes); 34633965Sjdp 34733965Sjdp size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES; 34833965Sjdp ASSERT (size >= 0); 34933965Sjdp DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0]))); 35033965Sjdp 35133965Sjdp new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes; 35233965Sjdp ASSERT (new_size > size); 35333965Sjdp 35433965Sjdp /* FIXME since ITBL_OPCODES culd be a static table, 35533965Sjdp we can't realloc or delete the old memory. */ 35633965Sjdp new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size); 35733965Sjdp if (!new_opcodes) 35833965Sjdp { 35960484Sobrien printf (_("Unable to allocate memory for new instructions\n")); 36033965Sjdp return; 36133965Sjdp } 36233965Sjdp if (size) /* copy prexisting opcodes table */ 36333965Sjdp memcpy (new_opcodes, ITBL_OPCODES, size); 36433965Sjdp 36533965Sjdp /* FIXME! some NUMOPCODES are calculated expressions. 36633965Sjdp These need to be changed before itbls can be supported. */ 36733965Sjdp 36833965Sjdp id = ITBL_NUM_MACROS; /* begin the next macro id after the last */ 36933965Sjdp o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */ 37033965Sjdp for (n = e_p0; n < e_nprocs; n++) 37133965Sjdp { 37233965Sjdp es = get_entries (n, e_insn); 37333965Sjdp for (e = *es; e; e = e->next) 37433965Sjdp { 37533965Sjdp /* name, args, mask, match, pinfo 37633965Sjdp * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, 37733965Sjdp * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, 37833965Sjdp * Construct args from itbl_fields. 37933965Sjdp */ 38033965Sjdp o->name = e->name; 38133965Sjdp o->args = strdup (form_args (e)); 38233965Sjdp o->mask = apply_range (e->value, e->range); 38333965Sjdp /* FIXME how to catch durring assembly? */ 38433965Sjdp /* mask to identify this insn */ 38533965Sjdp o->match = apply_range (e->value, e->range); 38633965Sjdp o->pinfo = 0; 38733965Sjdp 38833965Sjdp#ifdef USE_MACROS 38933965Sjdp o->mask = id++; /* FIXME how to catch durring assembly? */ 39033965Sjdp o->match = 0; /* for macros, the insn_isa number */ 39133965Sjdp o->pinfo = INSN_MACRO; 39233965Sjdp#endif 39333965Sjdp 39433965Sjdp /* Don't add instructions which caused an error */ 39533965Sjdp if (o->args) 39633965Sjdp o++; 39733965Sjdp else 39833965Sjdp new_num_opcodes--; 39933965Sjdp } 40033965Sjdp } 40133965Sjdp ITBL_OPCODES = new_opcodes; 40233965Sjdp ITBL_NUM_OPCODES = new_num_opcodes; 40333965Sjdp 40433965Sjdp /* FIXME 40533965Sjdp At this point, we can free the entries, as they should have 40633965Sjdp been added to the assembler's tables. 40733965Sjdp Don't free name though, since name is being used by the new 40833965Sjdp opcodes table. 40933965Sjdp 41033965Sjdp Eventually, we should also free the new opcodes table itself 41133965Sjdp on exit. 41233965Sjdp */ 41333965Sjdp} 41433965Sjdp 41533965Sjdpstatic char * 41633965Sjdpform_args (struct itbl_entry *e) 41733965Sjdp{ 41833965Sjdp static char s[31]; 41933965Sjdp char c = 0, *p = s; 42033965Sjdp struct itbl_field *f; 42133965Sjdp 42233965Sjdp ASSERT (e); 42333965Sjdp for (f = e->fields; f; f = f->next) 42433965Sjdp { 42533965Sjdp switch (f->type) 42633965Sjdp { 42733965Sjdp case e_dreg: 42833965Sjdp c = 'd'; 42933965Sjdp break; 43033965Sjdp case e_creg: 43133965Sjdp c = 't'; 43233965Sjdp break; 43333965Sjdp case e_greg: 43433965Sjdp c = 's'; 43533965Sjdp break; 43633965Sjdp case e_immed: 43733965Sjdp c = 'i'; 43833965Sjdp break; 43933965Sjdp case e_addr: 44033965Sjdp c = 'a'; 44133965Sjdp break; 44233965Sjdp default: 44333965Sjdp c = 0; /* ignore; unknown field type */ 44433965Sjdp } 44533965Sjdp if (c) 44633965Sjdp { 44733965Sjdp if (p != s) 44833965Sjdp *p++ = ','; 44933965Sjdp *p++ = c; 45033965Sjdp } 45133965Sjdp } 45233965Sjdp *p = 0; 45333965Sjdp return s; 45433965Sjdp} 45533965Sjdp#endif /* !STAND_ALONE */ 45633965Sjdp 45733965Sjdp 45833965Sjdp/* Get processor's register name from val */ 45933965Sjdp 46060484Sobrienint 46160484Sobrienitbl_get_reg_val (char *name, unsigned long *pval) 46233965Sjdp{ 46333965Sjdp e_type t; 46433965Sjdp e_processor p; 46560484Sobrien 46633965Sjdp for (p = e_p0; p < e_nprocs; p++) 46760484Sobrien { 46860484Sobrien for (t = e_regtype0; t < e_nregtypes; t++) 46960484Sobrien { 47060484Sobrien if (itbl_get_val (p, t, name, pval)) 47160484Sobrien return 1; 47260484Sobrien } 47360484Sobrien } 47433965Sjdp return 0; 47533965Sjdp} 47633965Sjdp 47733965Sjdpchar * 47833965Sjdpitbl_get_name (e_processor processor, e_type type, unsigned long val) 47933965Sjdp{ 48033965Sjdp struct itbl_entry *r; 48133965Sjdp /* type depends on instruction passed */ 48233965Sjdp r = find_entry_byval (processor, type, val, 0); 48333965Sjdp if (r) 48433965Sjdp return r->name; 48533965Sjdp else 48633965Sjdp return 0; /* error; invalid operand */ 48733965Sjdp} 48833965Sjdp 48933965Sjdp/* Get processor's register value from name */ 49033965Sjdp 49160484Sobrienint 49260484Sobrienitbl_get_val (e_processor processor, e_type type, char *name, 49360484Sobrien unsigned long *pval) 49433965Sjdp{ 49533965Sjdp struct itbl_entry *r; 49633965Sjdp /* type depends on instruction passed */ 49733965Sjdp r = find_entry_byname (processor, type, name); 49860484Sobrien if (r == NULL) 49960484Sobrien return 0; 50060484Sobrien *pval = r->value; 50160484Sobrien return 1; 50233965Sjdp} 50333965Sjdp 50433965Sjdp 50533965Sjdp/* Assemble instruction "name" with operands "s". 50633965Sjdp * name - name of instruction 50733965Sjdp * s - operands 50833965Sjdp * returns - long word for assembled instruction */ 50933965Sjdp 51033965Sjdpunsigned long 51133965Sjdpitbl_assemble (char *name, char *s) 51233965Sjdp{ 51333965Sjdp unsigned long opcode; 51433965Sjdp struct itbl_entry *e; 51533965Sjdp struct itbl_field *f; 51633965Sjdp char *n; 51733965Sjdp int processor; 51833965Sjdp 51933965Sjdp if (!name || !*name) 52033965Sjdp return 0; /* error! must have a opcode name/expr */ 52133965Sjdp 52233965Sjdp /* find entry in list of instructions for all processors */ 52333965Sjdp for (processor = 0; processor < e_nprocs; processor++) 52433965Sjdp { 52533965Sjdp e = find_entry_byname (processor, e_insn, name); 52633965Sjdp if (e) 52733965Sjdp break; 52833965Sjdp } 52933965Sjdp if (!e) 53033965Sjdp return 0; /* opcode not in table; invalid instrustion */ 53133965Sjdp opcode = build_opcode (e); 53233965Sjdp 53333965Sjdp /* parse opcode's args (if any) */ 53433965Sjdp for (f = e->fields; f; f = f->next) /* for each arg, ... */ 53533965Sjdp { 53633965Sjdp struct itbl_entry *r; 53733965Sjdp unsigned long value; 53833965Sjdp if (!s || !*s) 53933965Sjdp return 0; /* error - not enough operands */ 54033965Sjdp n = itbl_get_field (&s); 54133965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 54233965Sjdp switch (f->type) 54333965Sjdp { 54433965Sjdp case e_dreg: 54533965Sjdp case e_creg: 54633965Sjdp case e_greg: 54733965Sjdp /* Accept either a string name 54833965Sjdp * or '$' followed by the register number */ 54933965Sjdp if (*n == '$') 55033965Sjdp { 55133965Sjdp n++; 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 else 55833965Sjdp { 55933965Sjdp r = find_entry_byname (e->processor, f->type, n); 56033965Sjdp if (r) 56133965Sjdp value = r->value; 56233965Sjdp else 56333965Sjdp return 0; /* error; invalid operand */ 56433965Sjdp } 56533965Sjdp break; 56633965Sjdp case e_addr: 56733965Sjdp /* use assembler's symbol table to find symbol */ 56833965Sjdp /* FIXME!! Do we need this? 56933965Sjdp if so, what about relocs?? 57033965Sjdp my_getExpression (&imm_expr, s); 57133965Sjdp return 0; /-* error; invalid operand *-/ 57233965Sjdp break; 57333965Sjdp */ 57433965Sjdp /* If not a symbol, fall thru to IMMED */ 57533965Sjdp case e_immed: 57633965Sjdp if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ 57733965Sjdp { 57833965Sjdp n += 2; 57933965Sjdp value = strtol (n, 0, 16); 58033965Sjdp /* FIXME! could have "0xl"... then what?? */ 58133965Sjdp } 58233965Sjdp else 58333965Sjdp { 58433965Sjdp value = strtol (n, 0, 10); 58533965Sjdp /* FIXME! could have "0l"... then what?? */ 58633965Sjdp if (value == 0 && *n != '0') 58733965Sjdp return 0; /* error; invalid operand */ 58833965Sjdp } 58933965Sjdp break; 59033965Sjdp default: 59133965Sjdp return 0; /* error; invalid field spec */ 59233965Sjdp } 59333965Sjdp opcode |= apply_range (value, f->range); 59433965Sjdp } 59533965Sjdp if (s && *s) 59633965Sjdp return 0; /* error - too many operands */ 59733965Sjdp return opcode; /* done! */ 59833965Sjdp} 59933965Sjdp 60033965Sjdp/* Disassemble instruction "insn". 60133965Sjdp * insn - instruction 60233965Sjdp * s - buffer to hold disassembled instruction 60333965Sjdp * returns - 1 if succeeded; 0 if failed 60433965Sjdp */ 60533965Sjdp 60633965Sjdpint 60733965Sjdpitbl_disassemble (char *s, unsigned long insn) 60833965Sjdp{ 60933965Sjdp e_processor processor; 61033965Sjdp struct itbl_entry *e; 61133965Sjdp struct itbl_field *f; 61233965Sjdp 61333965Sjdp if (!ITBL_IS_INSN (insn)) 61433965Sjdp return 0; /* error*/ 61533965Sjdp processor = get_processor (ITBL_DECODE_PNUM (insn)); 61633965Sjdp 61733965Sjdp /* find entry in list */ 61833965Sjdp e = find_entry_byval (processor, e_insn, insn, 0); 61933965Sjdp if (!e) 62033965Sjdp return 0; /* opcode not in table; invalid instrustion */ 62133965Sjdp strcpy (s, e->name); 62233965Sjdp 62333965Sjdp /* parse insn's args (if any) */ 62433965Sjdp for (f = e->fields; f; f = f->next) /* for each arg, ... */ 62533965Sjdp { 62633965Sjdp struct itbl_entry *r; 62733965Sjdp unsigned long value; 62833965Sjdp 62933965Sjdp if (f == e->fields) /* first operand is preceeded by tab */ 63033965Sjdp strcat (s, "\t"); 63133965Sjdp else /* ','s separate following operands */ 63233965Sjdp strcat (s, ","); 63333965Sjdp value = extract_range (insn, f->range); 63433965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 63533965Sjdp switch (f->type) 63633965Sjdp { 63733965Sjdp case e_dreg: 63833965Sjdp case e_creg: 63933965Sjdp case e_greg: 64033965Sjdp /* Accept either a string name 64133965Sjdp * or '$' followed by the register number */ 64233965Sjdp r = find_entry_byval (e->processor, f->type, value, &f->range); 64333965Sjdp if (r) 64433965Sjdp strcat (s, r->name); 64533965Sjdp else 64660484Sobrien sprintf (s, "%s$%lu", s, value); 64733965Sjdp break; 64833965Sjdp case e_addr: 64933965Sjdp /* use assembler's symbol table to find symbol */ 65033965Sjdp /* FIXME!! Do we need this? 65133965Sjdp * if so, what about relocs?? 65233965Sjdp */ 65333965Sjdp /* If not a symbol, fall thru to IMMED */ 65433965Sjdp case e_immed: 65560484Sobrien sprintf (s, "%s0x%lx", s, value); 65633965Sjdp break; 65733965Sjdp default: 65833965Sjdp return 0; /* error; invalid field spec */ 65933965Sjdp } 66033965Sjdp } 66133965Sjdp return 1; /* done! */ 66233965Sjdp} 66333965Sjdp 66433965Sjdp/*======================================================================*/ 66533965Sjdp/* 66633965Sjdp * Local functions for manipulating private structures containing 66733965Sjdp * the names and format for the new instructions and registers 66833965Sjdp * for each processor. 66933965Sjdp */ 67033965Sjdp 67133965Sjdp/* Calculate instruction's opcode and function values from entry */ 67233965Sjdp 67333965Sjdpstatic unsigned long 67433965Sjdpbuild_opcode (struct itbl_entry *e) 67533965Sjdp{ 67633965Sjdp unsigned long opcode; 67733965Sjdp 67833965Sjdp opcode = apply_range (e->value, e->range); 67933965Sjdp opcode |= ITBL_ENCODE_PNUM (e->processor); 68033965Sjdp return opcode; 68133965Sjdp} 68233965Sjdp 68333965Sjdp/* Calculate absolute value given the relative value and bit position range 68433965Sjdp * within the instruction. 68533965Sjdp * The range is inclusive where 0 is least significant bit. 68633965Sjdp * A range of { 24, 20 } will have a mask of 68733965Sjdp * bit 3 2 1 68833965Sjdp * pos: 1098 7654 3210 9876 5432 1098 7654 3210 68933965Sjdp * bin: 0000 0001 1111 0000 0000 0000 0000 0000 69033965Sjdp * hex: 0 1 f 0 0 0 0 0 69133965Sjdp * mask: 0x01f00000. 69233965Sjdp */ 69333965Sjdp 69433965Sjdpstatic unsigned long 69533965Sjdpapply_range (unsigned long rval, struct itbl_range r) 69633965Sjdp{ 69733965Sjdp unsigned long mask; 69833965Sjdp unsigned long aval; 69933965Sjdp int len = MAX_BITPOS - r.sbit; 70033965Sjdp 70133965Sjdp ASSERT (r.sbit >= r.ebit); 70233965Sjdp ASSERT (MAX_BITPOS >= r.sbit); 70333965Sjdp ASSERT (r.ebit >= 0); 70433965Sjdp 70533965Sjdp /* create mask by truncating 1s by shifting */ 70633965Sjdp mask = 0xffffffff << len; 70733965Sjdp mask = mask >> len; 70833965Sjdp mask = mask >> r.ebit; 70933965Sjdp mask = mask << r.ebit; 71033965Sjdp 71133965Sjdp aval = (rval << r.ebit) & mask; 71233965Sjdp return aval; 71333965Sjdp} 71433965Sjdp 71533965Sjdp/* Calculate relative value given the absolute value and bit position range 71633965Sjdp * within the instruction. */ 71733965Sjdp 71833965Sjdpstatic unsigned long 71933965Sjdpextract_range (unsigned long aval, struct itbl_range r) 72033965Sjdp{ 72133965Sjdp unsigned long mask; 72233965Sjdp unsigned long rval; 72333965Sjdp int len = MAX_BITPOS - r.sbit; 72433965Sjdp 72533965Sjdp /* create mask by truncating 1s by shifting */ 72633965Sjdp mask = 0xffffffff << len; 72733965Sjdp mask = mask >> len; 72833965Sjdp mask = mask >> r.ebit; 72933965Sjdp mask = mask << r.ebit; 73033965Sjdp 73133965Sjdp rval = (aval & mask) >> r.ebit; 73233965Sjdp return rval; 73333965Sjdp} 73433965Sjdp 73533965Sjdp/* Extract processor's assembly instruction field name from s; 73633965Sjdp * forms are "n args" "n,args" or "n" */ 73733965Sjdp/* Return next argument from string pointer "s" and advance s. 73860484Sobrien * delimiters are " ,()" */ 73933965Sjdp 74033965Sjdpchar * 74133965Sjdpitbl_get_field (char **S) 74233965Sjdp{ 74333965Sjdp static char n[128]; 74460484Sobrien char *s; 74533965Sjdp int len; 74633965Sjdp 74733965Sjdp s = *S; 74833965Sjdp if (!s || !*s) 74933965Sjdp return 0; 75060484Sobrien /* FIXME: This is a weird set of delimiters. */ 75160484Sobrien len = strcspn (s, " \t,()"); 75233965Sjdp ASSERT (128 > len + 1); 75333965Sjdp strncpy (n, s, len); 75433965Sjdp n[len] = 0; 75533965Sjdp if (s[len] == '\0') 75633965Sjdp s = 0; /* no more args */ 75733965Sjdp else 75833965Sjdp s += len + 1; /* advance to next arg */ 75933965Sjdp 76033965Sjdp *S = s; 76133965Sjdp return n; 76233965Sjdp} 76333965Sjdp 76433965Sjdp/* Search entries for a given processor and type 76533965Sjdp * to find one matching the name "n". 76633965Sjdp * Return a pointer to the entry */ 76733965Sjdp 76833965Sjdpstatic struct itbl_entry * 76933965Sjdpfind_entry_byname (e_processor processor, 77033965Sjdp e_type type, char *n) 77133965Sjdp{ 77233965Sjdp struct itbl_entry *e, **es; 77333965Sjdp 77433965Sjdp es = get_entries (processor, type); 77533965Sjdp for (e = *es; e; e = e->next) /* for each entry, ... */ 77633965Sjdp { 77733965Sjdp if (!strcmp (e->name, n)) 77833965Sjdp return e; 77933965Sjdp } 78033965Sjdp return 0; 78133965Sjdp} 78233965Sjdp 78333965Sjdp/* Search entries for a given processor and type 78433965Sjdp * to find one matching the value "val" for the range "r". 78533965Sjdp * Return a pointer to the entry. 78633965Sjdp * This function is used for disassembling fields of an instruction. 78733965Sjdp */ 78833965Sjdp 78933965Sjdpstatic struct itbl_entry * 79033965Sjdpfind_entry_byval (e_processor processor, e_type type, 79133965Sjdp unsigned long val, struct itbl_range *r) 79233965Sjdp{ 79333965Sjdp struct itbl_entry *e, **es; 79433965Sjdp unsigned long eval; 79533965Sjdp 79633965Sjdp es = get_entries (processor, type); 79733965Sjdp for (e = *es; e; e = e->next) /* for each entry, ... */ 79833965Sjdp { 79933965Sjdp if (processor != e->processor) 80033965Sjdp continue; 80133965Sjdp /* For insns, we might not know the range of the opcode, 80233965Sjdp * so a range of 0 will allow this routine to match against 80333965Sjdp * the range of the entry to be compared with. 80433965Sjdp * This could cause ambiguities. 80533965Sjdp * For operands, we get an extracted value and a range. 80633965Sjdp */ 80733965Sjdp /* if range is 0, mask val against the range of the compared entry. */ 80833965Sjdp if (r == 0) /* if no range passed, must be whole 32-bits 80933965Sjdp * so create 32-bit value from entry's range */ 81033965Sjdp { 81133965Sjdp eval = apply_range (e->value, e->range); 81233965Sjdp val &= apply_range (0xffffffff, e->range); 81333965Sjdp } 81460484Sobrien else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit) 81560484Sobrien || (e->range.sbit == 0 && e->range.ebit == 0)) 81633965Sjdp { 81733965Sjdp eval = apply_range (e->value, *r); 81833965Sjdp val = apply_range (val, *r); 81933965Sjdp } 82033965Sjdp else 82133965Sjdp continue; 82233965Sjdp if (val == eval) 82333965Sjdp return e; 82433965Sjdp } 82533965Sjdp return 0; 82633965Sjdp} 82733965Sjdp 82833965Sjdp/* Return a pointer to the list of entries for a given processor and type. */ 82933965Sjdp 83033965Sjdpstatic struct itbl_entry ** 83133965Sjdpget_entries (e_processor processor, e_type type) 83233965Sjdp{ 83333965Sjdp return &entries[processor][type]; 83433965Sjdp} 83533965Sjdp 83633965Sjdp/* Return an integral value for the processor passed from yyparse. */ 83733965Sjdp 83833965Sjdpstatic e_processor 83933965Sjdpget_processor (int yyproc) 84033965Sjdp{ 84133965Sjdp /* translate from yacc's processor to enum */ 84233965Sjdp if (yyproc >= e_p0 && yyproc < e_nprocs) 84333965Sjdp return (e_processor) yyproc; 84433965Sjdp return e_invproc; /* error; invalid processor */ 84533965Sjdp} 84633965Sjdp 84733965Sjdp/* Return an integral value for the entry type passed from yyparse. */ 84833965Sjdp 84933965Sjdpstatic e_type 85033965Sjdpget_type (int yytype) 85133965Sjdp{ 85233965Sjdp switch (yytype) 85333965Sjdp { 85433965Sjdp /* translate from yacc's type to enum */ 85533965Sjdp case INSN: 85633965Sjdp return e_insn; 85733965Sjdp case DREG: 85833965Sjdp return e_dreg; 85933965Sjdp case CREG: 86033965Sjdp return e_creg; 86133965Sjdp case GREG: 86233965Sjdp return e_greg; 86333965Sjdp case ADDR: 86433965Sjdp return e_addr; 86533965Sjdp case IMMED: 86633965Sjdp return e_immed; 86733965Sjdp default: 86833965Sjdp return e_invtype; /* error; invalid type */ 86933965Sjdp } 87033965Sjdp} 87133965Sjdp 87233965Sjdp 87333965Sjdp/* Allocate and initialize an entry */ 87433965Sjdp 87533965Sjdpstatic struct itbl_entry * 87633965Sjdpalloc_entry (e_processor processor, e_type type, 87733965Sjdp char *name, unsigned long value) 87833965Sjdp{ 87933965Sjdp struct itbl_entry *e, **es; 88033965Sjdp if (!name) 88133965Sjdp return 0; 88233965Sjdp e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry)); 88333965Sjdp if (e) 88433965Sjdp { 88533965Sjdp memset (e, 0, sizeof (struct itbl_entry)); 88633965Sjdp e->name = (char *) malloc (sizeof (strlen (name)) + 1); 88733965Sjdp if (e->name) 88833965Sjdp strcpy (e->name, name); 88933965Sjdp e->processor = processor; 89033965Sjdp e->type = type; 89133965Sjdp e->value = value; 89233965Sjdp es = get_entries (e->processor, e->type); 89333965Sjdp e->next = *es; 89433965Sjdp *es = e; 89533965Sjdp } 89633965Sjdp return e; 89733965Sjdp} 89833965Sjdp 89933965Sjdp/* Allocate and initialize an entry's field */ 90033965Sjdp 90133965Sjdpstatic struct itbl_field * 90233965Sjdpalloc_field (e_type type, int sbit, int ebit, 90333965Sjdp unsigned long flags) 90433965Sjdp{ 90533965Sjdp struct itbl_field *f; 90633965Sjdp f = (struct itbl_field *) malloc (sizeof (struct itbl_field)); 90733965Sjdp if (f) 90833965Sjdp { 90933965Sjdp memset (f, 0, sizeof (struct itbl_field)); 91033965Sjdp f->type = type; 91133965Sjdp f->range.sbit = sbit; 91233965Sjdp f->range.ebit = ebit; 91333965Sjdp f->flags = flags; 91433965Sjdp } 91533965Sjdp return f; 91633965Sjdp} 917