- refactoring of backend generator scripts: You can create multiple constructors
[libfirm] / ir / be / TEMPLATE / TEMPLATE_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3
4 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
5
6 $arch = "TEMPLATE";
7
8 # The node description is done as a perl hash initializer with the
9 # following structure:
10 #
11 # %nodes = (
12 #
13 # <op-name> => {
14 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",                 # optional
15 #   irn_flags => "R|N|I"                                # optional
16 #   arity     => "0|1|2|3 ... |variable|dynamic|any",   # optional
17 #   state     => "floats|pinned|mem_pinned|exc_pinned", # optional
18 #   args      => [
19 #                    { type => "type 1", name => "name 1" },
20 #                    { type => "type 2", name => "name 2" },
21 #                    ...
22 #                  ],
23 #   comment   => "any comment for constructor",  # optional
24 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
25 #   cmp_attr  => "c source code for comparing node attributes", # optional
26 #   outs      => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
27 #   ins       => { "in1", "in2" },  # optional, creates n_op_in1, ... consts
28 #   mode      => "mode_Iu",         # optional, predefines the mode
29 #   emit      => "emit code with templates",   # optional for virtual nodes
30 #   attr      => "additional attribute arguments for constructor", # optional
31 #   init_attr => "emit attribute initialization template",         # optional
32 #   rd_constructor => "c source code which constructs an ir_node", # optional
33 #   hash_func => "name of the hash function for this operation",   # optional, get the default hash function else
34 #   latency   => "latency of this operation (can be float)"        # optional
35 #   attr_type => "name of the attribute struct",                   # optional
36 # },
37 #
38 # ... # (all nodes you need to describe)
39 #
40 # ); # close the %nodes initializer
41
42 # op_flags: flags for the operation, OPTIONAL (default is "N")
43 # the op_flags correspond to the firm irop_flags:
44 #   N   irop_flag_none
45 #   L   irop_flag_labeled
46 #   C   irop_flag_commutative
47 #   X   irop_flag_cfopcode
48 #   I   irop_flag_ip_cfopcode
49 #   F   irop_flag_fragile
50 #   Y   irop_flag_forking
51 #   H   irop_flag_highlevel
52 #   c   irop_flag_constlike
53 #   K   irop_flag_keep
54 #
55 # irn_flags: special node flags, OPTIONAL (default is 0)
56 # following irn_flags are supported:
57 #   R   rematerializeable
58 #   N   not spillable
59 #   I   ignore for register allocation
60 #
61 # state: state of the operation, OPTIONAL (default is "floats")
62 #
63 # arity: arity of the operation, MUST NOT BE OMITTED
64 #
65 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
66 #        are always the first 3 arguments and are always autmatically
67 #        created)
68 #        If this key is missing the following arguments will be created:
69 #        for i = 1 .. arity: ir_node *op_i
70 #        ir_mode *mode
71 #
72 # outs:  if a node defines more than one output, the names of the projections
73 #        nodes having outs having automatically the mode mode_T
74 #
75 # comment: OPTIONAL comment for the node constructor
76 #
77 # rd_constructor: for every operation there will be a
78 #      new_rd_<arch>_<op-name> function with the arguments from above
79 #      which creates the ir_node corresponding to the defined operation
80 #      you can either put the complete source code of this function here
81 #
82 #      This key is OPTIONAL. If omitted, the following constructor will
83 #      be created:
84 #      if (!op_<arch>_<op-name>) assert(0);
85 #      for i = 1 to arity
86 #         set in[i] = op_i
87 #      done
88 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
89 #      return res
90 #
91 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
92
93 # register types:
94 #   0 - no special type
95 #   1 - caller save (register must be saved by the caller of a function)
96 #   2 - callee save (register must be saved by the called function)
97 #   4 - ignore (do not assign this register)
98 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
99 %reg_classes = (
100         gp => [
101                 { name => "r0", type => 1 },
102                 { name => "r1", type => 1 },
103                 { name => "r2", type => 1 },
104                 { name => "r3", type => 1 },
105                 { name => "r4", type => 1 },
106                 { name => "r5", type => 1 },
107                 { name => "r6", type => 1 },
108                 { name => "r7", type => 2 },
109                 { name => "r8", type => 2 },
110                 { name => "r9", type => 2 },
111                 { name => "r10", type => 2 },
112                 { name => "r11", type => 2 },
113                 { name => "r12", type => 2 },
114                 { name => "r13", type => 2 },
115                 { name => "sp", realname => "r14", type => 4 },  # stackpointer
116                 { name => "bp", realname => "r15", type => 4 },  # basepointer
117                 { mode => "mode_Iu" }
118         ],
119         fp => [
120                 { name => "f0", type => 1 },
121                 { name => "f1", type => 1 },
122                 { name => "f2", type => 1 },
123                 { name => "f3", type => 1 },
124                 { name => "f4", type => 1 },
125                 { name => "f5", type => 1 },
126                 { name => "f6", type => 1 },
127                 { name => "f7", type => 1 },
128                 { name => "f8", type => 1 },
129                 { name => "f9", type => 1 },
130                 { name => "f10", type => 1 },
131                 { name => "f11", type => 1 },
132                 { name => "f12", type => 1 },
133                 { name => "f13", type => 1 },
134                 { name => "f14", type => 1 },
135                 { name => "f15", type => 1 },
136                 { mode => "mode_D" }
137         ]
138 );
139
140 %emit_templates = (
141         S1 => "${arch}_emit_source_register(node, 0);",
142         S2 => "${arch}_emit_source_register(node, 1);",
143         S3 => "${arch}_emit_source_register(node, 2);",
144         S4 => "${arch}_emit_source_register(node, 3);",
145         S5 => "${arch}_emit_source_register(node, 4);",
146         S6 => "${arch}_emit_source_register(node, 5);",
147         D1 => "${arch}_emit_dest_register(node, 0);",
148         D2 => "${arch}_emit_dest_register(node, 1);",
149         D3 => "${arch}_emit_dest_register(node, 2);",
150         D4 => "${arch}_emit_dest_register(node, 3);",
151         D5 => "${arch}_emit_dest_register(node, 4);",
152         D6 => "${arch}_emit_dest_register(node, 5);",
153         C  => "${arch}_emit_immediate(node);"
154 );
155
156 %nodes = (
157
158 # Integer nodes
159
160 Add => {
161         op_flags  => "C",
162         irn_flags => "R",
163         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
164         emit      => '. add %S1, %S2, %D1'
165 },
166
167 Add_i => {
168         irn_flags => "R",
169         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
170         emit      => '. add %S1, %C, %D1'
171 },
172
173 Mul => {
174         op_flags  => "C",
175         irn_flags => "R",
176         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
177         emit      =>'. mul %S1, %S2, %D1'
178 },
179
180 Mul_i => {
181         irn_flags => "R",
182         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
183         emit      => '. mul %S1, %C, %D1'
184 },
185
186 And => {
187         op_flags  => "C",
188         irn_flags => "R",
189         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
190         emit      => '. and %S1, %S2, %D1'
191 },
192
193 And_i => {
194         irn_flags => "R",
195         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
196         emit      => '. and %S1, %C, %D1'
197 },
198
199 Or => {
200         op_flags  => "C",
201         irn_flags => "R",
202         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
203         emit      => '. or %S1, %S2, %D1'
204 },
205
206 Or_i => {
207         op_flags  => "C",
208         irn_flags => "R",
209         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
210         emit      => '. or %S1, %C, %D1'
211 },
212
213 Eor => {
214         op_flags  => "C",
215         irn_flags => "R",
216         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
217         emit      => '. xor %S1, %S2, %D1'
218 },
219
220 Eor_i => {
221         irn_flags => "R",
222         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
223         emit      => '. xor %S1, %C, %D1'
224 },
225
226 Sub => {
227         irn_flags => "R",
228         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
229         emit      => '. sub %S1, %S2, %D1'
230 },
231
232 Sub_i => {
233         irn_flags => "R",
234         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
235         emit      => '. subl %S1, %C, %D1'
236 },
237
238 Shl => {
239         irn_flags => "R",
240         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
241         emit      => '. shl %S1, %S2, %D1'
242 },
243
244 Shl_i => {
245         irn_flags => "R",
246         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
247         emit      => '. shl %S1, %C, %D1'
248 },
249
250 Shr => {
251         irn_flags => "R",
252         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1" ] },
253         emit      => '. shr %S2, %D1'
254 },
255
256 Shr_i => {
257         irn_flags => "R",
258         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
259         emit      => '. shr %S1, %C, %D1'
260 },
261
262 RotR => {
263         irn_flags => "R",
264         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
265         emit      => '. ror %S1, %S2, %D1'
266 },
267
268 RotL => {
269         irn_flags => "R",
270         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
271         emit      => '. rol %S1, %S2, %D1'
272 },
273
274 RotL_i => {
275         irn_flags => "R",
276         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
277         emit      => '. rol %S1, %C, %D1'
278 },
279
280 Minus => {
281         irn_flags => "R",
282         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
283         emit      => '. neg %S1, %D1'
284 },
285
286 Inc => {
287         irn_flags => "R",
288         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
289         emit      => '. inc %S1, %D1'
290 },
291
292 Dec => {
293         irn_flags => "R",
294         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
295         emit      => '. dec %S1, %D1'
296 },
297
298 Not => {
299         arity       => 1,
300         remat       => 1,
301         reg_req     => { in => [ "gp" ], out => [ "gp" ] },
302         emit        => '. not %S1, %D1'
303 },
304
305 Const => {
306         op_flags  => "c",
307         irn_flags => "R",
308         reg_req   => { out => [ "gp" ] },
309         emit      => '. mov %C, %D1',
310         cmp_attr  =>
311 '
312         /* TODO: compare Const attributes */
313     return 1;
314 '
315 },
316
317 # Control Flow
318
319 Jmp => {
320         state     => "pinned",
321         op_flags  => "X",
322         irn_flags => "J",
323         reg_req   => { out => [ "none" ] },
324         mode      => "mode_X",
325 },
326
327 # Load / Store
328
329 Load => {
330         op_flags  => "L|F",
331         irn_flags => "R",
332         state     => "exc_pinned",
333         reg_req   => { in => [ "gp", "none" ], out => [ "gp" ] },
334         emit      => '. mov (%S1), %D1'
335 },
336
337 Store => {
338         op_flags  => "L|F",
339         irn_flags => "R",
340         state     => "exc_pinned",
341         reg_req   => { in => [ "gp", "gp", "none" ] },
342         emit      => '. movl %S2, (%S1)'
343 },
344
345 # Floating Point operations
346
347 fAdd => {
348         op_flags  => "C",
349         irn_flags => "R",
350         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
351         emit      => '. fadd %S1, %S2, %D1'
352 },
353
354 fMul => {
355         op_flags  => "C",
356         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
357         emit      =>'. fmul %S1, %S2, %D1'
358 },
359
360 fMax => {
361         op_flags  => "C",
362         irn_flags => "R",
363         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
364         emit      =>'. fmax %S1, %S2, %D1'
365 },
366
367 fMin => {
368         op_flags  => "C",
369         irn_flags => "R",
370         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
371         emit      =>'. fmin %S1, %S2, %D1'
372 },
373
374 fSub => {
375         irn_flags => "R",
376         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
377         emit      => '. fsub %S1, %S2, %D1'
378 },
379
380 fDiv => {
381         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
382         emit      => '. fdiv %S1, %S2, %D1'
383 },
384
385 fMinus => {
386         irn_flags => "R",
387         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
388         emit      => '. fneg %S1, %D1'
389 },
390
391 fConst => {
392         op_flags  => "c",
393         irn_flags => "R",
394         reg_req   => { out => [ "fp" ] },
395         emit      => '. fmov %C, %D1',
396         cmp_attr  =>
397 '
398         /* TODO: compare fConst attributes */
399         return 1;
400 '
401 },
402
403 # Load / Store
404
405 fLoad => {
406         op_flags  => "L|F",
407         irn_flags => "R",
408         state     => "exc_pinned",
409         reg_req   => { in => [ "gp", "none" ], out => [ "fp" ] },
410         emit      => '. fmov (%S1), %D1'
411 },
412
413 fStore => {
414         op_flags  => "L|F",
415         irn_flags => "R",
416         state     => "exc_pinned",
417         reg_req   => { in => [ "gp", "fp", "none" ] },
418         emit      => '. fmov %S2, (%S1)'
419 },
420
421 );