use new double wide register requirements; implement calling convention for sparc...
[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, 0);",
118         R2I => "${arch}_emit_reg_or_imm(node, 1);",
119         R3I => "${arch}_emit_reg_or_imm(node, 2);",
120         S1  => "${arch}_emit_source_register(node, 0);",
121         S2  => "${arch}_emit_source_register(node, 1);",
122         S3  => "${arch}_emit_source_register(node, 2);",
123         S4  => "${arch}_emit_source_register(node, 3);",
124         S5  => "${arch}_emit_source_register(node, 4);",
125         S6  => "${arch}_emit_source_register(node, 5);",
126         D1  => "${arch}_emit_dest_register(node, 0);",
127         D2  => "${arch}_emit_dest_register(node, 1);",
128         D3  => "${arch}_emit_dest_register(node, 2);",
129         D4  => "${arch}_emit_dest_register(node, 3);",
130         D5  => "${arch}_emit_dest_register(node, 4);",
131         D6  => "${arch}_emit_dest_register(node, 5);",
132         IM  => "${arch}_emit_immediate(node);",
133         LM  => "${arch}_emit_load_mode(node);",
134         SM  => "${arch}_emit_store_mode(node);",
135         FLSM => "${arch}_emit_float_load_store_mode(node);",
136         FPM  => "${arch}_emit_fp_mode_suffix(node);",
137         FCONVS => "${arch}_emit_fp_conv_source(node);",
138         FCONVD => "${arch}_emit_fp_conv_destination(node);",
139         O      => "${arch}_emit_offset(node);",
140 );
141
142 $default_attr_type = "sparc_attr_t";
143 $default_copy_attr = "sparc_copy_attr";
144
145
146 %init_attr = (
147         sparc_attr_t             => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
148         sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
149                                     "\tinit_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
150         sparc_symconst_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
151                                     "\tinit_sparc_symconst_attributes(res, entity);",
152         sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
153         sparc_jmp_switch_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
154         sparc_save_attr_t        => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
155         sparc_fp_attr_t          => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
156                                     "\tinit_sparc_fp_attributes(res, fp_mode);\n",
157         sparc_fp_conv_attr_t     => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);".
158                                     "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
159 );
160
161 %compare_attr = (
162         sparc_attr_t            => "cmp_attr_sparc",
163         sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
164         sparc_symconst_attr_t   => "cmp_attr_sparc_symconst",
165         sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
166         sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch",
167         sparc_save_attr_t       => "cmp_attr_sparc_save",
168         sparc_fp_attr_t         => "cmp_attr_sparc_fp",
169         sparc_fp_conv_attr_t    => "cmp_attr_sparc_fp_conv",
170 );
171
172 %custom_irn_flags = (
173         modifies_flags    => "sparc_arch_irn_flag_modifies_flags",
174         modifies_fp_flags => "sparc_arch_irn_flag_modifies_fp_flags",
175 );
176
177 # addressing modes: imm, reg, reg +/- imm, reg + reg
178 # max. imm = 13 bits signed (-4096 ... 4096)
179
180 my %cmp_operand_constructors = (
181         imm => {
182                 attr       => "int immediate_value",
183                 custominit => "sparc_set_attr_imm(res, immediate_value);",
184                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
185                 ins        => [ "left" ],
186         },
187         reg => {
188                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
189                 ins        => [ "left", "right" ],
190         },
191 );
192
193 my %unop_operand_constructors = (
194         imm => {
195                 attr       => "int immediate_value",
196                 custominit => "sparc_set_attr_imm(res, immediate_value);",
197                 reg_req    => { in => [], out => [ "gp" ] },
198         },
199         reg => {
200                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
201         },
202 );
203
204 my %binop_operand_constructors = (
205         imm => {
206                 attr       => "int immediate_value",
207                 custominit => "sparc_set_attr_imm(res, immediate_value);",
208                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
209                 ins        => [ "left" ],
210         },
211         reg => {
212                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
213                 ins        => [ "left", "right" ],
214         },
215 );
216
217 my %float_binop_constructors = (
218         s => {
219                 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
220                 ins     => [ "left", "right" ],
221                 mode    => $mode_fp,
222         },
223         d => {
224                 reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2" ] },
225                 ins     => [ "left", "right" ],
226                 mode    => $mode_fp2,
227         },
228         q => {
229                 reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4" ] },
230                 ins     => [ "left", "right" ],
231                 mode    => $mode_fp4,
232         }
233 );
234
235 %nodes = (
236
237 Add => {
238         irn_flags => [ "rematerializable" ],
239         mode            => $mode_gp,
240         emit      => '. add %S1, %R2I, %D1',
241         constructors => \%binop_operand_constructors,
242 },
243
244 Sub => {
245         irn_flags => [ "rematerializable" ],
246         mode            => $mode_gp,
247         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
248         emit      => '. sub %S1, %R2I, %D1',
249         constructors => \%binop_operand_constructors,
250 },
251
252
253 # Load / Store
254 Ld => {
255         op_flags  => [ "labeled", "fragile" ],
256         state     => "exc_pinned",
257         constructors => {
258                 "" => {
259                         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
260                 },
261                 d => {
262                         reg_req => { in => [ "gp", "none" ], out => [ "gp:a|2", "none" ] },
263                 },
264         },
265         outs      => [ "res", "M" ],
266         ins       => [ "ptr", "mem" ],
267         attr_type => "sparc_load_store_attr_t",
268         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
269         emit      => '. ld%LM [%S1%O], %D1'
270 },
271
272 HiImm => {
273         irn_flags => [ "rematerializable" ],
274         state     => "exc_pinned",
275         outs      => [ "res" ],
276         mode      => $mode_gp,
277         reg_req   => { in => [], out => [ "gp" ] },
278         attr       => "int immediate_value",
279         custominit => "sparc_set_attr_imm(res, immediate_value);",
280 },
281
282 LoImm => {
283         irn_flags => [ "rematerializable" ],
284         state     => "exc_pinned",
285         ins       => [ "hireg" ],
286         outs      => [ "res" ],
287         mode      => $mode_gp,
288         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
289         attr       => "int immediate_value",
290         custominit => "sparc_set_attr_imm(res, immediate_value);",
291 },
292
293 St => {
294         op_flags  => [ "labeled", "fragile" ],
295         mode      => "mode_M",
296         state     => "exc_pinned",
297         constructors => {
298                 "" => {
299                         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
300                 },
301                 d => {
302                         reg_req   => { in => [ "gp", "gp:a|2", "none" ], out => [ "none" ] },
303                 },
304         },
305         ins       => [ "ptr", "val", "mem" ],
306         outs      => [ "M" ],
307         attr_type => "sparc_load_store_attr_t",
308         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
309         emit      => '. st%SM %S2, [%S1%O]'
310 },
311
312 Mov => {
313         irn_flags => [ "rematerializable" ],
314         arity     => "variable",
315         emit      => '. mov %R1I, %D1',
316         mode      => $mode_gp,
317         constructors => \%unop_operand_constructors,
318 },
319
320 Save => {
321         reg_req   => {
322                 in => [ "sp", "none"],
323                 out => [ "sp:I|S", "frame_pointer:I", "none" ]
324         },
325         ins       => [ "stack", "mem" ],
326         outs      => [ "stack", "frame", "mem" ],
327         attr      => "int initial_stacksize",
328         attr_type => "sparc_save_attr_t",
329         init_attr => "\tinit_sparc_save_attributes(res, initial_stacksize);",
330 },
331
332 SubSP => {
333         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
334         ins       => [ "stack", "size", "mem" ],
335         outs      => [ "stack", "addr", "M" ],
336         emit      => ". sub %S1, %S2, %D1\n",
337 },
338
339 AddSP => {
340         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
341         ins       => [ "stack", "size", "mem" ],
342         outs      => [ "stack", "M" ],
343         emit      => ". add %S1, %S2, %D1\n",
344 },
345
346 SymConst => {
347         op_flags  => [ "constlike" ],
348         irn_flags => [ "rematerializable" ],
349         attr      => "ir_entity *entity",
350         reg_req   => { out => [ "gp" ] },
351         attr_type => "sparc_symconst_attr_t",
352         mode      => $mode_gp,
353 },
354
355 FrameAddr => {
356         op_flags  => [ "constlike" ],
357         irn_flags => [ "rematerializable" ],
358         attr      => "ir_entity *entity",
359         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
360         ins       => [ "base" ],
361         attr_type => "sparc_symconst_attr_t",
362         mode      => $mode_gp,
363 },
364
365 Bicc => {
366         op_flags  => [ "labeled", "cfopcode", "forking" ],
367         state     => "pinned",
368         mode      => "mode_T",
369         attr_type => "sparc_jmp_cond_attr_t",
370         attr      => "pn_Cmp pnc, bool is_unsigned",
371         init_attr => "\tinit_sparc_jmp_cond_attr(res, pnc, is_unsigned);",
372         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
373 },
374
375 fbfcc => {
376         op_flags  => [ "labeled", "cfopcode", "forking" ],
377         state     => "pinned",
378         mode      => "mode_T",
379         attr_type => "sparc_jmp_cond_attr_t",
380         attr      => "pn_Cmp pnc",
381         init_attr => "\tinit_sparc_jmp_cond_attr(res, pnc, false);",
382         reg_req   => { in => [ "fpflags" ], out => [ "none", "none" ] },
383 },
384
385 Ba => {
386         state     => "pinned",
387         op_flags  => [ "cfopcode" ],
388         irn_flags => [ "simple_jump" ],
389         reg_req   => { out => [ "none" ] },
390         mode      => "mode_X",
391 },
392
393 Call => {
394         irn_flags => [ "modifies_flags", "modifies_fp_flags" ],
395         state     => "exc_pinned",
396         arity     => "variable",
397         out_arity => "variable",
398         constructors => {
399                 imm => {
400                         attr       => "ir_entity *entity, long offset",
401                         custominit => "get_sparc_attr(res)->immediate_value_entity = entity;",
402                         arity     => "variable",
403                         out_arity => "variable",
404                 },
405                 reg => {
406                         arity     => "variable",
407                         out_arity => "variable",
408                 }
409         },
410 },
411
412 Cmp => {
413         irn_flags    => [ "rematerializable", "modifies_flags" ],
414         emit         => '. cmp %S1, %R2I',
415         reg_req      => { in => [ "gp", "gp" ], out => [ "flags" ] },
416         ins          => [ "left", "right" ],
417         mode         => $mode_flags,
418         constructors => \%cmp_operand_constructors,
419 },
420
421 Tst => {
422         irn_flags    => [ "rematerializable", "modifies_flags" ],
423         emit         => '. tst %S1',
424         mode         => $mode_flags,
425         reg_req      => { in => [ "gp" ], out => [ "flags" ] },
426         ins          => [ "val" ],
427 },
428
429 SwitchJmp => {
430         op_flags  => [ "labeled", "cfopcode", "forking" ],
431         irn_flags => [ "modifies_flags" ],
432         state     => "pinned",
433         mode      => "mode_T",
434         attr      => "int n_projs, long def_proj_num",
435         init_attr => "\tset_sparc_jmp_switch_n_projs(res, n_projs);\n".
436                                         "\tset_sparc_jmp_switch_default_proj_num(res, def_proj_num);",
437         reg_req   => { in => [ "gp" ], out => [ "none" ] },
438         attr_type => "sparc_jmp_switch_attr_t",
439 },
440
441 Sll => {
442         irn_flags => [ "rematerializable" ],
443         mode      => $mode_gp,
444         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
445         emit      => '. sll %S1, %R2I, %D1',
446         constructors => \%binop_operand_constructors,
447 },
448
449 Slr => {
450         irn_flags => [ "rematerializable" ],
451         mode      => $mode_gp,
452         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
453         emit      => '. srl %S1, %R2I, %D1',
454         constructors => \%binop_operand_constructors,
455 },
456
457 Sra => {
458         irn_flags => [ "rematerializable" ],
459         mode      => $mode_gp,
460         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
461         emit      => '. sra %S1, %R2I, %D1',
462         constructors => \%binop_operand_constructors,
463 },
464
465 And => {
466         irn_flags => [ "rematerializable" ],
467         mode      => $mode_gp,
468         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
469         emit      => '. and %S1, %R2I, %D1',
470         constructors => \%binop_operand_constructors,
471 },
472
473 Or => {
474         irn_flags => [ "rematerializable" ],
475         mode      => $mode_gp,
476         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
477         emit      => '. or %S1, %R2I, %D1',
478         constructors => \%binop_operand_constructors,
479 },
480
481 Xor => {
482         irn_flags => [ "rematerializable" ],
483         mode      => $mode_gp,
484         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
485         emit      => '. xor %S1, %R2I, %D1',
486         constructors => \%binop_operand_constructors,
487 },
488
489 Mul => {
490         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "y" ] },
491         constructors => \%binop_operand_constructors,
492         emit      => '. smul %S1, %R2I, %D1',
493         mode      => $mode_gp,
494 },
495
496 Mulh => {
497         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
498         outs      => [ "low", "high" ],
499         constructors => \%binop_operand_constructors,
500 },
501
502 # The div instructions are kinda hacky. Things to improve:
503 # * Make high-value input explicitely. Either as a gp at first or ideally
504 #   as an explicit y-register
505
506 SDiv => {
507         irn_flags => [ "rematerializable" ],
508         state     => "exc_pinned",
509         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "none" ] },
510         ins       => [ "dividend_low", "divisor" ],
511         outs      => [ "res", "M" ],
512         constructors => \%binop_operand_constructors,
513 },
514
515 UDiv => {
516         irn_flags => [ "rematerializable" ],
517         state     => "exc_pinned",
518         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "none" ] },
519         ins       => [ "dividend_low", "divisor" ],
520         outs      => [ "res", "M" ],
521         constructors => \%binop_operand_constructors,
522 },
523
524 Minus => {
525         irn_flags => [ "rematerializable" ],
526         mode      => $mode_gp,
527         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
528         emit      => ". sub %%g0, %S1, %D1"
529 },
530
531 Not => {
532         irn_flags => [ "rematerializable" ],
533         mode      => $mode_gp,
534         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
535         emit      => '. xnor %S1, %%g0, %D1'
536 },
537
538 Nop => {
539         op_flags => [ "keep" ],
540         reg_req  => { in => [], out => [ "none" ] },
541         emit     => '. nop',
542 },
543
544 fcmp => {
545         irn_flags => [ "rematerializable", "modifies_fp_flags" ],
546         reg_req   => { in => [ "fp", "fp" ], out => [ "fpflags" ] },
547         emit      => '. fcmp%FPM %S1, %S2',
548         attr_type => "sparc_fp_attr_t",
549         attr      => "ir_mode *fp_mode",
550         mode      => $mode_fpflags,
551 },
552
553 fadd => {
554         op_flags  => [ "commutative" ],
555         irn_flags => [ "rematerializable" ],
556         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
557         emit      => '. fadd%FPM %S1, %S2, %D1',
558         attr_type => "sparc_fp_attr_t",
559         attr      => "ir_mode *fp_mode",
560         constructors => \%float_binop_constructors,
561 },
562
563 fsub => {
564         irn_flags => [ "rematerializable" ],
565         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
566         emit      => '. fsub%FPM %S1, %S2, %D1',
567         attr_type => "sparc_fp_attr_t",
568         attr      => "ir_mode *fp_mode",
569         constructors => \%float_binop_constructors,
570 },
571
572 fmul => {
573         irn_flags => [ "rematerializable" ],
574         op_flags  => [ "commutative" ],
575         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
576         emit      =>'. fmul%FPM %S1, %S2, %D1',
577         attr_type => "sparc_fp_attr_t",
578         attr      => "ir_mode *fp_mode",
579         constructors => \%float_binop_constructors,
580 },
581
582 fdiv => {
583         irn_flags => [ "rematerializable" ],
584         reg_req   => { in => [ "fp", "fp" ], out => [ "fp", "none" ] },
585         emit      => '. fdiv%FPM %S1, %S2, %D1',
586         attr_type => "sparc_fp_attr_t",
587         attr      => "ir_mode *fp_mode",
588         outs      => [ "res", "M" ],
589         constructors => \%float_binop_constructors,
590 },
591
592 fneg => {
593         irn_flags => [ "rematerializable" ],
594         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
595         emit      => '. fneg%FPM %S1, %D1',
596         attr_type => "sparc_fp_attr_t",
597         attr      => "ir_mode *fp_mode",
598         mode      => $mode_fp,
599 },
600
601 "fabs" => {
602         irn_flags => [ "rematerializable" ],
603         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
604         emit      => '. fabs%FPM %S1, %D1',
605         attr_type => "sparc_fp_attr_t",
606         attr      => "ir_mode *fp_mode",
607         constructors => \%float_binop_constructors,
608 },
609
610 fftof => {
611         irn_flags => [ "rematerializable" ],
612         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
613         emit      => '. f%FCONVS%.to%FCONVD %S1, %D1',
614         attr_type => "sparc_fp_conv_attr_t",
615         attr      => "ir_mode *src_mode, ir_mode *dest_mode",
616         mode      => $mode_fp,
617 },
618
619 fitof => {
620         irn_flags => [ "rematerializable" ],
621         reg_req   => { in => [ "gp" ], out => [ "fp" ] },
622         emit      => '. fito%FPM %S1, %D1',
623         attr_type => "sparc_fp_attr_t",
624         attr      => "ir_mode *fp_mode",
625         mode      => $mode_fp,
626 },
627
628 fftoi => {
629         irn_flags => [ "rematerializable" ],
630         reg_req   => { in => [ "fp" ], out => [ "gp" ] },
631         emit      => '. f%FPM.toi %S1, %D1',
632         attr_type => "sparc_fp_attr_t",
633         attr      => "ir_mode *fp_mode",
634         mode      => $mode_gp,
635 },
636
637 Ldf => {
638         op_flags  => [ "labeled", "fragile" ],
639         state     => "exc_pinned",
640         ins       => [ "ptr", "mem" ],
641         outs      => [ "res", "M" ],
642         reg_req   => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
643         attr_type => "sparc_load_store_attr_t",
644         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
645         emit      => '. ld%FLSM [%S1%O], %D1'
646 },
647
648 Stf => {
649         op_flags  => [ "labeled", "fragile" ],
650         state     => "exc_pinned",
651         ins       => [ "ptr", "val", "mem" ],
652         outs      => [ "M" ],
653         reg_req   => { in => [ "gp", "fp", "none" ], out => [ "none" ] },
654         attr_type => "sparc_load_store_attr_t",
655         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
656         emit      => '. st%FLSM %S2, [%S1%O]',
657         mode      => 'mode_M',
658 },
659
660 ); # end of %nodes