Allow the first line to be a comment.
[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         arity     => "variable",
264         emit      => 'mov %D0, %O',
265         mode      => $mode_gp,
266         attr_type => "arm_shifter_operand_t",
267         constructors => \%unop_shifter_operand_constructors,
268 },
269
270 Mvn => {
271         irn_flags => [ "rematerializable" ],
272         attr_type => "arm_shifter_operand_t",
273         arity     => "variable",
274         emit      => 'mvn %D0, %O',
275         mode      => $mode_gp,
276         constructors => \%unop_shifter_operand_constructors,
277 },
278
279 Clz => {
280         irn_flags => [ "rematerializable" ],
281         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
282         emit      => 'clz %D0, %S0',
283         mode      => $mode_gp,
284 },
285
286 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
287 # pointers
288 LinkMovPC => {
289         state        => "exc_pinned",
290         arity        => "variable",
291         out_arity    => "variable",
292         attr_type    => "arm_shifter_operand_t",
293         attr         => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
294         custominit   => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
295                         "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);",
296         emit         => "mov lr, pc\n".
297                         "mov pc, %O",
298 },
299
300 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
301 # pointers
302 LinkLdrPC => {
303         state        => "exc_pinned",
304         arity        => "variable",
305         out_arity    => "variable",
306         attr_type    => "arm_load_store_attr_t",
307         attr         => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
308         custominit   => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
309         emit         => "mov lr, pc\n".
310                         "ldr pc, %O",
311 },
312
313 Bl => {
314         state      => "exc_pinned",
315         arity      => "variable",
316         out_arity  => "variable",
317         attr_type  => "arm_SymConst_attr_t",
318         attr       => "ir_entity *entity, int symconst_offset",
319         custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
320         emit       => 'bl %I',
321 },
322
323 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
324 EmptyReg => {
325         op_flags  => [ "constlike" ],
326         irn_flags => [ "rematerializable" ],
327         reg_req   => { out => [ "gp" ] },
328         emit      => '/* %D0 now available for calculations */',
329         cmp_attr  => 'return 1;',
330         mode      => $mode_gp,
331 },
332
333 CopyB => {
334         state     => "pinned",
335         attr      => "unsigned size",
336         attr_type => "arm_CopyB_attr_t",
337         reg_req   => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
338         outs      => [ "M" ],
339 },
340
341 FrameAddr => {
342         op_flags  => [ "constlike" ],
343         irn_flags => [ "rematerializable" ],
344         attr      => "ir_entity *entity, int symconst_offset",
345         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
346         ins       => [ "base" ],
347         attr_type => "arm_SymConst_attr_t",
348         mode      => $mode_gp,
349 },
350
351 SymConst => {
352         op_flags  => [ "constlike" ],
353         irn_flags => [ "rematerializable" ],
354         attr      => "ir_entity *entity, int symconst_offset",
355         reg_req   => { out => [ "gp" ] },
356         attr_type => "arm_SymConst_attr_t",
357         mode      => $mode_gp,
358 },
359
360 Cmp => {
361         irn_flags    => [ "rematerializable", "modify_flags" ],
362         emit         => 'cmp %S0, %O',
363         mode         => $mode_flags,
364         attr_type    => "arm_cmp_attr_t",
365         constructors => \%cmp_shifter_operand_constructors,
366 },
367
368 Tst => {
369         irn_flags    => [ "rematerializable", "modify_flags" ],
370         emit         => 'tst %S0, %O',
371         mode         => $mode_flags,
372         attr_type    => "arm_cmp_attr_t",
373         constructors => \%cmp_shifter_operand_constructors,
374 },
375
376 B => {
377         op_flags  => [ "cfopcode", "forking" ],
378         state     => "pinned",
379         mode      => "mode_T",
380         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
381         attr      => "ir_relation relation",
382         attr_type => "arm_CondJmp_attr_t",
383         init_attr => "\tset_arm_CondJmp_relation(res, relation);",
384 },
385
386 Jmp => {
387         state     => "pinned",
388         op_flags  => [ "cfopcode" ],
389         irn_flags => [ "simple_jump" ],
390         reg_req   => { out => [ "none" ] },
391         mode      => "mode_X",
392 },
393
394 SwitchJmp => {
395         op_flags  => [ "cfopcode", "forking" ],
396         state     => "pinned",
397         mode      => "mode_T",
398         attr      => "const ir_switch_table *table",
399         init_attr => "init_arm_SwitchJmp_attributes(res, table);",
400         reg_req   => { in => [ "gp" ], out => [ "none" ] },
401         out_arity => "variable",
402         attr_type => "arm_SwitchJmp_attr_t",
403 },
404
405 Ldr => {
406         op_flags  => [ "uses_memory" ],
407         state     => "exc_pinned",
408         ins       => [ "ptr", "mem" ],
409         outs      => [ "res", "M" ],
410         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
411         emit      => 'ldr%ML %D0, [%S0, #%o]',
412         attr_type => "arm_load_store_attr_t",
413         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
414 },
415
416 Str => {
417         op_flags  => [ "uses_memory" ],
418         state     => "exc_pinned",
419         ins       => [ "ptr", "val", "mem" ],
420         outs      => [ "M" ],
421         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
422         emit      => 'str%MS %S1, [%S0, #%o]',
423         mode      => "mode_M",
424         attr_type => "arm_load_store_attr_t",
425         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
426 },
427
428 StoreStackM4Inc => {
429         op_flags  => [ "uses_memory" ],
430         irn_flags => [ "rematerializable" ],
431         state     => "exc_pinned",
432         reg_req   => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
433         emit      => 'stmfd %S0!, {%S1, %S2, %S3, %S4}',
434         outs      => [ "ptr", "M" ],
435 },
436
437 LoadStackM3Epilogue => {
438         op_flags  => [ "uses_memory" ],
439         irn_flags => [ "rematerializable" ],
440         state     => "exc_pinned",
441         reg_req   => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
442         emit      => 'ldmfd %S0, {%D0, %D1, %D2}',
443         outs      => [ "res0", "res1", "res2", "M" ],
444 },
445
446
447
448 Adf => {
449         irn_flags => [ "rematerializable" ],
450         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
451         emit      => 'adf%MA %D0, %S0, %S1',
452         attr_type => "arm_farith_attr_t",
453         attr      => "ir_mode *op_mode",
454         mode      => $mode_fp,
455 },
456
457 Muf => {
458         irn_flags => [ "rematerializable" ],
459         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
460         emit      => 'muf%MA %D0, %S0, %S1',
461         attr_type => "arm_farith_attr_t",
462         attr      => "ir_mode *op_mode",
463         mode      => $mode_fp,
464 },
465
466 Suf => {
467         irn_flags => [ "rematerializable" ],
468         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
469         emit      => 'suf%MA %D0, %S0, %S1',
470         attr_type => "arm_farith_attr_t",
471         attr      => "ir_mode *op_mode",
472         mode      => $mode_fp,
473 },
474
475 Dvf => {
476         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
477         emit      => 'dvf%MA %D0, %S0, %S1',
478         outs      => [ "res", "M" ],
479         attr_type => "arm_farith_attr_t",
480         attr      => "ir_mode *op_mode",
481         mode      => $mode_fp,
482 },
483
484 Mvf => {
485         irn_flags => [ "rematerializable" ],
486         reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
487         emit      => 'mvf%MA %S0, %D0',
488         attr_type => "arm_farith_attr_t",
489         attr      => "ir_mode *op_mode",
490         mode      => $mode_fp,
491 },
492
493 FltX => {
494         irn_flags => [ "rematerializable" ],
495         reg_req   => { in => [ "gp" ], out => [ "fpa" ] },
496         emit      => 'flt%MA %D0, %S0',
497         attr_type => "arm_farith_attr_t",
498         attr      => "ir_mode *op_mode",
499         mode      => $mode_fp,
500 },
501
502 Cmfe => {
503         irn_flags => [ "rematerializable", "modify_flags" ],
504         mode      => $mode_flags,
505         attr_type => "arm_cmp_attr_t",
506         attr      => "bool ins_permuted",
507         init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
508         reg_req   => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
509         emit      => 'cmfe %S0, %S1',
510 },
511
512 Ldf => {
513         op_flags  => [ "uses_memory" ],
514         state     => "exc_pinned",
515         ins       => [ "ptr", "mem" ],
516         outs      => [ "res", "M" ],
517         reg_req   => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
518         emit      => 'ldf%MF %D0, [%S0, #%o]',
519         attr_type => "arm_load_store_attr_t",
520         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
521 },
522
523 Stf => {
524         op_flags  => [ "uses_memory" ],
525         state     => "exc_pinned",
526         ins       => [ "ptr", "val", "mem" ],
527         outs      => [ "M" ],
528         mode      => "mode_M",
529         reg_req   => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
530         emit      => 'stf%MF %S1, [%S0, #%o]',
531         attr_type => "arm_load_store_attr_t",
532         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
533 },
534
535 #
536 # floating point constants
537 #
538 fConst => {
539         op_flags  => [ "constlike" ],
540         irn_flags => [ "rematerializable" ],
541         attr      => "ir_tarval *tv",
542         init_attr => "attr->tv = tv;",
543         mode      => "get_tarval_mode(tv)",
544         reg_req   => { out => [ "fpa" ] },
545         attr_type => "arm_fConst_attr_t",
546 }
547
548 ); # end of %nodes