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