fb97f015894e333ecf9663e0b0ae7b09b1eed51e
[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 => "fp", 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 # simple reg emitters
110         S1 => "${arch}_emit_source_register(node, 0);",
111         S2 => "${arch}_emit_source_register(node, 1);",
112         S3 => "${arch}_emit_source_register(node, 2);",
113         S4 => "${arch}_emit_source_register(node, 3);",
114         S5 => "${arch}_emit_source_register(node, 4);",
115         S6 => "${arch}_emit_source_register(node, 5);",
116         D1 => "${arch}_emit_dest_register(node, 0);",
117         D2 => "${arch}_emit_dest_register(node, 1);",
118         D3 => "${arch}_emit_dest_register(node, 2);",
119         D4 => "${arch}_emit_dest_register(node, 3);",
120         D5 => "${arch}_emit_dest_register(node, 4);",
121         D6 => "${arch}_emit_dest_register(node, 5);",
122 # more custom emitters
123         C  => "${arch}_emit_immediate(node);",
124         LM  => "${arch}_emit_load_mode(node);",
125         SM  => "${arch}_emit_store_mode(node);",
126         EXTPREF  => "${arch}_emit_mode_sign_prefix(node);",
127         FPM  => "${arch}_emit_fp_mode_suffix(node);",
128         FPLM  => "${arch}_emit_fp_load_mode(node);",
129         FPSM  => "${arch}_emit_fp_store_mode(node);",
130         O  => "${arch}_emit_offset(node);",
131 );
132
133 $default_attr_type = "sparc_attr_t";
134 $default_copy_attr = "sparc_copy_attr";
135
136
137 %init_attr = (
138         sparc_attr_t             => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
139         sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
140                                     "\tinit_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
141         sparc_symconst_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
142                                     "\tinit_sparc_symconst_attributes(res, entity);",
143         sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
144         sparc_jmp_switch_attr_t  => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
145         sparc_save_attr_t        => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
146
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_symconst_attr_t   => "cmp_attr_sparc_symconst",
153         sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
154         sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch",
155         sparc_save_attr_t       => "cmp_attr_sparc_save",
156 );
157
158 # addressing modes: imm, reg, reg +/- imm, reg + reg
159 # max. imm = 13 bits signed (-4096 ... 4096)
160
161 my %cmp_operand_constructors = (
162         imm => {
163                 attr       => "int immediate_value",
164                 custominit => "sparc_set_attr_imm(res, immediate_value);",
165                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
166                 ins        => [ "left" ],
167         },
168         reg => {
169                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
170                 ins        => [ "left", "right" ],
171         },
172 );
173
174 my %unop_operand_constructors = (
175         imm => {
176                 attr       => "int immediate_value",
177                 custominit => "sparc_set_attr_imm(res, immediate_value);",
178                 reg_req    => { in => [], out => [ "gp" ] },
179         },
180         reg => {
181                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
182         },
183 );
184
185 my %binop_operand_constructors = (
186         imm => {
187                 attr       => "int immediate_value",
188                 custominit => "sparc_set_attr_imm(res, immediate_value);",
189                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
190                 ins        => [ "left" ],
191         },
192         reg => {
193                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
194                 ins        => [ "left", "right" ],
195         },
196 );
197
198 %nodes = (
199
200 Add => {
201         irn_flags => [ "rematerializable" ],
202         mode            => $mode_gp,
203         emit      => '. add %S1, %R2I, %D1',
204         constructors => \%binop_operand_constructors,
205 },
206
207 Sub => {
208         irn_flags => [ "rematerializable" ],
209         mode            => $mode_gp,
210         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
211         emit      => '. sub %S1, %R2I, %D1',
212         constructors => \%binop_operand_constructors,
213 },
214
215
216 # Load / Store
217 Ld => {
218         op_flags  => [ "labeled", "fragile" ],
219         state     => "exc_pinned",
220         ins       => [ "ptr", "mem" ],
221         outs      => [ "res", "M" ],
222         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
223         attr_type => "sparc_load_store_attr_t",
224         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
225         emit      => '. ld%LM [%S1%O], %D1'
226 },
227
228 HiImm => {
229         irn_flags => [ "rematerializable" ],
230         state     => "exc_pinned",
231         outs      => [ "res" ],
232         mode      => $mode_gp,
233         reg_req   => { in => [], out => [ "gp" ] },
234         attr       => "int immediate_value",
235         custominit => "sparc_set_attr_imm(res, immediate_value);",
236 },
237
238 LoImm => {
239         irn_flags => [ "rematerializable" ],
240         state     => "exc_pinned",
241         ins       => [ "hireg" ],
242         outs      => [ "res" ],
243         mode      => $mode_gp,
244         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
245         attr       => "int immediate_value",
246         custominit => "sparc_set_attr_imm(res, immediate_value);",
247 },
248
249 St => {
250         op_flags  => [ "labeled", "fragile" ],
251         mode            => "mode_M",
252         state     => "exc_pinned",
253         ins       => [ "ptr", "val", "mem" ],
254         outs      => [ "mem" ],
255         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
256         attr_type => "sparc_load_store_attr_t",
257         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
258         emit      => '. st%SM %S2, [%S1%O]'
259 },
260
261 Mov => {
262         irn_flags => [ "rematerializable" ],
263         arity     => "variable",
264         emit      => '. mov %R1I, %D1',
265         mode      => $mode_gp,
266         constructors => \%unop_operand_constructors,
267 },
268
269 Save => {
270         reg_req   => {
271                 in => [ "sp", "none"],
272                 out => [ "sp:I|S","none" ]
273         },
274         ins       => [ "stack", "mem" ],
275         outs      => [ "stack", "mem" ],
276         attr      => "int initial_stacksize",
277         attr_type => "sparc_save_attr_t",
278         init_attr => "\tinit_sparc_save_attr(res, initial_stacksize);",
279 },
280
281 SubSP => {
282         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
283         ins       => [ "stack", "size", "mem" ],
284         outs      => [ "stack", "addr", "M" ],
285         emit      => ". sub %S1, %S2, %D1\n",
286 },
287
288 AddSP => {
289         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
290         ins       => [ "stack", "size", "mem" ],
291         outs      => [ "stack", "M" ],
292         emit      => ". add %S1, %S2, %D1\n",
293 },
294
295 SymConst => {
296         op_flags  => [ "constlike" ],
297         irn_flags => [ "rematerializable" ],
298         attr      => "ir_entity *entity",
299         reg_req   => { out => [ "gp" ] },
300         attr_type => "sparc_symconst_attr_t",
301         mode      => $mode_gp,
302 },
303
304 FrameAddr => {
305         op_flags  => [ "constlike" ],
306         irn_flags => [ "rematerializable" ],
307         attr      => "ir_entity *entity",
308         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
309         ins       => [ "base" ],
310         attr_type => "sparc_symconst_attr_t",
311         mode      => $mode_gp,
312 },
313
314 BXX => {
315         op_flags  => [ "labeled", "cfopcode", "forking" ],
316         state     => "pinned",
317         mode      => "mode_T",
318         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
319         attr      => "int proj_num, bool is_unsigned",
320         attr_type => "sparc_jmp_cond_attr_t",
321         init_attr => "\tinit_sparc_jmp_cond_attr(res, proj_num, is_unsigned);",
322 },
323
324 Ba => {
325         state     => "pinned",
326         op_flags  => [ "cfopcode" ],
327         irn_flags => [ "simple_jump" ],
328         reg_req   => { out => [ "none" ] },
329         mode      => "mode_X",
330 },
331
332 Cmp => {
333         irn_flags    => [ "rematerializable", "modify_flags" ],
334         emit         => '. cmp %S1, %R2I',
335         mode         => $mode_flags,
336         constructors => \%cmp_operand_constructors,
337 },
338
339 Tst => {
340         irn_flags    => [ "rematerializable", "modify_flags" ],
341         emit         => '. tst %S1',
342         mode         => $mode_flags,
343         reg_req      => { in => [ "gp" ], out => [ "flags" ] },
344         ins          => [ "val" ],
345 },
346
347 SwitchJmp => {
348         op_flags  => [ "labeled", "cfopcode", "forking" ],
349         state     => "pinned",
350         mode      => "mode_T",
351         attr      => "int n_projs, long def_proj_num",
352         init_attr => "\tset_sparc_jmp_switch_n_projs(res, n_projs);\n".
353                                         "\tset_sparc_jmp_switch_default_proj_num(res, def_proj_num);",
354         reg_req   => { in => [ "gp" ], out => [ "none" ] },
355         attr_type => "sparc_jmp_switch_attr_t",
356 },
357
358 Sll => {
359         irn_flags => [ "rematerializable" ],
360         mode            => $mode_gp,
361         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
362         emit      => '. sll %S1, %R2I, %D1',
363         constructors => \%binop_operand_constructors,
364 },
365
366 Slr => {
367         irn_flags => [ "rematerializable" ],
368         mode            => $mode_gp,
369         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
370         emit      => '. srl %S1, %R2I, %D1',
371         constructors => \%binop_operand_constructors,
372 },
373
374 Sra => {
375         irn_flags => [ "rematerializable" ],
376         mode            => $mode_gp,
377         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
378         emit      => '. sra %S1, %R2I, %D1',
379         constructors => \%binop_operand_constructors,
380 },
381
382 And => {
383         irn_flags => [ "rematerializable" ],
384         mode            => $mode_gp,
385         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
386         emit      => '. and %S1, %R2I, %D1',
387         constructors => \%binop_operand_constructors,
388 },
389
390 Or => {
391         irn_flags => [ "rematerializable" ],
392         mode            => $mode_gp,
393         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
394         emit      => '. or %S1, %R2I, %D1',
395         constructors => \%binop_operand_constructors,
396 },
397
398 Xor => {
399         irn_flags => [ "rematerializable" ],
400         mode            => $mode_gp,
401         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
402         emit      => '. xor %S1, %R2I, %D1',
403         constructors => \%binop_operand_constructors,
404 },
405
406 Mul => {
407         state     => "exc_pinned",
408         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
409         outs      => [ "low", "high" ],
410         constructors => \%binop_operand_constructors,
411         #emit      =>'. mul %S1, %R2I, %D1'
412 },
413
414 Mulh => {
415         state     => "exc_pinned",
416         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
417         outs      => [ "low", "high" ],
418         constructors => \%binop_operand_constructors,
419 },
420
421 Div => {
422         irn_flags => [ "rematerializable" ],
423         state     => "exc_pinned",
424         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
425         outs      => [ "res" ],
426         constructors => \%binop_operand_constructors,
427         #mode      => $mode_gp,
428         #emit      =>'. div %S1, %R2I, %D1'
429 },
430
431 Minus => {
432         irn_flags => [ "rematerializable" ],
433         mode        => $mode_gp,
434         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
435         emit      => ". sub %%g0, %S1, %D1"
436 },
437
438 Not => {
439         irn_flags   => [ "rematerializable" ],
440         mode          => $mode_gp,
441         reg_req     => { in => [ "gp" ], out => [ "gp" ] },
442         emit        => '. xnor %S1, %%g0, %D1'
443 },
444
445 Nop => {
446         op_flags => [ "keep" ],
447         reg_req  => { in => [], out => [ "none" ] },
448         emit     => '. nop',
449 },
450
451 fAdd => {
452         op_flags  => [ "commutative" ],
453         irn_flags => [ "rematerializable" ],
454         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
455         emit      => '. fadd%FPM %S1, %S2, %D1'
456 },
457
458 fMul => {
459         op_flags  => [ "commutative" ],
460         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
461         emit      =>'. fmul%FPM %S1, %S2, %D1'
462 },
463
464 fsMuld => {
465         op_flags  => [ "commutative" ],
466         reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
467         emit      =>'. fsmuld %S1, %S2, %D1'
468 },
469
470 FsTOd => {
471         irn_flags => [ "rematerializable" ],
472         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
473         emit      =>'. FsTOd %S1, %D1'
474 },
475
476 FdTOs => {
477         irn_flags => [ "rematerializable" ],
478         reg_req   => { in => [ "fp" ], out => [ "fp" ] },
479         emit      =>'. FdTOs %S1, %D1'
480 },
481
482 FiTOs => {
483         irn_flags => [ "rematerializable" ],
484         reg_req   => { in => [ "gp" ], out => [ "fp" ] },
485         emit      =>'. FiTOs %S1, %D1'
486 },
487
488 FiTOd => {
489         irn_flags => [ "rematerializable" ],
490         reg_req   => { in => [ "gp" ], out => [ "fp" ] },
491         emit      =>'. FiTOd %S1, %D1'
492 },
493
494 FsTOi => {
495         irn_flags => [ "rematerializable" ],
496         reg_req   => { in => [ "fp" ], out => [ "gp" ] },
497         emit      =>'. FsTOi %S1, %D1'
498 },
499
500 FdTOi => {
501         irn_flags => [ "rematerializable" ],
502         reg_req   => { in => [ "fp" ], out => [ "gp" ] },
503         emit      =>'. FdTOi %S1, %D1'
504 },
505
506 ); # end of %nodes