implement some int to float conversions
[libfirm] / ir / be / arm / arm_spec.pl
1 # Creation: 2006/02/13
2 # Arm Architecure Specification
3 # Author: Matthias Braun, Michael Beck, Oliver Richter, Tobias Gneist
4 # $Id$
5
6 $arch = "arm";
7
8 #
9 # Modes
10 #
11 $mode_gp    = "mode_Iu";
12 $mode_flags = "mode_Bu";
13 $mode_fp    = "mode_E";
14
15 # register types:
16 $normal      =  0; # no special type
17 $caller_save =  1; # caller save (register must be saved by the caller of a function)
18 $callee_save =  2; # callee save (register must be saved by the called function)
19 $ignore      =  4; # ignore (do not assign this register)
20 $arbitrary   =  8; # emitter can choose an arbitrary register of this class
21 $virtual     = 16; # the register is a virtual one
22 $state       = 32; # register represents a state
23 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
24 %reg_classes = (
25         gp => [
26                 { name => "r0",  type => $caller_save },
27                 { name => "r1",  type => $caller_save },
28                 { name => "r2",  type => $caller_save },
29                 { name => "r3",  type => $caller_save },
30                 { name => "r4",  type => $callee_save },
31                 { name => "r5",  type => $callee_save },
32                 { name => "r6",  type => $callee_save },
33                 { name => "r7",  type => $callee_save },
34                 { name => "r8",  type => $callee_save },
35                 { name => "r9",  type => $callee_save },
36                 { name => "r10", type => $callee_save },
37                 { name => "r11", type => $callee_save },
38                 { name => "r12", type => $ignore }, # reserved for linker/immediate fixups
39                 { name => "sp",  type => $ignore }, # this is our stack pointer
40                 { name => "lr",  type => $callee_save | $caller_save }, # this is our return address
41                 { name => "pc",  type => $ignore }, # this is our program counter
42                 { mode => $mode_gp }
43         ],
44         fpa => [
45                 { name => "f0", type => $caller_save },
46                 { name => "f1", type => $caller_save },
47                 { name => "f2", type => $caller_save },
48                 { name => "f3", type => $caller_save },
49                 { name => "f4", type => $caller_save },
50                 { name => "f5", type => $caller_save },
51                 { name => "f6", type => $caller_save },
52                 { name => "f7", type => $caller_save },
53                 { mode => $mode_fp }
54         ],
55         flags => [
56                 { name => "fl", type => 0 },
57                 { mode => $mode_flags, flags => "manual_ra" }
58         ],
59 );
60
61 %emit_templates = (
62         FM  => "${arch}_emit_float_load_store_mode(node);",
63         AM  => "${arch}_emit_float_arithmetic_mode(node);",
64         LM  => "${arch}_emit_load_mode(node);",
65         SM  => "${arch}_emit_store_mode(node);",
66         SO  => "${arch}_emit_shifter_operand(node);",
67         S0  => "${arch}_emit_source_register(node, 0);",
68         SC  => "${arch}_emit_symconst(node);",
69         S1  => "${arch}_emit_source_register(node, 1);",
70         S2  => "${arch}_emit_source_register(node, 2);",
71         S3  => "${arch}_emit_source_register(node, 3);",
72         S4  => "${arch}_emit_source_register(node, 4);",
73         D0  => "${arch}_emit_dest_register(node, 0);",
74         D1  => "${arch}_emit_dest_register(node, 1);",
75         D2  => "${arch}_emit_dest_register(node, 2);",
76         O   => "${arch}_emit_offset(node);",
77 );
78
79 $default_attr_type = "arm_attr_t";
80 $default_copy_attr = "arm_copy_attr";
81
82 %init_attr = (
83         arm_attr_t           => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
84         arm_SymConst_attr_t  =>
85                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
86                 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
87         arm_CondJmp_attr_t   => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
88         arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
89         arm_fConst_attr_t    => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
90         arm_load_store_attr_t =>
91                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
92                 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
93         arm_shifter_operand_t =>
94                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
95         arm_cmp_attr_t =>
96                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
97         arm_farith_attr_t =>
98                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
99                 "\tinit_arm_farith_attributes(res, op_mode);",
100         arm_CopyB_attr_t =>
101                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
102                 "\tinit_arm_CopyB_attributes(res, size);",
103 );
104
105 %compare_attr = (
106         arm_attr_t            => "cmp_attr_arm",
107         arm_SymConst_attr_t   => "cmp_attr_arm_SymConst",
108         arm_CondJmp_attr_t    => "cmp_attr_arm_CondJmp",
109         arm_SwitchJmp_attr_t  => "cmp_attr_arm_SwitchJmp",
110         arm_fConst_attr_t     => "cmp_attr_arm_fConst",
111         arm_load_store_attr_t => "cmp_attr_arm_load_store",
112         arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
113         arm_CopyB_attr_t      => "cmp_attr_arm_CopyB",
114         arm_cmp_attr_t        => "cmp_attr_arm_cmp",
115         arm_farith_attr_t     => "cmp_attr_arm_farith",
116 );
117
118 my %unop_shifter_operand_constructors = (
119         imm => {
120                 attr       => "unsigned char immediate_value, unsigned char immediate_rot",
121                 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
122                 reg_req    => { in => [], out => [ "gp" ] },
123         },
124         reg => {
125                 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
126                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
127         },
128         reg_shift_reg => {
129                 attr       => "arm_shift_modifier_t shift_modifier",
130                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
131                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
132         },
133         reg_shift_imm => {
134                 attr       => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
135                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
136                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
137         },
138 );
139
140 my %binop_shifter_operand_constructors = (
141         imm => {
142                 attr       => "unsigned char immediate_value, unsigned char immediate_rot",
143                 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
144                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
145                 ins        => [ "left" ],
146         },
147         reg => {
148                 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
149                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
150                 ins        => [ "left", "right" ],
151         },
152         reg_shift_reg => {
153                 attr       => "arm_shift_modifier_t shift_modifier",
154                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
155                 reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
156                 ins        => [ "left", "right", "shift" ],
157         },
158         reg_shift_imm => {
159                 attr       => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
160                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
161                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
162                 ins        => [ "left", "right" ],
163         },
164 );
165
166 my %cmp_shifter_operand_constructors = (
167         imm => {
168                 attr       => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
169                 custominit =>
170                         "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
171                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
172                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
173                 ins        => [ "left" ],
174         },
175         reg => {
176                 attr       => "bool ins_permuted, bool is_unsigned",
177                 custominit =>
178                         "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
179                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
180                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
181                 ins        => [ "left", "right" ],
182         },
183         reg_shift_reg => {
184                 attr       => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
185                 custominit =>
186                         "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
187                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
188                 reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
189                 ins        => [ "left", "right", "shift" ],
190         },
191         reg_shift_imm => {
192                 attr       => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
193                 custominit =>
194                         "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
195                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
196                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
197                 ins        => [ "left", "right" ],
198         },
199 );
200
201
202 %nodes = (
203
204 Add => {
205         irn_flags => "R",
206         emit      => '. add %D0, %S0, %SO',
207         mode      => $mode_gp,
208         attr_type => "arm_shifter_operand_t",
209         constructors => \%binop_shifter_operand_constructors,
210 },
211
212 Mul => {
213         irn_flags => "R",
214         reg_req   => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
215         emit      =>'. mul %D0, %S0, %S1',
216         mode      => $mode_gp,
217 },
218
219 Smull => {
220         irn_flags => "R",
221         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
222         emit      =>'. smull %D0, %D1, %S0, %S1',
223         outs      => [ "low", "high" ],
224 },
225
226 Umull => {
227         irn_flags => "R",
228         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
229         emit      =>'. umull %D0, %D1, %S0, %S1',
230         outs      => [ "low", "high" ],
231         mode      => $mode_gp,
232 },
233
234 Mla => {
235         irn_flags => "R",
236         reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
237         emit      =>'. mla %D0, %S0, %S1, %S2',
238         mode      => $mode_gp,
239 },
240
241 And => {
242         irn_flags => "R",
243         emit      => '. and %D0, %S0, %SO',
244         mode      => $mode_gp,
245         attr_type => "arm_shifter_operand_t",
246         constructors => \%binop_shifter_operand_constructors,
247 },
248
249 Or => {
250         irn_flags => "R",
251         emit      => '. orr %D0, %S0, %SO',
252         mode      => $mode_gp,
253         attr_type => "arm_shifter_operand_t",
254         constructors => \%binop_shifter_operand_constructors,
255 },
256
257 Eor => {
258         irn_flags => "R",
259         emit      => '. eor %D0, %S0, %SO',
260         mode      => $mode_gp,
261         attr_type => "arm_shifter_operand_t",
262         constructors => \%binop_shifter_operand_constructors,
263 },
264
265 Bic => {
266         irn_flags => "R",
267         emit      => '. bic %D0, %S0, %SO',
268         mode      => $mode_gp,
269         attr_type => "arm_shifter_operand_t",
270         constructors => \%binop_shifter_operand_constructors,
271 },
272
273 Sub => {
274         irn_flags => "R",
275         emit      => '. sub %D0, %S0, %SO',
276         mode      => $mode_gp,
277         attr_type => "arm_shifter_operand_t",
278         constructors => \%binop_shifter_operand_constructors,
279 },
280
281 Rsb => {
282         irn_flags => "R",
283         emit      => '. rsb %D0, %S0, %SO',
284         mode      => $mode_gp,
285         attr_type => "arm_shifter_operand_t",
286         constructors => \%binop_shifter_operand_constructors,
287 },
288
289 Mov => {
290         irn_flags => "R",
291         arity     => "variable",
292         emit      => '. mov %D0, %SO',
293         mode      => $mode_gp,
294         attr_type => "arm_shifter_operand_t",
295         constructors => \%unop_shifter_operand_constructors,
296 },
297
298 Mvn => {
299         irn_flags => "R",
300         attr_type => "arm_shifter_operand_t",
301         arity     => "variable",
302         emit      => '. mvn %D0, %SO',
303         mode      => $mode_gp,
304         constructors => \%unop_shifter_operand_constructors,
305 },
306
307 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
308 # pointers
309 LinkMovPC => {
310         state        => "exc_pinned",
311         arity        => "variable",
312         out_arity    => "variable",
313         attr_type    => "arm_shifter_operand_t",
314         attr         => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
315         custominit   => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
316                         "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
317         emit         => ". mov lr, pc\n".
318                         ". mov pc, %SO",
319         mode         => "mode_T",
320 },
321
322 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
323 # pointers
324 LinkLdrPC => {
325         state        => "exc_pinned",
326         arity        => "variable",
327         out_arity    => "variable",
328         attr_type    => "arm_load_store_attr_t",
329         attr         => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
330         custominit   => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
331         emit         => ". mov lr, pc\n".
332                         ". ldr pc, %SO",
333         mode         => "mode_T",
334 },
335
336 Bl => {
337         state      => "exc_pinned",
338         arity      => "variable",
339         out_arity  => "variable",
340         attr_type  => "arm_SymConst_attr_t",
341         attr       => "ir_entity *entity, int symconst_offset",
342         custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
343         emit       => '. bl %SC',
344         mode       => "mode_T",
345 },
346
347 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
348 EmptyReg => {
349         op_flags  => "c",
350         irn_flags => "R",
351         reg_req   => { out => [ "gp" ] },
352         emit      => '. /* %D0 now available for calculations */',
353         cmp_attr  => 'return 1;',
354         mode      => $mode_gp,
355 },
356
357 CopyB => {
358         op_flags  => "F|H",
359         state     => "pinned",
360         attr      => "unsigned size",
361         attr_type => "arm_CopyB_attr_t",
362         reg_req   => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
363         outs      => [ "M" ],
364 },
365
366 FrameAddr => {
367         op_flags  => "c",
368         irn_flags => "R",
369         attr      => "ir_entity *entity, int symconst_offset",
370         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
371         ins       => [ "base" ],
372         attr_type => "arm_SymConst_attr_t",
373         mode      => $mode_gp,
374 },
375
376 SymConst => {
377         op_flags  => "c",
378         irn_flags => "R",
379         attr      => "ir_entity *entity, int symconst_offset",
380         reg_req   => { out => [ "gp" ] },
381         attr_type => "arm_SymConst_attr_t",
382         mode      => $mode_gp,
383 },
384
385 Cmp => {
386         irn_flags    => "R|F",
387         emit         => '. cmp %S0, %SO',
388         mode         => $mode_flags,
389         attr_type    => "arm_cmp_attr_t",
390         constructors => \%cmp_shifter_operand_constructors,
391 },
392
393 Tst => {
394         irn_flags    => "R|F",
395         emit         => '. tst %S0, %SO',
396         mode         => $mode_flags,
397         attr_type    => "arm_cmp_attr_t",
398         constructors => \%cmp_shifter_operand_constructors,
399 },
400
401 B => {
402         op_flags  => "L|X|Y",
403         state     => "pinned",
404         mode      => "mode_T",
405         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
406         attr      => "pn_Cmp pnc",
407         attr_type => "arm_CondJmp_attr_t",
408         init_attr => "\tset_arm_CondJmp_pnc(res, pnc);",
409 },
410
411 Jmp => {
412         state     => "pinned",
413         op_flags  => "X",
414         irn_flags => "J",
415         reg_req   => { out => [ "none" ] },
416         mode      => "mode_X",
417 },
418
419 SwitchJmp => {
420         op_flags  => "L|X|Y",
421         state     => "pinned",
422         mode      => "mode_T",
423         attr      => "int n_projs, long def_proj_num",
424         init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
425                      "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
426         reg_req   => { in => [ "gp" ], out => [ "none" ] },
427         attr_type => "arm_SwitchJmp_attr_t",
428 },
429
430 Ldr => {
431         op_flags  => "L|F",
432         state     => "exc_pinned",
433         ins       => [ "ptr", "mem" ],
434         outs      => [ "res", "M" ],
435         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
436         emit      => '. ldr%LM %D0, [%S0, #%O]',
437         attr_type => "arm_load_store_attr_t",
438         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
439 },
440
441 Str => {
442         op_flags  => "L|F",
443         state     => "exc_pinned",
444         ins       => [ "ptr", "val", "mem" ],
445         outs      => [ "mem" ],
446         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
447         emit      => '. str%SM %S1, [%S0, #%O]',
448         mode      => "mode_M",
449         attr_type => "arm_load_store_attr_t",
450         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
451 },
452
453 StoreStackM4Inc => {
454         op_flags  => "L|F",
455         irn_flags => "R",
456         state     => "exc_pinned",
457         reg_req   => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
458         emit      => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
459         outs      => [ "ptr", "M" ],
460 },
461
462 LoadStackM3Epilogue => {
463         op_flags  => "L|F",
464         irn_flags => "R",
465         state     => "exc_pinned",
466         reg_req   => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
467         emit      => '. ldmfd %S0, {%D0, %D1, %D2}',
468         outs      => [ "res0", "res1", "res2", "M" ],
469 },
470
471
472
473 Adf => {
474         irn_flags => "R",
475         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
476         emit      => '. adf%AM %D0, %S0, %S1',
477         attr_type => "arm_farith_attr_t",
478         attr      => "ir_mode *op_mode",
479         mode      => $mode_fp,
480 },
481
482 Muf => {
483         irn_flags => "R",
484         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
485         emit      =>'. muf%AM %D0, %S0, %S1',
486         attr_type => "arm_farith_attr_t",
487         attr      => "ir_mode *op_mode",
488         mode      => $mode_fp,
489 },
490
491 Suf => {
492         irn_flags => "R",
493         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
494         emit      => '. suf%AM %D0, %S0, %S1',
495         attr_type => "arm_farith_attr_t",
496         attr      => "ir_mode *op_mode",
497         mode      => $mode_fp,
498 },
499
500 Dvf => {
501         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
502         emit      =>'. dvf%AM %D0, %S0, %S1',
503         outs      => [ "res", "M" ],
504         attr_type => "arm_farith_attr_t",
505         attr      => "ir_mode *op_mode",
506         mode      => $mode_fp,
507 },
508
509 Mvf => {
510         irn_flags => "R",
511         reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
512         emit      => '. mvf%AM %S0, %D0',
513         attr_type => "arm_farith_attr_t",
514         attr      => "ir_mode *op_mode",
515         mode      => $mode_fp,
516 },
517
518 FltX => {
519         irn_flags => "R",
520         reg_req   => { in => [ "gp" ], out => [ "fpa" ] },
521         emit      => '. flt%AM %D0, %S0',
522         attr_type => "arm_farith_attr_t",
523         attr      => "ir_mode *op_mode",
524         mode      => $mode_fp,
525 },
526
527 Cmfe => {
528         irn_flags => "R|F",
529         mode      => $mode_flags,
530         attr_type => "arm_cmp_attr_t",
531         attr      => "bool ins_permuted",
532         init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
533         reg_req   => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
534         emit      => '. cmfe %S0, %S1',
535 },
536
537 Ldf => {
538         op_flags  => "L|F",
539         state     => "exc_pinned",
540         ins       => [ "ptr", "mem" ],
541         outs      => [ "res", "M" ],
542         reg_req   => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
543         emit      => '. ldf%FM %D0, [%S0, #%O]',
544         attr_type => "arm_load_store_attr_t",
545         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
546 },
547
548 Stf => {
549         op_flags  => "L|F",
550         state     => "exc_pinned",
551         ins       => [ "ptr", "val", "mem" ],
552         outs      => [ "M" ],
553         mode      => "mode_M",
554         reg_req   => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
555         emit      => '. stf%FM %S1, [%S0, #%O]',
556         attr_type => "arm_load_store_attr_t",
557         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
558 },
559
560 #
561 # floating point constants
562 #
563 fConst => {
564         op_flags  => "c",
565         irn_flags => "R",
566         attr      => "tarval *tv",
567         init_attr => "attr->tv = tv;",
568         mode      => "get_tarval_mode(tv)",
569         reg_req   => { out => [ "fpa" ] },
570         attr_type => "arm_fConst_attr_t",
571 }
572
573 ); # end of %nodes