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