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