inst-solver-gen.py 6.71 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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  public:
    void	solve(Program &program)
    {
      program_ = &program;

      int i;
      for (i = 0, pc_ = 4; i < program.text_section().size(); ++i, pc_ += 4)
	program_->text_section()[i].accept(*this);
    }
  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
106
107
108
109

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

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

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

} // namespace inst

#endif // !INST_PROGRAM_SOLVER_HH
"""

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


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

print license
print """#include \"inst/program_solver.hh\"
Benoit Perrot's avatar
Benoit Perrot committed
143
#include \"vm/cpu.hh\"
Benoit Perrot's avatar
Benoit Perrot committed
144
145
146

namespace inst
{
Benoit Perrot's avatar
Benoit Perrot committed
147
148
149
150
151
  void
  ProgramSolver::visit(IntExp &i)
  {
    i.set_immediate(i.get_integer());
  }
Benoit Perrot's avatar
Benoit Perrot committed
152

Benoit Perrot's avatar
Benoit Perrot committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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
  void
  ProgramSolver::visit(LabelExp &l)
  {
    if (! program_->data_section().has_label(l.get_label()))
      if (! program_->text_section().has_label(l.get_label()))
	{
	  std::cerr << \"Undefined label: \" << l.get_label()
		    << std::endl;
	  exit_set(exit_solve);
	}
      else
	l.set_immediate(program_->text_section().
			get_offset(l.get_label()) - pc_);
    else
      l.set_immediate(program_->data_section().get_offset(l.get_label()));
  }

  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
208
	  {
Benoit Perrot's avatar
Benoit Perrot committed
209
	    std::cerr << \"Caller-save register limited.\" << std::endl;
Benoit Perrot's avatar
Benoit Perrot committed
210
211
	    exit_set(exit_solve);
	  }
Benoit Perrot's avatar
Benoit Perrot committed
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
	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
228
    
Benoit Perrot's avatar
Benoit Perrot committed
229
230
231
232
233
234
235
236
237
  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
238

Benoit Perrot's avatar
Benoit Perrot committed
239
240
241
242
"""

for inst in instructions:
  if inst.level == "native":
Benoit Perrot's avatar
Benoit Perrot committed
243
    var_id = nolimips.var_id(inst.opcode)
Benoit Perrot's avatar
Benoit Perrot committed
244
245
246
    
    content = ""
    for attribute in inst.format.attributes:
Benoit Perrot's avatar
Benoit Perrot committed
247
      if attribute.type == "Exp":
Benoit Perrot's avatar
Benoit Perrot committed
248
249
        content = content + "    solve_exp(" + \
                  var_id + ".get_" + attribute.name + "());\n"
Benoit Perrot's avatar
Benoit Perrot committed
250
      elif attribute.type == "Register":
Benoit Perrot's avatar
Benoit Perrot committed
251
252
253
254
255
        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
256
257
258
    
    print "  void"
    if content != "":
Benoit Perrot's avatar
Benoit Perrot committed
259
      print "  ProgramSolver::visit(" + nolimips.class_id(inst.opcode) + \
Benoit Perrot's avatar
Benoit Perrot committed
260
261
262
            " &" + var_id + ")"
      print "  {\n" + content + "  }"
    else:
Benoit Perrot's avatar
Benoit Perrot committed
263
      print "  ProgramSolver::visit(" + nolimips.class_id(inst.opcode) + " &)"
Benoit Perrot's avatar
Benoit Perrot committed
264
265
266
267
268
269
270
271
      print "  {"
      print "  }"
  
print """
} // namespace inst"""

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