itbl-ops.c revision 33965
133965Sjdp/* itbl-ops.c 233965Sjdp Copyright (C) 1997 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 { 35933965Sjdp 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 46033965Sjdpunsigned long 46133965Sjdpitbl_get_reg_val (char *name) 46233965Sjdp{ 46333965Sjdp e_type t; 46433965Sjdp e_processor p; 46533965Sjdp int r = 0; 46633965Sjdp for (p = e_p0; p < e_nprocs; p++) 46733965Sjdp for (t = e_regtype0; t < e_nregtypes; t++) 46833965Sjdp { 46933965Sjdp if (r = itbl_get_val (p, t, name), r) 47033965Sjdp return r; 47133965Sjdp } 47233965Sjdp return 0; 47333965Sjdp} 47433965Sjdp 47533965Sjdpchar * 47633965Sjdpitbl_get_name (e_processor processor, e_type type, unsigned long val) 47733965Sjdp{ 47833965Sjdp struct itbl_entry *r; 47933965Sjdp /* type depends on instruction passed */ 48033965Sjdp r = find_entry_byval (processor, type, val, 0); 48133965Sjdp if (r) 48233965Sjdp return r->name; 48333965Sjdp else 48433965Sjdp return 0; /* error; invalid operand */ 48533965Sjdp} 48633965Sjdp 48733965Sjdp/* Get processor's register value from name */ 48833965Sjdp 48933965Sjdpunsigned long 49033965Sjdpitbl_get_val (e_processor processor, e_type type, char *name) 49133965Sjdp{ 49233965Sjdp struct itbl_entry *r; 49333965Sjdp /* type depends on instruction passed */ 49433965Sjdp r = find_entry_byname (processor, type, name); 49533965Sjdp if (r) 49633965Sjdp return r->value; 49733965Sjdp else 49833965Sjdp return 0; /* error; invalid operand */ 49933965Sjdp} 50033965Sjdp 50133965Sjdp 50233965Sjdp/* Assemble instruction "name" with operands "s". 50333965Sjdp * name - name of instruction 50433965Sjdp * s - operands 50533965Sjdp * returns - long word for assembled instruction */ 50633965Sjdp 50733965Sjdpunsigned long 50833965Sjdpitbl_assemble (char *name, char *s) 50933965Sjdp{ 51033965Sjdp unsigned long opcode; 51133965Sjdp struct itbl_entry *e; 51233965Sjdp struct itbl_field *f; 51333965Sjdp char *n; 51433965Sjdp int processor; 51533965Sjdp 51633965Sjdp if (!name || !*name) 51733965Sjdp return 0; /* error! must have a opcode name/expr */ 51833965Sjdp 51933965Sjdp /* find entry in list of instructions for all processors */ 52033965Sjdp for (processor = 0; processor < e_nprocs; processor++) 52133965Sjdp { 52233965Sjdp e = find_entry_byname (processor, e_insn, name); 52333965Sjdp if (e) 52433965Sjdp break; 52533965Sjdp } 52633965Sjdp if (!e) 52733965Sjdp return 0; /* opcode not in table; invalid instrustion */ 52833965Sjdp opcode = build_opcode (e); 52933965Sjdp 53033965Sjdp /* parse opcode's args (if any) */ 53133965Sjdp for (f = e->fields; f; f = f->next) /* for each arg, ... */ 53233965Sjdp { 53333965Sjdp struct itbl_entry *r; 53433965Sjdp unsigned long value; 53533965Sjdp if (!s || !*s) 53633965Sjdp return 0; /* error - not enough operands */ 53733965Sjdp n = itbl_get_field (&s); 53833965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 53933965Sjdp switch (f->type) 54033965Sjdp { 54133965Sjdp case e_dreg: 54233965Sjdp case e_creg: 54333965Sjdp case e_greg: 54433965Sjdp /* Accept either a string name 54533965Sjdp * or '$' followed by the register number */ 54633965Sjdp if (*n == '$') 54733965Sjdp { 54833965Sjdp n++; 54933965Sjdp value = strtol (n, 0, 10); 55033965Sjdp /* FIXME! could have "0l"... then what?? */ 55133965Sjdp if (value == 0 && *n != '0') 55233965Sjdp return 0; /* error; invalid operand */ 55333965Sjdp } 55433965Sjdp else 55533965Sjdp { 55633965Sjdp r = find_entry_byname (e->processor, f->type, n); 55733965Sjdp if (r) 55833965Sjdp value = r->value; 55933965Sjdp else 56033965Sjdp return 0; /* error; invalid operand */ 56133965Sjdp } 56233965Sjdp break; 56333965Sjdp case e_addr: 56433965Sjdp /* use assembler's symbol table to find symbol */ 56533965Sjdp /* FIXME!! Do we need this? 56633965Sjdp if so, what about relocs?? 56733965Sjdp my_getExpression (&imm_expr, s); 56833965Sjdp return 0; /-* error; invalid operand *-/ 56933965Sjdp break; 57033965Sjdp */ 57133965Sjdp /* If not a symbol, fall thru to IMMED */ 57233965Sjdp case e_immed: 57333965Sjdp if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ 57433965Sjdp { 57533965Sjdp n += 2; 57633965Sjdp value = strtol (n, 0, 16); 57733965Sjdp /* FIXME! could have "0xl"... then what?? */ 57833965Sjdp } 57933965Sjdp else 58033965Sjdp { 58133965Sjdp value = strtol (n, 0, 10); 58233965Sjdp /* FIXME! could have "0l"... then what?? */ 58333965Sjdp if (value == 0 && *n != '0') 58433965Sjdp return 0; /* error; invalid operand */ 58533965Sjdp } 58633965Sjdp break; 58733965Sjdp default: 58833965Sjdp return 0; /* error; invalid field spec */ 58933965Sjdp } 59033965Sjdp opcode |= apply_range (value, f->range); 59133965Sjdp } 59233965Sjdp if (s && *s) 59333965Sjdp return 0; /* error - too many operands */ 59433965Sjdp return opcode; /* done! */ 59533965Sjdp} 59633965Sjdp 59733965Sjdp/* Disassemble instruction "insn". 59833965Sjdp * insn - instruction 59933965Sjdp * s - buffer to hold disassembled instruction 60033965Sjdp * returns - 1 if succeeded; 0 if failed 60133965Sjdp */ 60233965Sjdp 60333965Sjdpint 60433965Sjdpitbl_disassemble (char *s, unsigned long insn) 60533965Sjdp{ 60633965Sjdp e_processor processor; 60733965Sjdp struct itbl_entry *e; 60833965Sjdp struct itbl_field *f; 60933965Sjdp 61033965Sjdp if (!ITBL_IS_INSN (insn)) 61133965Sjdp return 0; /* error*/ 61233965Sjdp processor = get_processor (ITBL_DECODE_PNUM (insn)); 61333965Sjdp 61433965Sjdp /* find entry in list */ 61533965Sjdp e = find_entry_byval (processor, e_insn, insn, 0); 61633965Sjdp if (!e) 61733965Sjdp return 0; /* opcode not in table; invalid instrustion */ 61833965Sjdp strcpy (s, e->name); 61933965Sjdp 62033965Sjdp /* parse insn's args (if any) */ 62133965Sjdp for (f = e->fields; f; f = f->next) /* for each arg, ... */ 62233965Sjdp { 62333965Sjdp struct itbl_entry *r; 62433965Sjdp unsigned long value; 62533965Sjdp 62633965Sjdp if (f == e->fields) /* first operand is preceeded by tab */ 62733965Sjdp strcat (s, "\t"); 62833965Sjdp else /* ','s separate following operands */ 62933965Sjdp strcat (s, ","); 63033965Sjdp value = extract_range (insn, f->range); 63133965Sjdp /* n should be in form $n or 0xhhh (are symbol names valid?? */ 63233965Sjdp switch (f->type) 63333965Sjdp { 63433965Sjdp case e_dreg: 63533965Sjdp case e_creg: 63633965Sjdp case e_greg: 63733965Sjdp /* Accept either a string name 63833965Sjdp * or '$' followed by the register number */ 63933965Sjdp r = find_entry_byval (e->processor, f->type, value, &f->range); 64033965Sjdp if (r) 64133965Sjdp strcat (s, r->name); 64233965Sjdp else 64333965Sjdp sprintf (s, "%s$%d", s, value); 64433965Sjdp break; 64533965Sjdp case e_addr: 64633965Sjdp /* use assembler's symbol table to find symbol */ 64733965Sjdp /* FIXME!! Do we need this? 64833965Sjdp * if so, what about relocs?? 64933965Sjdp */ 65033965Sjdp /* If not a symbol, fall thru to IMMED */ 65133965Sjdp case e_immed: 65233965Sjdp sprintf (s, "%s0x%x", s, value); 65333965Sjdp break; 65433965Sjdp default: 65533965Sjdp return 0; /* error; invalid field spec */ 65633965Sjdp } 65733965Sjdp } 65833965Sjdp return 1; /* done! */ 65933965Sjdp} 66033965Sjdp 66133965Sjdp/*======================================================================*/ 66233965Sjdp/* 66333965Sjdp * Local functions for manipulating private structures containing 66433965Sjdp * the names and format for the new instructions and registers 66533965Sjdp * for each processor. 66633965Sjdp */ 66733965Sjdp 66833965Sjdp/* Calculate instruction's opcode and function values from entry */ 66933965Sjdp 67033965Sjdpstatic unsigned long 67133965Sjdpbuild_opcode (struct itbl_entry *e) 67233965Sjdp{ 67333965Sjdp unsigned long opcode; 67433965Sjdp 67533965Sjdp opcode = apply_range (e->value, e->range); 67633965Sjdp opcode |= ITBL_ENCODE_PNUM (e->processor); 67733965Sjdp return opcode; 67833965Sjdp} 67933965Sjdp 68033965Sjdp/* Calculate absolute value given the relative value and bit position range 68133965Sjdp * within the instruction. 68233965Sjdp * The range is inclusive where 0 is least significant bit. 68333965Sjdp * A range of { 24, 20 } will have a mask of 68433965Sjdp * bit 3 2 1 68533965Sjdp * pos: 1098 7654 3210 9876 5432 1098 7654 3210 68633965Sjdp * bin: 0000 0001 1111 0000 0000 0000 0000 0000 68733965Sjdp * hex: 0 1 f 0 0 0 0 0 68833965Sjdp * mask: 0x01f00000. 68933965Sjdp */ 69033965Sjdp 69133965Sjdpstatic unsigned long 69233965Sjdpapply_range (unsigned long rval, struct itbl_range r) 69333965Sjdp{ 69433965Sjdp unsigned long mask; 69533965Sjdp unsigned long aval; 69633965Sjdp int len = MAX_BITPOS - r.sbit; 69733965Sjdp 69833965Sjdp ASSERT (r.sbit >= r.ebit); 69933965Sjdp ASSERT (MAX_BITPOS >= r.sbit); 70033965Sjdp ASSERT (r.ebit >= 0); 70133965Sjdp 70233965Sjdp /* create mask by truncating 1s by shifting */ 70333965Sjdp mask = 0xffffffff << len; 70433965Sjdp mask = mask >> len; 70533965Sjdp mask = mask >> r.ebit; 70633965Sjdp mask = mask << r.ebit; 70733965Sjdp 70833965Sjdp aval = (rval << r.ebit) & mask; 70933965Sjdp return aval; 71033965Sjdp} 71133965Sjdp 71233965Sjdp/* Calculate relative value given the absolute value and bit position range 71333965Sjdp * within the instruction. */ 71433965Sjdp 71533965Sjdpstatic unsigned long 71633965Sjdpextract_range (unsigned long aval, struct itbl_range r) 71733965Sjdp{ 71833965Sjdp unsigned long mask; 71933965Sjdp unsigned long rval; 72033965Sjdp int len = MAX_BITPOS - r.sbit; 72133965Sjdp 72233965Sjdp /* create mask by truncating 1s by shifting */ 72333965Sjdp mask = 0xffffffff << len; 72433965Sjdp mask = mask >> len; 72533965Sjdp mask = mask >> r.ebit; 72633965Sjdp mask = mask << r.ebit; 72733965Sjdp 72833965Sjdp rval = (aval & mask) >> r.ebit; 72933965Sjdp return rval; 73033965Sjdp} 73133965Sjdp 73233965Sjdp/* Extract processor's assembly instruction field name from s; 73333965Sjdp * forms are "n args" "n,args" or "n" */ 73433965Sjdp/* Return next argument from string pointer "s" and advance s. 73533965Sjdp * delimiters are " ,\0" */ 73633965Sjdp 73733965Sjdpchar * 73833965Sjdpitbl_get_field (char **S) 73933965Sjdp{ 74033965Sjdp static char n[128]; 74133965Sjdp char *p, *ps, *s; 74233965Sjdp int len; 74333965Sjdp 74433965Sjdp s = *S; 74533965Sjdp if (!s || !*s) 74633965Sjdp return 0; 74733965Sjdp p = s + strlen (s); 74833965Sjdp if (ps = strchr (s, ','), ps) 74933965Sjdp p = ps; 75033965Sjdp if (ps = strchr (s, ' '), ps) 75133965Sjdp p = min (p, ps); 75233965Sjdp if (ps = strchr (s, '\0'), ps) 75333965Sjdp p = min (p, ps); 75433965Sjdp if (p == 0) 75533965Sjdp return 0; /* error! */ 75633965Sjdp len = p - s; 75733965Sjdp ASSERT (128 > len + 1); 75833965Sjdp strncpy (n, s, len); 75933965Sjdp n[len] = 0; 76033965Sjdp if (s[len] == '\0') 76133965Sjdp s = 0; /* no more args */ 76233965Sjdp else 76333965Sjdp s += len + 1; /* advance to next arg */ 76433965Sjdp 76533965Sjdp *S = s; 76633965Sjdp return n; 76733965Sjdp} 76833965Sjdp 76933965Sjdp/* Search entries for a given processor and type 77033965Sjdp * to find one matching the name "n". 77133965Sjdp * Return a pointer to the entry */ 77233965Sjdp 77333965Sjdpstatic struct itbl_entry * 77433965Sjdpfind_entry_byname (e_processor processor, 77533965Sjdp e_type type, char *n) 77633965Sjdp{ 77733965Sjdp struct itbl_entry *e, **es; 77833965Sjdp 77933965Sjdp es = get_entries (processor, type); 78033965Sjdp for (e = *es; e; e = e->next) /* for each entry, ... */ 78133965Sjdp { 78233965Sjdp if (!strcmp (e->name, n)) 78333965Sjdp return e; 78433965Sjdp } 78533965Sjdp return 0; 78633965Sjdp} 78733965Sjdp 78833965Sjdp/* Search entries for a given processor and type 78933965Sjdp * to find one matching the value "val" for the range "r". 79033965Sjdp * Return a pointer to the entry. 79133965Sjdp * This function is used for disassembling fields of an instruction. 79233965Sjdp */ 79333965Sjdp 79433965Sjdpstatic struct itbl_entry * 79533965Sjdpfind_entry_byval (e_processor processor, e_type type, 79633965Sjdp unsigned long val, struct itbl_range *r) 79733965Sjdp{ 79833965Sjdp struct itbl_entry *e, **es; 79933965Sjdp unsigned long eval; 80033965Sjdp 80133965Sjdp es = get_entries (processor, type); 80233965Sjdp for (e = *es; e; e = e->next) /* for each entry, ... */ 80333965Sjdp { 80433965Sjdp if (processor != e->processor) 80533965Sjdp continue; 80633965Sjdp /* For insns, we might not know the range of the opcode, 80733965Sjdp * so a range of 0 will allow this routine to match against 80833965Sjdp * the range of the entry to be compared with. 80933965Sjdp * This could cause ambiguities. 81033965Sjdp * For operands, we get an extracted value and a range. 81133965Sjdp */ 81233965Sjdp /* if range is 0, mask val against the range of the compared entry. */ 81333965Sjdp if (r == 0) /* if no range passed, must be whole 32-bits 81433965Sjdp * so create 32-bit value from entry's range */ 81533965Sjdp { 81633965Sjdp eval = apply_range (e->value, e->range); 81733965Sjdp val &= apply_range (0xffffffff, e->range); 81833965Sjdp } 81933965Sjdp else if (r->sbit == e->range.sbit && r->ebit == e->range.ebit 82033965Sjdp || e->range.sbit == 0 && e->range.ebit == 0) 82133965Sjdp { 82233965Sjdp eval = apply_range (e->value, *r); 82333965Sjdp val = apply_range (val, *r); 82433965Sjdp } 82533965Sjdp else 82633965Sjdp continue; 82733965Sjdp if (val == eval) 82833965Sjdp return e; 82933965Sjdp } 83033965Sjdp return 0; 83133965Sjdp} 83233965Sjdp 83333965Sjdp/* Return a pointer to the list of entries for a given processor and type. */ 83433965Sjdp 83533965Sjdpstatic struct itbl_entry ** 83633965Sjdpget_entries (e_processor processor, e_type type) 83733965Sjdp{ 83833965Sjdp return &entries[processor][type]; 83933965Sjdp} 84033965Sjdp 84133965Sjdp/* Return an integral value for the processor passed from yyparse. */ 84233965Sjdp 84333965Sjdpstatic e_processor 84433965Sjdpget_processor (int yyproc) 84533965Sjdp{ 84633965Sjdp /* translate from yacc's processor to enum */ 84733965Sjdp if (yyproc >= e_p0 && yyproc < e_nprocs) 84833965Sjdp return (e_processor) yyproc; 84933965Sjdp return e_invproc; /* error; invalid processor */ 85033965Sjdp} 85133965Sjdp 85233965Sjdp/* Return an integral value for the entry type passed from yyparse. */ 85333965Sjdp 85433965Sjdpstatic e_type 85533965Sjdpget_type (int yytype) 85633965Sjdp{ 85733965Sjdp switch (yytype) 85833965Sjdp { 85933965Sjdp /* translate from yacc's type to enum */ 86033965Sjdp case INSN: 86133965Sjdp return e_insn; 86233965Sjdp case DREG: 86333965Sjdp return e_dreg; 86433965Sjdp case CREG: 86533965Sjdp return e_creg; 86633965Sjdp case GREG: 86733965Sjdp return e_greg; 86833965Sjdp case ADDR: 86933965Sjdp return e_addr; 87033965Sjdp case IMMED: 87133965Sjdp return e_immed; 87233965Sjdp default: 87333965Sjdp return e_invtype; /* error; invalid type */ 87433965Sjdp } 87533965Sjdp} 87633965Sjdp 87733965Sjdp 87833965Sjdp/* Allocate and initialize an entry */ 87933965Sjdp 88033965Sjdpstatic struct itbl_entry * 88133965Sjdpalloc_entry (e_processor processor, e_type type, 88233965Sjdp char *name, unsigned long value) 88333965Sjdp{ 88433965Sjdp struct itbl_entry *e, **es; 88533965Sjdp if (!name) 88633965Sjdp return 0; 88733965Sjdp e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry)); 88833965Sjdp if (e) 88933965Sjdp { 89033965Sjdp memset (e, 0, sizeof (struct itbl_entry)); 89133965Sjdp e->name = (char *) malloc (sizeof (strlen (name)) + 1); 89233965Sjdp if (e->name) 89333965Sjdp strcpy (e->name, name); 89433965Sjdp e->processor = processor; 89533965Sjdp e->type = type; 89633965Sjdp e->value = value; 89733965Sjdp es = get_entries (e->processor, e->type); 89833965Sjdp e->next = *es; 89933965Sjdp *es = e; 90033965Sjdp } 90133965Sjdp return e; 90233965Sjdp} 90333965Sjdp 90433965Sjdp/* Allocate and initialize an entry's field */ 90533965Sjdp 90633965Sjdpstatic struct itbl_field * 90733965Sjdpalloc_field (e_type type, int sbit, int ebit, 90833965Sjdp unsigned long flags) 90933965Sjdp{ 91033965Sjdp struct itbl_field *f; 91133965Sjdp f = (struct itbl_field *) malloc (sizeof (struct itbl_field)); 91233965Sjdp if (f) 91333965Sjdp { 91433965Sjdp memset (f, 0, sizeof (struct itbl_field)); 91533965Sjdp f->type = type; 91633965Sjdp f->range.sbit = sbit; 91733965Sjdp f->range.ebit = ebit; 91833965Sjdp f->flags = flags; 91933965Sjdp } 92033965Sjdp return f; 92133965Sjdp} 922