inst-solver-gen.py 6.87 KB
Newer Older
Benoit Perrot's avatar
Benoit Perrot committed
1
2
#!/usr/bin/env python
##
Benoit Perrot's avatar
Benoit Perrot committed
3
## This file is part of Nolimips, a MIPS simulator with unlimited registers
Benoit Perrot's avatar
Benoit Perrot committed
4
5
## Copyright (C) 2003, 2004 Benoit Perrot <benoit@lrde.epita.fr>
##
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
20
21
22
23
## 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
##

import sys, os
import string, re

Benoit Perrot's avatar
Benoit Perrot committed
24
25
import nolimips
from nolimips import license, depth, class_id
Benoit Perrot's avatar
Benoit Perrot committed
26

Benoit Perrot's avatar
Benoit Perrot committed
27
#### Nolimips' program solver 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()
Benoit Perrot's avatar
Benoit Perrot committed
35
36
37
38
39
40
41
42
43
44
instructions = parser.parse(sys.stdin)


## Generate interface
sys.stdout = file("program_solver.hh.tmp", "w")

print license
print """#ifndef INST_PROGRAM_SOLVER_HH
# define INST_PROGRAM_SOLVER_HH

Benoit Perrot's avatar
Benoit Perrot committed
45
46
# include "config.h"

Benoit Perrot's avatar
Benoit Perrot committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# include <stdint.h>

# include \"common.hh\"

# include \"inst/exp-visitor.hh\"
# include \"inst/exp.hh\"
# include \"inst/visitor.hh\"
# include \"inst/all.hh\"
# include \"inst/program.hh\"

// FIXME: dirty access unlimited registers flag
# include \"parse/libparse.hh\"

namespace inst
{

  class ProgramSolver:
    protected Visitor, 
    protected ExpVisitor
  {
  public:
Benoit Perrot's avatar
Benoit Perrot committed
68
69
70
71
72
    ProgramSolver():
      program_(0),
      max_callee_save_(8), max_caller_save_(10)
    {}
    virtual ~ProgramSolver()
Benoit Perrot's avatar
Benoit Perrot committed
73
74
    {}

Benoit Perrot's avatar
Benoit Perrot committed
75
76
77
78
79
80
81
82
83
84
  public:
    void set_max_callee_save(int max_callee_save)
    {
      max_callee_save_ = max_callee_save;
    }
    void set_max_caller_save(int max_caller_save)
    {
      max_caller_save_ = max_caller_save;
    }

Benoit Perrot's avatar
Benoit Perrot committed
85
86
87
88
89
  public:
    void	solve(Program &program)
    {
      program_ = &program;

Benoit Perrot's avatar
Benoit Perrot committed
90
91
92
      pc_ = 4;
      for (TextSection::instruction_list_type::const_iterator
             it = program.text_section().begin();
93
             it != program.text_section().end(); ++it, pc_ += 4)
Benoit Perrot's avatar
Benoit Perrot committed
94
	(*it)->accept(*this);
Benoit Perrot's avatar
Benoit Perrot committed
95
96
97
98
99
100
101
102
103
104
105
106
107
    }
  protected:
    int		pc_;

  protected:
    void	solve_exp(Exp &exp)
    {
      exp.accept(*this);
    }

    virtual void	visit(IntExp &i);
    virtual void	visit(LabelExp &l);
    virtual void	visit(OpExp &o);
Benoit Perrot's avatar
Benoit Perrot committed
108
109
110
111

  protected:
    void	solve_cpu_register(Register &reg) const;
    void	solve_cop_register(Register &reg) const;
Benoit Perrot's avatar
Benoit Perrot committed
112
113
114
115
116
"""

print "  protected:"
for inst in instructions:
  if inst.level == "native":
Benoit Perrot's avatar
Benoit Perrot committed
117
118
    print "    virtual void	visit(" +\
          nolimips.class_id(inst.opcode) + " &);"
Benoit Perrot's avatar
Benoit Perrot committed
119
120
121
122
    
print """
  protected:
    Program	*program_;
Benoit Perrot's avatar
Benoit Perrot committed
123
124
125

    int max_callee_save_;
    int max_caller_save_;
Benoit Perrot's avatar
Benoit Perrot committed
126
127
128
129
130
131
132
133
134
  };

} // namespace inst

#endif // !INST_PROGRAM_SOLVER_HH
"""

sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
135
136
nolimips.lazy_overwrite(srcdir + os.sep + "program_solver.hh",
                        "program_solver.hh.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
137
138
139
140
141
142
143
144
os.remove("program_solver.hh.tmp")


## Generate implementation
sys.stdout = file("program_solver.cc.tmp", "w")

print license
print """#include \"inst/program_solver.hh\"
145
146
147
148
#include \"inst/int_exp.hh\"
#include \"inst/label_exp.hh\"
#include \"inst/op_exp.hh\"

Benoit Perrot's avatar
Benoit Perrot committed
149
#include \"vm/cpu.hh\"
Benoit Perrot's avatar
Benoit Perrot committed
150
151
152

namespace inst
{
Benoit Perrot's avatar
Benoit Perrot committed
153
154
155
156
157
  void
  ProgramSolver::visit(IntExp &i)
  {
    i.set_immediate(i.get_integer());
  }
Benoit Perrot's avatar
Benoit Perrot committed
158

Benoit Perrot's avatar
Benoit Perrot committed
159
160
161
  void
  ProgramSolver::visit(LabelExp &l)
  {
Benoit Perrot's avatar
Benoit Perrot committed
162
163
    if (! program_->data_section().has_label(l.get_name()))
      if (! program_->text_section().has_label(l.get_name()))
Benoit Perrot's avatar
Benoit Perrot committed
164
	{
Benoit Perrot's avatar
Benoit Perrot committed
165
	  std::cerr << \"Undefined label: \" << l.get_name()
Benoit Perrot's avatar
Benoit Perrot committed
166
167
168
169
170
		    << std::endl;
	  exit_set(exit_solve);
	}
      else
	l.set_immediate(program_->text_section().
Benoit Perrot's avatar
Benoit Perrot committed
171
			get_offset(l.get_name()) - pc_);
Benoit Perrot's avatar
Benoit Perrot committed
172
    else
Benoit Perrot's avatar
Benoit Perrot committed
173
      l.set_immediate(program_->data_section().get_offset(l.get_name()));
Benoit Perrot's avatar
Benoit Perrot committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  }

  void
  ProgramSolver::visit(OpExp &o)
  {
    o.get_left().accept(*this);
    o.get_right().accept(*this);
    switch (o.kind_)
      {
      case OpExp::add:
	o.set_immediate(o.get_left().get_immediate() + 
			o.get_right().get_immediate());
	break;
      case OpExp::sub:
	o.set_immediate(o.get_left().get_immediate() - 
			o.get_right().get_immediate());
	break;
      case OpExp::mul: 
	o.set_immediate(o.get_left().get_immediate() * 
			o.get_right().get_immediate());
	break;
      case OpExp::div:
	o.set_immediate(o.get_left().get_immediate() / 
			o.get_right().get_immediate());
	break;
      }
  }

  void
  ProgramSolver::solve_cpu_register(Register &reg) const
  {
    switch (reg.get_kind())
      {
      case Register::generic:
	reg.set_kind(Register::general);
      case Register::general:
	if ((reg.get_index() == vm::Cpu::t9 && max_caller_save_ < 10)
	    || (reg.get_index() == vm::Cpu::t8 && max_caller_save_ < 9)
	    || (vm::Cpu::t0 + max_caller_save_ - 1 < reg.get_index()
		&& reg.get_index() <= vm::Cpu::t7))
Benoit Perrot's avatar
Benoit Perrot committed
214
	  {
Benoit Perrot's avatar
Benoit Perrot committed
215
	    std::cerr << \"Caller-save register limited.\" << std::endl;
Benoit Perrot's avatar
Benoit Perrot committed
216
217
	    exit_set(exit_solve);
	  }
Benoit Perrot's avatar
Benoit Perrot committed
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	else if (vm::Cpu::s0 + max_callee_save_ - 1 < reg.get_index() &&
		 reg.get_index() <= vm::Cpu::s7)
	  {
	    std::cerr << \"Callee-save register limited.\" << std::endl;
	    exit_set(exit_solve);
	  }
	break;
      case Register::unlimited:
	if (!parse::unlimited_regs_p)
	  {
	    std::cerr << \"Unlimited registers prohibited.\" << std::endl;
	    exit_set(exit_solve);
	  }
	break;
      };
  }
Benoit Perrot's avatar
Benoit Perrot committed
234
    
Benoit Perrot's avatar
Benoit Perrot committed
235
236
237
238
239
240
241
242
243
  void
  ProgramSolver::solve_cop_register(Register &reg) const
  {
    if (reg.get_kind() != Register::generic)
      {
	std::cerr << \"Coprocessor registers must be generic.\" << std::endl;
	exit_set(exit_solve);
      }
  }
Benoit Perrot's avatar
Benoit Perrot committed
244

Benoit Perrot's avatar
Benoit Perrot committed
245
246
247
248
"""

for inst in instructions:
  if inst.level == "native":
Benoit Perrot's avatar
Benoit Perrot committed
249
    var_id = nolimips.var_id(inst.opcode)
Benoit Perrot's avatar
Benoit Perrot committed
250
251
252
    
    content = ""
    for attribute in inst.format.attributes:
Benoit Perrot's avatar
Benoit Perrot committed
253
      if attribute.type == "Exp":
Benoit Perrot's avatar
Benoit Perrot committed
254
255
        content = content + "    solve_exp(" + \
                  var_id + ".get_" + attribute.name + "());\n"
Benoit Perrot's avatar
Benoit Perrot committed
256
      elif attribute.type == "Register":
Benoit Perrot's avatar
Benoit Perrot committed
257
258
259
260
261
        if attribute.restriction == "generic":
          content = content + "    solve_cop_register("
        else:
          content = content + "    solve_cpu_register("
        content = content + var_id + ".get_" + attribute.name + "());\n"
Benoit Perrot's avatar
Benoit Perrot committed
262
263
264
    
    print "  void"
    if content != "":
Benoit Perrot's avatar
Benoit Perrot committed
265
      print "  ProgramSolver::visit(" + nolimips.class_id(inst.opcode) + \
Benoit Perrot's avatar
Benoit Perrot committed
266
267
268
            " &" + var_id + ")"
      print "  {\n" + content + "  }"
    else:
Benoit Perrot's avatar
Benoit Perrot committed
269
      print "  ProgramSolver::visit(" + nolimips.class_id(inst.opcode) + " &)"
Benoit Perrot's avatar
Benoit Perrot committed
270
271
272
273
274
275
276
277
      print "  {"
      print "  }"
  
print """
} // namespace inst"""

sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
278
279
nolimips.lazy_overwrite(srcdir + os.sep + "program_solver.cc",
                        "program_solver.cc.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
280
os.remove("program_solver.cc.tmp")