beflags: transform modifies_flags property into a callback, use default rematerialisa...
[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_fp      = "mode_D";
9
10 $normal      =  0; # no special type
11 $caller_save =  1; # caller save (register must be saved by the caller of a function)
12 $callee_save =  2; # callee save (register must be saved by the called function)
13 $ignore      =  4; # ignore (do not assign this register)
14 $arbitrary   =  8; # emitter can choose an arbitrary register of this class
15 $virtual     = 16; # the register is a virtual one
16 $state       = 32; # register represents a state
17
18 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
19 %reg_classes = (
20         gp => [
21                 { name => "g0", realname => "g0", type => $ignore }, # hardwired 0, behaves like /dev/null
22                 { name => "g1", realname => "g1", type => $caller_save }, # temp. value
23                 { name => "g2", realname => "g2", type => $caller_save },
24                 { name => "g3", realname => "g3", type => $caller_save },
25                 { name => "g4", realname => "g4", type => $caller_save },
26                 { name => "g5", realname => "g5", type => $ignore }, # reserved by SPARC ABI
27                 { name => "g6", realname => "g6", type => $ignore }, # reserved by SPARC ABI
28                 { name => "g7", realname => "g7", type => $ignore }, # reserved by SPARC ABI
29
30                 # window's out registers
31                 { name => "o0", realname => "o0", type => $caller_save }, # param 1 / return value from callee
32                 { name => "o1", realname => "o1", type => $caller_save }, # param 2
33                 { name => "o2", realname => "o2", type => $caller_save }, # param 3
34                 { name => "o3", realname => "o3", type => $caller_save }, # param 4
35                 { name => "o4", realname => "o4", type => $caller_save }, # param 5
36                 { name => "o5", realname => "o5", type => $caller_save }, # param 6
37                 { name => "sp", realname => "sp", type => $ignore }, # our stackpointer
38                 { name => "o7", realname => "o6", type => $ignore }, # temp. value / address of CALL instr.
39
40                 # window's local registers
41                 { name => "l0", realname => "l0", type => 0 },
42                 { name => "l1", realname => "l1", type => 0 },
43                 { name => "l2", realname => "l2", type => 0 },
44                 { name => "l3", realname => "l3", type => 0 },
45                 { name => "l4", realname => "l4", type => 0 },
46                 { name => "l5", realname => "l5", type => 0 },
47                 { name => "l6", realname => "l6", type => 0 },
48                 { name => "l7", realname => "l7", type => 0 },
49
50                 # window's in registers
51                 { name => "i0", realname => "i0", type => 0 }, # incoming param1 / return value to caller
52                 { name => "i1", realname => "i1", type => 0 }, # param 2
53                 { name => "i2", realname => "i2", type => 0 }, # param 3
54                 { name => "i3", realname => "i3", type => 0 }, # param 4
55                 { name => "i4", realname => "i4", type => 0 }, # param 5
56                 { name => "i5", realname => "i5", type => 0 }, # param 6
57                 { name => "frame_pointer", realname => "fp", type => $ignore }, # our framepointer
58                 { name => "i7", realname => "i7", type => $ignore }, # return address - 8
59                 { mode => $mode_gp }
60         ],
61         flags => [
62                 { name => "y", realname => "y", type => $ignore },  # the multiply/divide state register
63                 { mode => $mode_flags, flags => "manual_ra" }
64         ],
65         # fp registers can be accessed any time
66         fp => [
67                 { name => "f0",  type => $caller_save },
68                 { name => "f1",  type => $caller_save },
69                 { name => "f2",  type => $caller_save },
70                 { name => "f3",  type => $caller_save },
71                 { name => "f4",  type => $caller_save },
72                 { name => "f5",  type => $caller_save },
73                 { name => "f6",  type => $caller_save },
74                 { name => "f7",  type => $caller_save },
75                 { name => "f8",  type => $caller_save },
76                 { name => "f9",  type => $caller_save },
77                 { name => "f10", type => $caller_save },
78                 { name => "f11", type => $caller_save },
79                 { name => "f12", type => $caller_save },
80                 { name => "f13", type => $caller_save },
81                 { name => "f14", type => $caller_save },
82                 { name => "f15", type => $caller_save },
83                 { name => "f16", type => $caller_save },
84                 { name => "f17", type => $caller_save },
85                 { name => "f18", type => $caller_save },
86                 { name => "f19", type => $caller_save },
87                 { name => "f20", type => $caller_save },
88                 { name => "f21", type => $caller_save },
89                 { name => "f22", type => $caller_save },
90                 { name => "f23", type => $caller_save },
91                 { name => "f24", type => $caller_save },
92                 { name => "f25", type => $caller_save },
93                 { name => "f26", type => $caller_save },
94                 { name => "f27", type => $caller_save },
95                 { name => "f28", type => $caller_save },
96                 { name => "f29", type => $caller_save },
97                 { name => "f30", type => $caller_save },
98                 { name => "f31", type => $caller_save },
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, 0);",
107         R2I => "${arch}_emit_reg_or_imm(node, 1);",
108         R3I => "${arch}_emit_reg_or_imm(node, 2);",
109         S1  => "${arch}_emit_source_register(node, 0);",
110         S2  => "${arch}_emit_source_register(node, 1);",
111         S3  => "${arch}_emit_source_register(node, 2);",
112         S4  => "${arch}_emit_source_register(node, 3);",
113         S5  => "${arch}_emit_source_register(node, 4);",
114         S6  => "${arch}_emit_source_register(node, 5);",
115         D1  => "${arch}_emit_dest_register(node, 0);",
116         D2  => "${arch}_emit_dest_register(node, 1);",
117         D3  => "${arch}_emit_dest_register(node, 2);",
118         D4  => "${arch}_emit_dest_register(node, 3);",
119         D5  => "${arch}_emit_dest_register(node, 4);",
120         D6  => "${arch}_emit_dest_register(node, 5);",
121         IM  => "${arch}_emit_immediate(node);",
122         LM  => "${arch}_emit_load_mode(node);",
123         SM  => "${arch}_emit_store_mode(node);",
124         EXTPREF => "${arch}_emit_mode_sign_prefix(node);",
125         FPM  => "${arch}_emit_fp_mode_suffix(node);",
126         FPLM => "${arch}_emit_fp_load_mode(node);",
127         FPSM => "${arch}_emit_fp_store_mode(node);",
128         O    => "${arch}_emit_offset(node);",
129 );
130
131 $default_attr_type = "sparc_attr_t";
132 $default_copy_attr = "sparc_copy_attr";
133
134
135 %init_attr = (
136         sparc_attr_t             => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
137         sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
138                                     "\tinit_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
139         sparc_symconst_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
140                                     "\tinit_sparc_symconst_attributes(res, entity);",
141         sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
142         sparc_jmp_switch_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
143         sparc_save_attr_t        => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
144
145 );
146
147 %compare_attr = (
148         sparc_attr_t            => "cmp_attr_sparc",
149         sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
150         sparc_symconst_attr_t   => "cmp_attr_sparc_symconst",
151         sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
152         sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch",
153         sparc_save_attr_t       => "cmp_attr_sparc_save",
154 );
155
156 # addressing modes: imm, reg, reg +/- imm, reg + reg
157 # max. imm = 13 bits signed (-4096 ... 4096)
158
159 my %cmp_operand_constructors = (
160         imm => {
161                 attr       => "int immediate_value",
162                 custominit => "sparc_set_attr_imm(res, immediate_value);",
163                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
164                 ins        => [ "left" ],
165         },
166         reg => {
167                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
168                 ins        => [ "left", "right" ],
169         },
170 );
171
172 my %unop_operand_constructors = (
173         imm => {
174                 attr       => "int immediate_value",
175                 custominit => "sparc_set_attr_imm(res, immediate_value);",
176                 reg_req    => { in => [], out => [ "gp" ] },
177         },
178         reg => {
179                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
180         },
181 );
182
183 my %binop_operand_constructors = (
184         imm => {
185                 attr       => "int immediate_value",
186                 custominit => "sparc_set_attr_imm(res, immediate_value);",
187                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
188                 ins        => [ "left" ],
189         },
190         reg => {
191                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
192                 ins        => [ "left", "right" ],
193         },
194 );
195
196 %nodes = (
197
198 Add => {
199         irn_flags => [ "rematerializable" ],
200         mode            => $mode_gp,
201         emit      => '. add %S1, %R2I, %D1',
202         constructors => \%binop_operand_constructors,
203 },
204
205 Sub => {
206         irn_flags => [ "rematerializable" ],
207         mode            => $mode_gp,
208         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
209         emit      => '. sub %S1, %R2I, %D1',
210         constructors => \%binop_operand_constructors,
211 },
212
213
214 # Load / Store
215 Ld => {
216         op_flags  => [ "labeled", "fragile" ],
217         state     => "exc_pinned",
218         ins       => [ "ptr", "mem" ],
219         outs      => [ "res", "M" ],
220         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
221         attr_type => "sparc_load_store_attr_t",
222         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
223         emit      => '. ld%LM [%S1%O], %D1'
224 },
225
226 HiImm => {
227         irn_flags => [ "rematerializable" ],
228         state     => "exc_pinned",
229         outs      => [ "res" ],
230         mode      => $mode_gp,
231         reg_req   => { in => [], out => [ "gp" ] },
232         attr       => "int immediate_value",
233         custominit => "sparc_set_attr_imm(res, immediate_value);",
234 },
235
236 LoImm => {
237         irn_flags => [ "rematerializable" ],
238         state     => "exc_pinned",
239         ins       => [ "hireg" ],
240         outs      => [ "res" ],
241         mode      => $mode_gp,
242         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
243         attr       => "int immediate_value",
244         custominit => "sparc_set_attr_imm(res, immediate_value);",
245 },
246
247 St => {
248         op_flags  => [ "labeled", "fragile" ],
249         mode            => "mode_M",
250         state     => "exc_pinned",
251         ins       => [ "ptr", "val", "mem" ],
252         outs      => [ "M" ],
253         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
254         attr_type => "sparc_load_store_attr_t",
255         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
256         emit      => '. st%SM %S2, [%S1%O]'
257 },
258
259 Mov => {
260         irn_flags => [ "rematerializable" ],
261         arity     => "variable",
262         emit      => '. mov %R1I, %D1',
263         mode      => $mode_gp,
264         constructors => \%unop_operand_constructors,
265 },
266
267 Save => {
268         reg_req   => {
269                 in => [ "sp", "none"],
270                 out => [ "sp:I|S", "frame_pointer:I", "none" ]
271         },
272         ins       => [ "stack", "mem" ],
273         outs      => [ "stack", "frame", "mem" ],
274         attr      => "int initial_stacksize",
275         attr_type => "sparc_save_attr_t",
276         init_attr => "\tinit_sparc_save_attr(res, initial_stacksize);",
277 },
278
279 SubSP => {
280         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
281         ins       => [ "stack", "size", "mem" ],
282         outs      => [ "stack", "addr", "M" ],
283         emit      => ". sub %S1, %S2, %D1\n",
284 },
285
286 AddSP => {
287         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
288         ins       => [ "stack", "size", "mem" ],
289         outs      => [ "stack", "M" ],
290         emit      => ". add %S1, %S2, %D1\n",
291 },
292
293 SymConst => {
294         op_flags  => [ "constlike" ],
295         irn_flags => [ "rematerializable" ],
296         attr      => "ir_entity *entity",
297         reg_req   => { out => [ "gp" ] },
298         attr_type => "sparc_symconst_attr_t",
299         mode      => $mode_gp,
300 },
301
302 FrameAddr => {
303         op_flags  => [ "constlike" ],
304         irn_flags => [ "rematerializable" ],
305         attr      => "ir_entity *entity",
306         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
307         ins       => [ "base" ],
308         attr_type => "sparc_symconst_attr_t",
309         mode      => $mode_gp,
310 },
311
312 BXX => {
313         op_flags  => [ "labeled", "cfopcode", "forking" ],
314         state     => "pinned",
315         mode      => "mode_T",
316         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
317         attr      => "int proj_num, bool is_unsigned",
318         attr_type => "sparc_jmp_cond_attr_t",
319         init_attr => "\tinit_sparc_jmp_cond_attr(res, proj_num, is_unsigned);",
320 },
321
322 Ba => {
323         state     => "pinned",
324         op_flags  => [ "cfopcode" ],
325         irn_flags => [ "simple_jump" ],
326         reg_req   => { out => [ "none" ] },
327         mode      => "mode_X",
328 },
329
330 Call => {
331         irn_flags => [ "modify_flags" ],
332         state     => "exc_pinned",
333         arity     => "variable",
334         out_arity => "variable",
335         constructors => {
336                 imm => {
337                         attr       => "ir_entity *entity, long offset",
338                         custominit => "get_sparc_attr(res)->immediate_value_entity = entity;",
339                         arity     => "variable",
340                         out_arity => "variable",
341                 },
342                 reg => {
343                         arity     => "variable",
344                         out_arity => "variable",
345                 }
346         },
347 },
348
349 Cmp => {
350         irn_flags    => [ "rematerializable", "modify_flags" ],
351         emit         => '. cmp %S1, %R2I',
352         mode         => $mode_flags,
353         constructors => \%cmp_operand_constructors,
354 },
355
356 Tst => {
357         irn_flags    => [ "rematerializable", "modify_flags" ],
358         emit         => '. tst %S1',
359         mode         => $mode_flags,
360         reg_req      => { in => [ "gp" ], out => [ "flags" ] },
361         ins          => [ "val" ],
362 },
363
364 SwitchJmp => {
365         op_flags  => [ "labeled", "cfopcode", "forking" ],
366         state     => "pinned",
367         mode      => "mode_T",
368         attr      => "int n_projs, long def_proj_num",
369         init_attr => "\tset_sparc_jmp_switch_n_projs(res, n_projs);\n".
370                                         "\tset_sparc_jmp_switch_default_proj_num(res, def_proj_num);",
371         reg_req   => { in => [ "gp" ], out => [ "none" ] },
372         attr_type => "sparc_jmp_switch_attr_t",
373 },
374
375 Sll => {
376         irn_flags => [ "rematerializable" ],
377         mode            => $mode_gp,
378         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
379         emit      => '. sll %S1, %R2I, %D1',
380         constructors => \%binop_operand_constructors,
381 },
382
383 Slr => {
384         irn_flags => [ "rematerializable" ],
385         mode            => $mode_gp,
386         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
387         emit      => '. srl %S1, %R2I, %D1',
388         constructors => \%binop_operand_constructors,
389 },
390
391 Sra => {
392         irn_flags => [ "rematerializable" ],
393         mode            => $mode_gp,
394         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
395         emit      => '. sra %S1, %R2I, %D1',
396         constructors => \%binop_operand_constructors,
397 },
398
399 And => {
400         irn_flags => [ "rematerializable" ],
401         mode            => $mode_gp,
402         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
403         emit      => '. and %S1, %R2I, %D1',
404         constructors => \%binop_operand_constructors,
405 },
406
407 Or => {
408         irn_flags => [ "rematerializable" ],
409         mode            => $mode_gp,
410         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
411         emit      => '. or %S1, %R2I, %D1',
412         constructors => \%binop_operand_constructors,
413 },
414
415 Xor => {
416         irn_flags => [ "rematerializable" ],
417         mode            => $mode_gp,
418         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
419         emit      => '. xor %S1, %R2I, %D1',
420         constructors => \%binop_operand_constructors,
421 },
422
423 Mul => {
424         state     => "exc_pinned",
425         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
426         outs      => [ "low", "high" ],
427         constructors => \%binop_operand_constructors,
428         #emit      =>'. mul %S1, %R2I, %D1'
429 },
430
431 Mulh => {
432         state     => "exc_pinned",
433         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
434         outs      => [ "low", "high" ],
435         constructors => \%binop_operand_constructors,
436 },
437
438 Div => {
439         irn_flags => [ "rematerializable" ],
440         state     => "exc_pinned",
441         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
442         outs      => [ "res" ],
443         constructors => \%binop_operand_constructors,
444         #mode      => $mode_gp,
445         #emit      =>'. div %S1, %R2I, %D1'
446 },
447
448 Minus => {
449         irn_flags => [ "rematerializable" ],
450         mode        => $mode_gp,
451         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
452         emit      => ". sub %%g0, %S1, %D1"
453 },
454
455 Not => {
456         irn_flags   => [ "rematerializable" ],
457         mode          => $mode_gp,
458         reg_req     => { in => [ "gp" ], out => [ "gp" ] },
459         emit        => '. xnor %S1, %%g0, %D1'
460 },
461
462 Nop => {
463         op_flags => [ "keep" ],
464         reg_req  => { in => [], out => [ "none" ] },
465         emit     => '. nop',
466 },
467
468 fAdd => {
469         op_flags  => [ "commutative" ],
470         irn_flags => [ "rematerializable" ],
471         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
472         emit      => '. fadd%FPM %S1, %S2, %D1'
473 },
474
475 fMul => {
476         op_flags  => [ "commutative" ],
477         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
478         emit      =>'. fmul%FPM %S1, %S2, %D1'
479 },
480
481 fsMuld => {
482         op_flags  => [ "commutative" ],
483         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
484         emit      =>'. fsmuld %S1, %S2, %D1'
485 },
486
487 FsTOd => {
488         irn_flags => [ "rematerializable" ],
489         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
490         emit      =>'. FsTOd %S1, %D1'
491 },
492
493 FdTOs => {
494         irn_flags => [ "rematerializable" ],
495         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
496         emit      =>'. FdTOs %S1, %D1'
497 },
498
499 FiTOs => {
500         irn_flags => [ "rematerializable" ],
501         reg_req   => { in => [ "gp" ], out => [ "fp" ] },
502         emit      =>'. FiTOs %S1, %D1'
503 },
504
505 FiTOd => {
506         irn_flags => [ "rematerializable" ],
507         reg_req   => { in => [ "gp" ], out => [ "fp" ] },
508         emit      =>'. FiTOd %S1, %D1'
509 },
510
511 FsTOi => {
512         irn_flags => [ "rematerializable" ],
513         reg_req   => { in => [ "fp" ], out => [ "gp" ] },
514         emit      =>'. FsTOi %S1, %D1'
515 },
516
517 FdTOi => {
518         irn_flags => [ "rematerializable" ],
519         reg_req   => { in => [ "fp" ], out => [ "gp" ] },
520         emit      =>'. FdTOi %S1, %D1'
521 },
522
523 Ldf => {
524         op_flags  => [ "labeled", "fragile" ],
525         state     => "exc_pinned",
526         ins       => [ "ptr", "mem" ],
527         outs      => [ "res", "M" ],
528         reg_req   => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
529         attr_type => "sparc_load_store_attr_t",
530         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
531         emit      => '. ld [%S1%O], %D1'
532 },
533
534 Stf => {
535         op_flags  => [ "labeled", "fragile" ],
536         state     => "exc_pinned",
537         ins       => [ "ptr", "val", "mem" ],
538         outs      => [ "M" ],
539         reg_req   => { in => [ "gp", "fp", "none" ], out => [ "none" ] },
540         attr_type => "sparc_load_store_attr_t",
541         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
542         emit      => '. st %S2, [%S1%O]',
543         mode      => 'mode_M',
544 },
545
546 ); # end of %nodes