1/* bfin-lex.l  ADI Blackfin lexer
2   Copyright 2005
3   Free Software Foundation, Inc.
4
5   This file is part of GAS, the GNU Assembler.
6
7   GAS is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11
12   GAS is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with GAS; see the file COPYING.  If not, write to the Free
19   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20   02110-1301, USA.  */
21%{
22
23#include <stdlib.h>
24#include <string.h>
25#include "bfin-defs.h"
26#include "bfin-parse.h"
27#include "as.h"
28
29static long parse_int (char **end);
30static int parse_halfreg (Register *r, int cl, char *hr);
31static int parse_reg (Register *r, int type, char *rt);
32int yylex (void);
33
34#define _REG yylval.reg
35
36
37%}
38
39/* Define Start States ... Actually we will use exclusion.
40   If no start state is specified it should match any state
41   and <INITIAL> would match some keyword rules only with
42   initial.  */
43%s KEYWORD
44
45%%
46[sS][fF][tT][rR][eE][sS][eE][tT]        _REG.regno = REG_sftreset;  return REG;
47[oO][mM][oO][dD][eE]                    _REG.regno = REG_omode;     return REG;
48[iI][dD][lL][eE]_[rR][eE][qQ]           _REG.regno = REG_idle_req;  return REG;
49[hH][wW][eE][rR][rR][cC][aA][uU][sS][eE] _REG.regno = REG_hwerrcause; return REG;
50[eE][xX][cC][aA][uU][sS][eE]            _REG.regno = REG_excause;   return REG;
51[eE][mM][uU][cC][aA][uU][sS][eE]	_REG.regno = REG_emucause;  return REG;
52[zZ]                                    return Z;
53[xX]                                    return X;
54[wW]32                                  yylval.value = M_W32; return MMOD;
55[wW]                                    return W;
56[vV][iI][tT]_[mM][aA][xX]               return VIT_MAX;
57[vV]               return V; /* Special: V is a statflag and a modifier.  */
58[uU][sS][pP]       _REG.regno = REG_USP; return REG;
59[tT][lL]                                return TL;
60[tT][hH]                                return TH;
61[tT][fF][uU]                            yylval.value = M_TFU; return MMOD;
62[tT][eE][sS][tT][sS][eE][tT]            return TESTSET;
63[tT]                                    yylval.value = M_T; return MMOD;
64[sS]                                                        return S;
65[sS][yY][sS][cC][fF][gG]       _REG.regno = REG_SYSCFG; return REG;
66[sS][tT][iI]                            return STI;
67[sS][sS][yY][nN][cC]                    return SSYNC;
68[sS][pP]"."[lL]                         _REG.regno = REG_SP; return HALF_REG;
69[sS][pP]"."[hH]                         _REG.regno = REG_SP | F_REG_HIGH; return HALF_REG;
70[sS][pP]                                _REG.regno = REG_SP; return REG;
71[sS][iI][gG][nN][bB][iI][tT][sS]        return SIGNBITS;
72[sS][iI][gG][nN]                        return SIGN;
73[sS][eE][qQ][sS][tT][aA][tT]     _REG.regno = REG_SEQSTAT; return REG;
74[sS][eE][aA][rR][cC][hH]                return SEARCH;
75[sS][hH][iI][fF][tT]                    return SHIFT;
76[sS][cC][oO]                            return SCO;
77
78[sS][aA][aA]                            return SAA;
79[sS]2[rR][nN][dD]                       yylval.value = M_S2RND; return MMOD;
80[rR][tT][xX]                            return RTX;
81[rR][tT][sS]                            return RTS;
82[rR][tT][nN]                            return RTN;
83[rR][tT][iI]                            return RTI;
84[rR][tT][eE]                            return RTE;
85[rR][oO][tT]                            return ROT;
86[rR][nN][dD]20                          return RND20;
87[rR][nN][dD]12                          return RND12;
88[rR][nN][dD][lL]                        return RNDL;
89[rR][nN][dD][hH]                        return RNDH;
90[rR][nN][dD]                            return RND;
91
92[rR][0-7]"."[lLhHbB]  return parse_halfreg(&yylval.reg, T_REG_R, yytext);
93
94[rR][eE][tT][sS]		_REG.regno = REG_RETS; return REG;
95[rR][eE][tT][iI]		_REG.regno = REG_RETI; return REG;
96[rR][eE][tT][xX]		_REG.regno = REG_RETX; return REG;
97[rR][eE][tT][nN]		_REG.regno = REG_RETN; return REG;
98[rR][eE][tT][eE]		_REG.regno = REG_RETE; return REG;
99[eE][mM][uU][dD][aA][tT]	_REG.regno = REG_EMUDAT; return REG;
100[rR][aA][iI][sS][eE]		return RAISE;
101
102[rR][0-7]           return parse_reg (&yylval.reg, T_REG_R, yytext);
103
104[rR]      return R;
105[pP][rR][nN][tT]                        return PRNT;
106[pP][cC]                                return PC;
107[pP][aA][cC][kK]                        return PACK;
108
109[pP][0-5]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_P, yytext);
110[pP][0-5]           return parse_reg (&yylval.reg, T_REG_P, yytext);
111
112[oO][uU][tT][cC]                        return OUTC;
113[oO][nN][eE][sS]                        return ONES;
114
115[nN][oO][tT]                            return NOT;
116[nN][oO][pP]                            return NOP;
117[mM][nN][oO][pP]                        return MNOP;
118[nN][sS]                                return NS;
119
120
121[mM][iI][nN]                            return MIN;
122[mM][aA][xX]                            return MAX;
123
124[mM][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_M, yytext);
125[mM][0-3]           return parse_reg (&yylval.reg, T_REG_M, yytext);
126
127[mM]                                    return M;
128[lL][tT]                                return LT;
129[lL][sS][hH][iI][fF][tT]                return LSHIFT;
130[lL][sS][eE][tT][uU][pP]                return LSETUP;
131[lL][oO][oO][pP]			return LOOP;
132[lL][oO][oO][pP]_[bB][eE][gG][iI][nN]	return LOOP_BEGIN;
133[lL][oO][oO][pP]_[eE][nN][dD]		return LOOP_END;
134
135[lL][eE]                                return LE;
136[lL][cC]0 _REG.regno = REG_LC0; return REG;
137[lL][tT]0 _REG.regno = REG_LT0; return REG;
138[lL][bB]0 _REG.regno = REG_LB0; return REG;
139[lL][cC]1 _REG.regno = REG_LC1; return REG;
140[lL][tT]1 _REG.regno = REG_LT1; return REG;
141[lL][bB]1 _REG.regno = REG_LB1; return REG;
142
143[lL][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_L, yytext);
144[lL][0-3]           return parse_reg (&yylval.reg, T_REG_L, yytext);
145[lL][oO]                                return LO;
146[jJ][uU][mM][pP]"."[sS]                 { BEGIN 0; return JUMP_DOT_S;}
147[jJ][uU][mM][pP]"."[lL]                 { BEGIN 0; return JUMP_DOT_L;}
148[jJ][uU][mM][pP]                        { BEGIN 0; return JUMP;}
149[jJ][uU][mM][pP]"."[xX]                 { BEGIN 0; return JUMP_DOT_L; }
150[iI][uU]                                yylval.value = M_IU;   return MMOD;
151[iI][sS][sS]2                           yylval.value = M_ISS2; return MMOD;
152[iI][sS]                                yylval.value = M_IS;   return MMOD;
153[iI][hH]                                yylval.value = M_IH;   return MMOD;
154[iI][fF]                                return IF;
155[iI][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_I, yytext);
156[iI][0-3]           return parse_reg (&yylval.reg, T_REG_I, yytext);
157[hH][lL][tT]                            return HLT;
158[hH][iI]                                return HI;
159[gG][tT]                                return GT;
160[gG][eE]                                return GE;
161[fF][uU]                                yylval.value = M_FU; return MMOD;
162[fF][pP]         _REG.regno = REG_FP; return REG;
163[fF][pP]"."[lL]  _REG.regno = REG_FP; return HALF_REG;
164[fF][pP]"."[hH]  _REG.regno = REG_FP | F_REG_HIGH; return HALF_REG;
165
166[eE][xX][tT][rR][aA][cC][tT]            return EXTRACT;
167[eE][xX][pP][aA][dD][jJ]                return EXPADJ;
168[eE][xX][cC][pP][tT]                    return EXCPT;
169[eE][mM][uU][eE][xX][cC][pP][tT]        return EMUEXCPT;
170[dD][iI][vV][sS]                        return DIVS;
171[dD][iI][vV][qQ]                        return DIVQ;
172[dD][iI][sS][aA][lL][gG][nN][eE][xX][cC][pP][tT]  return DISALGNEXCPT;
173[dD][eE][pP][oO][sS][iI][tT]            return DEPOSIT;
174[dD][bB][gG][hH][aA][lL][tT]            return DBGHALT;
175[dD][bB][gG][cC][mM][pP][lL][xX]        return DBGCMPLX;
176[dD][bB][gG][aA][lL]                    return DBGAL;
177[dD][bB][gG][aA][hH]                    return DBGAH;
178[dD][bB][gG][aA]                        return DBGA;
179[dD][bB][gG]                            return DBG;
180[cC][yY][cC][lL][eE][sS]2  { _REG.regno = REG_CYCLES2; return REG; }
181[cC][yY][cC][lL][eE][sS]  { _REG.regno = REG_CYCLES; return REG; }
182[cC][sS][yY][nN][cC]                    return CSYNC;
183[cC][oO]                                return CO;
184[cC][lL][iI]                            return CLI;
185
186[cC][cC]     _REG.regno = REG_CC; return CCREG;
187[cC][aA][lL][lL]"."[xX]                 { BEGIN 0; return CALL;}
188[cC][aA][lL][lL]                        { BEGIN 0; return CALL;}
189[bB][yY][tT][eE][uU][nN][pP][aA][cC][kK] return BYTEUNPACK;
190[bB][yY][tT][eE][pP][aA][cC][kK]        return BYTEPACK;
191[bB][yY][tT][eE][oO][pP]16[mM]          return BYTEOP16M;
192[bB][yY][tT][eE][oO][pP]16[pP]          return BYTEOP16P;
193[bB][yY][tT][eE][oO][pP]3[pP]           return BYTEOP3P;
194[bB][yY][tT][eE][oO][pP]2[mM]           return BYTEOP2M;
195[bB][yY][tT][eE][oO][pP]2[pP]           return BYTEOP2P;
196[bB][yY][tT][eE][oO][pP]1[pP]           return BYTEOP1P;
197[bB][yY]                                return BY;
198[bB][xX][oO][rR][sS][hH][iI][fF][tT]    return BXORSHIFT;
199[bB][xX][oO][rR]                        return BXOR;
200
201[bB][rR][eE][vV]                        return BREV;
202[bB][pP]                                return BP;
203[bB][iI][tT][tT][sS][tT]                return BITTST;
204[bB][iI][tT][tT][gG][lL]                return BITTGL;
205[bB][iI][tT][sS][eE][tT]                return BITSET;
206[bB][iI][tT][mM][uU][xX]                return BITMUX;
207[bB][iI][tT][cC][lL][rR]                return BITCLR;
208[bB][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_B, yytext);
209[bB][0-3]           return parse_reg (&yylval.reg, T_REG_B, yytext);
210[bB]                                    return B;
211[aA][zZ]  _REG.regno = S_AZ;   return STATUS_REG;
212[aA][nN]  _REG.regno = S_AN;   return STATUS_REG;
213[aA][qQ]  _REG.regno = S_AQ;   return STATUS_REG;
214[aA][cC]0 _REG.regno = S_AC0;  return STATUS_REG;
215[aA][cC]1 _REG.regno = S_AC1;  return STATUS_REG;
216[aA][vV]0 _REG.regno = S_AV0;  return STATUS_REG;
217[aA][vV]0[sS] _REG.regno = S_AV0S; return STATUS_REG;
218[aA][vV]1 _REG.regno = S_AV1;  return STATUS_REG;
219[aA][vV]1[sS] _REG.regno = S_AV1S; return STATUS_REG;
220[vV] _REG.regno = S_V; return STATUS_REG;
221[vV][sS]  _REG.regno = S_VS;   return STATUS_REG;
222
223
224[aA][sS][tT][aA][tT]   _REG.regno = REG_ASTAT; return REG;
225[aA][sS][hH][iI][fF][tT]                return ASHIFT;
226[aA][sS][lL]                            return ASL;
227[aA][sS][rR]                            return ASR;
228[aA][lL][iI][gG][nN]8                   return ALIGN8;
229[aA][lL][iI][gG][nN]16                  return ALIGN16;
230[aA][lL][iI][gG][nN]24                  return ALIGN24;
231[aA]1"."[lL]    return A_ONE_DOT_L;
232[aA]0"."[lL]    return A_ZERO_DOT_L;
233[aA]1"."[hH]    return A_ONE_DOT_H;
234[aA]0"."[hH]    return A_ZERO_DOT_H;
235[aA][bB][sS]                            return ABS;
236abort                                   return ABORT;
237[aA]1"."[xX]    _REG.regno = REG_A1x; return REG;
238[aA]1"."[wW]    _REG.regno = REG_A1w; return REG;
239[aA]1           _REG.regno = REG_A1;  return REG_A_DOUBLE_ONE;
240[aA]0"."[xX]    _REG.regno = REG_A0x; return REG;
241[aA]0"."[wW]    _REG.regno = REG_A0w; return REG;
242[aA]0           _REG.regno = REG_A0;  return REG_A_DOUBLE_ZERO;
243[Gg][Oo][Tt]	return GOT;
244[Gg][Oo][Tt]"17"[Mm]"4" return GOT17M4;
245[Ff][Uu][Nn][Cc][Dd][Ee][Ss][Cc]"_"[Gg][Oo][Tt]"17"[Mm]"4" return FUNCDESC_GOT17M4;
246[Pp][Ll][Tt][Pp][Cc]	return PLTPC;
247
248
249"~"                     return TILDA;
250"|="                    return _BAR_ASSIGN;
251"|"                     return BAR;
252"^="                    return _CARET_ASSIGN;
253"^"                     return CARET;
254"]"                     return RBRACK;
255"["                     return LBRACK;
256">>>="                  return _GREATER_GREATER_GREATER_THAN_ASSIGN;
257">>="                   return _GREATER_GREATER_ASSIGN;
258">>>"                   return _GREATER_GREATER_GREATER;
259">>"                    return GREATER_GREATER;
260"=="                    return _ASSIGN_ASSIGN;
261"="                     return ASSIGN;
262"<="                    return _LESS_THAN_ASSIGN;
263"<<="                   return _LESS_LESS_ASSIGN;
264"<<"                    return LESS_LESS;
265"<"                     return LESS_THAN;
266"("                     return LPAREN;
267")"                     return RPAREN;
268":"                     return COLON;
269"/"                     return SLASH;
270"-="                    return _MINUS_ASSIGN;
271"+|+"					return _PLUS_BAR_PLUS;
272"-|+"					return _MINUS_BAR_PLUS;
273"+|-"					return _PLUS_BAR_MINUS;
274"-|-"					return _MINUS_BAR_MINUS;
275"--"                    return _MINUS_MINUS;
276"-"                     return MINUS;
277","                     return COMMA;
278"+="                    return _PLUS_ASSIGN;
279"++"                    return _PLUS_PLUS;
280"+"                     return PLUS;
281"*="                    return _STAR_ASSIGN;
282"*"                     return STAR;
283"&="                    return _AMPERSAND_ASSIGN;
284"&"                     return AMPERSAND;
285"%"                     return PERCENT;
286"!"                     return BANG;
287";"                     return SEMICOLON;
288"=!"			return _ASSIGN_BANG;
289"||"			return DOUBLE_BAR;
290"@"			return AT;
291<KEYWORD>[pP][rR][eE][fF][eE][tT][cC][hH]        return PREFETCH;
292<KEYWORD>[uU][nN][lL][iI][nN][kK]                return UNLINK;
293<KEYWORD>[lL][iI][nN][kK]                        return LINK;
294<KEYWORD>[iI][dD][lL][eE]                        return IDLE;
295<KEYWORD>[iI][fF][lL][uU][sS][hH]                return IFLUSH;
296<KEYWORD>[fF][lL][uU][sS][hH][iI][nN][vV]        return FLUSHINV;
297<KEYWORD>[fF][lL][uU][sS][hH]                    return FLUSH;
298([0-9]+)|(0[xX][0-9a-fA-F]+)|([bhfodBHOFD]#[0-9a-fA-F]+)|(0.[0-9]+) {
299    yylval.value = parse_int (&yytext);
300    return NUMBER;
301  }
302[A-Za-z_$.][A-Za-z0-9_$.]* {
303    yylval.symbol = symbol_find_or_make (yytext);
304    symbol_mark_used (yylval.symbol);
305    return SYMBOL;
306  }
307[0-9][bfBF] {
308    char *name;
309    char *ref = strdup (yytext);
310    if (ref[1] == 'b' || ref[1] == 'B')
311      {
312        name = fb_label_name ((int) (ref[0] - '0'), 0);
313	yylval.symbol = symbol_find (name);
314
315	if ((yylval.symbol != NULL)
316             && (S_IS_DEFINED (yylval.symbol)))
317          return SYMBOL;
318	as_bad ("backward reference to unknown label %d:",
319						  (int) (ref[0] - '0'));
320      }
321    else if (ref[1] == 'f' || ref[1] == 'F')
322      {
323        /* Forward reference.  Expect symbol to be undefined or
324           unknown.  undefined: seen it before.  unknown: never seen
325           it before.
326
327           Construct a local label name, then an undefined symbol.
328           Just return it as never seen before.  */
329
330        name = fb_label_name ((int) (ref[0] - '0'), 1);
331	yylval.symbol = symbol_find_or_make (name);
332	/* We have no need to check symbol properties.  */
333	return SYMBOL;
334      }
335  }
336[ \t\n]                                    ;
337"/*".*"*/"                                 ;
338.                                          return yytext[0];
339%%
340static long parse_int (char **end)
341{
342  char fmt = '\0';
343  int not_done = 1;
344  int shiftvalue = 0;
345  char * char_bag;
346  long value = 0;
347  char c;
348  char *arg = *end;
349
350  while (*arg && *arg == ' ')
351    arg++;
352
353  switch (*arg)
354    {
355      case '1':
356      case '2':
357      case '3':
358      case '4':
359      case '5':
360      case '6':
361      case '7':
362      case '8':
363      case '9':
364        fmt = 'd';
365        break;
366
367      case '0':  /* Accept different formated integers hex octal and binary. */
368        {
369	  c = *++arg;
370          arg++;
371	  if (c == 'x' || c == 'X') /* Hex input.  */
372	    fmt = 'h';
373	  else if (c == 'b' || c == 'B')
374	    fmt = 'b';
375	  else if (c == '.')
376	    fmt = 'f';
377	  else
378            {             /* Octal.  */
379	      arg--;
380	      fmt = 'o';
381	    }
382	  break;
383        }
384
385      case 'd':
386      case 'D':
387      case 'h':
388      case 'H':
389      case 'o':
390      case 'O':
391      case 'b':
392      case 'B':
393      case 'f':
394      case 'F':
395        {
396	  fmt = *arg++;
397	  if (*arg == '#')
398	    arg++;
399        }
400    }
401
402  switch (fmt)
403    {
404      case 'h':
405      case 'H':
406        shiftvalue = 4;
407        char_bag = "0123456789ABCDEFabcdef";
408        break;
409
410      case 'o':
411      case 'O':
412        shiftvalue = 3;
413        char_bag = "01234567";
414        break;
415
416      case 'b':
417      case 'B':
418        shiftvalue = 1;
419        char_bag = "01";
420        break;
421
422/* The assembler allows for fractional constants to be created
423   by either the 0.xxxx or the f#xxxx format
424
425   i.e.   0.5 would result in 0x4000
426
427   note .5 would result in the identifier .5.
428
429   The assembler converts to fractional format 1.15 by the simple rule:
430
431             value = (short) (finput * (1 << 15)).  */
432
433      case 'f':
434      case 'F':
435        {
436          float fval = 0.0;
437          float pos = 10.0;
438          while (1)
439            {
440              int c;
441              c = *arg++;
442
443              if (c >= '0' && c <= '9')
444                {
445                  float digit = (c - '0') / pos;
446                  fval = fval + digit;
447                  pos = pos * 10.0;
448                }
449              else
450                {
451	          *--arg = c;
452                  value = (short) (fval * (1 << 15));
453                  break;
454                }
455            }
456          *end = arg+1;
457          return value;
458        }
459
460      case 'd':
461      case 'D':
462      default:
463        {
464          while (1)
465            {
466              int c;
467              c = *arg++;
468              if (c >= '0' && c <= '9')
469                value = (value * 10) + (c - '0');
470              else
471                {
472                  /* Constants that are suffixed with k|K are multiplied by 1024
473                     This suffix is only allowed on decimal constants. */
474                  if (c == 'k' || c == 'K')
475                    value *= 1024;
476                  else
477                    *--arg = c;
478                  break;
479                }
480            }
481          *end = arg+1;
482          return value;
483        }
484    }
485
486  while (not_done)
487    {
488      char c;
489      c = *arg++;
490      if (c == 0 || !index (char_bag, c))
491	{
492          not_done = 0;
493          *--arg = c;
494        }
495      else
496        {
497          if (c >= 'a' && c <= 'z')
498            c = c - ('a' - '9') + 1;
499          else if (c >= 'A' && c <= 'Z')
500            c = c - ('A' - '9') + 1;
501
502          c -= '0';
503          value = (value << shiftvalue) + c;
504        }
505    }
506  *end = arg+1;
507  return value;
508}
509
510
511static int parse_reg (Register *r, int cl, char *rt)
512{
513  r->regno = cl | (rt[1] - '0');
514  return REG;
515}
516
517static int parse_halfreg (Register *r, int cl, char *rt)
518{
519  r->regno = cl | (rt[1] - '0');
520
521  switch (rt[3])
522    {
523      case 'b':
524      case 'B':
525	return BYTE_DREG;
526
527      case 'l':
528      case 'L':
529	break;
530
531      case 'h':
532      case 'H':
533	r->regno |= F_REG_HIGH;
534	break;
535    }
536
537  return HALF_REG;
538}
539
540/* Our start state is KEYWORD as we have
541   command keywords such as PREFETCH.  */
542
543void
544set_start_state (void)
545{
546  BEGIN KEYWORD;
547}
548
549
550#ifndef yywrap
551int
552yywrap ()
553{
554  return 1;
555}
556#endif
557