refactor mode_b lowerer to have a create_set callback
[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_E"; # not correct, we need to register a new mode
12
13 $normal      =  0; # no special type
14 $caller_save =  1; # caller save (register must be saved by the caller of a function)
15 $callee_save =  2; # callee save (register must be saved by the called function)
16 $ignore      =  4; # ignore (do not assign this register)
17 $arbitrary   =  8; # emitter can choose an arbitrary register of this class
18 $virtual     = 16; # the register is a virtual one
19 $state       = 32; # register represents a state
20
21 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
22 %reg_classes = (
23         gp => [
24                 { name => "g0", type => $ignore }, # hardwired 0, behaves like /dev/null
25                 { name => "g1", type => $caller_save }, # temp. value
26                 { name => "g2", type => $caller_save },
27                 { name => "g3", type => $caller_save },
28                 { name => "g4", type => $caller_save },
29                 { name => "g5", type => $ignore }, # reserved by SPARC ABI
30                 { name => "g6", type => $ignore }, # reserved by SPARC ABI
31                 { name => "g7", type => $ignore }, # reserved by SPARC ABI
32
33                 # window's out registers
34                 { name => "o0", type => $caller_save }, # param 1 / return value from callee
35                 { name => "o1", type => $caller_save }, # param 2
36                 { name => "o2", type => $caller_save }, # param 3
37                 { name => "o3", type => $caller_save }, # param 4
38                 { name => "o4", type => $caller_save }, # param 5
39                 { name => "o5", type => $caller_save }, # param 6
40                 { name => "sp", type => $ignore }, # our stackpointer
41                 { name => "o7", type => $ignore }, # temp. value / address of CALL instr.
42
43                 # window's local registers
44                 { name => "l0", type => 0 },
45                 { name => "l1", type => 0 },
46                 { name => "l2", type => 0 },
47                 { name => "l3", type => 0 },
48                 { name => "l4", type => 0 },
49                 { name => "l5", type => 0 },
50                 { name => "l6", type => 0 },
51                 { name => "l7", type => 0 },
52
53                 # window's in registers
54                 { name => "i0", type => 0 }, # incoming param1 / return value to caller
55                 { name => "i1", type => 0 }, # param 2
56                 { name => "i2", type => 0 }, # param 3
57                 { name => "i3", type => 0 }, # param 4
58                 { name => "i4", type => 0 }, # param 5
59                 { name => "i5", type => 0 }, # param 6
60                 { name => "frame_pointer", realname => "fp", type => $ignore }, # our framepointer
61                 { name => "i7", type => $ignore }, # return address - 8
62                 { mode => $mode_gp }
63         ],
64         fpflags_class => [
65                 { name => "fpflags", type => $ignore },
66                 { mode => $mode_fpflags, flags => "manual_ra" }
67         ],
68         flags_class => [
69                 { name => "flags", type => $ignore },
70                 { mode => $mode_flags, flags => "manual_ra" }
71         ],
72         mul_div_high_res => [
73                 { name => "y", type => $ignore },
74                 { mode => $mode_gp, flags => "manual_ra" }
75         ],
76         # fp registers can be accessed any time
77         fp => [
78                 { name => "f0",  type => $caller_save },
79                 { name => "f1",  type => $caller_save },
80                 { name => "f2",  type => $caller_save },
81                 { name => "f3",  type => $caller_save },
82                 { name => "f4",  type => $caller_save },
83                 { name => "f5",  type => $caller_save },
84                 { name => "f6",  type => $caller_save },
85                 { name => "f7",  type => $caller_save },
86                 { name => "f8",  type => $caller_save },
87                 { name => "f9",  type => $caller_save },
88                 { name => "f10", type => $caller_save },
89                 { name => "f11", type => $caller_save },
90                 { name => "f12", type => $caller_save },
91                 { name => "f13", type => $caller_save },
92                 { name => "f14", type => $caller_save },
93                 { name => "f15", type => $caller_save },
94                 { name => "f16", type => $caller_save },
95                 { name => "f17", type => $caller_save },
96                 { name => "f18", type => $caller_save },
97                 { name => "f19", type => $caller_save },
98                 { name => "f20", type => $caller_save },
99                 { name => "f21", type => $caller_save },
100                 { name => "f22", type => $caller_save },
101                 { name => "f23", type => $caller_save },
102                 { name => "f24", type => $caller_save },
103                 { name => "f25", type => $caller_save },
104                 { name => "f26", type => $caller_save },
105                 { name => "f27", type => $caller_save },
106                 { name => "f28", type => $caller_save },
107                 { name => "f29", type => $caller_save },
108                 { name => "f30", type => $caller_save },
109                 { name => "f31", type => $caller_save },
110                 { mode => $mode_fp }
111         ]
112 ); # %reg_classes
113
114 %emit_templates = (
115 # emit source reg or imm dep. on node's arity
116         RI  => "${arch}_emit_reg_or_imm(node, -1);",
117         R1I => "${arch}_emit_reg_or_imm(node, 1);",
118         S0  => "${arch}_emit_source_register(node, 0);",
119         S1  => "${arch}_emit_source_register(node, 1);",
120         D0  => "${arch}_emit_dest_register(node, 0);",
121         HIM => "${arch}_emit_high_immediate(node);",
122         LM  => "${arch}_emit_load_mode(node);",
123         SM  => "${arch}_emit_store_mode(node);",
124         FLSM => "${arch}_emit_float_load_store_mode(node);",
125         FPM  => "${arch}_emit_fp_mode_suffix(node);",
126         FCONVS => "${arch}_emit_fp_conv_source(node);",
127         FCONVD => "${arch}_emit_fp_conv_destination(node);",
128         O1     => "${arch}_emit_offset(node, 1);",
129         O2     => "${arch}_emit_offset(node, 2);",
130 );
131
132 $default_attr_type = "sparc_attr_t";
133 $default_copy_attr = "sparc_copy_attr";
134
135
136 %init_attr = (
137         sparc_attr_t             => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
138         sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
139         sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
140         sparc_switch_jmp_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
141                                     "\tinit_sparc_switch_jmp_attributes(res, default_pn, jump_table);\n",
142         sparc_save_attr_t        => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
143         sparc_fp_attr_t          => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
144                                     "\tinit_sparc_fp_attributes(res, fp_mode);\n",
145         sparc_fp_conv_attr_t     => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);".
146                                     "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
147 );
148
149 %compare_attr = (
150         sparc_attr_t            => "cmp_attr_sparc",
151         sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
152         sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
153         sparc_switch_jmp_attr_t => "cmp_attr_sparc_switch_jmp",
154         sparc_save_attr_t       => "cmp_attr_sparc_save",
155         sparc_fp_attr_t         => "cmp_attr_sparc_fp",
156         sparc_fp_conv_attr_t    => "cmp_attr_sparc_fp_conv",
157 );
158
159 %custom_irn_flags = (
160         modifies_flags    => "sparc_arch_irn_flag_modifies_flags",
161         modifies_fp_flags => "sparc_arch_irn_flag_modifies_fp_flags",
162 );
163
164 # addressing modes: imm, reg, reg +/- imm, reg + reg
165 # max. imm = 13 bits signed (-4096 ... 4096)
166
167 my %cmp_operand_constructors = (
168         imm => {
169                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
170                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
171                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
172                 ins        => [ "left" ],
173         },
174         reg => {
175                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
176                 ins        => [ "left", "right" ],
177         },
178 );
179
180 my %binop_operand_constructors = (
181         imm => {
182                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
183                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
184                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
185                 ins        => [ "left" ],
186         },
187         reg => {
188                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
189                 ins        => [ "left", "right" ],
190         },
191 );
192
193 my %binopcczero_operand_constructors = (
194         imm => {
195                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
196                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
197                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
198                 ins        => [ "left" ],
199         },
200         reg => {
201                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
202                 ins        => [ "left", "right" ],
203         },
204 );
205
206 my %div_operand_constructors = (
207         imm => {
208                 attr       => "ir_entity *immediate_entity, int32_t immediate_value",
209                 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
210                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
211         },
212         reg => {
213                 reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
214         },
215 );
216
217 my %float_binop_constructors = (
218         s => {
219                 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
220                 mode    => $mode_fp,
221         },
222         d => {
223                 reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2" ] },
224                 mode    => $mode_fp2,
225         },
226         q => {
227                 reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4" ] },
228                 mode    => $mode_fp4,
229         }
230 );
231
232 my %float_unop_constructors = (
233         s => {
234                 reg_req => { in => [ "fp" ], out => [ "fp" ] },
235                 mode    => $mode_fp,
236         },
237         d => {
238                 reg_req => { in => [ "fp:a|2" ], out => [ "fp:a|2" ] },
239                 mode    => $mode_fp2,
240         },
241         q => {
242                 reg_req => { in => [ "fp:a|4" ], out => [ "fp:a|4" ] },
243                 mode    => $mode_fp4,
244         }
245 );
246
247 %nodes = (
248
249 Add => {
250         irn_flags    => [ "rematerializable" ],
251         mode         => $mode_gp,
252         emit         => '. add %S0, %R1I, %D0',
253         constructors => \%binop_operand_constructors,
254 },
255
256 Sub => {
257         irn_flags    => [ "rematerializable" ],
258         mode         => $mode_gp,
259         emit         => '. sub %S0, %R1I, %D0',
260         constructors => \%binop_operand_constructors,
261 },
262
263
264 # Load / Store
265 Ld => {
266         op_flags  => [ "labeled", "fragile" ],
267         state     => "exc_pinned",
268         constructors => {
269                 imm => {
270                         reg_req    => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
271                         ins        => [ "ptr", "mem" ],
272                         attr       => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
273                         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
274                 },
275                 reg => {
276                         reg_req    => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
277                         ins        => [ "ptr", "ptr2", "mem" ],
278                         attr       => "ir_mode *ls_mode",
279                         custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
280                 },
281         },
282         ins       => [ "ptr", "mem" ],
283         outs      => [ "res", "M" ],
284         attr_type => "sparc_load_store_attr_t",
285         emit      => '. ld%LM [%S0%O1], %D0'
286 },
287
288 SetHi => {
289         irn_flags  => [ "rematerializable" ],
290         outs       => [ "res" ],
291         mode       => $mode_gp,
292         reg_req    => { in => [], out => [ "gp" ] },
293         attr       => "ir_entity *entity, int32_t immediate_value",
294         custominit => "sparc_set_attr_imm(res, entity, immediate_value);",
295         emit       => '. sethi %HIM, %D0'
296 },
297
298 St => {
299         op_flags  => [ "labeled", "fragile" ],
300         mode      => "mode_M",
301         state     => "exc_pinned",
302         constructors => {
303                 imm => {
304                         reg_req    => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
305                         ins        => [ "val", "ptr", "mem" ],
306                         attr       => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
307                         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
308                 },
309                 reg => {
310                         reg_req    => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
311                         ins        => [ "val", "ptr", "ptr2", "mem" ],
312                         attr       => "ir_mode *ls_mode",
313                         custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
314                 },
315         },
316         ins       => [ "val", "ptr", "mem" ],
317         outs      => [ "M" ],
318         attr_type => "sparc_load_store_attr_t",
319         emit      => '. st%SM %S0, [%S1%O2]'
320 },
321
322 Save => {
323         reg_req   => {
324                 in => [ "sp", "none"],
325                 out => [ "sp:I|S", "frame_pointer:I", "none" ]
326         },
327         ins       => [ "stack", "mem" ],
328         outs      => [ "stack", "frame", "mem" ],
329         attr      => "int initial_stacksize",
330         attr_type => "sparc_save_attr_t",
331         init_attr => "\tinit_sparc_save_attributes(res, initial_stacksize);",
332 },
333
334 SubSP => {
335         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
336         ins       => [ "stack", "size", "mem" ],
337         outs      => [ "stack", "addr", "M" ],
338         emit      => ". sub %S0, %S1, %D0\n",
339 },
340
341 AddSP => {
342         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
343         ins       => [ "stack", "size", "mem" ],
344         outs      => [ "stack", "M" ],
345         emit      => ". add %S0, %S1, %D0\n",
346 },
347
348 FrameAddr => {
349         op_flags   => [ "constlike" ],
350         irn_flags  => [ "rematerializable" ],
351         attr       => "ir_entity *entity, int32_t offset",
352         reg_req    => { in => [ "gp" ], out => [ "gp" ] },
353         ins        => [ "base" ],
354         attr_type  => "sparc_attr_t",
355         custominit => "sparc_set_attr_imm(res, entity, offset);",
356         mode       => $mode_gp,
357 },
358
359 Bicc => {
360         op_flags  => [ "labeled", "cfopcode", "forking" ],
361         state     => "pinned",
362         mode      => "mode_T",
363         attr_type => "sparc_jmp_cond_attr_t",
364         attr      => "pn_Cmp pnc, bool is_unsigned",
365         init_attr => "\tinit_sparc_jmp_cond_attr(res, pnc, is_unsigned);",
366         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
367 },
368
369 fbfcc => {
370         op_flags  => [ "labeled", "cfopcode", "forking" ],
371         state     => "pinned",
372         mode      => "mode_T",
373         attr_type => "sparc_jmp_cond_attr_t",
374         attr      => "pn_Cmp pnc",
375         init_attr => "\tinit_sparc_jmp_cond_attr(res, pnc, false);",
376         reg_req   => { in => [ "fpflags" ], out => [ "none", "none" ] },
377 },
378
379 Ba => {
380         state     => "pinned",
381         op_flags  => [ "cfopcode" ],
382         irn_flags => [ "simple_jump" ],
383         reg_req   => { out => [ "none" ] },
384         mode      => "mode_X",
385 },
386
387 Call => {
388         irn_flags => [ "modifies_flags", "modifies_fp_flags" ],
389         state     => "exc_pinned",
390         arity     => "variable",
391         out_arity => "variable",
392         constructors => {
393                 imm => {
394                         attr       => "ir_entity *entity, int32_t offset",
395                         custominit => "\tsparc_set_attr_imm(res, entity, offset);",
396                         arity     => "variable",
397                         out_arity => "variable",
398                 },
399                 reg => {
400                         arity     => "variable",
401                         out_arity => "variable",
402                 }
403         },
404 },
405
406 Cmp => {  # aka SubccZero
407         irn_flags    => [ "rematerializable", "modifies_flags" ],
408         emit         => '. cmp %S0, %R1I',
409         mode         => $mode_flags,
410         constructors => \%binopcczero_operand_constructors,
411 },
412
413 SwitchJmp => {
414         op_flags     => [ "labeled", "cfopcode", "forking" ],
415         state        => "pinned",
416         mode         => "mode_T",
417         reg_req      => { in => [ "gp" ], out => [ ] },
418         attr_type    => "sparc_switch_jmp_attr_t",
419         attr         => "long default_pn, ir_entity *jump_table",
420         init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
421 },
422
423 Sll => {
424         irn_flags    => [ "rematerializable" ],
425         mode         => $mode_gp,
426         emit         => '. sll %S0, %R1I, %D0',
427         constructors => \%binop_operand_constructors,
428 },
429
430 Srl => {
431         irn_flags    => [ "rematerializable" ],
432         mode         => $mode_gp,
433         emit         => '. srl %S0, %R1I, %D0',
434         constructors => \%binop_operand_constructors,
435 },
436
437 Sra => {
438         irn_flags    => [ "rematerializable" ],
439         mode         => $mode_gp,
440         emit         => '. sra %S0, %R1I, %D0',
441         constructors => \%binop_operand_constructors,
442 },
443
444 And => {
445         irn_flags    => [ "rematerializable" ],
446         mode         => $mode_gp,
447         emit         => '. and %S0, %R1I, %D0',
448         constructors => \%binop_operand_constructors,
449 },
450
451 AndCCZero => {
452         irn_flags    => [ "rematerializable", "modifies_flags" ],
453         emit         => '. andcc %S0, %R1I, %%g0',
454         mode         => $mode_flags,
455         constructors => \%binopcczero_operand_constructors,
456 },
457
458 AndN => {
459         irn_flags => [ "rematerializable" ],
460         mode      => $mode_gp,
461         emit      => '. andn %S0, %R1I, %D0',
462         constructors => \%binop_operand_constructors,
463 },
464
465 AndNCCZero => {
466         irn_flags    => [ "rematerializable", "modifies_flags" ],
467         emit         => '. andncc %S0, %R1I, %%g0',
468         mode         => $mode_flags,
469         constructors => \%binopcczero_operand_constructors,
470 },
471
472 Or => {
473         irn_flags    => [ "rematerializable" ],
474         mode         => $mode_gp,
475         emit         => '. or %S0, %R1I, %D0',
476         constructors => \%binop_operand_constructors,
477 },
478
479 OrCCZero => {
480         irn_flags    => [ "rematerializable", "modifies_flags" ],
481         emit         => '. orcc %S0, %R1I, %%g0',
482         mode         => $mode_flags,
483         constructors => \%binopcczero_operand_constructors,
484 },
485
486 OrN => {
487         irn_flags => [ "rematerializable" ],
488         mode      => $mode_gp,
489         emit      => '. orn %S0, %R1I, %D0',
490         constructors => \%binop_operand_constructors,
491 },
492
493 OrNCCZero => {
494         irn_flags    => [ "rematerializable", "modifies_flags" ],
495         emit         => '. orncc %S0, %R1I, %%g0',
496         mode         => $mode_flags,
497         constructors => \%binopcczero_operand_constructors,
498 },
499
500 Xor => {
501         irn_flags    => [ "rematerializable" ],
502         mode         => $mode_gp,
503         emit         => '. xor %S0, %R1I, %D0',
504         constructors => \%binop_operand_constructors,
505 },
506
507 XorCCZero => {
508         irn_flags    => [ "rematerializable", "modifies_flags" ],
509         emit         => '. xorcc %S0, %R1I, %%g0',
510         mode         => $mode_flags,
511         constructors => \%binopcczero_operand_constructors,
512 },
513
514 XNor => {
515         irn_flags => [ "rematerializable" ],
516         mode      => $mode_gp,
517         emit      => '. xnor %S0, %R1I, %D0',
518         constructors => \%binop_operand_constructors,
519 },
520
521 XNorCCZero => {
522         irn_flags    => [ "rematerializable", "modifies_flags" ],
523         emit         => '. xnorcc %S0, %R1I, %%g0',
524         mode         => $mode_flags,
525         constructors => \%binopcczero_operand_constructors,
526 },
527
528 Mul => {
529         irn_flags    => [ "rematerializable" ],
530         mode         => $mode_gp,
531         emit         => '. smul %S0, %R1I, %D0',
532         constructors => \%binop_operand_constructors,
533 },
534
535 Mulh => {
536         irn_flags    => [ "rematerializable" ],
537         outs         => [ "low", "high" ],
538         constructors => \%binop_operand_constructors,
539 },
540
541 SDiv => {
542         irn_flags    => [ "rematerializable" ],
543         state        => "exc_pinned",
544         ins          => [ "dividend_high", "dividend_low", "divisor" ],
545         outs         => [ "res", "M" ],
546         constructors => \%div_operand_constructors,
547 },
548
549 UDiv => {
550         irn_flags    => [ "rematerializable" ],
551         state        => "exc_pinned",
552         ins          => [ "dividend_high", "dividend_low", "divisor" ],
553         outs         => [ "res", "M" ],
554         constructors => \%div_operand_constructors,
555 },
556
557 fcmp => {
558         irn_flags => [ "rematerializable", "modifies_fp_flags" ],
559         emit      => '. fcmp%FPM %S0, %S1',
560         attr_type => "sparc_fp_attr_t",
561         attr      => "ir_mode *fp_mode",
562         mode      => $mode_fpflags,
563         constructors => {
564                 s => {
565                         reg_req => { in => [ "fp", "fp" ], out => [ "fpflags" ] },
566                 },
567                 d => {
568                         reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fpflags" ] },
569                 },
570                 q => {
571                         reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fpflags" ] },
572                 },
573         },
574 },
575
576 fadd => {
577         op_flags     => [ "commutative" ],
578         irn_flags    => [ "rematerializable" ],
579         emit         => '. fadd%FPM %S0, %S1, %D0',
580         attr_type    => "sparc_fp_attr_t",
581         attr         => "ir_mode *fp_mode",
582         ins          => [ "left", "right" ],
583         constructors => \%float_binop_constructors,
584 },
585
586 fsub => {
587         irn_flags    => [ "rematerializable" ],
588         emit         => '. fsub%FPM %S0, %S1, %D0',
589         attr_type    => "sparc_fp_attr_t",
590         attr         => "ir_mode *fp_mode",
591         ins          => [ "left", "right" ],
592         constructors => \%float_binop_constructors,
593 },
594
595 fmul => {
596         irn_flags    => [ "rematerializable" ],
597         op_flags     => [ "commutative" ],
598         emit         =>'. fmul%FPM %S0, %S1, %D0',
599         attr_type    => "sparc_fp_attr_t",
600         attr         => "ir_mode *fp_mode",
601         ins          => [ "left", "right" ],
602         constructors => \%float_binop_constructors,
603 },
604
605 fdiv => {
606         irn_flags    => [ "rematerializable" ],
607         emit         => '. fdiv%FPM %S0, %S1, %D0',
608         attr_type    => "sparc_fp_attr_t",
609         attr         => "ir_mode *fp_mode",
610         ins          => [ "left", "right" ],
611         outs         => [ "res", "M" ],
612         constructors => {
613                 s => {
614                         reg_req => { in => [ "fp", "fp" ], out => [ "fp", "none" ] },
615                 },
616                 d => {
617                         reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2", "none" ] },
618                 },
619                 q => {
620                         reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4", "none" ] },
621                 }
622         },
623 },
624
625 fneg => {
626         irn_flags => [ "rematerializable" ],
627         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
628         # note that we only need the first register even for wide-values
629         emit      => '. fneg %S0, %D0',
630         attr_type => "sparc_fp_attr_t",
631         attr      => "ir_mode *fp_mode",
632         ins          => [ "val" ],
633         constructors => \%float_unop_constructors,
634 },
635
636 "fabs" => {
637         irn_flags    => [ "rematerializable" ],
638         # note that we only need the first register even for wide-values
639         emit         => '. fabs %S0, %D0',
640         attr_type    => "sparc_fp_attr_t",
641         attr         => "ir_mode *fp_mode",
642         ins          => [ "val" ],
643         constructors => \%float_unop_constructors,
644 },
645
646 fftof => {
647         irn_flags => [ "rematerializable" ],
648         emit      => '. f%FCONVS%.to%FCONVD %S0, %D0',
649         attr_type => "sparc_fp_conv_attr_t",
650         attr      => "ir_mode *src_mode, ir_mode *dest_mode",
651         constructors => {
652                 s_d => {
653                         reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
654                         mode    => $mode_fp2,
655                 },
656                 s_q => {
657                         reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
658                         mode    => $mode_fp4,
659                 },
660                 d_s => {
661                         reg_req => { in => [ "fp:a|2" ], out => [ "fp" ] },
662                         mode    => $mode_fp,
663                 },
664                 d_q => {
665                         reg_req => { in => [ "fp:a|2" ], out => [ "fp:a|4" ] },
666                         mode    => $mode_fp4,
667                 },
668                 q_s => {
669                         reg_req => { in => [ "fp:a|4" ], out => [ "fp" ] },
670                         mode    => $mode_fp,
671                 },
672                 q_d => {
673                         reg_req => { in => [ "fp:a|4" ], out => [ "fp:a|2" ] },
674                         mode    => $mode_fp2,
675                 },
676         },
677 },
678
679 fitof => {
680         irn_flags => [ "rematerializable" ],
681         emit      => '. fito%FPM %S0, %D0',
682         attr_type => "sparc_fp_attr_t",
683         attr      => "ir_mode *fp_mode",
684         constructors => {
685                 s => {
686                         reg_req => { in => [ "fp" ], out => [ "fp" ] },
687                         mode    => $mode_fp,
688                 },
689                 d => {
690                         reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
691                         mode    => $mode_fp2,
692                 },
693                 q => {
694                         reg_req => { in => [ "fp" ], out => [ "fp:a|4" ] },
695                         mode    => $mode_fp4,
696                 },
697         },
698 },
699
700 fftoi => {
701         irn_flags => [ "rematerializable" ],
702         emit      => '. f%FPM%.toi %S0, %D0',
703         attr_type => "sparc_fp_attr_t",
704         attr      => "ir_mode *fp_mode",
705         mode      => $mode_gp,
706         constructors => {
707                 s => {
708                         reg_req => { in => [ "fp" ], out => [ "fp" ] },
709                 },
710                 d => {
711                         reg_req => { in => [ "fp:a|2" ], out => [ "fp" ] },
712                 },
713                 q => {
714                         reg_req => { in => [ "fp:a|4" ], out => [ "fp" ] },
715                 },
716         },
717 },
718
719 Ldf => {
720         op_flags  => [ "labeled", "fragile" ],
721         state     => "exc_pinned",
722         constructors => {
723                 s => {
724                         reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
725                 },
726                 d => {
727                         reg_req => { in => [ "gp", "none" ], out => [ "fp:a|2", "none" ] },
728                 },
729                 q => {
730                         reg_req => { in => [ "gp", "none" ], out => [ "fp:a|4", "none" ] },
731                 },
732         },
733         ins       => [ "ptr", "mem" ],
734         outs      => [ "res", "M" ],
735         attr_type => "sparc_load_store_attr_t",
736         attr      => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
737         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
738         emit      => '. ld%FLSM [%S0%O1], %D0'
739 },
740
741 Stf => {
742         op_flags  => [ "labeled", "fragile" ],
743         state     => "exc_pinned",
744         constructors => {
745                 s => {
746                         reg_req => { in => [ "fp",     "gp", "none" ], out => [ "none" ] },
747                 },
748                 d => {
749                         reg_req => { in => [ "fp:a|2", "gp", "none" ], out => [ "none" ] },
750                 },
751                 q => {
752                         reg_req => { in => [ "fp:a|4", "gp", "none" ], out => [ "none" ] },
753                 },
754         },
755         ins       => [ "val", "ptr", "mem" ],
756         outs      => [ "M" ],
757         attr_type => "sparc_load_store_attr_t",
758         attr      => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
759         custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
760         emit      => '. st%FLSM %S0, [%S1%O2]',
761         mode      => 'mode_M',
762 },
763
764 ); # end of %nodes