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