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