asm-scan.ll.gen.py 8.3 KB
Newer Older
1
#!/usr/bin/env python
Benoit Perrot's avatar
Benoit Perrot committed
2
##
Benoit Perrot's avatar
Benoit Perrot committed
3
## This file is part of Nolimips, a MIPS simulator with unlimited registers
4
## Copyright (C) 2003, 2004, 2006 Benoit Perrot <benoit@lrde.epita.fr>
Benoit Perrot's avatar
Benoit Perrot committed
5
##
Benoit Perrot's avatar
Benoit Perrot committed
6
## Nolimips is free software; you can redistribute it and/or modify
Benoit Perrot's avatar
Benoit Perrot committed
7
8
9
10
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## 
Benoit Perrot's avatar
Benoit Perrot committed
11
## Nolimips is distributed in the hope that it will be useful,
Benoit Perrot's avatar
Benoit Perrot committed
12
13
14
15
16
17
18
19
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
20

Benoit Perrot's avatar
Benoit Perrot committed
21
import sys, os
22
23
import string, re

Benoit Perrot's avatar
Benoit Perrot committed
24
import nolimips
25
from nolimips import define_id
26

Benoit Perrot's avatar
Benoit Perrot committed
27
#### Nolimips' Flex scanner generator --------------------------
Benoit Perrot's avatar
Benoit Perrot committed
28

Benoit Perrot's avatar
Benoit Perrot committed
29
30
31
32
33
if __name__ != "__main__" or len(sys.argv) != 2:
  print "Usage: .. SRCDIR"
  sys.exit(1)
srcdir = sys.argv[1]

Benoit Perrot's avatar
Benoit Perrot committed
34
parser = nolimips.InstructionSetParser()
35
36
instructions = parser.parse(sys.stdin)

Benoit Perrot's avatar
Benoit Perrot committed
37
sys.stdout = file("asm-scan.ll.tmp", "w")
38
39
40

## Prologue ----------------------------
print "%{                                             /* -*- C++ -*- */"
41
42
print nolimips.license
print nolimips.generated_by_hand
43
44
print """
#include <string>
Benoit Perrot's avatar
Benoit Perrot committed
45
#include <sstream>
46
#include <cerrno>
47
48
49
50

#include \"common.hh\"
#include \"misc/escape.hh\"

51
52
#include \"vm/cpu.hh\"

53
54
55
56
57
58
59
#include \"parse/asm-scan.hh\"

#define YY_NEVER_INTERACTIVE 1

#define YY_USER_ACTION				\\
    yylloc->columns (yyleng);

60
using inst::Register;
61
using vm::Cpu;
62

63
64
typedef yy::parser::token token;

65
66
67
68
69
70
71
72
73
74
75
76
%}

%option noyywrap
%option nounput
%option debug

%x STATE_STRING
eol			\\n|\\r|\\n\\r|\\r\\n

dec_int			[0-9]+
hex_int			0x[0-9A-Fa-f]+

Benoit Perrot's avatar
Benoit Perrot committed
77
id			[a-zA-Z_][a-zA-Z_0-9]*
78
79
80
81
82
83
84
85
%%

%{
  yylloc->step ();
%}

[ \\t]+			yylloc->step ();
[#;][^\\n\\r]*		yylloc->step ();
Benoit Perrot's avatar
Benoit Perrot committed
86
{eol}			yylloc->lines (1); yylloc->step ();
87

88
89
90
\"(\"			return token::LPAREN;
\")\"			return token::RPAREN;
\",\"			return token::COMMA;
91

92
93
94
95
\"+\"			return token::EXP_ADD;
\"-\"			return token::EXP_SUB;
\"*\"			return token::EXP_MUL;
\"/\"			return token::EXP_DIV;
96

97
98
\".text\"			return token::DIR_TEXT;
\".data\"			return token::DIR_DATA;
Benoit Perrot's avatar
Benoit Perrot committed
99

100
101
102
103
104
105
\".space\"		return token::DIR_SPACE;
\".byte\"			return token::DIR_BYTE;
\".half\"			return token::DIR_HALF;
\".word\"			return token::DIR_WORD;
\".ascii\"		return token::DIR_ASCII;
\".asciiz\"		return token::DIR_ASCIIZ;
106
107
108
109
"""

## Body --------------------------------
for inst in instructions:
110
111
  print '"' + inst.opcode + \
        '"\t\t\treturn token::' + define_id(inst.opcode) + ";"
112
113
114

