1732dba8bb8b7489d4d0978074302420a04af67d
[libfirm] / ir / be / arm / arm_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3
4 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
5
6 $arch = "arm";
7
8 #
9 # Modes
10 #
11 $mode_gp      = "mode_Iu";
12 $mode_flags   = "mode_Bu";
13 $mode_fpa     = "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_fpa }
54         ],
55         flags => [
56                 { name => "fl", type => 0 },
57                 { mode => $mode_flags, flags => "manual_ra" }
58         ],
59 );
60
61 %emit_templates = (
62         M   => "${arch}_emit_mode(node);",
63         LM  => "${arch}_emit_load_mode(node);",
64         SM  => "${arch}_emit_store_mode(node);",
65         SO  => "${arch}_emit_shifter_operand(node);",
66         S0  => "${arch}_emit_source_register(node, 0);",
67         SC  => "${arch}_emit_symconst(node);",
68         S1  => "${arch}_emit_source_register(node, 1);",
69         S2  => "${arch}_emit_source_register(node, 2);",
70         S3  => "${arch}_emit_source_register(node, 3);",
71         S4  => "${arch}_emit_source_register(node, 4);",
72         D0  => "${arch}_emit_dest_register(node, 0);",
73         D1  => "${arch}_emit_dest_register(node, 1);",
74         D2  => "${arch}_emit_dest_register(node, 2);",
75         O   => "${arch}_emit_offset(node);",
76 );
77
78 $default_attr_type = "arm_attr_t";
79 $default_copy_attr = "arm_copy_attr";
80
81 %init_attr = (
82         arm_attr_t           => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
83         arm_SymConst_attr_t  =>
84                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
85                 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
86         arm_CondJmp_attr_t   => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
87         arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
88         arm_fpaConst_attr_t  => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
89         arm_load_store_attr_t =>
90                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
91                 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
92         arm_shifter_operand_t =>
93                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
94         arm_cmp_attr_t =>
95                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
96         arm_CopyB_attr_t =>
97                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
98                 "\tinit_arm_CopyB_attributes(res, size);",
99 );
100
101 %compare_attr = (
102         arm_attr_t            => "cmp_attr_arm",
103         arm_SymConst_attr_t   => "cmp_attr_arm_SymConst",
104         arm_CondJmp_attr_t    => "cmp_attr_arm_CondJmp",
105         arm_SwitchJmp_attr_t  => "cmp_attr_arm_SwitchJmp",
106         arm_fpaConst_attr_t   => "cmp_attr_arm_fpaConst",
107         arm_load_store_attr_t => "cmp_attr_arm_load_store",
108         arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
109         arm_CopyB_attr_t      => "cmp_attr_arm_CopyB",
110         arm_cmp_attr_t        => "cmp_attr_arm_cmp",
111 );
112
113 my %unop_shifter_operand_constructors = (
114         imm => {
115                 attr       => "unsigned char immediate_value, unsigned char immediate_rot",
116                 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
117                 reg_req    => { in => [], out => [ "gp" ] },
118         },
119         reg => {
120                 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
121                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
122         },
123         reg_shift_reg => {
124                 attr       => "arm_shift_modifier_t shift_modifier",
125                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
126                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
127         },
128         reg_shift_imm => {
129                 attr       => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
130                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
131                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
132         },
133 );
134
135 my %binop_shifter_operand_constructors = (
136         imm => {
137                 attr       => "unsigned char immediate_value, unsigned char immediate_rot",
138                 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
139                 reg_req    => { in => [ "gp" ], out => [ "gp" ] },
140                 ins        => [ "left" ],
141         },
142         reg => {
143                 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
144                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
145                 ins        => [ "left", "right" ],
146         },
147         reg_shift_reg => {
148                 attr       => "arm_shift_modifier_t shift_modifier",
149                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
150                 reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
151                 ins        => [ "left", "right", "shift" ],
152         },
153         reg_shift_imm => {
154                 attr       => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
155                 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
156                 reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
157                 ins        => [ "left", "right" ],
158         },
159 );
160
161 my %cmp_shifter_operand_constructors = (
162         imm => {
163                 attr       => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
164                 custominit =>
165                         "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
166                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
167                 reg_req    => { in => [ "gp" ], out => [ "flags" ] },
168                 ins        => [ "left" ],
169         },
170         reg => {
171                 attr       => "bool ins_permuted, bool is_unsigned",
172                 custominit =>
173                         "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
174                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
175                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
176                 ins        => [ "left", "right" ],
177         },
178         reg_shift_reg => {
179                 attr       => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
180                 custominit =>
181                         "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
182                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
183                 reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
184                 ins        => [ "left", "right", "shift" ],
185         },
186         reg_shift_imm => {
187                 attr       => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
188                 custominit =>
189                         "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
190                         "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
191                 reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
192                 ins        => [ "left", "right" ],
193         },
194 );
195
196
197 %nodes = (
198
199 Add => {
200         irn_flags => "R",
201         emit      => '. add %D0, %S0, %SO',
202         mode      => $mode_gp,
203         attr_type => "arm_shifter_operand_t",
204         constructors => \%binop_shifter_operand_constructors,
205 },
206
207 Mul => {
208         irn_flags => "R",
209         reg_req   => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
210         emit      =>'. mul %D0, %S0, %S1',
211         mode      => $mode_gp,
212 },
213
214 Smull => {
215         irn_flags => "R",
216         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
217         emit      =>'. smull %D0, %D1, %S0, %S1',
218         outs      => [ "low", "high" ],
219 },
220
221 Umull => {
222         irn_flags => "R",
223         reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
224         emit      =>'. umull %D0, %D1, %S0, %S1',
225         outs      => [ "low", "high" ],
226         mode      => $mode_gp,
227 },
228
229 Mla => {
230         irn_flags => "R",
231         reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
232         emit      =>'. mla %D0, %S0, %S1, %S2',
233         mode      => $mode_gp,
234 },
235
236 And => {
237         irn_flags => "R",
238         emit      => '. and %D0, %S0, %SO',
239         mode      => $mode_gp,
240         attr_type => "arm_shifter_operand_t",
241         constructors => \%binop_shifter_operand_constructors,
242 },
243
244 Or => {
245         irn_flags => "R",
246         emit      => '. orr %D0, %S0, %SO',
247         mode      => $mode_gp,
248         attr_type => "arm_shifter_operand_t",
249         constructors => \%binop_shifter_operand_constructors,
250 },
251
252 Eor => {
253         irn_flags => "R",
254         emit      => '. eor %D0, %S0, %SO',
255         mode      => $mode_gp,
256         attr_type => "arm_shifter_operand_t",
257         constructors => \%binop_shifter_operand_constructors,
258 },
259
260 Bic => {
261         irn_flags => "R",
262         emit      => '. bic %D0, %S0, %SO',
263         mode      => $mode_gp,
264         attr_type => "arm_shifter_operand_t",
265         constructors => \%binop_shifter_operand_constructors,
266 },
267
268 Sub => {
269         irn_flags => "R",
270         emit      => '. sub %D0, %S0, %SO',
271         mode      => $mode_gp,
272         attr_type => "arm_shifter_operand_t",
273         constructors => \%binop_shifter_operand_constructors,
274 },
275
276 Rsb => {
277         irn_flags => "R",
278         emit      => '. rsb %D0, %S0, %SO',
279         mode      => $mode_gp,
280         attr_type => "arm_shifter_operand_t",
281         constructors => \%binop_shifter_operand_constructors,
282 },
283
284 Mov => {
285         irn_flags => "R",
286         arity     => "variable",
287         emit      => '. mov %D0, %SO',
288         mode      => $mode_gp,
289         attr_type => "arm_shifter_operand_t",
290         constructors => \%unop_shifter_operand_constructors,
291 },
292
293 Mvn => {
294         irn_flags => "R",
295         attr_type => "arm_shifter_operand_t",
296         arity     => "variable",
297         emit      => '. mvn %D0, %SO',
298         mode      => $mode_gp,
299         constructors => \%unop_shifter_operand_constructors,
300 },
301
302 # Deprecated - we should construct the movs and rsbmi directly...
303 Abs => {
304         irn_flags => "R",
305         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
306         emit      =>
307 '. movs %S0, %S0, #0
308 . rsbmi %D0, %S0, #0',
309         mode      => $mode_gp,
310 },
311
312 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
313 # pointers
314 LinkMovPC => {
315         state        => "exc_pinned",
316         arity        => "variable",
317         out_arity    => "variable",
318         attr_type    => "arm_shifter_operand_t",
319         attr         => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
320         custominit   => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
321                         "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
322         emit         => ". mov lr, pc\n".
323                         ". mov pc, %SO",
324         mode         => "mode_T",
325 },
326
327 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
328 # pointers
329 LinkLdrPC => {
330         state        => "exc_pinned",
331         arity        => "variable",
332         out_arity    => "variable",
333         attr_type    => "arm_load_store_attr_t",
334         attr         => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
335         custominit   => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
336         emit         => ". mov lr, pc\n".
337                         ". ldr pc, %SO",
338         mode         => "mode_T",
339 },
340
341 Bl => {
342         state      => "exc_pinned",
343         arity      => "variable",
344         out_arity  => "variable",
345         attr_type  => "arm_SymConst_attr_t",
346         attr       => "ir_entity *entity, int symconst_offset",
347         custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
348         emit       => '. bl %SC',
349         mode       => "mode_T",
350 },
351
352 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
353 EmptyReg => {
354         op_flags  => "c",
355         irn_flags => "R",
356         reg_req   => { out => [ "gp" ] },
357         emit      => '. /* %D0 now available for calculations */',
358         cmp_attr  => 'return 1;',
359         mode      => $mode_gp,
360 },
361
362 CopyB => {
363         op_flags  => "F|H",
364         state     => "pinned",
365         attr      => "unsigned size",
366         attr_type => "arm_CopyB_attr_t",
367         reg_req   => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
368         outs      => [ "M" ],
369 },
370
371 FrameAddr => {
372         op_flags  => "c",
373         irn_flags => "R",
374         attr      => "ir_entity *entity, int symconst_offset",
375         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
376         ins       => [ "base" ],
377         attr_type => "arm_SymConst_attr_t",
378         mode      => $mode_gp,
379 },
380
381 SymConst => {
382         op_flags  => "c",
383         irn_flags => "R",
384         attr      => "ir_entity *entity, int symconst_offset",
385         reg_req   => { out => [ "gp" ] },
386         attr_type => "arm_SymConst_attr_t",
387         mode      => $mode_gp,
388 },
389
390 Cmp => {
391         irn_flags    => "R|F",
392         emit         => '. cmp %S0, %SO',
393         mode         => $mode_flags,
394         attr_type    => "arm_cmp_attr_t",
395         constructors => \%cmp_shifter_operand_constructors,
396 },
397
398 Tst => {
399         irn_flags    => "R|F",
400         emit         => '. tst %S0, %SO',
401         mode         => $mode_flags,
402         attr_type    => "arm_cmp_attr_t",
403         constructors => \%cmp_shifter_operand_constructors,
404 },
405
406 B => {
407         op_flags  => "L|X|Y",
408         state     => "pinned",
409         mode      => "mode_T",
410         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
411         attr      => "pn_Cmp pnc",
412         attr_type => "arm_CondJmp_attr_t",
413         init_attr => "\tset_arm_CondJmp_pnc(res, pnc);",
414 },
415
416 Jmp => {
417         state     => "pinned",
418         op_flags  => "X",
419         irn_flags => "J",
420         reg_req   => { out => [ "none" ] },
421         mode      => "mode_X",
422 },
423
424 SwitchJmp => {
425         op_flags  => "L|X|Y",
426         state     => "pinned",
427         mode      => "mode_T",
428         attr      => "int n_projs, long def_proj_num",
429         init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
430                      "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
431         reg_req   => { in => [ "gp" ], out => [ "none" ] },
432         attr_type => "arm_SwitchJmp_attr_t",
433 },
434
435 Ldr => {
436         op_flags  => "L|F",
437         state     => "exc_pinned",
438         ins       => [ "ptr", "mem" ],
439         outs      => [ "res", "M" ],
440         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
441         emit      => '. ldr%LM %D0, [%S0, #%O]',
442         attr_type => "arm_load_store_attr_t",
443         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
444 },
445
446 Str => {
447         op_flags  => "L|F",
448         state     => "exc_pinned",
449         ins       => [ "ptr", "val", "mem" ],
450         outs      => [ "mem" ],
451         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
452         emit      => '. str%SM %S1, [%S0, #%O]',
453         mode      => "mode_M",
454         attr_type => "arm_load_store_attr_t",
455         attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
456 },
457
458 StoreStackM4Inc => {
459         op_flags  => "L|F",
460         irn_flags => "R",
461         state     => "exc_pinned",
462         reg_req   => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
463         emit      => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
464         outs      => [ "ptr", "M" ],
465 },
466
467 LoadStackM3Epilogue => {
468         op_flags  => "L|F",
469         irn_flags => "R",
470         state     => "exc_pinned",
471         reg_req   => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
472         emit      => '. ldmfd %S0, {%D0, %D1, %D2}',
473         outs      => [ "res0", "res1", "res2", "M" ],
474 },
475
476
477
478 fpaAdf => {
479         irn_flags => "R",
480         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
481         emit      => '. adf%M %D0, %S0, %S1',
482 },
483
484 fpaMuf => {
485         irn_flags => "R",
486         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
487         emit      =>'. muf%M %D0, %S0, %S1',
488 },
489
490 fpaFml => {
491         irn_flags => "R",
492         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
493         emit      =>'. fml%M %D0, %S0, %S1',
494 },
495
496 fpaMax => {
497         irn_flags => "R",
498         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
499         emit      =>'. fmax %S0, %S1, %D0',
500 },
501
502 fpaMin => {
503         irn_flags => "R",
504         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
505         emit      =>'. fmin %S0, %S1, %D0',
506 },
507
508 fpaSuf => {
509         irn_flags => "R",
510         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
511         emit      => '. suf%M %D0, %S0, %S1'
512 },
513
514 fpaRsf => {
515         irn_flags => "R",
516         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
517         emit      => '. rsf%M %D0, %S0, %S1'
518 },
519
520 fpaDvf => {
521         attr      => "ir_mode *op_mode",
522         init_attr => "attr->op_mode = op_mode;",
523         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
524         emit      =>'. dvf%M %D0, %S0, %S1',
525         outs      => [ "res", "M" ],
526 },
527
528 fpaRdf => {
529         attr      => "ir_mode *op_mode",
530         init_attr => "attr->op_mode = op_mode;",
531         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
532         emit      =>'. rdf%M %D0, %S0, %S1',
533         outs      => [ "res", "M" ],
534 },
535
536 fpaFdv => {
537         attr      => "ir_mode *op_mode",
538         init_attr => "attr->op_mode = op_mode;",
539         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
540         emit      =>'. fdv%M %D0, %S0, %S1',
541         outs      => [ "res", "M" ],
542 },
543
544 fpaFrd => {
545         attr      => "ir_mode *op_mode",
546         init_attr => "attr->op_mode = op_mode;",
547         reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
548         emit      =>'. frd%M %D0, %S0, %S1',
549         outs      => [ "res", "M" ],
550 },
551
552 fpaMvf => {
553         irn_flags => "R",
554         reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
555         emit      => '. mvf%M %S0, %D0',
556 },
557
558 fpaMnf => {
559         irn_flags => "R",
560         reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
561         emit      => '. mnf%M %S0, %D0',
562 },
563
564 fpaAbs => {
565         irn_flags => "R",
566         reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
567         emit      => '. abs%M %D0, %S0',
568 },
569
570 fpaFlt => {
571         irn_flags => "R",
572         reg_req   => { in => ["gp"], out => [ "fpa" ] },
573         emit      => '. flt%M %D0, %S0',
574 },
575
576 fpaFix => {
577         irn_flags => "R",
578         reg_req   => { in => ["fpa"], out => [ "gp" ] },
579         emit      => '. fix %D0, %S0',
580 },
581
582 Cmf => {
583         irn_flags => "R|F",
584         mode      => $mode_flags,
585         attr_type => "arm_cmp_attr_t",
586         attr      => "bool ins_permuted",
587         init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
588         reg_req   => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
589         emit      => '. cmf %S0, %S1',
590 },
591
592 Cmfe => {
593         irn_flags => "R|F",
594         mode      => $mode_flags,
595         attr_type => "arm_cmp_attr_t",
596         attr      => "bool ins_permuted",
597         init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
598         reg_req   => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
599         emit      => '. cmfe %S0, %S1',
600 },
601
602 fpaLdf => {
603         op_flags  => "L|F",
604         irn_flags => "R",
605         state     => "exc_pinned",
606         attr      => "ir_mode *op_mode",
607         init_attr => "attr->op_mode = op_mode;",
608         reg_req   => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
609         emit      => '. ldf%M %D0, [%S0]',
610         outs      => [ "res", "M" ],
611 },
612
613 fpaStf => {
614         op_flags  => "L|F",
615         irn_flags => "R",
616         state     => "exc_pinned",
617         attr      => "ir_mode *op_mode",
618         init_attr => "attr->op_mode = op_mode;",
619         reg_req   => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
620         emit      => '. stf%M %S1, [%S0]',
621         mode      => "mode_M",
622 },
623
624 fpaDbl2GP => {
625         op_flags  => "L|F",
626         irn_flags => "R",
627         reg_req   => { in => [ "fpa", "none" ], out => [ "gp", "gp", "none" ] },
628         outs      => [ "low", "high", "M" ],
629 },
630
631 AddSP => {
632         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
633         emit      => '. add %D0, %S0, %S1',
634         outs      => [ "stack", "M" ],
635 },
636
637 SubSPandCopy => {
638         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
639         ins       => [ "stack", "size", "mem" ],
640         emit      => ". sub %D0, %S0, %S1\n".
641                      ". mov sp, %D1",
642         outs      => [ "stack", "addr", "M" ],
643 },
644
645 LdTls => {
646         irn_flags => "R",
647         reg_req   => { out => [ "gp" ] },
648         mode      => $mode_gp,
649 },
650
651
652 #
653 # floating point constants
654 #
655 fpaConst => {
656         op_flags  => "c",
657         irn_flags => "R",
658         attr      => "tarval *tv",
659         init_attr => "attr->tv = tv;",
660         mode      => "get_tarval_mode(tv)",
661         reg_req   => { out => [ "fpa" ] },
662         attr_type => "arm_fpaConst_attr_t",
663 }
664
665 ); # end of %nodes