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