warning fixes
[libfirm] / ir / be / ppc32 / ppc32_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3 # This is a template specification for the Firm-Backend
4
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc32, ...)
6
7 $arch = "ppc32";
8 $new_emit_syntax = 1;
9
10 # The node description is done as a perl hash initializer with the
11 # following structure:
12 #
13 # %nodes = (
14 #
15 # <op-name> => {
16 #   "op_flags"  => "N|L|C|X|I|F|Y|H|c|K",
17 #   "irn_flags" => "R|N|I"
18 #   "arity"     => "0|1|2|3 ... |variable|dynamic|any",
19 #   "state"     => "floats|pinned|mem_pinned|exc_pinned",
20 #   "args"      => [
21 #                    { "type" => "type 1", "name" => "name 1" },
22 #                    { "type" => "type 2", "name" => "name 2" },
23 #                    ...
24 #                  ],
25 #   "comment"   => "any comment for constructor",
26 #   "reg_req"   => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] },
27 #   "cmp_attr"  => "c source code for comparing node attributes",
28 #   "emit"      => "emit code with templates",
29 #   "rd_constructor" => "c source code which constructs an ir_node"
30 # },
31 #
32 # ... # (all nodes you need to describe)
33 #
34 # ); # close the %nodes initializer
35
36 # op_flags: flags for the operation, OPTIONAL (default is "N")
37 # the op_flags correspond to the firm irop_flags:
38 #   N   irop_flag_none
39 #   L   irop_flag_labeled
40 #   C   irop_flag_commutative
41 #   X   irop_flag_cfopcode
42 #   I   irop_flag_ip_cfopcode
43 #   F   irop_flag_fragile
44 #   Y   irop_flag_forking
45 #   H   irop_flag_highlevel
46 #   c   irop_flag_constlike
47 #   K   irop_flag_keep
48 #
49 # irn_flags: special node flags, OPTIONAL (default is 0)
50 # following irn_flags are supported:
51 #   R   rematerializeable
52 #   N   not spillable
53 #   I   ignore for register allocation
54 #
55 # state: state of the operation, OPTIONAL (default is "floats")
56 #
57 # arity: arity of the operation, MUST NOT BE OMITTED
58 #
59 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
60 #        are always the first 3 arguments and are always autmatically
61 #        created)
62 #        If this key is missing the following arguments will be created:
63 #        for i = 1 .. arity: ir_node *op_i
64 #        ir_mode *mode
65 #
66 # outs:  if a node defines more than one output, the names of the projections
67 #        nodes having outs having automatically the mode mode_T
68 #
69 # comment: OPTIONAL comment for the node constructor
70 #
71 # rd_constructor: for every operation there will be a
72 #      new_rd_<arch>_<op-name> function with the arguments from above
73 #      which creates the ir_node corresponding to the defined operation
74 #      you can either put the complete source code of this function here
75 #
76 #      This key is OPTIONAL. If omitted, the following constructor will
77 #      be created:
78 #      if (!op_<arch>_<op-name>) assert(0);
79 #      for i = 1 to arity
80 #         set in[i] = op_i
81 #      done
82 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
83 #      return res
84 #
85 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
86
87 # register types:
88 #   0 - no special type
89 #   1 - caller save (register must be saved by the caller of a function)
90 #   2 - callee save (register must be saved by the called function)
91 #   4 - ignore (do not assign this register)
92 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
93 %reg_classes = (
94   "gp" => [
95                          { "name" => "r0", "type" => 1 },
96                          { "name" => "r2", "type" => 1 },
97                          { "name" => "r3", "type" => 1 },
98                          { "name" => "r4", "type" => 1 },
99                          { "name" => "r5", "type" => 1 },
100                          { "name" => "r6", "type" => 1 },
101                          { "name" => "r7", "type" => 1 },
102                          { "name" => "r8", "type" => 1 },
103                          { "name" => "r9", "type" => 1 },
104                          { "name" => "r10", "type" => 1 },
105 #                        { "name" => "r11", "type" => 1 },
106 #                        { "name" => "r12", "type" => 1 },
107                          { "name" => "r13", "type" => 2 },
108                          { "name" => "r14", "type" => 2 },
109                          { "name" => "r15", "type" => 2 },
110 #                        { "name" => "r16", "type" => 2 },
111 #                        { "name" => "r17", "type" => 2 },
112 #                        { "name" => "r18", "type" => 2 },
113 #                        { "name" => "r19", "type" => 2 },
114 #                        { "name" => "r20", "type" => 2 },
115 #                        { "name" => "r21", "type" => 2 },
116 #                        { "name" => "r22", "type" => 2 },
117 #                        { "name" => "r23", "type" => 2 },
118 #                        { "name" => "r24", "type" => 2 },
119 #                        { "name" => "r25", "type" => 2 },
120 #                        { "name" => "r26", "type" => 2 },
121 #                        { "name" => "r27", "type" => 2 },
122 #                        { "name" => "r28", "type" => 2 },
123 #                        { "name" => "r29", "type" => 2 },
124 #                        { "name" => "r30", "type" => 2 },
125                          { "name" => "r31", "type" => 2 },
126                          { "name" => "r1", "type" => 6 }, # this is our stackpointer
127                          { "mode" => "mode_P" }
128                        ],
129   "fp"  => [
130 #                        { "name" => "f0", "type" => 1 }, # => reserved for FP Perm
131                          { "name" => "f1", "type" => 1 },
132                          { "name" => "f2", "type" => 1 },
133                          { "name" => "f3", "type" => 1 },
134                          { "name" => "f4", "type" => 1 },
135                          { "name" => "f5", "type" => 1 },
136                          { "name" => "f6", "type" => 1 },
137                          { "name" => "f7", "type" => 1 },
138                          { "name" => "f8", "type" => 1 },
139                          { "name" => "f9", "type" => 1 },
140                          { "name" => "f10", "type" => 1 },
141                          { "name" => "f11", "type" => 1 },
142                          { "name" => "f12", "type" => 1 },
143                          { "name" => "f13", "type" => 1 },
144                          { "name" => "f14", "type" => 2 },
145                          { "name" => "f15", "type" => 2 },
146                          { "name" => "f16", "type" => 2 },
147 #                        { "name" => "f17", "type" => 2 },
148 #                        { "name" => "f18", "type" => 2 },
149 #                        { "name" => "f19", "type" => 2 },
150 #                        { "name" => "f20", "type" => 2 },
151 #                        { "name" => "f21", "type" => 2 },
152 #                        { "name" => "f22", "type" => 2 },
153 #                        { "name" => "f23", "type" => 2 },
154 #                        { "name" => "f24", "type" => 2 },
155 #                        { "name" => "f25", "type" => 2 },
156 #                        { "name" => "f26", "type" => 2 },
157 #                        { "name" => "f27", "type" => 2 },
158 #                        { "name" => "f28", "type" => 2 },
159 #                        { "name" => "f29", "type" => 2 },
160 #                        { "name" => "f30", "type" => 2 },
161 #                        { "name" => "f31", "type" => 2 },
162                          { "mode" => "mode_D" }
163                        ],
164   "condition" => [
165                          { "name" => "cr0", "type" => 1 },
166                          { "name" => "cr1", "type" => 1 },
167                          { "name" => "cr2", "type" => 2 },
168                          { "name" => "cr3", "type" => 2 },
169                          { "name" => "cr4", "type" => 2 },
170                          { "name" => "cr5", "type" => 1 },
171                          { "name" => "cr6", "type" => 1 },
172 #                        { "name" => "cr7", "type" => 1 }, # => reserved for Condition Perm
173                          { "mode" => "mode_P" } # real mode is 4 bit, but doesn't matter ...
174                        ],
175   "link" => [
176                          { "name" => "lr", "type" => 4 }, # 3
177                          { "mode" => "mode_P" }
178                        ],
179   "count" => [
180                          { "name" => "ctr", "type" => 1 },
181                          { "mode" => "mode_P" }
182                        ]
183 ); # %reg_classes
184
185 %emit_templates = (
186     S0 => "${arch}_emit_source_register(env, node, 0);",
187     S1 => "${arch}_emit_source_register(env, node, 1);",
188     S2 => "${arch}_emit_source_register(env, node, 2);",
189     D0 => "${arch}_emit_dest_register(env, node, 0);",
190     D1 => "${arch}_emit_dest_register(env, node, 1);",
191     D2 => "${arch}_emit_dest_register(env, node, 2);",
192         O  => "${arch}_emit_offset(env, node);",
193         C  => "${arch}_emit_immediate(env, node);",
194         RLWIMI => "${arch}_emit_rlwimi_helper(env, node);",
195 );
196
197 $default_cmp_attr = "NULL";
198
199 #--------------------------------------------------#
200 #                        _                         #
201 #                       (_)                        #
202 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
203 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
204 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
205 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
206 #                                      | |         #
207 #                                      |_|         #
208 #--------------------------------------------------#
209
210 %nodes = (
211
212 #-----------------------------------------------------------------#
213 #  _       _                                         _            #
214 # (_)     | |                                       | |           #
215 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
216 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
217 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
218 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
219 #                   __/ |                                         #
220 #                  |___/                                          #
221 #-----------------------------------------------------------------#
222
223 # commutative operations
224
225 "Add" => {
226   "op_flags"  => "C",
227   "irn_flags" => "R",
228   "comment"   => "construct Add: Add(a, b) = Add(b, a) = a + b",
229   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
230   "emit"      => '. add     %D0, %S0, %S1',
231 },
232
233 "Addi" => {
234   "op_flags"  => "c",
235   "irn_flags" => "R",
236   "comment"   => "construct Add: Addi(a, const) = Addi(const, a) = a + const",
237   "reg_req"   => { "in" => [ "!r0" ], "out" => [ "gp" ] },
238 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
239   "emit"      => '. addi    %D0, %S0, %C',
240   "cmp_attr"  =>
241 '
242         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
243 ',
244 },
245
246
247 "Mullw" => {
248   "op_flags"  => "C",
249   "irn_flags" => "R",
250   "comment"   => "construct Mul: Mullw(a, b) = Mullw(b, a) = lo32(a * b)",
251   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
252   "emit"      => '. mullw   %D0, %S0, %S1',
253 },
254
255 "Mulhw" => {
256   "op_flags"  => "C",
257   "irn_flags" => "R",
258   "comment"   => "construct Mul: Mulhw(a, b) = Mulhw(b, a) = hi32(a * b)",
259   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
260   "emit"      => '. mulhw   %D0, %S0, %S1',
261 },
262
263 "Mulhwu" => {
264   "op_flags"  => "C",
265   "irn_flags" => "R",
266   "comment"   => "construct Mul: Mulhwu(a, b) = Mulhwu(b, a) = hi32(a * b)",
267   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
268   "emit"      => '. mulhwu  %D0, %S0, %S1',
269 },
270
271 #"Mul_i" => {
272 #  "irn_flags" => "R",
273 #  "comment"   => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
274 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
275 #  "emit"      => '. mul %S0, %C, %D0',
276 #},
277
278 "And" => {
279   "op_flags"  => "C",
280   "irn_flags" => "R",
281   "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
282   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
283   "emit"      => '. and     %D0, %S0, %S1',
284 },
285
286 #"And_i" => {
287 #  "irn_flags" => "R",
288 #  "comment"   => "construct And: And(a, const) = And(const, a) = a AND const",
289 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
290 #  "emit"      => '. and %S0, %C, %D0',
291 #},
292
293 "Or" => {
294   "op_flags"  => "C",
295   "irn_flags" => "R",
296   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
297   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
298   "emit"      => '. or      %D0, %S0, %S1',
299 },
300
301 #"Or_i" => {
302 #  "op_flags"  => "C",
303 #  "irn_flags" => "R",
304 #  "comment"   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
305 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
306 #  "emit"      => '. or %S0, %C, %D0',
307 #},
308
309 "Xor" => {
310   "op_flags"  => "C",
311   "irn_flags" => "R",
312   "comment"   => "construct Xor: Xor(a, b) = Xor(b, a) = a XOR b",
313   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
314   "emit"      => '. xor     %D0, %S0, %S1',
315 },
316
317 #"Xor_i" => {
318 #  "irn_flags" => "R",
319 #  "comment"   => "construct Xor: Xor(a, const) = Xor(const, a) = a EOR const",
320 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
321 #  "emit"      => '. xor %S0, %C, %D0',
322 #},
323
324 # not commutative operations
325
326 "Sub" => {
327   "irn_flags" => "R",
328   "comment"   => "construct Sub: Sub(a, b) = a - b",
329   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
330   "emit"      => '. sub %D0, %S0, %S1',
331 },
332
333 #"Sub_i" => {
334 #  "irn_flags" => "R",
335 #  "comment"   => "construct Sub: Sub(a, const) = a - const",
336 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
337 #  "emit"      => '. subl %S0, %C, %D0',
338 #},
339
340 "Slw" => {
341   "irn_flags" => "R",
342   "comment"   => "construct Shl: Shl(a, b) = a << b",
343   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
344   "emit"      => '. slw %D0, %S0, %S1',
345 },
346
347 #"Shl_i" => {
348 #  "irn_flags" => "R",
349 #  "comment"   => "construct Shl: Shl(a, const) = a << const",
350 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
351 #  "emit"      => '. shl %S0, %C, %D0',
352 #},
353
354 "Srw" => {
355   "irn_flags" => "R",
356   "comment"   => "construct Shr: Srw(a, b): c = a >> b",
357   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
358   "emit"      => '. srw     %D0, %S0, %S1',
359 },
360
361 #"Shr_i" => {
362 #  "irn_flags" => "R",
363 #  "comment"   => "construct Shr: Shr(a, const) = a >> const",
364 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
365 #  "emit"      => '. shr %S0, %C, %D0',
366 #},
367
368 "Sraw" => {
369   "irn_flags" => "R",
370   "comment"   => "construct Shrs: Sraw(a, b): c = a >> b",
371   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
372   "emit"      => '. sraw %D0, %S0, %S1',
373 },
374
375 "Srawi" => {
376   "irn_flags" => "R",
377   "comment"   => "construct Shrs: Srawi(a, const): c = a >> const",
378   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
379   "emit"      => '. sraw %D0, %S0, %C',
380   "cmp_attr"  =>
381 '
382         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
383 ',
384
385 },
386
387 "Rlwnm" => {
388   "irn_flags" => "R",
389   "comment"   => "construct ???: Rlwnm(a, b): c = a ROTL b",
390   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
391   "emit"      => '. rlwnm %D0, %S0, %S1',
392 },
393
394 "Rlwinm" => {
395   "irn_flags" => "R",
396   "comment"   => "construct ???: Rlwinm(a, b_const, c_const, d_const): (m = MASK(c, d)) e = (a ROTL b) & m",
397   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
398   "emit"      => '. rlwinm %D0, %S0, %RLWIMI',
399   "cmp_attr"  =>
400 '
401         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
402 ',
403 },
404
405
406 "Neg" => {
407   "irn_flags" => "R",
408   "comment"   => "construct Minus: Neg(a) = -a",
409   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
410   "emit"      => '. neg %D0, %S0',
411 },
412
413 "Not" => {
414   "irn_flags" => "R",
415   "comment"   => "construct Not: Not(a) = !a",
416   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
417   "emit"      => '. nor %D0, %S0, %S0',
418 },
419
420 "Extsb" => {
421   "irn_flags" => "R",
422   "comment"   => "construct Sign extension of byte: Extsb(char a) = (int) a",
423   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
424   "emit"      => '. extsb %D0, %S0',
425 },
426
427 "Extsh" => {
428   "irn_flags" => "R",
429   "comment"   => "construct Sign extension of halfword: Extsh(char a) = (short) a",
430   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
431   "emit"      => '. extsh %D0, %S0',
432 },
433
434 "Divw" => {
435   "irn_flags" => "R",
436   "comment"   => "construct Div (signed): Div(a, b) = a div b",
437   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
438   "emit"      => '. divw %D0, %S0, %S1',
439 },
440
441 "Divwu" => {
442   "irn_flags" => "R",
443   "comment"   => "construct Div (unsigned): Div(a, b) = a div b",
444   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
445   "emit"      => '. divwu %D0, %S0, %S1',
446 },
447
448 "Mtctr" => {
449   "irn_flags" => "R",
450   "comment"   => "construct Mtctr: Ctr = a",
451   "reg_req"   => { "in" => [ "gp" ], "out" => [ "count" ] },
452   "emit"      => '. mtctr %S0',
453 },
454
455
456 # other operations
457
458 "Const" => {
459   "op_flags"  => "c",
460   "irn_flags" => "R",
461   "comment"   => "Const (high-level node)",
462   "reg_req"   => { "out" => [ "gp" ] },
463   "cmp_attr"  =>
464 '
465         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
466 ',
467 },
468
469 "fConst" => {
470   "op_flags"  => "c",
471   "irn_flags" => "R",
472   "comment"   => "float Const (high-level node)",
473   "reg_req"   => { "out" => [ "fp" ] },
474   "cmp_attr"  =>
475 '
476         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
477 ',
478 },
479
480 "SymConst" => {
481   "op_flags"  => "c",
482   "irn_flags" => "R",
483   "comment"   => "SymConst (high-level node)",
484   "reg_req"   => { "out" => [ "gp" ] },
485   "cmp_attr"  =>
486 '
487         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
488 ',
489 },
490
491 "Unknown" => {
492   "op_flags"  => "c",
493   "irn_flags" => "R",
494   "comment"   => "construct unknown register",
495   "reg_req"   => { "out" => [ "gp" ] },
496   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
497   "cmp_attr"  =>
498 '
499         return 1;
500 ',
501 },
502
503 "fUnknown" => {
504   "op_flags"  => "c",
505   "irn_flags" => "R",
506   "comment"   => "construct unknown float register",
507   "reg_req"   => { "out" => [ "fp" ] },
508   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
509   "cmp_attr"  =>
510 '
511         return 1;
512 ',
513 },
514
515 "cUnknown" => {
516   "op_flags"  => "c",
517   "irn_flags" => "R",
518   "comment"   => "construct unknown condition register",
519   "reg_req"   => { "out" => [ "condition" ] },
520   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
521   "cmp_attr"  =>
522 '
523         return 1;
524 ',
525 },
526
527 "Addi_zero" => {
528   "op_flags"  => "c",
529   "irn_flags" => "R",
530   "comment"   => "load constant (16bit with sign extension)",
531   "reg_req"   => { "out" => [ "gp" ] },
532   "emit"      => '. addi    %D0, 0, %C',
533   "cmp_attr"  =>
534 '
535         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
536 ',
537 },
538
539 "Branch" => {
540   "op_flags"  => "L|X|Y",
541   "comment"   => "branch somewhere",
542   "reg_req"   => { "in" => [ "condition" ], "out" => [ "none", "none" ] },
543   "cmp_attr"  =>
544 '
545         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
546 ',
547 },
548
549 "LoopCopy" => {
550   "irn_flags" => "R",
551   "comment"   => "construct LoopCopy(src, dest, count, mem): Copy count words from src to dest",
552   "reg_req"   => { "in" => [ "gp", "gp", "count", "none" ], "out" => [ "none", "in_r1", "in_r2", "in_r3", "gp" ] },
553 },
554
555 "Switch" => {
556   "op_flags" => "L|X|Y",
557   "comment"   => "construct Switch(selector): Jump to whatever",
558   "reg_req"   => { "in" => [ "gp", "gp", "condition" ], "out" => [ "none" ] },
559   "cmp_attr"  =>
560 '
561         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
562 ',
563 },
564
565 "Addis_zero" => {
566   "op_flags"  => "c",
567   "irn_flags" => "R",
568   "comment"   => "load the constant to higher 16 bit of register",
569   "reg_req"   => { "out" => [ "gp" ] },
570   "emit"      => '. addis %D0, 0, %C',
571   "attr"      => "ppc32_attr_offset_mode om, tarval *tv, ident *id",
572   "init_attr" =>
573 '
574         attr->offset_mode = om;
575         if (tv) {
576                 attr->content_type = ppc32_ac_Const;
577                 attr->data.constant_tarval = tv;
578         }
579         else if (id) {
580                 attr->content_type = ppc32_ac_SymConst;
581                 attr->data.symconst_ident = id;
582         }
583 ',
584   "cmp_attr"  =>
585 '
586         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
587 ',
588 },
589
590 "Ori" => {
591   "op_flags"  => "c",
592   "irn_flags" => "R",
593   "comment"   => "ors constant with register",
594   "reg_req"   => { "in" => [ "gp"], "out" => [ "gp" ] },
595   "emit"      => '. ori %D0, %S0, %C',
596   "cmp_attr"  =>
597 '
598         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
599 ',
600 },
601
602 "Andi_dot" => {
603   "op_flags"  => "c",
604   "irn_flags" => "R",
605   "comment"   => "ands constant with register with cr0 update",
606   "reg_req"   => { "in" => [ "gp"], "out" => [ "gp", "cr0" ] },
607   "emit"      => '. andi. %D0, %S0,%C',
608   "cmp_attr"  =>
609 '
610         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
611 ',
612 },
613
614 "Cmp" => {
615   "irn_flags" => "R",
616   "comment"   => "construct Cmp: Cmp(a, b) = Flags in crX",
617   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "condition" ] },
618   "emit"      => '. cmp %D0, 0, %S0, %S1',
619 },
620
621 "Cmpi" => {
622   "irn_flags" => "R",
623   "comment"   => "construct Cmp immediate: Cmpi(a, const) = Flags in crX",
624   "reg_req"   => { "in" => [ "gp" ], "out" => [ "condition" ] },
625   "emit"      => '. cmpi %D0, 0, %S0, %C',
626   "cmp_attr"  =>
627 '
628         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
629 ',
630 },
631
632
633 "Cmpl" => {
634   "irn_flags" => "R",
635   "comment"   => "construct Cmp logical: Cmpl(a, b) = Flags in crX",
636   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "condition" ] },
637   "emit"      => '. cmpl %D0, 0, %S0, %S1',
638 },
639
640 "Cmpli" => {
641   "irn_flags" => "R",
642   "comment"   => "construct Cmp logical immediate: Cmpli(a, const) = Flags in crX",
643   "reg_req"   => { "in" => [ "gp" ], "out" => [ "condition" ] },
644   "emit"      => '. cmpli %D0, 0, %S0, %C',
645   "cmp_attr"  =>
646 '
647         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
648 ',
649 },
650
651
652 # Load / Store
653
654 "Lbz" => {
655   "op_flags"  => "L|F",
656   "irn_flags" => "R",
657   "state"     => "exc_pinned",
658   "comment"   => "construct Load (byte unsigned): Load(ptr, mem) = LD ptr -> reg",
659   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
660   "emit"      => '. lbz %D0, %O(%S0)',
661   "cmp_attr"  =>
662 '
663         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
664 ',
665   "outs"      => [ "res", "M" ],
666 },
667
668 "Lhz" => {
669   "op_flags"  => "L|F",
670   "irn_flags" => "R",
671   "state"     => "exc_pinned",
672   "comment"   => "construct Load (halfword unsigned): Load(ptr, mem) = LD ptr -> reg",
673   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
674   "emit"      => '. lhz %D0, %O(%S0)',
675   "cmp_attr"  =>
676 '
677         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
678 ',
679   "outs"      => [ "res", "M" ],
680 },
681
682 "Lha" => {
683   "op_flags"  => "L|F",
684   "irn_flags" => "R",
685   "state"     => "exc_pinned",
686   "comment"   => "construct Load (halfword signed): Load(ptr, mem) = LD ptr -> reg",
687   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
688   "emit"      => '. lha %D0, %O(%S0)',
689   "cmp_attr"  =>
690 '
691         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
692 ',
693   "outs"      => [ "res", "M" ],
694 },
695
696 "Lwz" => {
697   "op_flags"  => "L|F",
698   "irn_flags" => "R",
699   "state"     => "exc_pinned",
700   "comment"   => "construct Load (word): Load(ptr, mem) = LD ptr -> reg",
701   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
702   "emit"      => '. lwz %D0, %O(%S0)',
703   "cmp_attr"  =>
704 '
705         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
706 ',
707   "outs"      => [ "res", "M" ],
708 },
709
710 "Lwzu" => {
711   "op_flags"  => "L|F",
712   "irn_flags" => "R",
713   "state"     => "exc_pinned",
714   "comment"   => "construct Load with update (word): Load(ptr, mem) = LD ptr -> reg",
715   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "in_r1", "none"] },
716   "emit"      => '. lwzu %D0, %O(%S0)',
717   "cmp_attr"  =>
718 '
719         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
720 ',
721   "outs"      => [ "res", "ptr", "M" ],
722 },
723
724 "Stb" => {
725   "op_flags"  => "L|F",
726   "state"     => "exc_pinned",
727   "comment"   => "construct Store: Store (byte) (ptr, val, mem) = ST ptr,val",
728   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
729   "emit"      => '. stb %S1, %O(%S0)',
730   "cmp_attr"  =>
731 '
732         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
733 ',
734   "outs"      => [ "M" ],
735 },
736
737 "Sth" => {
738   "op_flags"  => "L|F",
739   "state"     => "exc_pinned",
740   "comment"   => "construct Store: Store (halfword) (ptr, val, mem) = ST ptr,val",
741   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
742   "emit"      => '. sth %S1, %O(%S0)',
743   "cmp_attr"  =>
744 '
745         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
746 ',
747   "outs"      => [ "M" ],
748 },
749
750 "Stw" => {
751   "op_flags"  => "L|F",
752   "state"     => "exc_pinned",
753   "comment"   => "construct Store: Store (word) (ptr, val, mem) = ST ptr,val",
754   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
755   "emit"      => '. stw %S1, %O(%S0)',
756   "cmp_attr"  =>
757 '
758         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
759 ',
760   "outs"      => [ "M" ],
761 },
762
763 #--------------------------------------------------------#
764 #    __ _             _                     _            #
765 #   / _| |           | |                   | |           #
766 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
767 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
768 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
769 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
770 #--------------------------------------------------------#
771
772 # commutative operations
773
774 "fAdd" => {
775   "op_flags"  => "C",
776   "irn_flags" => "R",
777   "comment"   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
778   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
779   "emit"      => '. fadd %D0, %S0, %S1',
780 },
781
782 "fAdds" => {
783   "op_flags"  => "C",
784   "irn_flags" => "R",
785   "comment"   => "construct FP Add (single): Add(a, b) = Add(b, a) = a + b",
786   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
787   "emit"      => '. fadds %D0, %S0, %S1',
788 },
789
790 "fMul" => {
791   "op_flags"  => "C",
792   "comment"   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
793   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
794   "emit"      => '. fmul %D0, %S0, %S1',
795 },
796
797 "fMuls" => {
798   "op_flags"  => "C",
799   "comment"   => "construct FP Mul (single): Mul(a, b) = Mul(b, a) = a * b",
800   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
801   "emit"      => '. fmuls %D0, %S0, %S1',
802 },
803
804 "fNeg" => {
805   "comment"   => "construct FP Negation: fNeg(a) = -a",
806   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
807   "emit"      => '. fneg %D0, %S0',
808 },
809
810
811 "fMax" => {
812   "op_flags"  => "C",
813   "irn_flags" => "R",
814   "comment"   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
815   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
816   "emit"      => '. fmax %S0, %S1, %D0',
817 },
818
819 "fMin" => {
820   "op_flags"  => "C",
821   "irn_flags" => "R",
822   "comment"   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
823   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
824   "emit"      => '. fmin %S0, %S1, %D0',
825 },
826
827 # not commutative operations
828
829 "fSub" => {
830   "irn_flags" => "R",
831   "comment"   => "construct FP Sub: Sub(a, b) = a - b",
832   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
833   "emit"      => '. fsub %D0, %S0, %S1',
834 },
835
836 "fSubs" => {
837   "irn_flags" => "R",
838   "comment"   => "construct FP Sub (single): Sub(a, b) = a - b",
839   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
840   "emit"      => '. fsubs %D0, %S0, %S1',
841 },
842
843 "fDiv" => {
844   "comment"   => "construct FP Div: Div(a, b) = a / b",
845   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
846   "emit"      => '. fdiv %D0, %S0, %S1',
847 },
848
849 "fDivs" => {
850   "comment"   => "construct FP Div (single): Div(a, b) = a / b",
851   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
852   "emit"      => '. fdivs %D0, %S0, %S1',
853 },
854
855 "fMinus" => {
856   "irn_flags" => "R",
857   "comment"   => "construct FP Minus: fMinus(a) = -a",
858   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
859   "emit"      => '. fneg %D0, %S0',
860 },
861
862 "fCtiw" => {
863   "irn_flags" => "R",
864   "comment"   => "construct FP Convert to integer word: fCtiw(a) = (int) a",
865   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
866   "emit"      => '. fctiw %D0, %S0',
867 },
868
869 "fRsp" => {
870   "irn_flags" => "R",
871   "comment"   => "construct FP Round to single: fRsp(a) = (float) a",
872   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
873   "emit"      => '. frsp %D0, %S0',
874 },
875
876 "fAbs" => {
877   "irn_flags" => "R",
878   "comment"   => "construct FP Abs: fAbs(a) = |a|",
879   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
880   "emit"      => '. fabs %D0, %S0',
881 },
882
883 "fCmpu" => {
884   "irn_flags" => "R",
885   "comment"   => "construct FP Cmp unordered: fCmpu(a, b) = a ? b",
886   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "condition" ] },
887   "emit"      => '. fcmpu %D0, %S0, %S1',
888 },
889
890 # other operations
891
892 #"fConst" => {
893 #  "op_flags"  => "c",
894 #  "irn_flags" => "R",
895 #  "comment"   => "represents a FP constant",
896 #  "reg_req"   => { "out" => [ "fp" ] },
897 #  "emit"      => '. fmov %C, %D0',
898 #  "cmp_attr"  =>
899 #'
900 #       /* TODO: compare fConst attributes */
901 #       return 1;
902 #',
903 #},
904
905 "fUnknown" => {
906   "op_flags"  => "c",
907   "irn_flags" => "R",
908   "comment"   => "construct unknown floating point register",
909   "reg_req"   => { "out" => [ "fp" ] },
910   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
911   "cmp_attr"  =>
912 '
913         return 1;
914 ',
915 },
916
917 # Load / Store
918
919 "Lfd" => {
920   "op_flags"  => "L|F",
921   "irn_flags" => "R",
922   "state"     => "exc_pinned",
923   "comment"   => "construct FP Load (double): Load(ptr, mem) = LD ptr",
924   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "fp", "none" ] },
925   "emit"      => '. lfd %D0, %O(%S0)',
926   "cmp_attr"  =>
927 '
928         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
929 ',
930   "outs"      => [ "res", "M" ],
931 },
932
933 "Lfs" => {
934   "op_flags"  => "L|F",
935   "irn_flags" => "R",
936   "state"     => "exc_pinned",
937   "comment"   => "construct FP Load (single): Load(ptr, mem) = LD ptr",
938   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "fp","none" ] },
939   "emit"      => '. lfs %D0, %O(%S0)',
940   "cmp_attr"  =>
941 '
942         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
943 ',
944   "outs"      => [ "res", "M" ],
945 },
946
947 "Stfd" => {
948   "op_flags"  => "L|F",
949   "state"     => "exc_pinned",
950   "comment"   => "construct Store (double): Store(ptr, val, mem)  = ST ptr,val",
951   "reg_req"   => { "in" => [ "!r0", "fp", "none" ], "out" => [ "none" ] },
952   "emit"      => '. stfd %S1, %O(%S0)',
953   "cmp_attr"  =>
954 '
955         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
956 ',
957   "outs"      => [ "M" ],
958 },
959
960 "Stfs" => {
961   "op_flags"  => "L|F",
962   "state"     => "exc_pinned",
963   "comment"   => "construct Store (single): Store(ptr, val, mem)  = ST ptr,val",
964   "reg_req"   => { "in" => [ "!r0", "fp", "none" ], "out" => [ "none" ] },
965   "emit"      => '. stfs %S1, %O(%S0)',
966   "cmp_attr"  =>
967 '
968         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
969 ',
970   "outs"      => [ "M" ],
971 },
972
973 ); # end of %nodes