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