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