133965Sjdp/* itbl-parse.y
2218822Sdim   Copyright 1997, 2002, 2003, 2005, 2006, 2007 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
18218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19218822Sdim   02110-1301, USA.  */
2033965Sjdp
2133965Sjdp%{
2233965Sjdp
2333965Sjdp/*
2433965Sjdp
2533965SjdpYacc grammar for instruction table entries.
2633965Sjdp
2733965Sjdp=======================================================================
2833965SjdpOriginal Instruction table specification document:
2933965Sjdp
3033965Sjdp	    MIPS Coprocessor Table Specification
3133965Sjdp	    ====================================
3233965Sjdp
3333965SjdpThis document describes the format of the MIPS coprocessor table.  The
3433965Sjdptable specifies a list of valid functions, data registers and control
3533965Sjdpregisters that can be used in coprocessor instructions.  This list,
3633965Sjdptogether with the coprocessor instruction classes listed below,
3733965Sjdpspecifies the complete list of coprocessor instructions that will
3833965Sjdpbe recognized and assembled by the GNU assembler.  In effect,
3933965Sjdpthis makes the GNU assembler table-driven, where the table is
4033965Sjdpspecified by the programmer.
4133965Sjdp
4233965SjdpThe table is an ordinary text file that the GNU assembler reads when
4333965Sjdpit starts.  Using the information in the table, the assembler
4433965Sjdpgenerates an internal list of valid coprocessor registers and
4533965Sjdpfunctions.  The assembler uses this internal list in addition to the
4633965Sjdpstandard MIPS registers and instructions which are built-in to the
4733965Sjdpassembler during code generation.
4833965Sjdp
4933965SjdpTo specify the coprocessor table when invoking the GNU assembler, use
5033965Sjdpthe command line option "--itbl file", where file is the
5133965Sjdpcomplete name of the table, including path and extension.
5233965Sjdp
5333965SjdpExamples:
5433965Sjdp
5533965Sjdp	    gas -t cop.tbl test.s -o test.o
5633965Sjdp	    gas -t /usr/local/lib/cop.tbl test.s -o test.o
5733965Sjdp	    gas --itbl d:\gnu\data\cop.tbl test.s -o test.o
5833965Sjdp
5933965SjdpOnly one table may be supplied during a single invocation of
6033965Sjdpthe assembler.
6133965Sjdp
6233965Sjdp
6333965SjdpInstruction classes
6433965Sjdp===================
6533965Sjdp
6633965SjdpBelow is a list of the valid coprocessor instruction classes for
6733965Sjdpany given coprocessor "z".  These instructions are already recognized
6833965Sjdpby the assembler, and are listed here only for reference.
6933965Sjdp
7033965SjdpClass   format	    	    	      instructions
7133965Sjdp-------------------------------------------------
7233965SjdpClass1:
7333965Sjdp	op base rt offset
7433965Sjdp	    	    	    	    	    	    	    LWCz rt,offset (base)
7533965Sjdp	    	    	    	    	    	    	    SWCz rt,offset (base)
7633965SjdpClass2:
7733965Sjdp	COPz sub rt rd 0
7833965Sjdp	    	    	    	    	    	    	    MTCz rt,rd
7933965Sjdp	    	    	    	    	    	    	    MFCz rt,rd
8033965Sjdp	    	    	    	    	    	    	    CTCz rt,rd
8133965Sjdp	    	    	    	    	    	    	    CFCz rt,rd
8233965SjdpClass3:
8333965Sjdp	COPz CO cofun
8433965Sjdp	    	    	    	    	    	    	    COPz cofun
8533965SjdpClass4:
8633965Sjdp	COPz BC br offset
8733965Sjdp	    	    	    	    	    	    	    BCzT offset
8833965Sjdp	    	    	    	    	    	    	    BCzF offset
8933965SjdpClass5:
9033965Sjdp	COPz sub rt rd 0
9133965Sjdp	    	    	    	    	    	    	    DMFCz rt,rd
9233965Sjdp	    	    	    	    	    	    	    DMTCz rt,rd
9333965SjdpClass6:
9433965Sjdp	op base rt offset
9533965Sjdp	    	    	    	    	    	    	    LDCz rt,offset (base)
9633965Sjdp	    	    	    	    	    	    	    SDCz rt,offset (base)
9733965SjdpClass7:
9833965Sjdp	COPz BC br offset
9933965Sjdp	    	    	    	    	    	    	    BCzTL offset
10033965Sjdp	    	    	    	    	    	    	    BCzFL offset
10133965Sjdp
10233965SjdpThe coprocessor table defines coprocessor-specific registers that can
10333965Sjdpbe used with all of the above classes of instructions, where
10433965Sjdpappropriate.  It also defines additional coprocessor-specific
10533965Sjdpfunctions for Class3 (COPz cofun) instructions, Thus, the table allows
10633965Sjdpthe programmer to use convenient mnemonics and operands for these
10733965Sjdpfunctions, instead of the COPz mmenmonic and cofun operand.
10833965Sjdp
10933965SjdpThe names of the MIPS general registers and their aliases are defined
11033965Sjdpby the assembler and will be recognized as valid register names by the
11133965Sjdpassembler when used (where allowed) in coprocessor instructions.
11233965SjdpHowever, the names and values of all coprocessor data and control
11333965Sjdpregister mnemonics must be specified in the coprocessor table.
11433965Sjdp
11533965Sjdp
11633965SjdpTable Grammar
11733965Sjdp=============
11833965Sjdp
11933965SjdpHere is the grammar for the coprocessor table:
12033965Sjdp
12133965Sjdp	    table -> entry*
12233965Sjdp
12333965Sjdp	    entry -> [z entrydef] [comment] '\n'
12433965Sjdp
12533965Sjdp	    entrydef -> type name val
12633965Sjdp	    entrydef -> 'insn' name val funcdef ; type of entry (instruction)
12733965Sjdp
12833965Sjdp	    z -> 'p'['0'..'3']	    	     ; processor number
12933965Sjdp	    type -> ['dreg' | 'creg' | 'greg' ]	     ; type of entry (register)
13033965Sjdp	; 'dreg', 'creg' or 'greg' specifies a data, control, or general
13133965Sjdp	;	    register mnemonic, respectively
13233965Sjdp	    name -> [ltr|dec]*	    	     ; mnemonic of register/function
13333965Sjdp	    val -> [dec|hex]	    	     ; register/function number (integer constant)
13433965Sjdp
13533965Sjdp	    funcdef -> frange flags fields
13633965Sjdp	    	    	    	; bitfield range for opcode
13733965Sjdp	    	    	    	; list of fields' formats
13833965Sjdp	    fields -> field*
13933965Sjdp	    field -> [','] ftype frange flags
14033965Sjdp	    flags -> ['*' flagexpr]
14133965Sjdp	    flagexpr -> '[' flagexpr ']'
14233965Sjdp	    flagexpr -> val '|' flagexpr
14333965Sjdp	    ftype -> [ type | 'immed' | 'addr' ]
14433965Sjdp	; 'immed' specifies an immediate value; see grammar for "val" above
14533965Sjdp	    	; 'addr' specifies a C identifier; name of symbol to be resolved at
14633965Sjdp	;	    link time
14733965Sjdp	    frange -> ':' val '-' val	; starting to ending bit positions, where
14833965Sjdp	    	    	    	; where 0 is least significant bit
14933965Sjdp	    frange -> (null)	    	; default range of 31-0 will be assumed
15033965Sjdp
15133965Sjdp	    comment -> [';'|'#'] [char]*
15233965Sjdp	    char -> any printable character
15333965Sjdp	    ltr -> ['a'..'z'|'A'..'Z']
15433965Sjdp	    dec -> ['0'..'9']*	    	    	    	    	     ; value in decimal
155218822Sdim	    hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']*	; value in hexadecimal
15633965Sjdp
15733965Sjdp
15833965SjdpExamples
15933965Sjdp========
16033965Sjdp
16133965SjdpExample 1:
16233965Sjdp
16333965SjdpThe table:
16433965Sjdp
16533965Sjdp	    p1 dreg d1 1	     ; data register "d1" for COP1 has value 1
16633965Sjdp	    p1 creg c3 3	     ; ctrl register "c3" for COP1 has value 3
16733965Sjdp	    p3 func fill 0x1f:24-20	      ; function "fill" for COP3 has value 31 and
16833965Sjdp	    	    	; no fields
16933965Sjdp
17033965Sjdpwill allow the assembler to accept the following coprocessor instructions:
17133965Sjdp
17233965Sjdp	    LWC1 d1,0x100 ($2)
17333965Sjdp	    fill
17433965Sjdp
17533965SjdpHere, the general purpose register "$2", and instruction "LWC1", are standard
17633965Sjdpmnemonics built-in to the MIPS assembler.
17733965Sjdp
17833965Sjdp
17933965SjdpExample 2:
18033965Sjdp
18133965SjdpThe table:
18233965Sjdp
18333965Sjdp	    p3 dreg d3 3	     ; data register "d3" for COP3 has value 3
18433965Sjdp	    p3 creg c2 22	     ; control register "c2" for COP3 has value 22
18533965Sjdp	    p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0
18633965Sjdp	    	; function "fee" for COP3 has value 31, and 3 fields
18733965Sjdp	    	; consisting of a data register, a control register,
18833965Sjdp	    	; and an immediate value.
18933965Sjdp
19033965Sjdpwill allow the assembler to accept the following coprocessor instruction:
19133965Sjdp
19233965Sjdp	    fee d3,c2,0x1
19333965Sjdp
19433965Sjdpand will emit the object code:
19533965Sjdp
19633965Sjdp	    31-26  25 24-20 19-18  17-13 12-8  7-0
19733965Sjdp	    COPz   CO fun	    	      dreg  creg  immed
19833965Sjdp	    010011 1  11111 00	     00011 10110 00000001
19933965Sjdp
20033965Sjdp	    0x4ff07601
20133965Sjdp
20233965Sjdp
20333965SjdpExample 3:
20433965Sjdp
20533965SjdpThe table:
20633965Sjdp
20733965Sjdp	    p3 dreg d3 3	     ; data register "d3" for COP3 has value 3
20833965Sjdp	    p3 creg c2 22	     ; control register "c2" for COP3 has value 22
20933965Sjdp	    p3 func fuu 0x01f00001 dreg:17-13 creg:12-8
21033965Sjdp
21133965Sjdpwill allow the assembler to accept the following coprocessor
21233965Sjdpinstruction:
21333965Sjdp
21433965Sjdp	    fuu d3,c2
21533965Sjdp
21633965Sjdpand will emit the object code:
21733965Sjdp
21833965Sjdp	    31-26  25 24-20 19-18  17-13 12-8  7-0
21933965Sjdp	    COPz   CO fun	    	      dreg  creg
22033965Sjdp	    010011 1  11111 00	     00011 10110 00000001
22133965Sjdp
22233965Sjdp	    0x4ff07601
22333965Sjdp
22433965SjdpIn this way, the programmer can force arbitrary bits of an instruction
22533965Sjdpto have predefined values.
22633965Sjdp
22733965Sjdp=======================================================================
22833965SjdpAdditional notes:
22933965Sjdp
23033965SjdpEncoding of ranges:
23133965SjdpTo handle more than one bit position range within an instruction,
23233965Sjdpuse 0s to mask out the ranges which don't apply.
23333965SjdpMay decide to modify the syntax to allow commas separate multiple
23433965Sjdpranges within an instruction (range','range).
23533965Sjdp
23633965SjdpChanges in grammar:
23733965Sjdp	The number of parms argument to the function entry
23833965Sjdpwas deleted from the original format such that we now count the fields.
23933965Sjdp
24033965Sjdp----
24133965SjdpFIXME! should really change lexical analyzer
242218822Sdimto recognize 'dreg' etc. in context sensitive way.
24333965SjdpCurrently function names or mnemonics may be incorrectly parsed as keywords
24433965Sjdp
24533965SjdpFIXME! hex is ambiguous with any digit
24633965Sjdp
24733965Sjdp*/
24833965Sjdp
249218822Sdim#include "as.h"
250218822Sdim#include "itbl-lex.h"
25133965Sjdp#include "itbl-ops.h"
25233965Sjdp
25333965Sjdp/* #define DEBUG */
25433965Sjdp
25533965Sjdp#ifdef DEBUG
25633965Sjdp#ifndef DBG_LVL
25733965Sjdp#define DBG_LVL 1
25833965Sjdp#endif
25933965Sjdp#else
26033965Sjdp#define DBG_LVL 0
26133965Sjdp#endif
26233965Sjdp
26333965Sjdp#if DBG_LVL >= 1
26433965Sjdp#define DBG(x) printf x
26533965Sjdp#else
26633965Sjdp#define DBG(x)
26733965Sjdp#endif
26833965Sjdp
26933965Sjdp#if DBG_LVL >= 2
27033965Sjdp#define DBGL2(x) printf x
27133965Sjdp#else
27233965Sjdp#define DBGL2(x)
27333965Sjdp#endif
27433965Sjdp
27533965Sjdpstatic int sbit, ebit;
27633965Sjdpstatic struct itbl_entry *insn=0;
277218822Sdimstatic int yyerror (const char *);
27833965Sjdp
27933965Sjdp%}
28033965Sjdp
28133965Sjdp%union
28233965Sjdp  {
28333965Sjdp    char *str;
28433965Sjdp    int num;
28533965Sjdp    int processor;
28633965Sjdp    unsigned long val;
28733965Sjdp  }
28833965Sjdp
28933965Sjdp%token	    DREG CREG GREG IMMED ADDR INSN NUM ID NL PNUM
29033965Sjdp%type	    <val> value flags flagexpr
29133965Sjdp%type	    <num> number NUM ftype regtype pnum PNUM
29233965Sjdp%type	    <str> ID name
29333965Sjdp
29433965Sjdp%start insntbl
29533965Sjdp
29633965Sjdp%%
29733965Sjdp
29833965Sjdpinsntbl:
29933965Sjdp	entrys
30033965Sjdp	;
30133965Sjdp
30233965Sjdpentrys:
30333965Sjdp	entry entrys
30433965Sjdp	|
30533965Sjdp	;
30633965Sjdp
30733965Sjdpentry:
30833965Sjdp	pnum regtype name value NL
30933965Sjdp	  {
31033965Sjdp	    DBG (("line %d: entry pnum=%d type=%d name=%s value=x%x\n",
31133965Sjdp	    	    insntbl_line, $1, $2, $3, $4));
31233965Sjdp	    itbl_add_reg ($1, $2, $3, $4);
31333965Sjdp	  }
31433965Sjdp	| pnum INSN name value range flags
31533965Sjdp	  {
31633965Sjdp	    DBG (("line %d: entry pnum=%d type=INSN name=%s value=x%x",
31733965Sjdp	    	    insntbl_line, $1, $3, $4));
31833965Sjdp	    DBG ((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, $6));
31933965Sjdp	    insn=itbl_add_insn ($1, $3, $4, sbit, ebit, $6);
32033965Sjdp	  }
32133965Sjdp	fieldspecs NL
322107492Sobrien	  {}
32333965Sjdp	| NL
32433965Sjdp	| error NL
32533965Sjdp	;
32633965Sjdp
32733965Sjdpfieldspecs:
32833965Sjdp	',' fieldspec fieldspecs
32933965Sjdp	| fieldspec fieldspecs
33033965Sjdp	|
33133965Sjdp	;
33233965Sjdp
33333965Sjdpftype:
33433965Sjdp	regtype
33533965Sjdp	  {
33633965Sjdp	    DBGL2 (("ftype\n"));
33733965Sjdp	    $$ = $1;
33833965Sjdp	  }
33933965Sjdp	| ADDR
34033965Sjdp	  {
34133965Sjdp	    DBGL2 (("addr\n"));
34233965Sjdp	    $$ = ADDR;
34333965Sjdp	  }
34433965Sjdp	| IMMED
34533965Sjdp	  {
34633965Sjdp	    DBGL2 (("immed\n"));
34733965Sjdp	    $$ = IMMED;
34833965Sjdp	  }
34933965Sjdp	;
35033965Sjdp
35133965Sjdpfieldspec:
35233965Sjdp	ftype range flags
35333965Sjdp	  {
35433965Sjdp	    DBG (("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n",
35533965Sjdp	    	    insntbl_line, $1, sbit, ebit, $3));
35633965Sjdp	    itbl_add_operand (insn, $1, sbit, ebit, $3);
35733965Sjdp	  }
35833965Sjdp	;
35933965Sjdp
36033965Sjdpflagexpr:
36133965Sjdp	NUM '|' flagexpr
36233965Sjdp	  {
36333965Sjdp	    $$ = $1 | $3;
36433965Sjdp	  }
36533965Sjdp	| '[' flagexpr ']'
36633965Sjdp	  {
36733965Sjdp	    $$ = $2;
36833965Sjdp	  }
36933965Sjdp	| NUM
37033965Sjdp	  {
37133965Sjdp	    $$ = $1;
37233965Sjdp	  }
37333965Sjdp	;
37433965Sjdp
37533965Sjdpflags:
37633965Sjdp	'*' flagexpr
37733965Sjdp	  {
37833965Sjdp	    DBGL2 (("flags=%d\n", $2));
37933965Sjdp	    $$ = $2;
38033965Sjdp	  }
38133965Sjdp	|
38233965Sjdp	  {
38333965Sjdp	    $$ = 0;
38433965Sjdp	  }
38533965Sjdp	;
38633965Sjdp
38733965Sjdprange:
38833965Sjdp	':' NUM '-' NUM
38933965Sjdp	  {
39033965Sjdp	    DBGL2 (("range %d %d\n", $2, $4));
39133965Sjdp	    sbit = $2;
39233965Sjdp	    ebit = $4;
39333965Sjdp	  }
39433965Sjdp	|
39533965Sjdp	  {
39633965Sjdp	    sbit = 31;
39733965Sjdp	    ebit = 0;
39833965Sjdp	  }
39933965Sjdp	;
40033965Sjdp
40133965Sjdppnum:
40233965Sjdp	PNUM
40333965Sjdp	  {
40433965Sjdp	    DBGL2 (("pnum=%d\n",$1));
40533965Sjdp	    $$ = $1;
40633965Sjdp	  }
40733965Sjdp	;
40833965Sjdp
40933965Sjdpregtype:
41033965Sjdp	     DREG
41133965Sjdp	  {
41233965Sjdp	    DBGL2 (("dreg\n"));
41333965Sjdp	    $$ = DREG;
41433965Sjdp	  }
41533965Sjdp	| CREG
41633965Sjdp	  {
41733965Sjdp	    DBGL2 (("creg\n"));
41833965Sjdp	    $$ = CREG;
41933965Sjdp	  }
42033965Sjdp	| GREG
42133965Sjdp	  {
42233965Sjdp	    DBGL2 (("greg\n"));
42333965Sjdp	    $$ = GREG;
42433965Sjdp	  }
42533965Sjdp	;
42633965Sjdp
42733965Sjdpname:
42833965Sjdp	ID
42933965Sjdp	  {
43033965Sjdp	    DBGL2 (("name=%s\n",$1));
43133965Sjdp	    $$ = $1;
43233965Sjdp	  }
43333965Sjdp	;
43433965Sjdp
43533965Sjdpnumber:
43633965Sjdp	NUM
43733965Sjdp	  {
43833965Sjdp	    DBGL2 (("num=%d\n",$1));
43933965Sjdp	    $$ = $1;
44033965Sjdp	  }
44133965Sjdp	;
44233965Sjdp
44333965Sjdpvalue:
44433965Sjdp	NUM
44533965Sjdp	  {
44633965Sjdp	    DBGL2 (("val=x%x\n",$1));
44733965Sjdp	    $$ = $1;
44833965Sjdp	  }
44933965Sjdp	;
45033965Sjdp%%
45133965Sjdp
45233965Sjdpstatic int
45333965Sjdpyyerror (msg)
45433965Sjdp     const char *msg;
45533965Sjdp{
45633965Sjdp  printf ("line %d: %s\n", insntbl_line, msg);
45733965Sjdp  return 0;
45833965Sjdp}
459