- further refactoring and finally eliminated the callback for get_out_reg_reqs
[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 Jmp => {
371         state    => "pinned",
372         op_flags => "X",
373         reg_req  => { out => [ "none" ] },
374         mode     => "mode_X",
375 },
376
377 # Load / Store
378
379 Load => {
380         op_flags  => "L|F",
381         irn_flags => "R",
382         state     => "exc_pinned",
383         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
384         reg_req   => { in => [ "general_purpose", "none" ], out => [ "general_purpose" ] },
385         emit      => '. mov (%S1), %D1'
386 },
387
388 Store => {
389         op_flags  => "L|F",
390         irn_flags => "R",
391         state     => "exc_pinned",
392         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
393         reg_req   => { in => [ "general_purpose", "general_purpose", "none" ] },
394         emit      => '. movl %S2, (%S1)'
395 },
396
397 #--------------------------------------------------------#
398 #    __ _             _                     _            #
399 #   / _| |           | |                   | |           #
400 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
401 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
402 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
403 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
404 #--------------------------------------------------------#
405
406 # commutative operations
407
408 fAdd => {
409         op_flags  => "C",
410         irn_flags => "R",
411         comment   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
412         reg_req   => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
413         emit      => '. fadd %S1, %S2, %D1'
414 },
415
416 fMul => {
417         op_flags  => "C",
418         comment   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
419         reg_req   => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
420         emit      =>'. fmul %S1, %S2, %D1'
421 },
422
423 fMax => {
424         op_flags  => "C",
425         irn_flags => "R",
426         comment   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
427         reg_req   => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
428         emit      =>'. fmax %S1, %S2, %D1'
429 },
430
431 fMin => {
432         op_flags  => "C",
433         irn_flags => "R",
434         comment   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
435         reg_req   => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
436         emit      =>'. fmin %S1, %S2, %D1'
437 },
438
439 # not commutative operations
440
441 fSub => {
442         irn_flags => "R",
443         comment   => "construct FP Sub: Sub(a, b) = a - b",
444         reg_req   => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
445         emit      => '. fsub %S1, %S2, %D1'
446 },
447
448 fDiv => {
449         comment   => "construct FP Div: Div(a, b) = a / b",
450         reg_req   => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
451         emit      => '. fdiv %S1, %S2, %D1'
452 },
453
454 fMinus => {
455         irn_flags => "R",
456         comment   => "construct FP Minus: Minus(a) = -a",
457         reg_req   => { in => [ "floating_point" ], out => [ "floating_point" ] },
458         emit      => '. fneg %S1, %D1'
459 },
460
461 # other operations
462
463 fConst => {
464         op_flags  => "c",
465         irn_flags => "R",
466         comment   => "represents a FP constant",
467         reg_req   => { out => [ "floating_point" ] },
468         emit      => '. fmov %C, %D1',
469         cmp_attr  =>
470 '
471         /* TODO: compare fConst attributes */
472         return 1;
473 '
474 },
475
476 # Load / Store
477
478 fLoad => {
479         op_flags  => "L|F",
480         irn_flags => "R",
481         state     => "exc_pinned",
482         comment   => "construct FP Load: Load(ptr, mem) = LD ptr",
483         reg_req   => { in => [ "general_purpose", "none" ], out => [ "floating_point" ] },
484         emit      => '. fmov (%S1), %D1'
485 },
486
487 fStore => {
488         op_flags  => "L|F",
489         irn_flags => "R",
490         state     => "exc_pinned",
491         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
492         reg_req   => { in => [ "general_purpose", "floating_point", "none" ] },
493         emit      => '. fmov %S2, (%S1)'
494 },
495
496 ); # end of %nodes