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