ir_mode: simplify interface, improve float-mode handling
[libfirm] / ir / be / sparc / sparc_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3
4 $arch = "sparc";
5
6 $mode_gp      = "mode_Iu";
7 $mode_flags   = "mode_Bu";
8 $mode_fpflags = "mode_Bu";
9 $mode_fp      = "mode_F";
10 $mode_fp2     = "mode_D";
11 $mode_fp4     = "mode_Q";
12
13 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
14 %reg_classes = (
15         gp => [
16                 { name => "g0" },
17                 { name => "g1" },
18                 { name => "g2" },
19                 { name => "g3" },
20                 { name => "g4" },
21                 { name => "g5" },
22                 { name => "g6" },
23                 { name => "g7" },
24
25                 { name => "o0" },
26                 { name => "o1" },
27                 { name => "o2" },
28                 { name => "o3" },
29                 { name => "o4" },
30                 { name => "o5" },
31                 { name => "sp" },
32                 { name => "o7" },
33
34                 { name => "l0" },
35                 { name => "l1" },
36                 { name => "l2" },
37                 { name => "l3" },
38                 { name => "l4" },
39                 { name => "l5" },
40                 { name => "l6" },
41                 { name => "l7" },
42
43                 { name => "i0" },
44                 { name => "i1" },
45                 { name => "i2" },
46                 { name => "i3" },
47                 { name => "i4" },
48                 { name => "i5" },
49                 { name => "frame_pointer", realname => "fp" },
50                 { name => "i7" },
51                 { mode => $mode_gp }
52         ],
53         fpflags_class => [
54                 { name => "fpflags" },
55                 { mode => $mode_fpflags, flags => "manual_ra" }
56         ],
57         flags_class => [
58                 { name => "flags" },
59                 { mode => $mode_flags, flags => "manual_ra" }
60         ],
61         mul_div_high_res => [
62                 { name => "y" },
63                 { mode => $mode_gp, flags => "manual_ra" }
64         ],
65         # fp registers can be accessed any time
66         fp => [
67                 { name => "f0" },
68                 { name => "f1" },
69                 { name => "f2" },
70                 { name => "f3" },
71                 { name => "f4" },
72                 { name => "f5" },
73                 { name => "f6" },
74                 { name => "f7" },
75                 { name => "f8" },
76                 { name => "f9" },
77                 { name => "f10" },
78                 { name => "f11" },
79                 { name => "f12" },
80                 { name => "f13" },
81                 { name => "f14" },
82                 { name => "f15" },
83                 { name => "f16" },
84                 { name => "f17" },
85                 { name => "f18" },
86                 { name => "f19" },
87                 { name => "f20" },
88                 { name => "f21" },
89                 { name => "f22" },
90                 { name => "f23" },
91                 { name => "f24" },
92                 { name => "f25" },
93                 { name => "f26" },
94                 { name => "f27" },
95                 { name => "f28" },
96                 { name => "f29" },
97                 { name => "f30" },
98                 { name => "f31" },
99                 { mode => $mode_fp }
100         ]
101 ); # %reg_classes
102
103 %emit_templates = (
104 # emit source reg or imm dep. on node's arity
105         RI  => "${arch}_emit_reg_or_imm(node, -1);",
106         R1I => "${arch}_emit_reg_or_imm(node, 1);",
107         R2I => "${arch}_emit_reg_or_imm(node, 2);",
108         S0  => "${arch}_emit_source_register(node, 0);",
109         S1  => "${arch}_emit_source_register(node, 1);",
110         D0  => "${arch}_emit_dest_register(node, 0);",
111         D1  => "${arch}_emit_dest_register(node, 1);",
112         HIM => "${arch}_emit_high_immediate(node);",
113         LM  => "${arch}_emit_load_mode(node);",
114         SM  => "${arch}_emit_store_mode(node);",
115         FLSM => "${arch}_emit_float_load_store_mode(node);",
116         FPM  => "${arch}_emit_fp_mode_suffix(node);",
117         FCONVS => "${arch}_emit_fp_conv_source(node);",
118         FCONVD => "${arch}_emit_fp_conv_destination(node);",
119         O1     => "${arch}_emit_offset(node, 1);",
120         O2     => "${arch}_emit_offset(node, 2);",
121         S0O1   => "${arch}_emit_source_reg_and_offset(node, 0, 1);",
122         S1O2   => "${arch}_emit_source_reg_and_offset(node, 1, 2);",
123 );
124 $indent_line_func = "sparc_emit_indent()";
125
126 $default_attr_type = "sparc_attr_t";
127 $default_copy_attr = "sparc_copy_attr";
128
129 %init_attr = (
130         sparc_attr_t             => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
131         sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
132         sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
133         sparc_switch_jmp_attr_t  => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
134                                     "\tinit_sparc_switch_jmp_attributes(res, default_pn, jump_table);\n",
135         sparc_fp_attr_t          => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
136                                     "\tinit_sparc_fp_attributes(res, fp_mode);\n",
137         sparc_fp_conv_attr_t     => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);".
138                                     "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
139 );
140
141 %compare_attr = (
142         sparc_attr_t            => "cmp_attr_sparc",
143         sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
144         sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
145         sparc_switch_jmp_attr_t => "cmp_attr_sparc_switch_jmp",
146         sparc_fp_attr_t         => "cmp_attr_sparc_fp",
147         sparc_fp_conv_attr_t    => "cmp_attr_sparc_fp_conv",
148 );
149
150 %custom_irn_flags = (
151         modifies_flags    => "(arch_irn_flags_t)sparc_arch_irn_flag_modifies_flags",
152         modifies_fp_flags => "(arch_irn_flags_t)sparc_arch_irn_flag_modifies_fp_flags",
153         has_delay_slot    => "(arch_irn_flags_t)sparc_arch_irn_flag_has_delay_slot",
154 );
155
156 my %cmp_operand_constructors = (
157         imm => {
158                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
159                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
160                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
161                 ins        => [ "left" ],
162         },
163         reg => {
164                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
165                 ins        => [ "left", "right" ],
166         },
167 );
168
169 my %binop_operand_constructors = (
170         imm => {
171                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
172                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
173                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
174                 ins        => [ "left" ],
175         },
176         reg => {
177                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
178                 ins        => [ "left", "right" ],
179         },
180 );
181
182 my %binopcc_operand_constructors = (
183         imm => {
184                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
185                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
186                 reg_req    => { in => [ "gp" ], out => [ "gp", "flags" ] },
187                 ins        => [ "left" ],
188         },
189         reg => {
190                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
191                 ins        => [ "left", "right" ],
192         },
193 );
194
195 my %binopx_operand_constructors = (
196         imm => {
197                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
198                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
199                 reg_req    => { in => [ "gp", "flags" ], out => [ "gp" ] },
200                 ins        => [ "left", "carry" ],
201         },
202         reg => {
203                 reg_req    => { in => [ "gp", "gp", "flags" ], out => [ "gp" ] },
204                 ins        => [ "left", "right", "carry" ],
205         },
206 );
207
208
209 my %binopcczero_operand_constructors = (
210         imm => {
211                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
212                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
213                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
214                 ins        => [ "left" ],
215         },
216         reg => {
217                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
218                 ins        => [ "left", "right" ],
219         },
220 );
221
222 my %div_operand_constructors = (
223         imm => {
224                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
225                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
226                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
227         },
228         reg => {
229                 reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
230         },
231 );
232
233 my %float_binop_constructors = (
234         s => {
235                 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
236                 mode    => $mode_fp,
237         },
238         d => {
239                 reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2" ] },
240                 mode    => $mode_fp2,
241         },
242         q => {
243                 reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4" ] },
244                 mode    => $mode_fp4,
245         }
246 );
247
248 my %float_unop_constructors = (
249         s => {
250                 reg_req => { in => [ "fp" ], out => [ "fp" ] },
251                 mode    => $mode_fp,
252         },
253         d => {
254                 reg_req => { in => [ "fp:a|2" ], out => [ "fp:a|2" ] },
255                 mode    => $mode_fp2,
256         },
257         q => {
258                 reg_req => { in => [ "fp:a|4" ], out => [ "fp:a|4" ] },
259                 mode    => $mode_fp4,
260         }
261 );
262
263 %nodes = (
264
265 Add => {
266         irn_flags    => [ "rematerializable" ],
267         mode         => $mode_gp,
268         emit         => '. add %S0, %R1I, %D0',
269         constructors => \%binop_operand_constructors,
270 },
271
272 AddCC => {
273         irn_flags    => [ "rematerializable", "modifies_flags" ],
274         emit         => '. addcc %S0, %R1I, %D0',
275         outs         => [ "res", "flags" ],
276         constructors => \%binopcc_operand_constructors,
277 },
278
279 AddCCZero => {
280         irn_flags    => [ "rematerializable", "modifies_flags" ],
281         emit         => '. addcc %S0, %R1I, %%g0',
282         mode         => $mode_flags,
283         constructors => \%binopcczero_operand_constructors,
284 },
285
286 AddX => {
287         # At the moment not rematerializable because of assert in beflags.c/
288         # (it claims that spiller can't rematerialize flag stuff correctly)
289         #irn_flags    => [ "rematerializable" ],
290         emit         => '. addx %S0, %R1I, %D0',
291         constructors => \%binopx_operand_constructors,
292         mode         => $mode_gp,
293 },
294
295 AddCC_t => {
296         ins       => [ "left", "right" ],
297         outs      => [ "res", "flags" ],
298         attr_type => "",
299         dump_func => "NULL",
300 },
301
302 AddX_t => {
303         ins       => [ "left", "right", "flags_input" ],
304         attr_type => "",
305         dump_func => "NULL",
306 },
307
308 Sub => {
309         irn_flags    => [ "rematerializable" ],
310         mode         => $mode_gp,
311         emit         => '. sub %S0, %R1I, %D0',
312         constructors => \%binop_operand_constructors,
313 },
314
315 SubCC => {
316         irn_flags    => [ "rematerializable", "modifies_flags" ],
317         emit         => '. subcc %S0, %R1I, %D0',
318         outs         => [ "res", "flags" ],
319         constructors => \%binopcc_operand_constructors,
320 },
321
322 SubCCZero => {
323         irn_flags    => [ "rematerializable", "modifies_flags" ],
324         emit         => '. subcc %S0, %R1I, %%g0',
325         mode         => $mode_flags,
326         constructors => \%binopcczero_operand_constructors,
327 },
328
329 SubX => {
330         # Not rematerializable (see AddX)
331         emit         => '. subx %S0, %R1I, %D0',
332         constructors => \%binopx_operand_constructors,
333         mode         => $mode_gp,
334 },
335
336 SubCC_t => {
337         ins       => [ "left", "right" ],
338         outs      => [ "res", "flags" ],
339         attr_type => "",
340         dump_func => "NULL",
341 },
342
343 SubX_t => {
344         ins       => [ "left", "right", "flags_input" ],
345         attr_type => "",
346         dump_func => "NULL",
347 },
348
349 # Load / Store
350 Ld => {
351         op_flags  => [ "labeled" ],
352         state     => "exc_pinned",
353         constructors => {
354                 imm => {
355                         reg_req    => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
356                         ins        => [ "ptr", "mem" ],
357                         attr       => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
358                         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
359                 },
360                 reg => {
361                         reg_req    => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
362                         ins        => [ "ptr", "ptr2", "mem" ],
363                         attr       => "ir_mode *ls_mode",
364                         custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
365                 },
366         },
367         ins       => [ "ptr", "mem" ],
368         outs      => [ "res", "M" ],
369         attr_type => "sparc_load_store_attr_t",
370         emit      => '. ld%LM [%S0O1], %D0'
371 },
372
373 SetHi => {
374         irn_flags  => [ "rematerializable" ],
375         outs       => [ "res" ],
376         mode       => $mode_gp,
377         reg_req    => { in => [], out => [ "gp" ] },
378         attr       => "ir_entity *entity, int32_t immediate_value",
379         custominit => "sparc_set_attr_imm(res, entity, immediate_value);",
380         emit       => '. sethi %HIM, %D0'
381 },
382
383 St => {
384         op_flags  => [ "labeled" ],
385         mode      => "mode_M",
386         state     => "exc_pinned",
387         constructors => {
388                 imm => {
389                         reg_req    => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
390                         ins        => [ "val", "ptr", "mem" ],
391                         attr       => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
392                         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
393                 },
394                 reg => {
395                         reg_req    => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
396                         ins        => [ "val", "ptr", "ptr2", "mem" ],
397                         attr       => "ir_mode *ls_mode",
398                         custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
399                 },
400         },
401         ins       => [ "val", "ptr", "mem" ],
402         outs      => [ "M" ],
403         attr_type => "sparc_load_store_attr_t",
404         emit      => '. st%SM %S0, [%S1O2]'
405 },
406
407 Save => {
408         emit      => '. save %S0, %R1I, %D0',
409         outs      => [ "stack" ],
410         ins       => [ "stack" ],
411         constructors => {
412                 imm => {
413                         attr       => "ir_entity *immediate_entity, int32_t immediate_value",
414                         custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
415                         reg_req    => { in => [ "sp" ], out => [ "sp:I|S" ] },
416                         ins        => [ "stack" ],
417                 },
418                 reg => {
419                         reg_req    => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
420                         ins        => [ "stack", "increment" ],
421                 }
422         },
423         mode => $mode_gp,
424 },
425
426 Restore => {
427         outs => [ "stack", "res" ],
428         constructors => {
429                 imm => {
430                         attr       => "ir_entity *immediate_entity, int32_t immediate_value",
431                         custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
432                         reg_req    => { in => [ "frame_pointer", "gp" ], out => [ "sp:I|S", "gp" ] },
433                         ins        => [ "frame_pointer", "left" ],
434                 },
435                 reg => {
436                         reg_req    => { in => [ "frame_pointer", "gp", "gp" ], out => [ "sp:I|S", "gp" ] },
437                         ins        => [ "frame_pointer", "left", "right" ],
438                 }
439         },
440 },
441
442 RestoreZero => {
443         reg_req => { in => [ "frame_pointer" ], out => [ "sp:I|S" ] },
444         ins     => [ "frame_pointer" ],
445         outs    => [ "stack" ],
446         emit    => '. restore',
447         mode    => $mode_gp,
448 },
449
450 SubSP => {
451         reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
452         ins     => [ "stack", "size" ],
453         outs    => [ "stack" ],
454         emit    => ". sub %S0, %S1, %D0\n",
455         mode    => $mode_gp,
456 },
457
458 AddSP => {
459         reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
460         ins     => [ "stack", "size" ],
461         outs    => [ "stack" ],
462         emit    => ". add %S0, %S1, %D0\n",
463         mode    => $mode_gp,
464 },
465
466 FrameAddr => {
467         op_flags   => [ "constlike" ],
468         irn_flags  => [ "rematerializable" ],
469         attr       => "ir_entity *entity, int32_t offset",
470         reg_req    => { in => [ "gp" ], out => [ "gp" ] },
471         ins        => [ "base" ],
472         attr_type  => "sparc_attr_t",
473         custominit => "sparc_set_attr_imm(res, entity, offset);",
474         mode       => $mode_gp,
475 },
476
477 Bicc => {
478         op_flags  => [ "labeled", "cfopcode", "forking" ],
479         irn_flags => [ "has_delay_slot" ],
480         state     => "pinned",
481         mode      => "mode_T",
482         attr_type => "sparc_jmp_cond_attr_t",
483         attr      => "ir_relation relation, bool is_unsigned",
484         init_attr => "\tinit_sparc_jmp_cond_attr(res, relation, is_unsigned);",
485         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
486         ins       => [ "flags" ],
487         outs      => [ "false", "true" ],
488 },
489
490 fbfcc => {
491         op_flags  => [ "labeled", "cfopcode", "forking" ],
492         irn_flags => [ "has_delay_slot" ],
493         state     => "pinned",
494         mode      => "mode_T",
495         attr_type => "sparc_jmp_cond_attr_t",
496         attr      => "ir_relation relation",
497         init_attr => "\tinit_sparc_jmp_cond_attr(res, relation, false);",
498         reg_req   => { in => [ "fpflags" ], out => [ "none", "none" ] },
499         ins       => [ "flags" ],
500         outs      => [ "false", "true" ],
501 },
502
503 Ba => {
504         # Note: has_delay_slot depends on wether it is a fallthrough or not, so we
505         # have special code for this in sparc_emitter
506         state     => "pinned",
507         op_flags  => [ "cfopcode" ],
508         irn_flags => [ "simple_jump" ],
509         reg_req   => { out => [ "none" ] },
510         mode      => "mode_X",
511 },
512
513 Start => {
514         state     => "pinned",
515         out_arity => "variable",
516         ins       => [],
517 },
518
519 # This is a Jump instruction, but with the addition that you can add custom
520 # register constraints to model your calling conventions
521 Return => {
522         state     => "pinned",
523         op_flags  => [ "cfopcode" ],
524         irn_flags => [ "has_delay_slot" ],
525         arity     => "variable",
526         mode      => "mode_X",
527         constructors => {
528                 imm => {
529                         attr       => "ir_entity *entity, int32_t offset",
530                         custominit => "\tsparc_set_attr_imm(res, entity, offset);",
531                         arity     => "variable",
532                         reg_req   => { out => [ "none" ] },
533                 },
534                 reg => {
535                         arity     => "variable",
536                         reg_req   => { out => [ "none" ] },
537                 }
538         },
539 },
540
541 # This is a JumpLink instruction, but with the addition that you can add custom
542 # register constraints to model your calling conventions
543 Call => {
544         irn_flags => [ "modifies_flags", "modifies_fp_flags", "has_delay_slot" ],
545         state     => "exc_pinned",
546         arity     => "variable",
547         out_arity => "variable",
548         constructors => {
549                 imm => {
550                         attr       => "ir_entity *entity, int32_t offset, bool aggregate_return",
551                         custominit => "\tsparc_set_attr_imm(res, entity, offset);".
552                                       "\tif (aggregate_return) arch_add_irn_flags(res, sparc_arch_irn_flag_aggregate_return);",
553                         arity     => "variable",
554                         out_arity => "variable",
555                 },
556                 reg => {
557                         attr       => "bool aggregate_return",
558                         arity      => "variable",
559                         out_arity  => "variable",
560                         custominit => "\tif (aggregate_return) arch_add_irn_flags(res, sparc_arch_irn_flag_aggregate_return);",
561                 }
562         },
563 },
564
565 Cmp => {  # aka SubccZero
566         irn_flags    => [ "rematerializable", "modifies_flags" ],
567         emit         => '. cmp %S0, %R1I',
568         mode         => $mode_flags,
569         constructors => \%binopcczero_operand_constructors,
570 },
571
572 SwitchJmp => {
573         op_flags     => [ "labeled", "cfopcode", "forking" ],
574         irn_flags    => [ "has_delay_slot" ],
575         state        => "pinned",
576         mode         => "mode_T",
577         reg_req      => { in => [ "gp" ], out => [ ] },
578         attr_type    => "sparc_switch_jmp_attr_t",
579         attr         => "long default_pn, ir_entity *jump_table",
580         init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
581 },
582
583 Sll => {
584         irn_flags    => [ "rematerializable" ],
585         mode         => $mode_gp,
586         emit         => '. sll %S0, %R1I, %D0',
587         constructors => \%binop_operand_constructors,
588 },
589
590 Srl => {
591         irn_flags    => [ "rematerializable" ],
592         mode         => $mode_gp,
593         emit         => '. srl %S0, %R1I, %D0',
594         constructors => \%binop_operand_constructors,
595 },
596
597 Sra => {
598         irn_flags    => [ "rematerializable" ],
599         mode         => $mode_gp,
600         emit         => '. sra %S0, %R1I, %D0',
601         constructors => \%binop_operand_constructors,
602 },
603
604 And => {
605         irn_flags    => [ "rematerializable" ],
606         mode         => $mode_gp,
607         emit         => '. and %S0, %R1I, %D0',
608         constructors => \%binop_operand_constructors,
609 },
610
611 AndCCZero => {
612         irn_flags    => [ "rematerializable", "modifies_flags" ],
613         emit         => '. andcc %S0, %R1I, %%g0',
614         mode         => $mode_flags,
615         constructors => \%binopcczero_operand_constructors,
616 },
617
618 AndN => {
619         irn_flags => [ "rematerializable" ],
620         mode      => $mode_gp,
621         emit      => '. andn %S0, %R1I, %D0',
622         constructors => \%binop_operand_constructors,
623 },
624
625 AndNCCZero => {
626         irn_flags    => [ "rematerializable", "modifies_flags" ],
627         emit         => '. andncc %S0, %R1I, %%g0',
628         mode         => $mode_flags,
629         constructors => \%binopcczero_operand_constructors,
630 },
631
632 Or => {
633         irn_flags    => [ "rematerializable" ],
634         mode         => $mode_gp,
635         emit         => '. or %S0, %R1I, %D0',
636         constructors => \%binop_operand_constructors,
637 },
638
639 OrCCZero => {
640         irn_flags    => [ "rematerializable", "modifies_flags" ],
641         emit         => '. orcc %S0, %R1I, %%g0',
642         mode         => $mode_flags,
643         constructors => \%binopcczero_operand_constructors,
644 },
645
646 OrN => {
647         irn_flags => [ "rematerializable" ],
648         mode      => $mode_gp,
649         emit      => '. orn %S0, %R1I, %D0',
650         constructors => \%binop_operand_constructors,
651 },
652
653 OrNCCZero => {
654         irn_flags    => [ "rematerializable", "modifies_flags" ],
655         emit         => '. orncc %S0, %R1I, %%g0',
656         mode         => $mode_flags,
657         constructors => \%binopcczero_operand_constructors,
658 },
659
660 Xor => {
661         irn_flags    => [ "rematerializable" ],
662         mode         => $mode_gp,
663         emit         => '. xor %S0, %R1I, %D0',
664         constructors => \%binop_operand_constructors,
665 },
666
667 XorCCZero => {
668         irn_flags    => [ "rematerializable", "modifies_flags" ],
669         emit         => '. xorcc %S0, %R1I, %%g0',
670         mode         => $mode_flags,
671         constructors => \%binopcczero_operand_constructors,
672 },
673
674 XNor => {
675         irn_flags => [ "rematerializable" ],
676         mode      => $mode_gp,
677         emit      => '. xnor %S0, %R1I, %D0',
678         constructors => \%binop_operand_constructors,
679 },
680
681 XNorCCZero => {
682         irn_flags    => [ "rematerializable", "modifies_flags" ],
683         emit         => '. xnorcc %S0, %R1I, %%g0',
684         mode         => $mode_flags,
685         constructors => \%binopcczero_operand_constructors,
686 },
687
688 Mul => {
689         irn_flags    => [ "rematerializable" ],
690         mode         => $mode_gp,
691         emit         => '. smul %S0, %R1I, %D0',
692         constructors => \%binop_operand_constructors,
693 },
694
695 MulCCZero => {
696         irn_flags    => [ "rematerializable", "modifies_flags" ],
697         emit         => '. smulcc %S0, %R1I, %%g0',
698         mode         => $mode_flags,
699         constructors => \%binopcczero_operand_constructors,
700 },
701
702 SMulh => {
703         irn_flags    => [ "rematerializable" ],
704         outs         => [ "low", "high" ],
705         constructors => \%binop_operand_constructors,
706 },
707
708 UMulh => {
709         irn_flags    => [ "rematerializable" ],
710         outs         => [ "low", "high" ],
711         constructors => \%binop_operand_constructors,
712 },
713
714 SDiv => {
715         irn_flags    => [ "rematerializable", "has_delay_slot" ],
716         state        => "exc_pinned",
717         ins          => [ "dividend_high", "dividend_low", "divisor" ],
718         outs         => [ "res", "M" ],
719         constructors => \%div_operand_constructors,
720 },
721
722 UDiv => {
723         irn_flags    => [ "rematerializable", "has_delay_slot" ],
724         state        => "exc_pinned",
725         ins          => [ "dividend_high", "dividend_low", "divisor" ],
726         outs         => [ "res", "M" ],
727         constructors => \%div_operand_constructors,
728 },
729
730 fcmp => {
731         irn_flags => [ "rematerializable", "modifies_fp_flags" ],
732         emit      => '. fcmp%FPM %S0, %S1',
733         attr_type => "sparc_fp_attr_t",
734         attr      => "ir_mode *fp_mode",
735         mode      => $mode_fpflags,
736         constructors => {
737                 s => {
738                         reg_req => { in => [ "fp", "fp" ], out => [ "fpflags" ] },
739                 },
740                 d => {
741                         reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fpflags" ] },
742                 },
743                 q => {
744                         reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fpflags" ] },
745                 },
746         },
747 },
748
749 fadd => {
750         op_flags     => [ "commutative" ],
751         irn_flags    => [ "rematerializable" ],
752         emit         => '. fadd%FPM %S0, %S1, %D0',
753         attr_type    => "sparc_fp_attr_t",
754         attr         => "ir_mode *fp_mode",
755         ins          => [ "left", "right" ],
756         constructors => \%float_binop_constructors,
757 },
758
759 fsub => {
760         irn_flags    => [ "rematerializable" ],
761         emit         => '. fsub%FPM %S0, %S1, %D0',
762         attr_type    => "sparc_fp_attr_t",
763         attr         => "ir_mode *fp_mode",
764         ins          => [ "left", "right" ],
765         constructors => \%float_binop_constructors,
766 },
767
768 fmul => {
769         irn_flags    => [ "rematerializable" ],
770         op_flags     => [ "commutative" ],
771         emit         =>'. fmul%FPM %S0, %S1, %D0',
772         attr_type    => "sparc_fp_attr_t",
773         attr         => "ir_mode *fp_mode",
774         ins          => [ "left", "right" ],
775         constructors => \%float_binop_constructors,
776 },
777
778 fdiv => {
779         irn_flags    => [ "rematerializable" ],
780         emit         => '. fdiv%FPM %S0, %S1, %D0',
781         attr_type    => "sparc_fp_attr_t",
782         attr         => "ir_mode *fp_mode",
783         ins          => [ "left", "right" ],
784         outs         => [ "res", "M" ],
785         constructors => {
786                 s => {
787                         reg_req => { in => [ "fp", "fp" ], out => [ "fp", "none" ] },
788                 },
789                 d => {
790                         reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2", "none" ] },
791                 },
792                 q => {
793                         reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4", "none" ] },
794                 }
795         },
796 },
797
798 fneg => {
799         irn_flags => [ "rematerializable" ],
800         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
801         # note that we only need the first register even for wide-values
802         emit      => '. fnegs %S0, %D0',
803         attr_type => "sparc_fp_attr_t",
804         attr      => "ir_mode *fp_mode",
805         ins          => [ "val" ],
806         constructors => \%float_unop_constructors,
807 },
808
809 "fabs" => {
810         irn_flags    => [ "rematerializable" ],
811         # note that we only need the first register even for wide-values
812         emit         => '. fabs %S0, %D0',
813         attr_type    => "sparc_fp_attr_t",
814         attr         => "ir_mode *fp_mode",
815         ins          => [ "val" ],
816         constructors => \%float_unop_constructors,
817 },
818
819 fftof => {
820         irn_flags => [ "rematerializable" ],
821         emit      => '. f%FCONVS%.to%FCONVD %S0, %D0',
822         attr_type => "sparc_fp_conv_attr_t",
823         attr      => "ir_mode *src_mode, ir_mode *dest_mode",
824         constructors => {
825                 s_d => {
826                         reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
827                         mode    => $mode_fp2,
828                 },
829                 s_q => {
830                         reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
831                         mode    => $mode_fp4,
832                 },
833                 d_s => {
834                         reg_req => { in => [ "fp:a|2" ], out => [ "fp" ] },
835                         mode    => $mode_fp,
836                 },
837                 d_q => {
838                         reg_req => { in => [ "fp:a|2" ], out => [ "fp:a|4" ] },
839                         mode    => $mode_fp4,
840                 },
841                 q_s => {
842                         reg_req => { in => [ "fp:a|4" ], out => [ "fp" ] },
843                         mode    => $mode_fp,
844                 },
845                 q_d => {
846                         reg_req => { in => [ "fp:a|4" ], out => [ "fp:a|2" ] },
847                         mode    => $mode_fp2,
848                 },
849         },
850 },
851
852 fitof => {
853         irn_flags => [ "rematerializable" ],
854         emit      => '. fito%FPM %S0, %D0',
855         attr_type => "sparc_fp_attr_t",
856         attr      => "ir_mode *fp_mode",
857         constructors => {
858                 s => {
859                         reg_req => { in => [ "fp" ], out => [ "fp" ] },
860                         mode    => $mode_fp,
861                 },
862                 d => {
863                         reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
864                         mode    => $mode_fp2,
865                 },
866                 q => {
867                         reg_req => { in => [ "fp" ], out => [ "fp:a|4" ] },
868                         mode    => $mode_fp4,
869                 },
870         },
871 },
872
873 fftoi => {
874         irn_flags => [ "rematerializable" ],
875         emit      => '. f%FPM%.toi %S0, %D0',
876         attr_type => "sparc_fp_attr_t",
877         attr      => "ir_mode *fp_mode",
878         mode      => $mode_gp,
879         constructors => {
880                 s => {
881                         reg_req => { in => [ "fp" ], out => [ "fp" ] },
882                 },
883                 d => {
884                         reg_req => { in => [ "fp:a|2" ], out => [ "fp" ] },
885                 },
886                 q => {
887                         reg_req => { in => [ "fp:a|4" ], out => [ "fp" ] },
888                 },
889         },
890 },
891
892 Ldf => {
893         op_flags  => [ "labeled" ],
894         state     => "exc_pinned",
895         constructors => {
896                 s => {
897                         reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
898                 },
899                 d => {
900                         reg_req => { in => [ "gp", "none" ], out => [ "fp:a|2", "none" ] },
901                 },
902                 q => {
903                         reg_req => { in => [ "gp", "none" ], out => [ "fp:a|4", "none" ] },
904                 },
905         },
906         ins       => [ "ptr", "mem" ],
907         outs      => [ "res", "M" ],
908         attr_type => "sparc_load_store_attr_t",
909         attr      => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
910         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
911         emit      => '. ld%FLSM [%S0%O1], %D0'
912 },
913
914 Stf => {
915         op_flags  => [ "labeled" ],
916         state     => "exc_pinned",
917         constructors => {
918                 s => {
919                         reg_req => { in => [ "fp",     "gp", "none" ], out => [ "none" ] },
920                 },
921                 d => {
922                         reg_req => { in => [ "fp:a|2", "gp", "none" ], out => [ "none" ] },
923                 },
924                 q => {
925                         reg_req => { in => [ "fp:a|4", "gp", "none" ], out => [ "none" ] },
926                 },
927         },
928         ins       => [ "val", "ptr", "mem" ],
929         outs      => [ "M" ],
930         attr_type => "sparc_load_store_attr_t",
931         attr      => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
932         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
933         emit      => '. st%FLSM %S0, [%S1%O2]',
934         mode      => 'mode_M',
935 },
936
937 ); # end of %nodes