## Epilogue ----------------------------
print """
Benoit Perrot's avatar
Benoit Perrot committed
115
116
\"$\"([0-9]|[12][0-9]|3[01])	{
  yylval->reg = new Register(Register::generic, atoi(yytext +1));
117
  return token::REGISTER;
Benoit Perrot's avatar
Benoit Perrot committed
118
119
}

120
\"$zero\"			{
121
  yylval->reg = new Register(Register::general, Cpu::zero);
122
  return token::REGISTER;
123
}"""
Benoit Perrot's avatar
Benoit Perrot committed
124
125
126
127
128
129
for k, r in [("v", range(2)), ("a", range(4)),
             ("t", range(10)), ("s", range(8))]:
  for i in r:
    print "\"$" + k + str(i) + "\"			{"
    print "  yylval->reg = new Register(Register::general, " + \
          "Cpu::" + k + str(i)+ ");"
130
    print "  return token::REGISTER;\n}"
131
print """
132
\"$sp\"			{
133
  yylval->reg = new Register(Register::general, Cpu::sp);
134
  return token::REGISTER;
135
136
}
\"$fp\"			{
137
  yylval->reg = new Register(Register::general, Cpu::fp);
138
  return token::REGISTER;
139
140
}
\"$ra\"			{
141
  yylval->reg = new Register(Register::general, Cpu::ra);
142
  return token::REGISTER;
143
144
145
}

\"$x\"{dec_int}		{
146
  yylval->reg = new Register(Register::unlimited, atoi(yytext +2));
147
  return token::REGISTER;
148
149
150
}


Benoit Perrot's avatar
Benoit Perrot committed
151
{id}			{
152
  yylval->id = new misc::unique_string(yytext);
153
  return token::LABEL;
154
}
Benoit Perrot's avatar
Benoit Perrot committed
155
{id}\":\"		{
156
157
  yytext[yyleng - 1] = 0; // Remove last character (side-effects on yytext are allowed)
  yylval->id = new misc::unique_string(yytext);
158
  return token::LABEL_DEF;
159
160
161
}


Benoit Perrot's avatar
Benoit Perrot committed
162
163
-?{dec_int}		{
  std::istringstream iss(yytext);
164
165
166
167
168
169

  if (iss.peek() == '-')
    iss >> std::dec >> yylval->i;
  else
    iss >> std::dec >> (unsigned&) yylval->i;

Benoit Perrot's avatar
Benoit Perrot committed
170
171
172
173
174
175
176
  if (iss.fail())
    {
      std::cerr << *yylloc
		<< \": unrecognized integer (may be too large): \"
		<< yytext << std::endl;
      exit_set (exit_scan);
    }
177
  return token::INTEGER;
Benoit Perrot's avatar
Benoit Perrot committed
178
}
Benoit Perrot's avatar
Benoit Perrot committed
179
-?{hex_int}		{
Benoit Perrot's avatar
Benoit Perrot committed
180
  std::istringstream iss(yytext);
181
182
183
184
185
186

  if (iss.peek() == '-')
    iss >> std::hex >> yylval->i;
  else
    iss >> std::hex >> (unsigned&) yylval->i;

Benoit Perrot's avatar
Benoit Perrot committed
187
188
189
190
191
192
193
  if (iss.fail())
    {
      std::cerr << *yylloc
		<< \": unrecognized integer (may be too large): \"
		<< yytext << std::endl;
      exit_set (exit_scan);
    }
194
  return token::INTEGER;
Benoit Perrot's avatar
Benoit Perrot committed
195
}
196

197
198
199
200
201
202
203
204
'\\\\a'			yylval->i = '\\a'; return token::INTEGER;
'\\\\b'			yylval->i = '\\b'; return token::INTEGER;
'\\\\f'			yylval->i = '\\f'; return token::INTEGER;
'\\\\n'			yylval->i = '\\n'; return token::INTEGER;
'\\\\r'			yylval->i = '\\r'; return token::INTEGER;
'\\\\t'			yylval->i = '\\t'; return token::INTEGER;
'\\\\v'			yylval->i = '\\v'; return token::INTEGER;
'\\\\[\\\\\\']'		yylval->i = yytext[1]; return token::INTEGER;
Benoit Perrot's avatar
Benoit Perrot committed
205
206
207
208
209
'\\\\.'			{
  std::cerr << *yylloc
	    << \": unrecognized escape: \" << escape (yytext) << std::endl;
  exit_set (exit_scan);
}
210
'[^\\'\\n\\r\\\\]'	yylval->i = yytext[1]; return token::INTEGER;
Benoit Perrot's avatar
Benoit Perrot committed
211

212
213
214
215
216

\\\"			yylval->s = new std::string; BEGIN STATE_STRING;
<STATE_STRING>{
  \\\"			{
    BEGIN INITIAL;
217
    return token::STRING;
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  }

  \\\\[0-7]{3}		{
    long c = strtol (yytext + 1, 0, 8);
    if (c > 255)
      {
	std::cerr << *yylloc
		  << \": invalid escape: \" << escape (yytext) << std::endl;
	exit_set (exit_scan);
      }
    else
      *(yylval->s) += c;
  }
  
  \\\\x[0-9a-fA-F]{2}	{
    *(yylval->s) += strtol (yytext + 2, 0, 16);
  }
  
  \\\\a			*(yylval->s) += '\\a';
  \\\\b			*(yylval->s) += '\\b';
  \\\\f			*(yylval->s) += '\\f';
  \\\\n			*(yylval->s) += '\\n';
  \\\\r			*(yylval->s) += '\\r';
  \\\\t			*(yylval->s) += '\\t';
  \\\\v			*(yylval->s) += '\\v';
  \\\\[\\\\\"\"]		*(yylval->s) += yytext[1];
  \\\\.			{
    std::cerr << *yylloc
	      << \": unrecognized escape: \" << escape (yytext) << std::endl;
    exit_set (exit_scan);
  }
  
  [^\\\"\\n\\r\\\\]+		yylval->s->append (yytext, yyleng);
  
Benoit Perrot's avatar
Benoit Perrot committed
252
253
  {eol}			{
    yylloc->lines (1);
Benoit Perrot's avatar
Benoit Perrot committed
254
    yylval->s->append (\"\\n\", 1);
255
256
257
258
259
260
261
262
  }
  
  <<EOF>>		{
    std::cerr
      << *yylloc << \": unexpected end of file in a string\" << std::endl;
    exit_set (exit_scan);
    
    BEGIN INITIAL;
263
    return token::STRING;
264
265
266
267
268
269
270
  }
}

.                       {
  std::cerr << *yylloc
	    << \": invalid character: `\"
	    << escape (yytext) << \"'\" << std::endl;
Benoit Perrot's avatar
Benoit Perrot committed
271
  yylloc->step ();
272
273
274
275
  exit_set (exit_scan);
}

%%
Benoit Perrot's avatar
Benoit Perrot committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

/* Depending upon the version of Flex (> 2.5.4), there might be a
   function to reclaim all the memory Flex has allocated.  If not,
   simulate it. */
#if !(   YY_FLEX_MAJOR_VERSION >= 2             \
      && YY_FLEX_MINOR_VERSION >= 5             \
      && defined YY_FLEX_SUBMINOR_VERSION       \
      && YY_FLEX_SUBMINOR_VERSION >= 5)
static void
yylex_destroy(void)
{
  yy_delete_buffer(YY_CURRENT_BUFFER);
}
#endif

291
292
#include <stack>

293
294
295
namespace parse
{

Benoit Perrot's avatar
Benoit Perrot committed
296
297
298
299
300
  // Stack of scanning states, used to have some (weak) reentrancy.
  static std::stack<YY_BUFFER_STATE> states;

  // Keep this scan_open valid for multiple calls (i.e., do use
  // yyrestart).
301
  void
Benoit Perrot's avatar
Benoit Perrot committed
302
  scan_open(const std::string &filename, bool trace_p)
303
  {
Benoit Perrot's avatar
Benoit Perrot committed
304
305
306
307
308
309
310
311
312
313
314
315
    static bool first = true;
    if (first)
      {
        first = false;

        // Reclaim all the memory allocated by Flex at program termination
        std::atexit((void (*) (void)) yylex_destroy);
      }

    // Save the current state
    states.push(YY_CURRENT_BUFFER);
  
Benoit Perrot's avatar
Benoit Perrot committed
316
    yy_flex_debug = trace_p;
317

Benoit Perrot's avatar
Benoit Perrot committed
318
319
    if (filename == \"-\")
      yyin = stdin;
320
321
    else
      {
Benoit Perrot's avatar
Benoit Perrot committed
322
	yyin = fopen (filename.c_str (), \"r\");
323
324
325
326
	if (!yyin)
	  {
	    std::cerr
	      << program_name
Benoit Perrot's avatar
Benoit Perrot committed
327
	      << \": cannot open `\" << filename << \"': \"
328
329
330
331
	      << strerror (errno) << std::endl;
	    exit (1);
	  }
      }
Benoit Perrot's avatar
Benoit Perrot committed
332
333

    yy_switch_to_buffer(yy_create_buffer (yyin, YY_BUF_SIZE));
334
335
336
337
338
339
  }

  void
  scan_close (void)
  {
    fclose (yyin);
Benoit Perrot's avatar
Benoit Perrot committed
340
341
342
343
344
345
    
    // Restore the current scanning state.
    assertion(!states.empty());
    yy_delete_buffer(YY_CURRENT_BUFFER);
    yy_switch_to_buffer(states.top());
    states.pop();
346
347
348
  }
}
"""
Benoit Perrot's avatar
Benoit Perrot committed
349
350
351

sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
352
nolimips.lazy_overwrite(srcdir + os.sep + "asm-scan.ll", "asm-scan.ll.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
353
os.remove("asm-scan.ll.tmp")