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