- bring arm backend back to shape: cleanup and fix lots of stuff
[libfirm] / ir / be / arm / arm_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3 # This is a template specification for the Firm-Backend
4
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
6
7 $arch = "arm";
8
9 # the number of additional opcodes you want to register
10 #$additional_opcodes = 0;
11
12 #
13 # Modes
14 #
15 $mode_gp      = "mode_Iu";
16 $mode_fpa     = "mode_E";
17
18 # register types:
19 $normal      =  0; # no special type
20 $caller_save =  1; # caller save (register must be saved by the caller of a function)
21 $callee_save =  2; # callee save (register must be saved by the called function)
22 $ignore      =  4; # ignore (do not assign this register)
23 $arbitrary   =  8; # emitter can choose an arbitrary register of this class
24 $virtual     = 16; # the register is a virtual one
25 $state       = 32; # register represents a state
26 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
27 %reg_classes = (
28         gp => [
29                 { name => "r0",  type => $caller_save },
30                 { name => "r1",  type => $caller_save },
31                 { name => "r2",  type => $caller_save },
32                 { name => "r3",  type => $caller_save },
33                 { name => "r4",  type => $callee_save },
34                 { name => "r5",  type => $callee_save },
35                 { name => "r6",  type => $callee_save },
36                 { name => "r7",  type => $callee_save },
37                 { name => "r8",  type => $callee_save },
38                 { name => "r9",  type => $callee_save },
39                 { name => "r10", type => $callee_save },
40                 { name => "r11", type => $callee_save },
41                 { name => "r12", type => $ignore | $callee_save }, # reserved for linker
42                 { name => "sp",  type => $ignore | $callee_save }, # this is our stack pointer
43                 { name => "lr",  type => $callee_save | $caller_save }, # this is our return address
44                 { name => "pc",  type => $ignore | $callee_save }, # this is our program counter
45                 { name => "gp_UKNWN", type => $ignore | $arbitrary | $virtual },  # we need a dummy register for Unknown nodes
46                 { mode => $mode_gp }
47         ],
48         fpa  => [
49                 { name => "f0", type => $caller_save },
50                 { name => "f1", type => $caller_save },
51                 { name => "f2", type => $caller_save },
52                 { name => "f3", type => $caller_save },
53                 { name => "f4", type => $caller_save },
54                 { name => "f5", type => $caller_save },
55                 { name => "f6", type => $caller_save },
56                 { name => "f7", type => $caller_save },
57                 { name => "fpa_UKNWN", type => $ignore | $arbitrary | $virtual },  # we need a dummy register for Unknown nodes
58                 { mode => $mode_fpa }
59         ]
60 );
61
62 %emit_templates = (
63         M  => "${arch}_emit_mode(node);",
64         X  => "${arch}_emit_shift(node);",
65         S0 => "${arch}_emit_source_register(node, 0);",
66         S1 => "${arch}_emit_source_register(node, 1);",
67         S2 => "${arch}_emit_source_register(node, 2);",
68         S3 => "${arch}_emit_source_register(node, 3);",
69         S4 => "${arch}_emit_source_register(node, 4);",
70         D0 => "${arch}_emit_dest_register(node, 0);",
71         D1 => "${arch}_emit_dest_register(node, 1);",
72         D2 => "${arch}_emit_dest_register(node, 2);",
73         C  => "${arch}_emit_immediate(node);",
74         O  => "${arch}_emit_offset(mode);",
75 );
76
77 #--------------------------------------------------#
78 #                        _                         #
79 #                       (_)                        #
80 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
81 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
82 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
83 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
84 #                                      | |         #
85 #                                      |_|         #
86 #--------------------------------------------------#
87
88 $default_attr_type = "arm_attr_t";
89 $default_copy_attr = "arm_copy_attr";
90
91 %init_attr = (
92         arm_attr_t           => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
93         arm_SymConst_attr_t  => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
94         arm_CondJmp_attr_t   => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
95         arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
96         arm_fpaConst_attr_t  => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
97         arm_load_store_attr_t =>
98                 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
99                 "\tinit_arm_load_store_attributes(res, entity, entity_sign, offset);",
100 );
101
102 %compare_attr = (
103         arm_attr_t            => "cmp_attr_arm",
104         arm_SymConst_attr_t   => "cmp_attr_arm_SymConst",
105         arm_CondJmp_attr_t    => "cmp_attr_arm_CondJmp",
106         arm_SwitchJmp_attr_t  => "cmp_attr_arm_SwitchJmp",
107         arm_fpaConst_attr_t   => "cmp_attr_arm_fpaConst",
108         arm_load_store_attr_t => "cmp_attr_arm_load_store",
109 );
110
111 #%operands = (
112 #
113 #Immediate => {
114 #       comment   => "blup di dup",
115 #       irn_flags => "R",
116 #       emit      => ". [%S0]-10",
117 #       reg_req   => { },
118 #       attr      => "tarval *tv",
119 #       init_attr => "(void) attri;",
120 #       # op_flags => O
121 #       # cmp => "return 1;"
122 #},
123 #
124 #ShfOp_I => {
125 #       irn_flags => "R",
126 #       emit      => ". ...",
127 #       reg_req   => { in => [ "gp" ] },
128 #       attr      => "tarval *tv",
129 #       init_attr => "(void) tv;",
130 #},
131 #
132 #ShfOp => {
133 #       irn_flags => "R",
134 #       emit      => ". ...",
135 #       reg_req   => { in => [ "gp", "gp" ] },
136 #},
137 #
138 #);
139
140 %nodes = (
141
142 Unknown_GP => {
143         state     => "pinned",
144         op_flags  => "c",
145         reg_req   => { out => [ "gp_UKNWN:I" ] },
146         emit      => "",
147         mode      => $mode_gp,
148 },
149
150 Unknown_FPA => {
151         state     => "pinned",
152         op_flags  => "c",
153         reg_req   => { out => [ "fpa_UKNWN:I" ] },
154         emit      => "",
155         mode      => $mode_fpa,
156 },
157
158 #-----------------------------------------------------------------#
159 #  _       _                                         _            #
160 # (_)     | |                                       | |           #
161 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
162 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
163 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
164 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
165 #                   __/ |                                         #
166 #                  |___/                                          #
167 #-----------------------------------------------------------------#
168
169 # commutative operations
170
171 Add => {
172         op_flags  => "C",
173         irn_flags => "R",
174         comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
175         attr      => "arm_shift_modifier mod, long shf",
176         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
177         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
178         emit      => '. add %D0, %S0, %S1%X'
179 },
180
181 Add_i => {
182         irn_flags => "R",
183         comment   => "construct Add: Add(a, const) = Add(const, a) = a + const",
184         attr      => "long imm",
185         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
186         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
187         emit      => '. add %D0, %S0, %C'
188 },
189
190 Mul => {
191         #op_flags  => "C",
192         irn_flags => "R",
193         comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
194         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
195         emit      =>'. mul %D0, %S0, %S1'
196 },
197
198 Smull => {
199         #op_flags  => "C",
200         irn_flags => "R",
201         comment   => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
202         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
203         emit      =>'. smull %D0, %D1, %S0, %S1',
204         outs      => [ "low", "high" ],
205 },
206
207 Umull => {
208         #op_flags  => "C",
209         irn_flags => "R",
210         comment   => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
211         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
212         emit      =>'. umull %D0, %D1, %S0, %S1',
213         outs      => [ "low", "high" ],
214 },
215
216 Mla => {
217         #op_flags  => "C",
218         irn_flags => "R",
219         comment   => "construct Mla: Mla(a, b, c) = a * b + c",
220         reg_req   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
221         emit      =>'. mla %D0, %S0, %S1, %S2'
222 },
223
224 And => {
225         op_flags  => "C",
226         irn_flags => "R",
227         comment   => "construct And: And(a, b) = And(b, a) = a AND b",
228         attr      => "arm_shift_modifier mod, long shf",
229         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
230         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
231         emit      => '. and %D0, %S0, %S1%X'
232 },
233
234 And_i => {
235         irn_flags => "R",
236         comment   => "construct And: And(a, const) = And(const, a) = a AND const",
237         attr      => "long imm",
238         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
239         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
240         emit      => '. and %D0, %S0, %C',
241 },
242
243 Or => {
244         op_flags  => "C",
245         irn_flags => "R",
246         comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
247         attr      => "arm_shift_modifier mod, long shf",
248         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
249         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
250         emit      => '. orr %D0, %S0, %S1%X'
251 },
252
253 Or_i => {
254         irn_flags => "R",
255         comment   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
256         attr      => "long imm",
257         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
258         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
259         emit      => '. orr %D0, %S0, %C'
260 },
261
262 Eor => {
263         op_flags  => "C",
264         irn_flags => "R",
265         comment   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
266         attr      => "arm_shift_modifier mod, long shf",
267         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
268         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
269         emit      => '. eor %D0, %S0, %S1%X'
270 },
271
272 Eor_i => {
273         irn_flags => "R",
274         comment   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
275         attr      => "long imm",
276         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
277         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
278         emit      => '. eor %D0, %S0, %C'
279 },
280
281 # not commutative operations
282
283 Bic => {
284         irn_flags => "R",
285         comment   => "construct Bic: Bic(a, b) = a AND ~b",
286         attr      => "arm_shift_modifier mod, long shf",
287         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
288         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
289         emit      => '. bic %D0, %S0, %S1%X'
290 },
291
292 Bic_i => {
293         irn_flags => "R",
294         comment   => "construct Bic: Bic(a, const) = a AND ~const",
295         attr      => "long imm",
296         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
297         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
298         emit      => '. bic %D0, %S0, %C',
299 },
300
301 Sub => {
302         irn_flags => "R",
303         comment   => "construct Sub: Sub(a, b) = a - b",
304         attr      => "arm_shift_modifier mod, long shf",
305         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
306         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
307         emit      => '. sub %D0, %S0, %S1%X'
308 },
309
310 Sub_i => {
311         irn_flags => "R",
312         comment   => "construct Sub: Sub(a, const) = a - const",
313         attr      => "long imm",
314         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
315         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
316         emit      => '. sub %D0, %S0, %C',
317 },
318
319 Rsb => {
320         irn_flags => "R",
321         comment   => "construct Rsb: Rsb(a, b) = b - a",
322         attr      => "arm_shift_modifier mod, long shf",
323         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
324         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
325         emit      => '. rsb %D0, %S0, %S1%X'
326 },
327
328 Rsb_i => {
329         irn_flags => "R",
330         comment   => "construct Rsb: Rsb(a, const) = const - a",
331         attr      => "long imm",
332         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
333         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
334         emit      => '. rsb %D0, %S0, %C',
335 },
336
337 Shl => {
338         irn_flags => "R",
339         comment   => "construct Shl: Shl(a, b) = a << b",
340         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
341         emit      => '. mov %D0, %S0, lsl %S1'
342 },
343
344 Shr => {
345         irn_flags => "R",
346         comment   => "construct Shr: Shr(a, b) = a >>u b",
347         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
348         emit      => '. mov %D0, %S0, lsr %S1'
349 },
350
351 Shrs => {
352         irn_flags => "R",
353         comment   => "construct Shrs: Shrs(a, b) = a >>s b",
354         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
355         emit      => '. mov %D0, %S0, asr %S1'
356 },
357
358 Ror => {
359         irn_flags => "R",
360         comment   => "construct Ror: Ror(a, b) = a <<r>> b",
361         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
362         emit      => '. mov %D0, %S0, ror %S1'
363 },
364
365 #RotL => {
366 #  irn_flags => "R",
367 #  comment   => "construct RotL: RotL(a, b) = a ROTL b",
368 #  reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
369 #  emit      => '. rol %S0, %S1, %D0'
370 #},
371
372 #RotL_i => {
373 #       irn_flags => "R",
374 #       comment   => "construct RotL: RotL(a, const) = a ROTL const",
375 #       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
376 #       emit      => '. rol %S0, %C, %D0'
377 #},
378
379 Mov => {
380         irn_flags => "R",
381         comment   => "construct Mov: a = b",
382         attr      => "arm_shift_modifier mod, long shf",
383         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
384         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
385         emit      => '. mov %D0, %S0%X'
386 },
387
388 Mov_i => {
389         irn_flags => "R",
390         comment   => "represents an integer constant",
391         attr      => "long imm",
392         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
393         reg_req   => { "out" => [ "gp" ] },
394         emit      => '. mov %D0, %C',
395 },
396
397 Mvn => {
398         irn_flags => "R",
399         comment   => "construct Not: Not(a) = !a",
400         attr      => "arm_shift_modifier mod, long shf",
401         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
402         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
403         emit      => '. mvn %D0, %S0%X'
404 },
405
406 Mvn_i => {
407         irn_flags => "R",
408         comment   => "represents a negated integer constant",
409         attr      => "long imm",
410         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
411         reg_req   => { "out" => [ "gp" ] },
412         emit      => '. mvn %D0, %C',
413 },
414
415 Abs => {
416         irn_flags => "R",
417         comment   => "construct Abs: Abs(a) = |a|",
418         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
419         emit      =>
420 '. movs %S0, %S0, #0
421 . rsbmi %D0, %S0, #0'
422 },
423
424 # other operations
425
426 #
427 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
428 #
429 EmptyReg => {
430         op_flags  => "c",
431         irn_flags => "R",
432         comment   => "allocate an empty register for calculations",
433         reg_req   => { "out" => [ "gp" ] },
434         emit      => '. /* %D0 now available for calculations */',
435         cmp_attr  => 'return 1;'
436 },
437
438 Copy => {
439         comment  => "implements a register copy",
440         reg_req  => { "in" => [ "gp" ], "out" => [ "gp" ] },
441 },
442
443 CopyB => {
444         op_flags  => "F|H",
445         state     => "pinned",
446         comment   => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
447         attr      => "long imm",
448         init_attr => 'attr->imm_value = imm;',
449         reg_req   => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
450         outs      => [ "M" ],
451 },
452
453 SymConst => {
454         op_flags  => "c",
455         irn_flags => "R",
456         comment   => "represents a symbolic constant",
457         attr      => "ident *id",
458         init_attr => "\tset_arm_symconst_id(res, id);",
459         reg_req   => { "out" => [ "gp" ] },
460         attr_type   => "arm_SymConst_attr_t",
461 },
462
463 CmpBra => {
464         op_flags  => "L|X|Y",
465         state     => "pinned",
466         comment   => "construct conditional branch: CMP A, B && JMPxx LABEL",
467         mode      => "mode_T",
468         attr      => "int proj_num",
469         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
470         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
471         attr_type => "arm_CondJmp_attr_t",
472 },
473
474 TstBra => {
475         op_flags  => "L|X|Y",
476         state     => "pinned",
477         comment   => "construct conditional branch: TST A, B && JMPxx LABEL",
478         mode      => "mode_T",
479         attr      => "int proj_num",
480         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
481         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
482         attr_type => "arm_CondJmp_attr_t",
483 },
484
485 Jmp => {
486         state     => "pinned",
487         op_flags  => "X",
488         irn_flags => "J",
489         reg_req   => { out => [ "none" ] },
490         mode      => "mode_X",
491 },
492
493 SwitchJmp => {
494         op_flags  => "L|X|Y",
495         state     => "pinned",
496         comment   => "construct switch",
497         mode      => "mode_T",
498         attr      => "int n_projs, long def_proj_num",
499         init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
500                      "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
501         reg_req   => { "in" => [ "gp" ], "out" => [ "none" ] },
502         attr_type => "arm_SwitchJmp_attr_t",
503 },
504
505 # Load / Store
506
507 Ldr => {
508         op_flags  => "L|F",
509         state     => "exc_pinned",
510         ins       => [ "ptr", "mem" ],
511         outs      => [ "res", "M" ],
512         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
513         emit      => '. ldr %D0, [%S0, #0]',
514         attr_type => "arm_load_store_attr_t",
515         attr      => "ir_entity *entity, int entity_sign, long offset",
516 },
517
518 Ldrb => {
519         op_flags  => "L|F",
520         state     => "exc_pinned",
521         ins       => [ "ptr", "mem" ],
522         outs      => [ "res", "M" ],
523         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
524         emit      => '. ldrb %D0, [%S0, #0]',
525         attr_type => "arm_load_store_attr_t",
526         attr      => "ir_entity *entity, int entity_sign, long offset",
527 },
528
529 Ldrbs => {
530         op_flags  => "L|F",
531         state     => "exc_pinned",
532         ins       => [ "ptr", "mem" ],
533         outs      => [ "res", "M" ],
534         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
535         emit      => '. ldrsb %D0, [%S0, #0]',
536         attr_type => "arm_load_store_attr_t",
537         attr      => "ir_entity *entity, int entity_sign, long offset",
538 },
539
540 Ldrh => {
541         op_flags  => "L|F",
542         state     => "exc_pinned",
543         ins       => [ "ptr", "mem" ],
544         outs      => [ "res", "M" ],
545         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
546         emit      => '. ldrh %D0, [%S0, #0]',
547         attr_type => "arm_load_store_attr_t",
548         attr      => "ir_entity *entity, int entity_sign, long offset",
549 },
550
551 Ldrhs => {
552         op_flags  => "L|F",
553         state     => "exc_pinned",
554         ins       => [ "ptr", "mem" ],
555         outs      => [ "res", "M" ],
556         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
557         emit      => '. ldrsh %D0, [%S0, #0]',
558         attr_type => "arm_load_store_attr_t",
559         attr      => "ir_entity *entity, int entity_sign, long offset",
560 },
561
562 Strb => {
563         op_flags  => "L|F",
564         state     => "exc_pinned",
565         ins       => [ "ptr", "val", "mem" ],
566         outs      => [ "mem" ],
567         reg_req   => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
568         emit      => '. strb %S1, [%S0, #0]',
569         mode      => "mode_M",
570         attr_type => "arm_load_store_attr_t",
571         attr      => "ir_entity *entity, int entity_sign, long offset",
572 },
573
574 Strh => {
575         op_flags  => "L|F",
576         state     => "exc_pinned",
577         ins       => [ "ptr", "val", "mem" ],
578         outs      => [ "mem" ],
579         reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
580         emit      => '. strh %S1, [%S0, #0]',
581         mode      => "mode_M",
582         attr_type => "arm_load_store_attr_t",
583         attr      => "ir_entity *entity, int entity_sign, long offset",
584 },
585
586 Str => {
587         op_flags  => "L|F",
588         state     => "exc_pinned",
589         ins       => [ "ptr", "val", "mem" ],
590         outs      => [ "mem" ],
591         reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
592         emit      => '. str %S1, [%S0, #0]',
593         mode      => "mode_M",
594         attr_type => "arm_load_store_attr_t",
595         attr      => "ir_entity *entity, int entity_sign, long offset",
596 },
597
598 StoreStackM4Inc => {
599         op_flags  => "L|F",
600         irn_flags => "R",
601         state     => "exc_pinned",
602         comment   => "construct Store: Push 4 Registers = ST ptr,val",
603         reg_req   => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "sp:I|S", "none" ] },
604         emit      => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
605         outs      => [ "ptr", "M" ],
606 },
607
608 LoadStackM3Epilogue => {
609         op_flags  => "L|F",
610         irn_flags => "R",
611         state     => "exc_pinned",
612         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
613         reg_req   => { "in" => [ "sp", "none" ], "out" => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
614         emit      => '. ldmfd %S0, {%D0, %D1, %D2}',
615         outs      => [ "res0", "res1", "res2", "M" ],
616 },
617
618
619 #---------------------------------------------------#
620 #    __                               _             #
621 #   / _|                             | |            #
622 #  | |_ _ __   __ _   _ __   ___   __| | ___  ___   #
623 #  |  _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __|  #
624 #  | | | |_) | (_| | | | | | (_) | (_| |  __/\__ \  #
625 #  |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/  #
626 #      | |                                          #
627 #      |_|                                          #
628 #---------------------------------------------------#
629
630 # commutative operations
631
632 fpaAdf => {
633         op_flags  => "C",
634         irn_flags => "R",
635         comment   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
636         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
637         emit      => '. adf%M %D0, %S0, %S1',
638 },
639
640 fpaAdf_i => {
641         irn_flags => "R",
642         comment   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
643         attr      => "long imm",
644         init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
645         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
646         emit      => '. adf%M %D0, %S0, %C',
647 },
648
649 fpaMuf => {
650         op_flags  => "C",
651         irn_flags => "R",
652         comment   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
653         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
654         emit      =>'. muf%M %D0, %S0, %S1',
655 },
656
657 fpaMuf_i => {
658         irn_flags => "R",
659         comment   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
660         attr      => "long imm",
661         init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
662         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
663         emit      => '. muf%M %D0, %S0, %C',
664 },
665
666 fpaFml => {
667         op_flags  => "C",
668         irn_flags => "R",
669         comment   => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
670         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
671         emit      =>'. fml%M %D0, %S0, %S1',
672 },
673
674 fpaMax => {
675         op_flags  => "C",
676         irn_flags => "R",
677         comment   => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
678         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
679         emit      =>'. fmax %S0, %S1, %D0',
680 },
681
682 fpaMin => {
683         op_flags  => "C",
684         irn_flags => "R",
685         comment   => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
686         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
687         emit      =>'. fmin %S0, %S1, %D0',
688 },
689
690 # not commutative operations
691
692 fpaSuf => {
693         irn_flags => "R",
694         comment   => "construct FPA Sub: Sub(a, b) = a - b",
695         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
696         emit      => '. suf%M %D0, %S0, %S1'
697 },
698
699 fpaSuf_i => {
700         irn_flags => "R",
701         comment   => "construct FPA Sub: Sub(a, b) = a - b",
702         attr      => "long imm",
703         init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
704         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
705         emit      => '. suf%M %D0, %S0, %C'
706 },
707
708 fpaRsf => {
709         irn_flags => "R",
710         comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
711         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
712         emit      => '. rsf%M %D0, %S0, %S1'
713 },
714
715 fpaRsf_i => {
716         irn_flags => "R",
717         comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
718         attr      => "long imm",
719         init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
720         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
721         emit      => '. rsf%M %D0, %S0, %C'
722 },
723
724 fpaDvf => {
725         comment   => "construct FPA Div: Div(a, b) = a / b",
726         attr      => "ir_mode *op_mode",
727         init_attr => "attr->op_mode = op_mode;",
728         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
729         emit      =>'. dvf%M %D0, %S0, %S1',
730         outs      => [ "res", "M" ],
731 },
732
733 fpaDvf_i => {
734         comment   => "construct FPA Div: Div(a, b) = a / b",
735         attr      => "ir_mode *op_mode, long imm",
736         init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
737         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
738         emit      =>'. dvf%M %D0, %S0, %C',
739         outs      => [ "res", "M" ],
740 },
741
742 fpaRdf => {
743         comment   => "construct FPA reverse Div: Div(a, b) = b / a",
744         attr      => "ir_mode *op_mode",
745         init_attr => "attr->op_mode = op_mode;",
746         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
747         emit      =>'. rdf%M %D0, %S0, %S1',
748         outs      => [ "res", "M" ],
749 },
750
751 fpaRdf_i => {
752         comment   => "construct FPA reverse Div: Div(a, b) = b / a",
753         attr      => "ir_mode *op_mode, long imm",
754         init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
755         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
756         emit      =>'. rdf%M %D0, %S0, %S1',
757         outs      => [ "res", "M" ],
758 },
759
760 fpaFdv => {
761         comment   => "construct FPA Fast Div: Div(a, b) = a / b",
762         attr      => "ir_mode *op_mode",
763         init_attr => "attr->op_mode = op_mode;",
764         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
765         emit      =>'. fdv%M %D0, %S0, %S1',
766         outs      => [ "res", "M" ],
767 },
768
769 fpaFdv_i => {
770         comment   => "construct FPA Fast Div: Div(a, b) = a / b",
771         attr      => "ir_mode *op_mode, long imm",
772         init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
773         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
774         emit      =>'. fdv%M %D0, %S0, %C',
775         outs      => [ "res", "M" ],
776 },
777
778 fpaFrd => {
779         comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
780         attr      => "ir_mode *op_mode",
781         init_attr => "attr->op_mode = op_mode;",
782         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
783         emit      =>'. frd%M %D0, %S0, %S1',
784         outs      => [ "res", "M" ],
785 },
786
787 fpaFrd_i => {
788         comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
789         attr      => "ir_mode *op_mode, long imm",
790         init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
791         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
792         emit      =>'. frd%M %D0, %S0, %C',
793         outs      => [ "res", "M" ],
794 },
795
796 fpaMvf => {
797         irn_flags => "R",
798         comment   => "construct FPA Move: b = a",
799         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
800         emit      => '. mvf%M %S0, %D0',
801 },
802
803 fpaMvf_i => {
804         irn_flags => "R",
805         comment   => "represents a float constant",
806         attr      => "long imm",
807         init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
808         reg_req   => { "out" => [ "fpa" ] },
809         emit      => '. mvf%M %D0, %C',
810 },
811
812 fpaMnf => {
813         irn_flags => "R",
814         comment   => "construct FPA Move Negated: b = -a",
815         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
816         emit      => '. mnf%M %S0, %D0',
817 },
818
819 fpaMnf_i => {
820         irn_flags => "R",
821         comment   => "represents a float constant",
822         attr      => "long imm",
823         init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
824         reg_req   => { "out" => [ "fpa" ] },
825         emit      => '. mnf%M %D0, %C',
826 },
827
828 fpaAbs => {
829         irn_flags => "R",
830         comment   => "construct FPA Absolute value: fAbsd(a) = |a|",
831         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
832         emit      => '. abs%M %D0, %S0',
833 },
834
835 # other operations
836
837 fpaFlt => {
838         irn_flags => "R",
839         comment   => "construct a FPA integer->float conversion",
840         reg_req   => { "in" => ["gp"], "out" => [ "fpa" ] },
841         emit      => '. flt%M %D0, %S0',
842 },
843
844 fpaFix => {
845         irn_flags => "R",
846         comment   => "construct a FPA float->integer conversion",
847         reg_req   => { "in" => ["fpa"], "out" => [ "gp" ] },
848         emit      => '. fix %D0, %S0',
849 },
850
851 fpaCmfBra => {
852         op_flags  => "L|X|Y",
853         state     => "pinned",
854         comment   => "construct floating point Compare and Branch: CMF A, B && JMPxx LABEL",
855         mode      => "mode_T",
856         attr      => "int proj_num",
857         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
858         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
859         attr_type => "arm_CondJmp_attr_t",
860 },
861
862 fpaCnfBra => {
863         op_flags  => "L|X|Y",
864         state     => "pinned",
865         comment   => "construct floating point Compare negative and Branch: CMF A, -B && JMPxx LABEL",
866         mode      => "mode_T",
867         attr      => "int proj_num",
868         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
869         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
870         attr_type => "arm_CondJmp_attr_t",
871 },
872
873 fpaCmfeBra => {
874         op_flags  => "L|X|Y",
875         state     => "pinned",
876         comment   => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL",
877         mode      => "mode_T",
878         attr      => "int proj_num",
879         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
880         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
881         attr_type => "arm_CondJmp_attr_t",
882 },
883
884 fpaCnfeBra => {
885         op_flags  => "L|X|Y",
886         state     => "pinned",
887         comment   => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL",
888         mode      => "mode_T",
889         attr      => "int proj_num",
890         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
891         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
892         attr_type => "arm_CondJmp_attr_t",
893 },
894
895 # Load / Store
896
897 fpaLdf => {
898         op_flags  => "L|F",
899         irn_flags => "R",
900         state     => "exc_pinned",
901         comment   => "construct FPA Load: Load(ptr, mem) = LD ptr",
902         attr      => "ir_mode *op_mode",
903         init_attr => "attr->op_mode = op_mode;",
904         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
905         emit      => '. ldf%M %D0, [%S0]',
906         outs      => [ "res", "M" ],
907 },
908
909 fpaStf => {
910         op_flags  => "L|F",
911         irn_flags => "R",
912         state     => "exc_pinned",
913         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
914         attr      => "ir_mode *op_mode",
915         init_attr => "attr->op_mode = op_mode;",
916         reg_req   => { "in" => [ "gp", "fpa", "none" ], "out" => [ "none" ] },
917         emit      => '. stf%M %S1, [%S0]',
918         mode      => "mode_M",
919 },
920
921 fpaDbl2GP => {
922         op_flags  => "L|F",
923         irn_flags => "R",
924         comment   => "construct fp double to 2 gp register transfer",
925         reg_req   => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] },
926         outs      => [ "low", "high", "M" ],
927 },
928
929 AddSP => {
930         comment   => "construct Add to stack pointer",
931         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
932         emit      => '. add %D0, %S0, %S1',
933         outs      => [ "stack", "M" ],
934 },
935
936 SubSPandCopy => {
937         comment   => "construct Sub from stack pointer and copy to Register",
938         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
939         ins       => [ "stack", "size", "mem" ],
940         emit      => ". sub %D0, %S0, %S1\n".
941                      ". mov sp, %D1",
942         outs      => [ "stack", "addr", "M" ],
943 },
944
945 LdTls => {
946         irn_flags => "R",
947         comment   => "load the TLS address",
948         reg_req   => { out => [ "gp" ] },
949 },
950
951
952 #
953 # floating point constants
954 #
955 fpaConst => {
956         op_flags  => "c",
957         irn_flags => "R",
958         comment   => "construct a floating point constant",
959         attr      => "tarval *tv",
960         init_attr => "attr->tv = tv;",
961         mode      => "get_tarval_mode(tv)",
962         reg_req   => { "out" => [ "fpa" ] },
963         attr_type => "arm_fpaConst_attr_t",
964 }
965
966 #---------------------------------------------------#
967 #          __                         _             #
968 #         / _|                       | |            #
969 #  __   _| |_ _ __    _ __   ___   __| | ___  ___   #
970 #  \ \ / /  _| '_ \  | '_ \ / _ \ / _` |/ _ \/ __|  #
971 #   \ V /| | | |_) | | | | | (_) | (_| |  __/\__ \  #
972 #    \_/ |_| | .__/  |_| |_|\___/ \__,_|\___||___/  #
973 #            | |                                    #
974 #            |_|                                    #
975 #---------------------------------------------------#
976
977 ); # end of %nodes