program_builder.hh.gen.py 5.55 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
Benoit Perrot's avatar
Benoit Perrot committed
4
## Copyright (C) 2003, 2004 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
25
import nolimips
from nolimips import license, depth, class_id
26

Benoit Perrot's avatar
Benoit Perrot committed
27
#### Nolimips' program builder 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("program_builder.hh.tmp", "w")
38
39
40
41
42
43

print license
print """#ifndef INST_PROGRAM_BUILDER_HH
# define INST_PROGRAM_BUILDER_HH

# include \"inst/all.hh\"
44
45
46
# include \"inst/int_exp.hh\"
# include \"inst/label_exp.hh\"
# include \"inst/op_exp.hh\"
47
48
# include \"inst/program.hh\"

49
50
# include \"vm/cpu.hh\"

51
52
53
54
namespace inst
{

  using namespace inst;
55
  using vm::Cpu;
56
57
58
59
  
  class ProgramBuilder
  {
  public:
60
61
    ProgramBuilder():
      program_(0), nop_after_branch_p_(false)
62
63
64
65
    {
    }

  public:
66
    void	reset()
67
    {
Benoit Perrot's avatar
Benoit Perrot committed
68
      program_ = new Program();
69
    }
70
71
72
73
74

    void	set_nop_after_branch(bool nop_after_branch_p)
    {
      nop_after_branch_p_ = nop_after_branch_p;
    }
75
76
77
    
    Program*		get()
    {
Benoit Perrot's avatar
Benoit Perrot committed
78
79
      // FIXME: fill end of program with NOPs for pipeline (really dirty!)
      for (unsigned i = 0; i < 6; ++i)
Benoit Perrot's avatar
Benoit Perrot committed
80
        program_->text_section().
Benoit Perrot's avatar
Benoit Perrot committed
81
82
          add_inst (new Sll(Register(Register::general, Cpu::zero),
			    Register(Register::general, Cpu::zero),
Benoit Perrot's avatar
Benoit Perrot committed
83
			    new IntExp(0)));
Benoit Perrot's avatar
Benoit Perrot committed
84
      return program_;
85
86
87
    }
    
  public:
88
    void define_inst_label(const misc::unique_string &id)
Benoit Perrot's avatar
Benoit Perrot committed
89
    {
90
91
92
93
94
95
      if (!program_->text_section ().define_label(id))
        {
          std::cerr << \"Instruction label already defined in this section.\"
                    << std::endl;
          exit_set(exit_solve);
        }
Benoit Perrot's avatar
Benoit Perrot committed
96
97
    }

98
    void define_data_label(const misc::unique_string &id)
99
    {
100
101
102
103
104
105
      if (!program_->data_section ().define_label(id))
        {
          std::cerr << \"Data label already defined in this section.\"
                    << std::endl;
          exit_set(exit_solve);
        }
106
    }
Benoit Perrot's avatar
Benoit Perrot committed
107
108
109

  public:
    void		add_byte(int imm)
110
    {
Benoit Perrot's avatar
Benoit Perrot committed
111
      program_->data_section ().add_byte(imm);
112
113
    }

Benoit Perrot's avatar
Benoit Perrot committed
114
    void		add_half(int imm)
115
    {
Benoit Perrot's avatar
Benoit Perrot committed
116
117
118
      // FIXME: check that imm is less than 0x10000!
      add_byte((imm >> 8) && 0xff);
      add_byte(imm && 0xff);
119
120
    }

Benoit Perrot's avatar
Benoit Perrot committed
121
    void		add_word(int imm)
122
    {
Benoit Perrot's avatar
Benoit Perrot committed
123
      program_->data_section ().add_word (imm);
124
    }
Benoit Perrot's avatar
Benoit Perrot committed
125
    void		add_word(LabelExp *l)
126
    {
Benoit Perrot's avatar
Benoit Perrot committed
127
      // FIXME: use a precondition
Benoit Perrot's avatar
Benoit Perrot committed
128
      program_->data_section ().
Benoit Perrot's avatar
Benoit Perrot committed
129
        add_word (program_->data_section ().get_offset(l->get_name()));
130
131
    }

Benoit Perrot's avatar
Benoit Perrot committed
132
    void		add_ascii(const std::string *str)
133
    {
Benoit Perrot's avatar
Benoit Perrot committed
134
135
136
137
138
139
140
141
142
143
144
145
      for (unsigned i = 0; i < str->size (); ++i)
	program_->data_section ().add_byte((*str)[i]);
    }
    void		add_asciiz(const std::string *str)
    {
      add_ascii(str);
      add_byte(0);
    }

    void                add_space (int size)
    {
      program_->data_section ().add_space(size);    
146
147
148
149
150
    }

  public:"""

