itbl-ops.c revision 77298
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 11777298Sobrienstruct itbl_range { 11877298Sobrien int sbit; /* mask starting bit position */ 11977298Sobrien int ebit; /* mask ending bit position */ 12077298Sobrien}; 12133965Sjdp 12277298Sobrienstruct itbl_field { 12377298Sobrien e_type type; /* dreg/creg/greg/immed/symb */ 12477298Sobrien struct itbl_range range; /* field's bitfield range within instruction */ 12577298Sobrien unsigned long flags; /* field flags */ 12677298Sobrien struct itbl_field *next; /* next field in list */ 12777298Sobrien}; 12833965Sjdp 12933965Sjdp/* These structures define the instructions and registers for a processor. 13033965Sjdp * If the type is an instruction, the structure defines the format of an 13133965Sjdp * instruction where the fields are the list of operands. 13233965Sjdp * The flags field below uses the same values as those defined in the 13377298Sobrien * gnu assembler and are machine specific. */ 13477298Sobrienstruct itbl_entry { 13577298Sobrien e_processor processor; /* processor number */ 13677298Sobrien e_type type; /* dreg/creg/greg/insn */ 13777298Sobrien char *name; /* mnemionic name for insn/register */ 13877298Sobrien unsigned long value; /* opcode/instruction mask/register number */ 13977298Sobrien unsigned long flags; /* effects of the instruction */ 14077298Sobrien struct itbl_range range; /* bit range within instruction for value */ 14177298Sobrien struct itbl_field *fields; /* list of operand definitions (if any) */ 14277298Sobrien struct itbl_entry *next; /* next entry */ 14377298Sobrien}; 14433965Sjdp 14533965Sjdp/* local data and structures */ 14633965Sjdp 14733965Sjdpstatic int itbl_num_opcodes = 0; 14833965Sjdp/* Array of entries for each processor and entry type */ 14977298Sobrienstatic struct itbl_entry *entries[e_nprocs][e_ntypes] = { 15033965Sjdp {0, 0, 0, 0, 0, 0}, 15133965Sjdp {0, 0, 0, 0, 0, 0}, 15233965Sjdp {0, 0, 0, 0, 0, 0}, 15333965Sjdp {0, 0, 0, 0, 0, 0} 15433965Sjdp}; 15533965Sjdp 15633965Sjdp/* local prototypes */ 15733965Sjdpstatic unsigned long build_opcode PARAMS ((struct itbl_entry *e)); 15833965Sjdpstatic e_type get_type PARAMS ((int yytype)); 15933965Sjdpstatic e_processor get_processor PARAMS ((int yyproc)); 16077298Sobrienstatic struct itbl_entry **get_entries PARAMS ((e_processor processor, 16133965Sjdp e_type type)); 16277298Sobrienstatic struct itbl_entry *find_entry_byname PARAMS ((e_processor processor, 16333965Sjdp e_type type, char *name)); 16477298Sobrienstatic struct itbl_entry *find_entry_byval PARAMS ((e_processor processor, 16533965Sjdp e_type type, unsigned long val, struct itbl_range *r)); 16677298Sobrienstatic struct itbl_entry *alloc_entry PARAMS ((e_processor processor, 16733965Sjdp e_type type, char *name, unsigned long value)); 16877298Sobrienstatic unsigned long apply_range PARAMS ((unsigned long value, 16933965Sjdp struct itbl_range r)); 17077298Sobrienstatic unsigned long extract_range PARAMS ((unsigned long value, 17133965Sjdp struct itbl_range r)); 17277298Sobrienstatic struct itbl_field *alloc_field PARAMS ((e_type type, int sbit, 17333965Sjdp int ebit, unsigned long flags)); 17433965Sjdp 17533965Sjdp/*======================================================================*/ 17633965Sjdp/* Interfaces to the parser */ 17733965Sjdp 17833965Sjdp/* Open the table and use lex and yacc to parse the entries. 17933965Sjdp * Return 1 for failure; 0 for success. */ 18033965Sjdp 18177298Sobrienint 18233965Sjdpitbl_parse (char *insntbl) 18333965Sjdp{ 18433965Sjdp extern FILE *yyin; 18533965Sjdp extern int yyparse (void); 18633965Sjdp yyin = fopen (insntbl, "r"); 18733965Sjdp if (yyin == 0) 18833965Sjdp { 18933965Sjdp printf ("Can't open processor instruction specification file \"%s\"\n", 19033965Sjdp insntbl); 19133965Sjdp return 1; 19233965Sjdp } 19333965Sjdp else 19433965Sjdp { 19533965Sjdp while (yyparse ()); 19633965Sjdp } 19733965Sjdp fclose (yyin); 19833965Sjdp itbl_have_entries = 1; 19933965Sjdp return 0; 20033965Sjdp} 20133965Sjdp 20233965Sjdp/* Add a register entry */ 20333965Sjdp 20433965Sjdpstruct itbl_entry * 20533965Sjdpitbl_add_reg (int yyprocessor, int yytype, char *regname, 20633965Sjdp int regnum) 20733965Sjdp{ 20877298Sobrien#if 0 20933965Sjdp#include "as.h" 21033965Sjdp#include "symbols.h" 21133965Sjdp /* Since register names don't have a prefix, we put them in the symbol table so 21233965Sjdp they can't be used as symbols. This also simplifies argument parsing as 21333965Sjdp we can let gas parse registers for us. The recorded register number is 21433965Sjdp regnum. */ 21533965Sjdp /* Use symbol_create here instead of symbol_new so we don't try to 21633965Sjdp output registers into the object file's symbol table. */ 21733965Sjdp symbol_table_insert (symbol_create (regname, reg_section, 21833965Sjdp regnum, &zero_address_frag)); 21933965Sjdp#endif 22033965Sjdp return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname, 22133965Sjdp (unsigned long) regnum); 22233965Sjdp} 22333965Sjdp 22433965Sjdp/* Add an instruction entry */ 22533965Sjdp 22633965Sjdpstruct itbl_entry * 22733965Sjdpitbl_add_insn (int yyprocessor, char *name, unsigned long value, 22833965Sjdp int sbit, int ebit, unsigned long flags) 22933965Sjdp{ 23033965Sjdp struct itbl_entry *e; 23133965Sjdp e = alloc_entry (get_processor (yyprocessor), e_insn, name, value); 23233965Sjdp if (e) 23333965Sjdp { 23433965Sjdp e->range.sbit = sbit; 23533965Sjdp e->range.ebit = ebit; 23633965Sjdp e->flags = flags; 23733965Sjdp itbl_num_opcodes++; 23833965Sjdp } 23933965Sjdp return e; 24033965Sjdp} 24133965Sjdp 24233965Sjdp/* Add an operand to an instruction entry */ 24333965Sjdp 24433965Sjdpstruct itbl_field * 24533965Sjdpitbl_add_operand (struct itbl_entry *e, int yytype, int sbit, 24633965Sjdp int ebit, unsigned long flags) 24733965Sjdp{ 24833965Sjdp struct itbl_field *f, **last_f; 24933965Sjdp if (!e) 25033965Sjdp return 0; 25177298Sobrien /* Add to end of fields' list. */ 25233965Sjdp f = alloc_field (get_type (yytype), sbit, ebit, flags); 25333965Sjdp if (f) 25433965Sjdp { 25533965Sjdp last_f = &e->fields; 25633965Sjdp while (*last_f) 25733965Sjdp last_f = &(*last_f)->next; 25833965Sjdp *last_f = f; 25933965Sjdp f->next = 0; 26033965Sjdp } 26133965Sjdp return f; 26233965Sjdp} 26333965Sjdp 26433965Sjdp/*======================================================================*/ 26533965Sjdp/* Interfaces for assembler and disassembler */ 26633965Sjdp 26733965Sjdp#ifndef STAND_ALONE 26833965Sjdp#include "as.h" 26933965Sjdp#include "symbols.h" 27033965Sjdpstatic void append_insns_as_macros (void); 27133965Sjdp 27277298Sobrien/* Initialize for gas. */ 27377298Sobrien 27477298Sobrienvoid 27533965Sjdpitbl_init (void) 27633965Sjdp{ 27733965Sjdp struct itbl_entry *e, **es; 27833965Sjdp e_processor procn; 27933965Sjdp e_type type; 28033965Sjdp 28133965Sjdp if (!itbl_have_entries) 28277298Sobrien return; 28333965Sjdp 28433965Sjdp /* Since register names don't have a prefix, put them in the symbol table so 28533965Sjdp they can't be used as symbols. This simplifies argument parsing as 28677298Sobrien we can let gas parse registers for us. */ 28733965Sjdp /* Use symbol_create instead of symbol_new so we don't try to 28833965Sjdp output registers into the object file's symbol table. */ 28933965Sjdp 29033965Sjdp for (type = e_regtype0; type < e_nregtypes; type++) 29133965Sjdp for (procn = e_p0; procn < e_nprocs; procn++) 29233965Sjdp { 29333965Sjdp es = get_entries (procn, type); 29433965Sjdp for (e = *es; e; e = e->next) 29533965Sjdp { 29633965Sjdp symbol_table_insert (symbol_create (e->name, reg_section, 29777298Sobrien e->value, &zero_address_frag)); 29833965Sjdp } 29933965Sjdp } 30033965Sjdp append_insns_as_macros (); 30133965Sjdp} 30233965Sjdp 30377298Sobrien/* Append insns to opcodes table and increase number of opcodes 30477298Sobrien * Structure of opcodes table: 30533965Sjdp * struct itbl_opcode 30633965Sjdp * { 30733965Sjdp * const char *name; 30877298Sobrien * const char *args; - string describing the arguments. 30977298Sobrien * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO 31077298Sobrien * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO 31177298Sobrien * unsigned long pinfo; - insn flags, or INSN_MACRO 31233965Sjdp * }; 31333965Sjdp * examples: 31433965Sjdp * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, 31533965Sjdp * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, 31633965Sjdp */ 31733965Sjdp 31833965Sjdpstatic char *form_args (struct itbl_entry *e); 31977298Sobrienstatic void 32033965Sjdpappend_insns_as_macros (void) 32133965Sjdp{ 32233965Sjdp struct ITBL_OPCODE_STRUCT *new_opcodes, *o; 32333965Sjdp struct itbl_entry *e, **es; 32433965Sjdp int n, id, size, new_size, new_num_opcodes; 32533965Sjdp 32633965Sjdp if (!itbl_have_entries) 32777298Sobrien return; 32833965Sjdp 32933965Sjdp if (!itbl_num_opcodes) /* no new instructions to add! */ 33033965Sjdp { 33133965Sjdp return; 33233965Sjdp } 33333965Sjdp DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES)); 33433965Sjdp 33533965Sjdp new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes; 33633965Sjdp ASSERT (new_num_opcodes >= itbl_num_opcodes); 33733965Sjdp 33833965Sjdp size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES; 33933965Sjdp ASSERT (size >= 0); 34033965Sjdp DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0]))); 34133965Sjdp 34233965Sjdp new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes; 34333965Sjdp ASSERT (new_size > size); 34433965Sjdp 34533965Sjdp /* FIXME since ITBL_OPCODES culd be a static table, 34677298Sobrien we can't realloc or delete the old memory. */ 34733965Sjdp new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size); 34833965Sjdp if (!new_opcodes) 34933965Sjdp { 35060484Sobrien printf (_("Unable to allocate memory for new instructions\n")); 35133965Sjdp return; 35233965Sjdp } 35333965Sjdp if (size) /* copy prexisting opcodes table */ 35433965Sjdp memcpy (new_opcodes, ITBL_OPCODES, size); 35533965Sjdp 35633965Sjdp /* FIXME! some NUMOPCODES are calculated expressions. 35777298Sobrien These need to be changed before itbls can be supported. */ 35833965Sjdp 35933965Sjdp id = ITBL_NUM_MACROS; /* begin the next macro id after the last */ 36033965Sjdp o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */ 36133965Sjdp for (n = e_p0; n < e_nprocs; n++) 36233965Sjdp { 36333965Sjdp es = get_entries (n, e_insn); 36433965Sjdp for (e = *es; e; e = e->next) 36533965Sjdp { 36633965Sjdp /* name, args, mask, match, pinfo 36733965Sjdp * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, 36833965Sjdp * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, 36933965Sjdp * Construct args from itbl_fields. 37033965Sjdp */ 37133965Sjdp o->name = e->name; 37233965Sjdp o->args = strdup (form_args (e)); 37333965Sjdp o->mask = apply_range (e->value, e->range); 37433965Sjdp /* FIXME how to catch durring assembly? */ 37533965Sjdp /* mask to identify this insn */ 37633965Sjdp o->match = apply_range (e->value, e->range); 37733965Sjdp o->pinfo = 0; 37833965Sjdp 37933965Sjdp#ifdef USE_MACROS 38033965Sjdp o->mask = id++; /* FIXME how to catch durring assembly? */ 38133965Sjdp o->match = 0; /* for macros, the insn_isa number */ 38233965Sjdp o->pinfo = INSN_MACRO; 38333965Sjdp#endif 38433965Sjdp 38533965Sjdp /* Don't add instructions which caused an error */ 38633965Sjdp if (o->args) 38733965Sjdp o++; 38833965Sjdp else 38933965Sjdp new_num_opcodes--; 39033965Sjdp } 39133965Sjdp } 39233965Sjdp ITBL_OPCODES = new_opcodes; 39333965Sjdp ITBL_NUM_OPCODES = new_num_opcodes; 39433965Sjdp 39533965Sjdp /* FIXME 39633965Sjdp At this point, we can free the entries, as they should have 39733965Sjdp been added to the assembler's tables. 39833965Sjdp Don't free name though, since name is being used by the new 39933965Sjdp opcodes table. 40033965Sjdp 40177298Sobrien Eventually, we should also free the new opcodes table itself 40233965Sjdp on exit. 40333965Sjdp */ 40433965Sjdp} 40533965Sjdp 40633965Sjdpstatic char * 40733965Sjdpform_args (struct itbl_entry *e) 40833965Sjdp{ 40933965Sjdp static char s[31]; 41033965Sjdp char c = 0, *p = s; 41133965Sjdp struct itbl_field *f; 41233965Sjdp 41333965Sjdp ASSERT (e); 41433965Sjdp for (f = e->fields; f; f = f->next) 41533965Sjdp { 41633965Sjdp switch (f->type) 41733965Sjdp { 41833965Sjdp case e_dreg: 41933965Sjdp c = 'd'; 42033965Sjdp break; 42133965Sjdp case e_creg: 42233965Sjdp c = 't'; 42333965Sjdp break; 42433965Sjdp case e_greg: 42533965Sjdp c = 's'; 42633965Sjdp break; 42733965Sjdp case e_immed: 42833965Sjdp c = 'i'; 42933965Sjdp break; 43033965Sjdp case e_addr: 43133965Sjdp c = 'a'; 43233965Sjdp break; 43333965Sjdp default: 43433965Sjdp c = 0; /* ignore; unknown field type */ 43533965Sjdp } 43633965Sjdp if (c) 43733965Sjdp { 43833965Sjdp if (p != s) 43933965Sjdp *p++ = ','; 44033965Sjdp *p++ = c; 44133965Sjdp } 44233965Sjdp } 44333965Sjdp *p = 0; 44433965Sjdp return s; 44533965Sjdp} 44633965Sjdp#endif /* !STAND_ALONE */ 44733965Sjdp 44833965Sjdp/* Get processor's register name from val */ 44933965Sjdp 45060484Sobrienint 45160484Sobrienitbl_get_reg_val (char *name, unsigned long *pval) 45233965Sjdp{ 45333965Sjdp e_type t; 45433965Sjdp e_processor p; 45560484Sobrien 45633965Sjdp for (p = e_p0; p < e_nprocs; p++) 45760484Sobrien { 45860484Sobrien for (t = e_regtype0; t < e_nregtypes; t++) 45960484Sobrien { 46060484Sobrien if (itbl_get_val (p, t, name, pval)) 46160484Sobrien return 1; 46260484Sobrien } 46360484Sobrien } 46433965Sjdp return 0; 46533965Sjdp} 46633965Sjdp 46733965Sjdpchar * 46833965Sjdpitbl_get_name (e_processor processor, e_type type, unsigned long val) 46933965Sjdp{ 47033965Sjdp struct itbl_entry *r; 47133965Sjdp /* type depends on instruction passed */ 47233965Sjdp r = find_entry_byval (processor, type, val, 0); 47333965Sjdp if (r) 47433965Sjdp return r->name; 47533965Sjdp else 47633965Sjdp return 0; /* error; invalid operand */ 47733965Sjdp} 47833965Sjdp 47933965Sjdp/* Get processor's register value from name */ 48033965Sjdp 48160484Sobrienint 48260484Sobrienitbl_get_val (e_processor processor, e_type type, char *name, 48360484Sobrien unsigned long *pval) 48433965Sjdp{ 48533965Sjdp struct itbl_entry *r; 48633965Sjdp /* type depends on instruction passed */ 48733965Sjdp r = find_entry_byname (processor, type, name); 48860484Sobrien if (r == NULL) 48960484Sobrien return 0; 49060484Sobrien *pval = r->value; 49160484Sobrien return 1; 49233965Sjdp} 49333965Sjdp 49433965Sjdp/* Assemble instruction "name" with operands "s". 49533965Sjdp * name - name of instruction 49633965Sjdp * s - operands 49733965Sjdp * returns - long word for assembled instruction */ 49833965Sjdp 49977298Sobrienunsigned long 50033965Sjdpitbl_assemble (char *name, char *s) 50133965Sjdp{ 50233965Sjdp unsigned long opcode; 50333965Sjdp struct itbl_entry *e; 50433965Sjdp struct itbl_field *f; 50533965Sjdp char *n; 50633965Sjdp int processor; 50733965Sjdp 50833965Sjdp if (!name || !*name) 50933965Sjdp return 0; /* error! must have a opcode name/expr */ 51033965Sjdp 51133965Sjdp /* find entry in list of instructions for all processors */ 51233965Sjdp for (processor = 0; processor < e_nprocs; processor++) 51333965Sjdp { 51433965Sjdp e = find_entry_byname (processor, e_insn, name); 51533965Sjdp if (e) 51633965Sjdp break; 51733965Sjdp } 51833965Sjdp if (!e) 51977298Sobrien return 0; /* opcode not in table; invalid instruction */ 52033965Sjdp opcode = build_opcode (e); 52133965Sjdp 52233965Sjdp /* parse opcode's args (if any) */ 52377298Sobrien for (f = e->fields; f; f = f->next) /* for each arg, ... */ 52433965Sjdp { 52533965Sjdp struct itbl_entry *r; 52633965Sjdp unsigned long value; 52733965Sjdp if (!s || !*s) 52833965Sjdp return 0; /* error - not enough operands */ 52933965Sjdp n = itbl_get_field (&s); 53033965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 53133965Sjdp switch (f->type) 53233965Sjdp { 53333965Sjdp case e_dreg: 53433965Sjdp case e_creg: 53533965Sjdp case e_greg: 53633965Sjdp /* Accept either a string name 53733965Sjdp * or '$' followed by the register number */ 53833965Sjdp if (*n == '$') 53933965Sjdp { 54033965Sjdp n++; 54133965Sjdp value = strtol (n, 0, 10); 54233965Sjdp /* FIXME! could have "0l"... then what?? */ 54333965Sjdp if (value == 0 && *n != '0') 54433965Sjdp return 0; /* error; invalid operand */ 54533965Sjdp } 54633965Sjdp else 54733965Sjdp { 54833965Sjdp r = find_entry_byname (e->processor, f->type, n); 54933965Sjdp if (r) 55033965Sjdp value = r->value; 55133965Sjdp else 55233965Sjdp return 0; /* error; invalid operand */ 55333965Sjdp } 55433965Sjdp break; 55533965Sjdp case e_addr: 55633965Sjdp /* use assembler's symbol table to find symbol */ 55733965Sjdp /* FIXME!! Do we need this? 55833965Sjdp if so, what about relocs?? 55933965Sjdp my_getExpression (&imm_expr, s); 56033965Sjdp return 0; /-* error; invalid operand *-/ 56133965Sjdp break; 56233965Sjdp */ 56333965Sjdp /* If not a symbol, fall thru to IMMED */ 56433965Sjdp case e_immed: 56577298Sobrien if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ 56633965Sjdp { 56733965Sjdp n += 2; 56833965Sjdp value = strtol (n, 0, 16); 56933965Sjdp /* FIXME! could have "0xl"... then what?? */ 57033965Sjdp } 57133965Sjdp else 57233965Sjdp { 57333965Sjdp value = strtol (n, 0, 10); 57433965Sjdp /* FIXME! could have "0l"... then what?? */ 57533965Sjdp if (value == 0 && *n != '0') 57633965Sjdp return 0; /* error; invalid operand */ 57733965Sjdp } 57833965Sjdp break; 57933965Sjdp default: 58033965Sjdp return 0; /* error; invalid field spec */ 58133965Sjdp } 58233965Sjdp opcode |= apply_range (value, f->range); 58333965Sjdp } 58433965Sjdp if (s && *s) 58533965Sjdp return 0; /* error - too many operands */ 58633965Sjdp return opcode; /* done! */ 58733965Sjdp} 58833965Sjdp 58933965Sjdp/* Disassemble instruction "insn". 59033965Sjdp * insn - instruction 59133965Sjdp * s - buffer to hold disassembled instruction 59233965Sjdp * returns - 1 if succeeded; 0 if failed 59333965Sjdp */ 59433965Sjdp 59577298Sobrienint 59633965Sjdpitbl_disassemble (char *s, unsigned long insn) 59733965Sjdp{ 59833965Sjdp e_processor processor; 59933965Sjdp struct itbl_entry *e; 60033965Sjdp struct itbl_field *f; 60133965Sjdp 60233965Sjdp if (!ITBL_IS_INSN (insn)) 60377298Sobrien return 0; /* error */ 60433965Sjdp processor = get_processor (ITBL_DECODE_PNUM (insn)); 60533965Sjdp 60633965Sjdp /* find entry in list */ 60733965Sjdp e = find_entry_byval (processor, e_insn, insn, 0); 60833965Sjdp if (!e) 60977298Sobrien return 0; /* opcode not in table; invalid instruction */ 61033965Sjdp strcpy (s, e->name); 61133965Sjdp 61277298Sobrien /* Parse insn's args (if any). */ 61377298Sobrien for (f = e->fields; f; f = f->next) /* for each arg, ... */ 61433965Sjdp { 61533965Sjdp struct itbl_entry *r; 61633965Sjdp unsigned long value; 61733965Sjdp 61877298Sobrien if (f == e->fields) /* First operand is preceeded by tab. */ 61933965Sjdp strcat (s, "\t"); 62077298Sobrien else /* ','s separate following operands. */ 62133965Sjdp strcat (s, ","); 62233965Sjdp value = extract_range (insn, f->range); 62333965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 62433965Sjdp switch (f->type) 62533965Sjdp { 62633965Sjdp case e_dreg: 62733965Sjdp case e_creg: 62833965Sjdp case e_greg: 62933965Sjdp /* Accept either a string name 63077298Sobrien or '$' followed by the register number. */ 63133965Sjdp r = find_entry_byval (e->processor, f->type, value, &f->range); 63233965Sjdp if (r) 63333965Sjdp strcat (s, r->name); 63433965Sjdp else 63560484Sobrien sprintf (s, "%s$%lu", s, value); 63633965Sjdp break; 63733965Sjdp case e_addr: 63877298Sobrien /* Use assembler's symbol table to find symbol. */ 63977298Sobrien /* FIXME!! Do we need this? If so, what about relocs?? */ 64077298Sobrien /* If not a symbol, fall through to IMMED. */ 64133965Sjdp case e_immed: 64260484Sobrien sprintf (s, "%s0x%lx", s, value); 64333965Sjdp break; 64433965Sjdp default: 64533965Sjdp return 0; /* error; invalid field spec */ 64633965Sjdp } 64733965Sjdp } 64877298Sobrien return 1; /* Done! */ 64933965Sjdp} 65033965Sjdp 65133965Sjdp/*======================================================================*/ 65233965Sjdp/* 65333965Sjdp * Local functions for manipulating private structures containing 65433965Sjdp * the names and format for the new instructions and registers 65533965Sjdp * for each processor. 65633965Sjdp */ 65733965Sjdp 65833965Sjdp/* Calculate instruction's opcode and function values from entry */ 65933965Sjdp 66077298Sobrienstatic unsigned long 66133965Sjdpbuild_opcode (struct itbl_entry *e) 66233965Sjdp{ 66333965Sjdp unsigned long opcode; 66433965Sjdp 66533965Sjdp opcode = apply_range (e->value, e->range); 66633965Sjdp opcode |= ITBL_ENCODE_PNUM (e->processor); 66733965Sjdp return opcode; 66833965Sjdp} 66933965Sjdp 67033965Sjdp/* Calculate absolute value given the relative value and bit position range 67133965Sjdp * within the instruction. 67233965Sjdp * The range is inclusive where 0 is least significant bit. 67333965Sjdp * A range of { 24, 20 } will have a mask of 67433965Sjdp * bit 3 2 1 67533965Sjdp * pos: 1098 7654 3210 9876 5432 1098 7654 3210 67633965Sjdp * bin: 0000 0001 1111 0000 0000 0000 0000 0000 67733965Sjdp * hex: 0 1 f 0 0 0 0 0 67833965Sjdp * mask: 0x01f00000. 67933965Sjdp */ 68033965Sjdp 68177298Sobrienstatic unsigned long 68233965Sjdpapply_range (unsigned long rval, struct itbl_range r) 68333965Sjdp{ 68433965Sjdp unsigned long mask; 68533965Sjdp unsigned long aval; 68633965Sjdp int len = MAX_BITPOS - r.sbit; 68733965Sjdp 68833965Sjdp ASSERT (r.sbit >= r.ebit); 68933965Sjdp ASSERT (MAX_BITPOS >= r.sbit); 69033965Sjdp ASSERT (r.ebit >= 0); 69133965Sjdp 69233965Sjdp /* create mask by truncating 1s by shifting */ 69333965Sjdp mask = 0xffffffff << len; 69433965Sjdp mask = mask >> len; 69533965Sjdp mask = mask >> r.ebit; 69633965Sjdp mask = mask << r.ebit; 69733965Sjdp 69833965Sjdp aval = (rval << r.ebit) & mask; 69933965Sjdp return aval; 70033965Sjdp} 70133965Sjdp 70233965Sjdp/* Calculate relative value given the absolute value and bit position range 70333965Sjdp * within the instruction. */ 70433965Sjdp 70577298Sobrienstatic unsigned long 70633965Sjdpextract_range (unsigned long aval, struct itbl_range r) 70733965Sjdp{ 70833965Sjdp unsigned long mask; 70933965Sjdp unsigned long rval; 71033965Sjdp int len = MAX_BITPOS - r.sbit; 71133965Sjdp 71233965Sjdp /* create mask by truncating 1s by shifting */ 71333965Sjdp mask = 0xffffffff << len; 71433965Sjdp mask = mask >> len; 71533965Sjdp mask = mask >> r.ebit; 71633965Sjdp mask = mask << r.ebit; 71733965Sjdp 71833965Sjdp rval = (aval & mask) >> r.ebit; 71933965Sjdp return rval; 72033965Sjdp} 72133965Sjdp 72233965Sjdp/* Extract processor's assembly instruction field name from s; 72333965Sjdp * forms are "n args" "n,args" or "n" */ 72433965Sjdp/* Return next argument from string pointer "s" and advance s. 72560484Sobrien * delimiters are " ,()" */ 72633965Sjdp 72733965Sjdpchar * 72833965Sjdpitbl_get_field (char **S) 72933965Sjdp{ 73033965Sjdp static char n[128]; 73160484Sobrien char *s; 73233965Sjdp int len; 73333965Sjdp 73433965Sjdp s = *S; 73533965Sjdp if (!s || !*s) 73633965Sjdp return 0; 73760484Sobrien /* FIXME: This is a weird set of delimiters. */ 73860484Sobrien len = strcspn (s, " \t,()"); 73933965Sjdp ASSERT (128 > len + 1); 74033965Sjdp strncpy (n, s, len); 74133965Sjdp n[len] = 0; 74233965Sjdp if (s[len] == '\0') 74333965Sjdp s = 0; /* no more args */ 74433965Sjdp else 74533965Sjdp s += len + 1; /* advance to next arg */ 74633965Sjdp 74733965Sjdp *S = s; 74833965Sjdp return n; 74933965Sjdp} 75033965Sjdp 75133965Sjdp/* Search entries for a given processor and type 75233965Sjdp * to find one matching the name "n". 75333965Sjdp * Return a pointer to the entry */ 75433965Sjdp 75533965Sjdpstatic struct itbl_entry * 75633965Sjdpfind_entry_byname (e_processor processor, 75733965Sjdp e_type type, char *n) 75833965Sjdp{ 75933965Sjdp struct itbl_entry *e, **es; 76033965Sjdp 76133965Sjdp es = get_entries (processor, type); 76277298Sobrien for (e = *es; e; e = e->next) /* for each entry, ... */ 76333965Sjdp { 76433965Sjdp if (!strcmp (e->name, n)) 76533965Sjdp return e; 76633965Sjdp } 76733965Sjdp return 0; 76833965Sjdp} 76933965Sjdp 77033965Sjdp/* Search entries for a given processor and type 77133965Sjdp * to find one matching the value "val" for the range "r". 77233965Sjdp * Return a pointer to the entry. 77333965Sjdp * This function is used for disassembling fields of an instruction. 77433965Sjdp */ 77533965Sjdp 77633965Sjdpstatic struct itbl_entry * 77733965Sjdpfind_entry_byval (e_processor processor, e_type type, 77833965Sjdp unsigned long val, struct itbl_range *r) 77933965Sjdp{ 78033965Sjdp struct itbl_entry *e, **es; 78133965Sjdp unsigned long eval; 78233965Sjdp 78333965Sjdp es = get_entries (processor, type); 78477298Sobrien for (e = *es; e; e = e->next) /* for each entry, ... */ 78533965Sjdp { 78633965Sjdp if (processor != e->processor) 78733965Sjdp continue; 78833965Sjdp /* For insns, we might not know the range of the opcode, 78933965Sjdp * so a range of 0 will allow this routine to match against 79033965Sjdp * the range of the entry to be compared with. 79133965Sjdp * This could cause ambiguities. 79233965Sjdp * For operands, we get an extracted value and a range. 79333965Sjdp */ 79477298Sobrien /* if range is 0, mask val against the range of the compared entry. */ 79533965Sjdp if (r == 0) /* if no range passed, must be whole 32-bits 79633965Sjdp * so create 32-bit value from entry's range */ 79733965Sjdp { 79833965Sjdp eval = apply_range (e->value, e->range); 79933965Sjdp val &= apply_range (0xffffffff, e->range); 80033965Sjdp } 80160484Sobrien else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit) 80260484Sobrien || (e->range.sbit == 0 && e->range.ebit == 0)) 80333965Sjdp { 80433965Sjdp eval = apply_range (e->value, *r); 80533965Sjdp val = apply_range (val, *r); 80633965Sjdp } 80733965Sjdp else 80833965Sjdp continue; 80933965Sjdp if (val == eval) 81033965Sjdp return e; 81133965Sjdp } 81233965Sjdp return 0; 81333965Sjdp} 81433965Sjdp 81577298Sobrien/* Return a pointer to the list of entries for a given processor and type. */ 81633965Sjdp 81733965Sjdpstatic struct itbl_entry ** 81833965Sjdpget_entries (e_processor processor, e_type type) 81933965Sjdp{ 82033965Sjdp return &entries[processor][type]; 82133965Sjdp} 82233965Sjdp 82377298Sobrien/* Return an integral value for the processor passed from yyparse. */ 82433965Sjdp 82577298Sobrienstatic e_processor 82633965Sjdpget_processor (int yyproc) 82733965Sjdp{ 82833965Sjdp /* translate from yacc's processor to enum */ 82933965Sjdp if (yyproc >= e_p0 && yyproc < e_nprocs) 83033965Sjdp return (e_processor) yyproc; 83133965Sjdp return e_invproc; /* error; invalid processor */ 83233965Sjdp} 83333965Sjdp 83477298Sobrien/* Return an integral value for the entry type passed from yyparse. */ 83533965Sjdp 83677298Sobrienstatic e_type 83733965Sjdpget_type (int yytype) 83833965Sjdp{ 83933965Sjdp switch (yytype) 84033965Sjdp { 84133965Sjdp /* translate from yacc's type to enum */ 84233965Sjdp case INSN: 84333965Sjdp return e_insn; 84433965Sjdp case DREG: 84533965Sjdp return e_dreg; 84633965Sjdp case CREG: 84733965Sjdp return e_creg; 84833965Sjdp case GREG: 84933965Sjdp return e_greg; 85033965Sjdp case ADDR: 85133965Sjdp return e_addr; 85233965Sjdp case IMMED: 85333965Sjdp return e_immed; 85433965Sjdp default: 85533965Sjdp return e_invtype; /* error; invalid type */ 85633965Sjdp } 85733965Sjdp} 85833965Sjdp 85933965Sjdp/* Allocate and initialize an entry */ 86033965Sjdp 86133965Sjdpstatic struct itbl_entry * 86233965Sjdpalloc_entry (e_processor processor, e_type type, 86333965Sjdp char *name, unsigned long value) 86433965Sjdp{ 86533965Sjdp struct itbl_entry *e, **es; 86633965Sjdp if (!name) 86733965Sjdp return 0; 86833965Sjdp e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry)); 86933965Sjdp if (e) 87033965Sjdp { 87133965Sjdp memset (e, 0, sizeof (struct itbl_entry)); 87233965Sjdp e->name = (char *) malloc (sizeof (strlen (name)) + 1); 87333965Sjdp if (e->name) 87433965Sjdp strcpy (e->name, name); 87533965Sjdp e->processor = processor; 87633965Sjdp e->type = type; 87733965Sjdp e->value = value; 87833965Sjdp es = get_entries (e->processor, e->type); 87933965Sjdp e->next = *es; 88033965Sjdp *es = e; 88133965Sjdp } 88233965Sjdp return e; 88333965Sjdp} 88433965Sjdp 88533965Sjdp/* Allocate and initialize an entry's field */ 88633965Sjdp 88733965Sjdpstatic struct itbl_field * 88833965Sjdpalloc_field (e_type type, int sbit, int ebit, 88933965Sjdp unsigned long flags) 89033965Sjdp{ 89133965Sjdp struct itbl_field *f; 89233965Sjdp f = (struct itbl_field *) malloc (sizeof (struct itbl_field)); 89333965Sjdp if (f) 89433965Sjdp { 89533965Sjdp memset (f, 0, sizeof (struct itbl_field)); 89633965Sjdp f->type = type; 89733965Sjdp f->range.sbit = sbit; 89833965Sjdp f->range.ebit = ebit; 89933965Sjdp f->flags = flags; 90033965Sjdp } 90133965Sjdp return f; 90233965Sjdp} 903