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