type_map = {
Benoit Perrot's avatar
Benoit Perrot committed
151
152
153
154
    "register": "Register *",
    "immediate": "Exp *",
    "label": "Exp *",
    "address": "Register *"
155
156
157
    }

for inst in instructions:
Benoit Perrot's avatar
Benoit Perrot committed
158
159
160
  for syntax in inst.syntaxes:
    if (syntax.alias != "") or (syntax.level == "pseudo"):
      continue
161
    
Benoit Perrot's avatar
Benoit Perrot committed
162
163
164
    if syntax.level == "native":
      proto = ""
      call = ""
Benoit Perrot's avatar
Benoit Perrot committed
165
      for attribute in inst.format.attributes:
Benoit Perrot's avatar
Benoit Perrot committed
166
        proto = proto + attribute.type + " *" + attribute.name + ", "
Benoit Perrot's avatar
Benoit Perrot committed
167
168
        if attribute.type == "Register":
          call = call + "*"
Benoit Perrot's avatar
Benoit Perrot committed
169
170
171
172
173
        call = call + attribute.name + ", "
      proto = string.rstrip(proto, ", ")
      call = string.rstrip(call, ", ")
      print "    void\tadd_" + inst.opcode + "(" + proto + ")"
      print "    {"
Benoit Perrot's avatar
Benoit Perrot committed
174
      call = "new " + class_id(inst.opcode) + "(" + call + ")"
Benoit Perrot's avatar
Benoit Perrot committed
175
      print "      program_->text_section().add_inst (" + call + ");"
176
      if inst.kind == "branch":
Benoit Perrot's avatar
Benoit Perrot committed
177
        print "      if (nop_after_branch_p_)"
Benoit Perrot's avatar
Benoit Perrot committed
178
        print "	program_->text_section()."
Benoit Perrot's avatar
Benoit Perrot committed
179
        print "	  add_inst (new Sll(Register(Register::general, " + \
180
              "Cpu::zero), "
Benoit Perrot's avatar
Benoit Perrot committed
181
        print "			    Register(Register::general, " + \
182
              "Cpu::zero), "
Benoit Perrot's avatar
Benoit Perrot committed
183
        print "			    new IntExp(0)));"
Benoit Perrot's avatar
Benoit Perrot committed
184
185
186
      print "    }"
      
    else: # syntax.level == "complex"
187
      proto = ""
Benoit Perrot's avatar
Benoit Perrot committed
188
189
190
      for token in syntax.tokens:
        proto = proto + type_map[token.kind]
        if token.name:
Benoit Perrot's avatar
Benoit Perrot committed
191
          proto = proto + token.name
192
193
194
195
196
197
        proto = proto + ", "
      proto = string.rstrip(proto, ", ")
      print "    void\tadd_" + inst.opcode + "(" + proto + ");"
      
print """
  protected:
Benoit Perrot's avatar
Benoit Perrot committed
198
    Program*		program_;
Benoit Perrot's avatar
Benoit Perrot committed
199
    bool                nop_after_branch_p_;
200
201
202
203
204
  };

} // namespace inst

#endif // !INST_PROGRAM_BUILDER_HH"""
Benoit Perrot's avatar
Benoit Perrot committed
205
206
207
208

## Epilogue
sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
209
210
nolimips.lazy_overwrite(srcdir + os.sep + "program_builder.hh",
                        "program_builder.hh.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
211
os.remove("program_builder.hh.tmp")