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