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