- add support for opcode specific hash function
[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   "op_flags"  => "c",
243   "irn_flags" => "R",
244   "comment"   => "construct Add: Addi(a, const) = Addi(const, a) = a + const",
245   "reg_req"   => { "in" => [ "!r0" ], "out" => [ "gp" ] },
246 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
247   "emit"      => '. addi    %D0, %S0, %C',
248   "cmp_attr"  =>
249 '
250         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
251 ',
252 },
253
254
255 "Mullw" => {
256   "op_flags"  => "C",
257   "irn_flags" => "R",
258   "comment"   => "construct Mul: Mullw(a, b) = Mullw(b, a) = lo32(a * b)",
259   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
260   "emit"      => '. mullw   %D0, %S0, %S1',
261 },
262
263 "Mulhw" => {
264   "op_flags"  => "C",
265   "irn_flags" => "R",
266   "comment"   => "construct Mul: Mulhw(a, b) = Mulhw(b, a) = hi32(a * b)",
267   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
268   "emit"      => '. mulhw   %D0, %S0, %S1',
269 },
270
271 "Mulhwu" => {
272   "op_flags"  => "C",
273   "irn_flags" => "R",
274   "comment"   => "construct Mul: Mulhwu(a, b) = Mulhwu(b, a) = hi32(a * b)",
275   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
276   "emit"      => '. mulhwu  %D0, %S0, %S1',
277 },
278
279 #"Mul_i" => {
280 #  "irn_flags" => "R",
281 #  "comment"   => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
282 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
283 #  "emit"      => '. mul %S0, %C, %D0',
284 #},
285
286 "And" => {
287   "op_flags"  => "C",
288   "irn_flags" => "R",
289   "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
290   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
291   "emit"      => '. and     %D0, %S0, %S1',
292 },
293
294 #"And_i" => {
295 #  "irn_flags" => "R",
296 #  "comment"   => "construct And: And(a, const) = And(const, a) = a AND const",
297 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
298 #  "emit"      => '. and %S0, %C, %D0',
299 #},
300
301 "Or" => {
302   "op_flags"  => "C",
303   "irn_flags" => "R",
304   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
305   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
306   "emit"      => '. or      %D0, %S0, %S1',
307 },
308
309 #"Or_i" => {
310 #  "op_flags"  => "C",
311 #  "irn_flags" => "R",
312 #  "comment"   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
313 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
314 #  "emit"      => '. or %S0, %C, %D0',
315 #},
316
317 "Xor" => {
318   "op_flags"  => "C",
319   "irn_flags" => "R",
320   "comment"   => "construct Xor: Xor(a, b) = Xor(b, a) = a XOR b",
321   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
322   "emit"      => '. xor     %D0, %S0, %S1',
323 },
324
325 #"Xor_i" => {
326 #  "irn_flags" => "R",
327 #  "comment"   => "construct Xor: Xor(a, const) = Xor(const, a) = a EOR const",
328 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
329 #  "emit"      => '. xor %S0, %C, %D0',
330 #},
331
332 # not commutative operations
333
334 "Sub" => {
335   "irn_flags" => "R",
336   "comment"   => "construct Sub: Sub(a, b) = a - b",
337   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
338   "emit"      => '. sub %D0, %S0, %S1',
339 },
340
341 #"Sub_i" => {
342 #  "irn_flags" => "R",
343 #  "comment"   => "construct Sub: Sub(a, const) = a - const",
344 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
345 #  "emit"      => '. subl %S0, %C, %D0',
346 #},
347
348 "Slw" => {
349   "irn_flags" => "R",
350   "comment"   => "construct Shl: Shl(a, b) = a << b",
351   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
352   "emit"      => '. slw %D0, %S0, %S1',
353 },
354
355 #"Shl_i" => {
356 #  "irn_flags" => "R",
357 #  "comment"   => "construct Shl: Shl(a, const) = a << const",
358 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
359 #  "emit"      => '. shl %S0, %C, %D0',
360 #},
361
362 "Srw" => {
363   "irn_flags" => "R",
364   "comment"   => "construct Shr: Srw(a, b): c = a >> b",
365   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
366   "emit"      => '. srw     %D0, %S0, %S1',
367 },
368
369 #"Shr_i" => {
370 #  "irn_flags" => "R",
371 #  "comment"   => "construct Shr: Shr(a, const) = a >> const",
372 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
373 #  "emit"      => '. shr %S0, %C, %D0',
374 #},
375
376 "Sraw" => {
377   "irn_flags" => "R",
378   "comment"   => "construct Shrs: Sraw(a, b): c = a >> b",
379   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
380   "emit"      => '. sraw %D0, %S0, %S1',
381 },
382
383 "Srawi" => {
384   "irn_flags" => "R",
385   "comment"   => "construct Shrs: Srawi(a, const): c = a >> const",
386   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
387   "emit"      => '. sraw %D0, %S0, %C',
388   "cmp_attr"  =>
389 '
390         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
391 ',
392
393 },
394
395 "Rlwnm" => {
396   "irn_flags" => "R",
397   "comment"   => "construct ???: Rlwnm(a, b): c = a ROTL b",
398   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
399   "emit"      => '. rlwnm %D0, %S0, %S1',
400 },
401
402 "Rlwinm" => {
403   "irn_flags" => "R",
404   "comment"   => "construct ???: Rlwinm(a, b_const, c_const, d_const): (m = MASK(c, d)) e = (a ROTL b) & m",
405   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
406   "emit"      => '. rlwinm %D0, %S0, %RLWIMI',
407   "cmp_attr"  =>
408 '
409         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
410 ',
411 },
412
413
414 "Neg" => {
415   "irn_flags" => "R",
416   "comment"   => "construct Minus: Neg(a) = -a",
417   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
418   "emit"      => '. neg %D0, %S0',
419 },
420
421 "Not" => {
422   "irn_flags" => "R",
423   "comment"   => "construct Not: Not(a) = !a",
424   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
425   "emit"      => '. nor %D0, %S0, %S0',
426 },
427
428 "Extsb" => {
429   "irn_flags" => "R",
430   "comment"   => "construct Sign extension of byte: Extsb(char a) = (int) a",
431   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
432   "emit"      => '. extsb %D0, %S0',
433 },
434
435 "Extsh" => {
436   "irn_flags" => "R",
437   "comment"   => "construct Sign extension of halfword: Extsh(char a) = (short) a",
438   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
439   "emit"      => '. extsh %D0, %S0',
440 },
441
442 "Divw" => {
443   "irn_flags" => "R",
444   "comment"   => "construct Div (signed): Div(a, b) = a div b",
445   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
446   "emit"      => '. divw %D0, %S0, %S1',
447 },
448
449 "Divwu" => {
450   "irn_flags" => "R",
451   "comment"   => "construct Div (unsigned): Div(a, b) = a div b",
452   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
453   "emit"      => '. divwu %D0, %S0, %S1',
454 },
455
456 "Mtctr" => {
457   "irn_flags" => "R",
458   "comment"   => "construct Mtctr: Ctr = a",
459   "reg_req"   => { "in" => [ "gp" ], "out" => [ "count" ] },
460   "emit"      => '. mtctr %S0',
461 },
462
463
464 # other operations
465
466 "Const" => {
467   "op_flags"  => "c",
468   "irn_flags" => "R",
469   "comment"   => "Const (high-level node)",
470   "reg_req"   => { "out" => [ "gp" ] },
471   "cmp_attr"  =>
472 '
473         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
474 ',
475 },
476
477 "fConst" => {
478   "op_flags"  => "c",
479   "irn_flags" => "R",
480   "comment"   => "float Const (high-level node)",
481   "reg_req"   => { "out" => [ "fp" ] },
482   "cmp_attr"  =>
483 '
484         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
485 ',
486 },
487
488 "SymConst" => {
489   "op_flags"  => "c",
490   "irn_flags" => "R",
491   "comment"   => "SymConst (high-level node)",
492   "reg_req"   => { "out" => [ "gp" ] },
493   "cmp_attr"  =>
494 '
495         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
496 ',
497 },
498
499 "Unknown" => {
500   "op_flags"  => "c",
501   "irn_flags" => "R",
502   "comment"   => "construct unknown register",
503   "reg_req"   => { "out" => [ "gp" ] },
504   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
505   "cmp_attr"  =>
506 '
507         return 1;
508 ',
509 },
510
511 "fUnknown" => {
512   "op_flags"  => "c",
513   "irn_flags" => "R",
514   "comment"   => "construct unknown float register",
515   "reg_req"   => { "out" => [ "fp" ] },
516   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
517   "cmp_attr"  =>
518 '
519         return 1;
520 ',
521 },
522
523 "cUnknown" => {
524   "op_flags"  => "c",
525   "irn_flags" => "R",
526   "comment"   => "construct unknown condition register",
527   "reg_req"   => { "out" => [ "condition" ] },
528   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
529   "cmp_attr"  =>
530 '
531         return 1;
532 ',
533 },
534
535 "Addi_zero" => {
536   "op_flags"  => "c",
537   "irn_flags" => "R",
538   "comment"   => "load constant (16bit with sign extension)",
539   "reg_req"   => { "out" => [ "gp" ] },
540   "emit"      => '. addi    %D0, 0, %C',
541   "cmp_attr"  =>
542 '
543         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
544 ',
545 },
546
547 "Branch" => {
548   "op_flags"  => "L|X|Y",
549   "comment"   => "branch somewhere",
550   "reg_req"   => { "in" => [ "condition" ], "out" => [ "none", "none" ] },
551   "cmp_attr"  =>
552 '
553         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
554 ',
555 },
556
557 "LoopCopy" => {
558   "irn_flags" => "R",
559   "comment"   => "construct LoopCopy(src, dest, count, mem): Copy count words from src to dest",
560   "reg_req"   => { "in" => [ "gp", "gp", "count", "none" ], "out" => [ "none", "in_r1", "in_r2", "in_r3", "gp" ] },
561 },
562
563 "Switch" => {
564   "op_flags" => "L|X|Y",
565   "comment"   => "construct Switch(selector): Jump to whatever",
566   "reg_req"   => { "in" => [ "gp", "gp", "condition" ], "out" => [ "none" ] },
567   "cmp_attr"  =>
568 '
569         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
570 ',
571 },
572
573 "Addis_zero" => {
574   "op_flags"  => "c",
575   "irn_flags" => "R",
576   "comment"   => "load the constant to higher 16 bit of register",
577   "reg_req"   => { "out" => [ "gp" ] },
578   "emit"      => '. addis %D0, 0, %C',
579   "attr"      => "ppc32_attr_offset_mode om, tarval *tv, ident *id",
580   "init_attr" =>
581 '
582         attr->offset_mode = om;
583         if (tv) {
584                 attr->content_type = ppc32_ac_Const;
585                 attr->data.constant_tarval = tv;
586         }
587         else if (id) {
588                 attr->content_type = ppc32_ac_SymConst;
589                 attr->data.symconst_ident = id;
590         }
591 ',
592   "cmp_attr"  =>
593 '
594         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
595 ',
596 },
597
598 "Ori" => {
599   "op_flags"  => "c",
600   "irn_flags" => "R",
601   "comment"   => "ors constant with register",
602   "reg_req"   => { "in" => [ "gp"], "out" => [ "gp" ] },
603   "emit"      => '. ori %D0, %S0, %C',
604   "cmp_attr"  =>
605 '
606         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
607 ',
608 },
609
610 "Andi_dot" => {
611   "op_flags"  => "c",
612   "irn_flags" => "R",
613   "comment"   => "ands constant with register with cr0 update",
614   "reg_req"   => { "in" => [ "gp"], "out" => [ "gp", "cr0" ] },
615   "emit"      => '. andi. %D0, %S0,%C',
616   "cmp_attr"  =>
617 '
618         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
619 ',
620 },
621
622 "Cmp" => {
623   "irn_flags" => "R",
624   "comment"   => "construct Cmp: Cmp(a, b) = Flags in crX",
625   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "condition" ] },
626   "emit"      => '. cmp %D0, 0, %S0, %S1',
627 },
628
629 "Cmpi" => {
630   "irn_flags" => "R",
631   "comment"   => "construct Cmp immediate: Cmpi(a, const) = Flags in crX",
632   "reg_req"   => { "in" => [ "gp" ], "out" => [ "condition" ] },
633   "emit"      => '. cmpi %D0, 0, %S0, %C',
634   "cmp_attr"  =>
635 '
636         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
637 ',
638 },
639
640
641 "Cmpl" => {
642   "irn_flags" => "R",
643   "comment"   => "construct Cmp logical: Cmpl(a, b) = Flags in crX",
644   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "condition" ] },
645   "emit"      => '. cmpl %D0, 0, %S0, %S1',
646 },
647
648 "Cmpli" => {
649   "irn_flags" => "R",
650   "comment"   => "construct Cmp logical immediate: Cmpli(a, const) = Flags in crX",
651   "reg_req"   => { "in" => [ "gp" ], "out" => [ "condition" ] },
652   "emit"      => '. cmpli %D0, 0, %S0, %C',
653   "cmp_attr"  =>
654 '
655         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
656 ',
657 },
658
659
660 # Load / Store
661
662 "Lbz" => {
663   "op_flags"  => "L|F",
664   "irn_flags" => "R",
665   "state"     => "exc_pinned",
666   "comment"   => "construct Load (byte unsigned): Load(ptr, mem) = LD ptr -> reg",
667   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
668   "emit"      => '. lbz %D0, %O(%S0)',
669   "cmp_attr"  =>
670 '
671         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
672 ',
673   "outs"      => [ "res", "M" ],
674 },
675
676 "Lhz" => {
677   "op_flags"  => "L|F",
678   "irn_flags" => "R",
679   "state"     => "exc_pinned",
680   "comment"   => "construct Load (halfword unsigned): Load(ptr, mem) = LD ptr -> reg",
681   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
682   "emit"      => '. lhz %D0, %O(%S0)',
683   "cmp_attr"  =>
684 '
685         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
686 ',
687   "outs"      => [ "res", "M" ],
688 },
689
690 "Lha" => {
691   "op_flags"  => "L|F",
692   "irn_flags" => "R",
693   "state"     => "exc_pinned",
694   "comment"   => "construct Load (halfword signed): Load(ptr, mem) = LD ptr -> reg",
695   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
696   "emit"      => '. lha %D0, %O(%S0)',
697   "cmp_attr"  =>
698 '
699         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
700 ',
701   "outs"      => [ "res", "M" ],
702 },
703
704 "Lwz" => {
705   "op_flags"  => "L|F",
706   "irn_flags" => "R",
707   "state"     => "exc_pinned",
708   "comment"   => "construct Load (word): Load(ptr, mem) = LD ptr -> reg",
709   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
710   "emit"      => '. lwz %D0, %O(%S0)',
711   "cmp_attr"  =>
712 '
713         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
714 ',
715   "outs"      => [ "res", "M" ],
716 },
717
718 "Lwzu" => {
719   "op_flags"  => "L|F",
720   "irn_flags" => "R",
721   "state"     => "exc_pinned",
722   "comment"   => "construct Load with update (word): Load(ptr, mem) = LD ptr -> reg",
723   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "in_r1", "none"] },
724   "emit"      => '. lwzu %D0, %O(%S0)',
725   "cmp_attr"  =>
726 '
727         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
728 ',
729   "outs"      => [ "res", "ptr", "M" ],
730 },
731
732 "Stb" => {
733   "op_flags"  => "L|F",
734   "state"     => "exc_pinned",
735   "comment"   => "construct Store: Store (byte) (ptr, val, mem) = ST ptr,val",
736   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
737   "emit"      => '. stb %S1, %O(%S0)',
738   "cmp_attr"  =>
739 '
740         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
741 ',
742   "outs"      => [ "M" ],
743 },
744
745 "Sth" => {
746   "op_flags"  => "L|F",
747   "state"     => "exc_pinned",
748   "comment"   => "construct Store: Store (halfword) (ptr, val, mem) = ST ptr,val",
749   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
750   "emit"      => '. sth %S1, %O(%S0)',
751   "cmp_attr"  =>
752 '
753         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
754 ',
755   "outs"      => [ "M" ],
756 },
757
758 "Stw" => {
759   "op_flags"  => "L|F",
760   "state"     => "exc_pinned",
761   "comment"   => "construct Store: Store (word) (ptr, val, mem) = ST ptr,val",
762   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
763   "emit"      => '. stw %S1, %O(%S0)',
764   "cmp_attr"  =>
765 '
766         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
767 ',
768   "outs"      => [ "M" ],
769 },
770
771 #--------------------------------------------------------#
772 #    __ _             _                     _            #
773 #   / _| |           | |                   | |           #
774 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
775 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
776 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
777 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
778 #--------------------------------------------------------#
779
780 # commutative operations
781
782 "fAdd" => {
783   "op_flags"  => "C",
784   "irn_flags" => "R",
785   "comment"   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
786   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
787   "emit"      => '. fadd %D0, %S0, %S1',
788 },
789
790 "fAdds" => {
791   "op_flags"  => "C",
792   "irn_flags" => "R",
793   "comment"   => "construct FP Add (single): Add(a, b) = Add(b, a) = a + b",
794   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
795   "emit"      => '. fadds %D0, %S0, %S1',
796 },
797
798 "fMul" => {
799   "op_flags"  => "C",
800   "comment"   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
801   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
802   "emit"      => '. fmul %D0, %S0, %S1',
803 },
804
805 "fMuls" => {
806   "op_flags"  => "C",
807   "comment"   => "construct FP Mul (single): Mul(a, b) = Mul(b, a) = a * b",
808   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
809   "emit"      => '. fmuls %D0, %S0, %S1',
810 },
811
812 "fNeg" => {
813   "comment"   => "construct FP Negation: fNeg(a) = -a",
814   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
815   "emit"      => '. fneg %D0, %S0',
816 },
817
818
819 "fMax" => {
820   "op_flags"  => "C",
821   "irn_flags" => "R",
822   "comment"   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
823   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
824   "emit"      => '. fmax %S0, %S1, %D0',
825 },
826
827 "fMin" => {
828   "op_flags"  => "C",
829   "irn_flags" => "R",
830   "comment"   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
831   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
832   "emit"      => '. fmin %S0, %S1, %D0',
833 },
834
835 # not commutative operations
836
837 "fSub" => {
838   "irn_flags" => "R",
839   "comment"   => "construct FP Sub: Sub(a, b) = a - b",
840   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
841   "emit"      => '. fsub %D0, %S0, %S1',
842 },
843
844 "fSubs" => {
845   "irn_flags" => "R",
846   "comment"   => "construct FP Sub (single): Sub(a, b) = a - b",
847   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
848   "emit"      => '. fsubs %D0, %S0, %S1',
849 },
850
851 "fDiv" => {
852   "comment"   => "construct FP Div: Div(a, b) = a / b",
853   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
854   "emit"      => '. fdiv %D0, %S0, %S1',
855 },
856
857 "fDivs" => {
858   "comment"   => "construct FP Div (single): Div(a, b) = a / b",
859   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
860   "emit"      => '. fdivs %D0, %S0, %S1',
861 },
862
863 "fMinus" => {
864   "irn_flags" => "R",
865   "comment"   => "construct FP Minus: fMinus(a) = -a",
866   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
867   "emit"      => '. fneg %D0, %S0',
868 },
869
870 "fCtiw" => {
871   "irn_flags" => "R",
872   "comment"   => "construct FP Convert to integer word: fCtiw(a) = (int) a",
873   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
874   "emit"      => '. fctiw %D0, %S0',
875 },
876
877 "fRsp" => {
878   "irn_flags" => "R",
879   "comment"   => "construct FP Round to single: fRsp(a) = (float) a",
880   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
881   "emit"      => '. frsp %D0, %S0',
882 },
883
884 "fAbs" => {
885   "irn_flags" => "R",
886   "comment"   => "construct FP Abs: fAbs(a) = |a|",
887   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
888   "emit"      => '. fabs %D0, %S0',
889 },
890
891 "fCmpu" => {
892   "irn_flags" => "R",
893   "comment"   => "construct FP Cmp unordered: fCmpu(a, b) = a ? b",
894   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "condition" ] },
895   "emit"      => '. fcmpu %D0, %S0, %S1',
896 },
897
898 # other operations
899
900 #"fConst" => {
901 #  "op_flags"  => "c",
902 #  "irn_flags" => "R",
903 #  "comment"   => "represents a FP constant",
904 #  "reg_req"   => { "out" => [ "fp" ] },
905 #  "emit"      => '. fmov %C, %D0',
906 #  "cmp_attr"  =>
907 #'
908 #       /* TODO: compare fConst attributes */
909 #       return 1;
910 #',
911 #},
912
913 "fUnknown" => {
914   "op_flags"  => "c",
915   "irn_flags" => "R",
916   "comment"   => "construct unknown floating point register",
917   "reg_req"   => { "out" => [ "fp" ] },
918   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
919   "cmp_attr"  =>
920 '
921         return 1;
922 ',
923 },
924
925 # Load / Store
926
927 "Lfd" => {
928   "op_flags"  => "L|F",
929   "irn_flags" => "R",
930   "state"     => "exc_pinned",
931   "comment"   => "construct FP Load (double): Load(ptr, mem) = LD ptr",
932   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "fp", "none" ] },
933   "emit"      => '. lfd %D0, %O(%S0)',
934   "cmp_attr"  =>
935 '
936         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
937 ',
938   "outs"      => [ "res", "M" ],
939 },
940
941 "Lfs" => {
942   "op_flags"  => "L|F",
943   "irn_flags" => "R",
944   "state"     => "exc_pinned",
945   "comment"   => "construct FP Load (single): Load(ptr, mem) = LD ptr",
946   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "fp","none" ] },
947   "emit"      => '. lfs %D0, %O(%S0)',
948   "cmp_attr"  =>
949 '
950         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
951 ',
952   "outs"      => [ "res", "M" ],
953 },
954
955 "Stfd" => {
956   "op_flags"  => "L|F",
957   "state"     => "exc_pinned",
958   "comment"   => "construct Store (double): Store(ptr, val, mem)  = ST ptr,val",
959   "reg_req"   => { "in" => [ "!r0", "fp", "none" ], "out" => [ "none" ] },
960   "emit"      => '. stfd %S1, %O(%S0)',
961   "cmp_attr"  =>
962 '
963         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
964 ',
965   "outs"      => [ "M" ],
966 },
967
968 "Stfs" => {
969   "op_flags"  => "L|F",
970   "state"     => "exc_pinned",
971   "comment"   => "construct Store (single): Store(ptr, val, mem)  = ST ptr,val",
972   "reg_req"   => { "in" => [ "!r0", "fp", "none" ], "out" => [ "none" ] },
973   "emit"      => '. stfs %S1, %O(%S0)',
974   "cmp_attr"  =>
975 '
976         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
977 ',
978   "outs"      => [ "M" ],
979 },
980
981 ); # end of %nodes