fixed syntax of fpa ldf/stf instructions
[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 # The node description is done as a perl hash initializer with the
14 # following structure:
15 #
16 # %nodes = (
17 #
18 # <op-name> => {
19 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
20 #   irn_flags => "R|N|I|S"
21 #   arity     => "0|1|2|3 ... |variable|dynamic|any",
22 #   state     => "floats|pinned|mem_pinned|exc_pinned",
23 #   args      => [
24 #                    { type => "type 1", name => "name 1" },
25 #                    { type => "type 2", name => "name 2" },
26 #                    ...
27 #                  ],
28 #   comment   => "any comment for constructor",
29 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
30 #   cmp_attr  => "c source code for comparing node attributes",
31 #   emit      => "emit code with templates",
32 #   attr      => "attitional attribute arguments for constructor"
33 #   init_attr => "emit attribute initialization template"
34 #   rd_constructor => "c source code which constructs an ir_node"
35 #   latency   => "latency of this operation (can be float)"
36 #   attr_type => "name of the attribute struct",
37 # },
38 #
39 # ... # (all nodes you need to describe)
40 #
41 # ); # close the %nodes initializer
42
43 # op_flags: flags for the operation, OPTIONAL (default is "N")
44 # the op_flags correspond to the firm irop_flags:
45 #   N   irop_flag_none
46 #   L   irop_flag_labeled
47 #   C   irop_flag_commutative
48 #   X   irop_flag_cfopcode
49 #   I   irop_flag_ip_cfopcode
50 #   F   irop_flag_fragile
51 #   Y   irop_flag_forking
52 #   H   irop_flag_highlevel
53 #   c   irop_flag_constlike
54 #   K   irop_flag_keep
55 #
56 # irn_flags: special node flags, OPTIONAL (default is 0)
57 # following irn_flags are supported:
58 #   R   rematerializeable
59 #   N   not spillable
60 #   I   ignore for register allocation
61 #   S   modifies stack pointer
62 #
63 # state: state of the operation, OPTIONAL (default is "floats")
64 #
65 # arity: arity of the operation, MUST NOT BE OMITTED
66 #
67 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
68 #        are always the first 3 arguments and are always autmatically
69 #        created)
70 #        If this key is missing the following arguments will be created:
71 #        for i = 1 .. arity: ir_node *op_i
72 #        ir_mode *mode
73 #
74 # outs:  if a node defines more than one output, the names of the projections
75 #        nodes having outs having automatically the mode mode_T
76 #        One can also annotate some flags for each out, additional to irn_flags.
77 #        They are separated from name with a colon ':', and concatenated by pipe '|'
78 #        Only I and S are available at the moment (same meaning as in irn_flags).
79 #        example: [ "frame:I", "stack:I|S", "M" ]
80 #
81 # comment: OPTIONAL comment for the node constructor
82 #
83 # rd_constructor: for every operation there will be a
84 #      new_rd_<arch>_<op-name> function with the arguments from above
85 #      which creates the ir_node corresponding to the defined operation
86 #      you can either put the complete source code of this function here
87 #
88 #      This key is OPTIONAL. If omitted, the following constructor will
89 #      be created:
90 #      if (!op_<arch>_<op-name>) assert(0);
91 #      for i = 1 to arity
92 #         set in[i] = op_i
93 #      done
94 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
95 #      return res
96 #
97 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
98 #
99 # latency: the latency of the operation, default is 1
100 #
101
102 #
103 # Modes
104 #
105 $mode_gp      = "mode_Iu";
106 $mode_fpa     = "mode_E";
107
108 # register types:
109 #   0 - no special type
110 #   1 - caller save (register must be saved by the caller of a function)
111 #   2 - callee save (register must be saved by the called function)
112 #   4 - ignore (do not assign this register)
113 #   8 - emitter can choose an arbitrary register of this class
114 #  16 - the register is a virtual one
115 #  32 - register represents a state
116 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
117 %reg_classes = (
118         gp => [
119                 { "name" => "r0", "type" => 1 },
120                 { "name" => "r1", "type" => 1 },
121                 { "name" => "r2", "type" => 1 },
122                 { "name" => "r3", "type" => 1 },
123                 { "name" => "r4", "type" => 2 },
124                 { "name" => "r5", "type" => 2 },
125                 { "name" => "r6", "type" => 2 },
126                 { "name" => "r7", "type" => 2 },
127                 { "name" => "r8", "type" => 2 },
128                 { "name" => "r9", "type" => 2 },
129                 { "name" => "r10", "type" => 2 },
130                 { "name" => "r11", "type" => 2 },
131                 { "name" => "r12", "type" => 6 }, # reserved for linker
132                 { "name" => "sp", "type" => 6 }, # this is our stack pointer
133                 { "name" => "lr", "type" => 3 }, # this is our return address
134                 { "name" => "pc", "type" => 6 }, # this is our program counter
135                 { name => "gp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
136                 { "mode" => $mode_gp }
137         ],
138         fpa  => [
139                 { "name" => "f0", "type" => 1 },
140                 { "name" => "f1", "type" => 1 },
141                 { "name" => "f2", "type" => 1 },
142                 { "name" => "f3", "type" => 1 },
143                 { "name" => "f4", "type" => 1 },
144                 { "name" => "f5", "type" => 1 },
145                 { "name" => "f6", "type" => 1 },
146                 { "name" => "f7", "type" => 1 },
147                 { name => "fpa_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
148                 { "mode" => $mode_fpa }
149         ]
150 ); # %reg_classes
151
152 %emit_templates = (
153         M  => "${arch}_emit_mode(env, node);",
154         X  => "${arch}_emit_shift(env, node);",
155         S0 => "${arch}_emit_source_register(env, node, 0);",
156         S1 => "${arch}_emit_source_register(env, node, 1);",
157         S2 => "${arch}_emit_source_register(env, node, 2);",
158         S3 => "${arch}_emit_source_register(env, node, 3);",
159         S4 => "${arch}_emit_source_register(env, node, 4);",
160         D0 => "${arch}_emit_dest_register(env, node, 0);",
161         D1 => "${arch}_emit_dest_register(env, node, 1);",
162         D2 => "${arch}_emit_dest_register(env, node, 2);",
163         C  => "${arch}_emit_immediate(env, node);",
164         O  => "${arch}_emit_offset(env, mode);",
165 );
166
167 #--------------------------------------------------#
168 #                        _                         #
169 #                       (_)                        #
170 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
171 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
172 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
173 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
174 #                                      | |         #
175 #                                      |_|         #
176 #--------------------------------------------------#
177
178 $default_attr_type = "arm_attr_t";
179
180 %init_attr = (
181         arm_attr_t           => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
182         arm_SymConst_attr_t  => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
183         arm_CondJmp_attr_t   => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
184         arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
185 );
186
187 %compare_attr = (
188         arm_attr_t           => "cmp_attr_arm",
189         arm_SymConst_attr_t  => "cmp_attr_arm_SymConst",
190         arm_CondJmp_attr_t   => "cmp_attr_arm_CondJmp",
191         arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
192 );
193
194 #%operands = (
195 #
196 #Immediate => {
197 #       comment   => "blup di dup",
198 #       irn_flags => "R",
199 #       emit      => ". [%S0]-10",
200 #       reg_req   => { },
201 #       attr      => "tarval *tv",
202 #       init_attr => "(void) attri;",
203 #       # op_flags => O
204 #       # cmp => "return 1;"
205 #},
206 #
207 #ShfOp_I => {
208 #       irn_flags => "R",
209 #       emit      => ". ...",
210 #       reg_req   => { in => [ "gp" ] },
211 #       attr      => "tarval *tv",
212 #       init_attr => "(void) tv;",
213 #},
214 #
215 #ShfOp => {
216 #       irn_flags => "R",
217 #       emit      => ". ...",
218 #       reg_req   => { in => [ "gp", "gp" ] },
219 #},
220 #
221 #);
222
223 %nodes = (
224
225 Unknown_GP => {
226         state     => "pinned",
227         op_flags  => "c",
228         irn_flags => "I",
229         reg_req   => { out => [ "gp_UKNWN" ] },
230         emit      => "",
231         mode      => $mode_gp,
232 },
233
234 Unknown_FPA => {
235         state     => "pinned",
236         op_flags  => "c",
237         irn_flags => "I",
238         reg_req   => { out => [ "fpa_UKNWN" ] },
239         emit      => "",
240         mode      => $mode_fpa,
241 },
242
243 #-----------------------------------------------------------------#
244 #  _       _                                         _            #
245 # (_)     | |                                       | |           #
246 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
247 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
248 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
249 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
250 #                   __/ |                                         #
251 #                  |___/                                          #
252 #-----------------------------------------------------------------#
253
254 # commutative operations
255
256 Add => {
257         op_flags  => "C",
258         irn_flags => "R",
259         comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
260         attr      => "arm_shift_modifier mod, tarval *shf",
261         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
262         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
263         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
264         emit      => '. add %D0, %S0, %S1%X'
265 },
266
267 Add_i => {
268         irn_flags => "R",
269         comment   => "construct Add: Add(a, const) = Add(const, a) = a + const",
270         attr      => "tarval *tv",
271         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
272         cmp_attr  => 'return attr_a->value != attr_b->value;',
273         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
274         emit      => '. add %D0, %S0, %C'
275 },
276
277 Mul => {
278         #op_flags  => "C",
279         irn_flags => "R",
280         comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
281         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
282         emit      =>'. mul %D0, %S0, %S1'
283 },
284
285 Smull => {
286         #op_flags  => "C",
287         irn_flags => "R",
288         comment   => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
289         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
290         emit      =>'. smull %D0, %D1, %S0, %S1',
291         outs      => [ "low", "high" ],
292 },
293
294 Umull => {
295         #op_flags  => "C",
296         irn_flags => "R",
297         comment   => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
298         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
299         emit      =>'. umull %D0, %D1, %S0, %S1',
300         outs      => [ "low", "high" ],
301 },
302
303 Mla => {
304         #op_flags  => "C",
305         irn_flags => "R",
306         comment   => "construct Mla: Mla(a, b, c) = a * b + c",
307         reg_req   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
308         emit      =>'. mla %D0, %S0, %S1, %S2'
309 },
310
311 And => {
312         op_flags  => "C",
313         irn_flags => "R",
314         comment   => "construct And: And(a, b) = And(b, a) = a AND b",
315         attr      => "arm_shift_modifier mod, tarval *shf",
316         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
317         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
318         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
319         emit      => '. and %D0, %S0, %S1%X'
320 },
321
322 And_i => {
323         irn_flags => "R",
324         comment   => "construct And: And(a, const) = And(const, a) = a AND const",
325         attr      => "tarval *tv",
326         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
327         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
328         emit      => '. and %D0, %S0, %C',
329         cmp_attr  => 'return attr_a->value != attr_b->value;'
330 },
331
332 Or => {
333         op_flags  => "C",
334         irn_flags => "R",
335         comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
336         attr      => "arm_shift_modifier mod, tarval *shf",
337         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
338         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
339         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
340         emit      => '. orr %D0, %S0, %S1%X'
341 },
342
343 Or_i => {
344         irn_flags => "R",
345         comment   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
346         attr      => "tarval *tv",
347         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
348         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
349         cmp_attr  => 'return attr_a->value != attr_b->value;',
350         emit      => '. orr %D0, %S0, %C'
351 },
352
353 Eor => {
354         op_flags  => "C",
355         irn_flags => "R",
356         comment   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
357         attr      => "arm_shift_modifier mod, tarval *shf",
358         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
359         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
360         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
361         emit      => '. eor %D0, %S0, %S1%X'
362 },
363
364 Eor_i => {
365         irn_flags => "R",
366         comment   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
367         attr      => "tarval *tv",
368         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
369         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
370         cmp_attr  => 'return attr_a->value != attr_b->value;',
371         emit      => '. eor %D0, %S0, %C'
372 },
373
374 # not commutative operations
375
376 Bic => {
377         irn_flags => "R",
378         comment   => "construct Bic: Bic(a, b) = a AND ~b",
379         attr      => "arm_shift_modifier mod, tarval *shf",
380         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
381         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
382         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
383         emit      => '. bic %D0, %S0, %S1%X'
384 },
385
386 Bic_i => {
387         irn_flags => "R",
388         comment   => "construct Bic: Bic(a, const) = a AND ~const",
389         attr      => "tarval *tv",
390         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
391         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
392         emit      => '. bic %D0, %S0, %C',
393         cmp_attr  => 'return attr_a->value != attr_b->value;'
394 },
395
396 Sub => {
397         irn_flags => "R",
398         comment   => "construct Sub: Sub(a, b) = a - b",
399         attr      => "arm_shift_modifier mod, tarval *shf",
400         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
401         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
402         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
403         emit      => '. sub %D0, %S0, %S1%X'
404 },
405
406 Sub_i => {
407         irn_flags => "R",
408         comment   => "construct Sub: Sub(a, const) = a - const",
409         attr      => "tarval *tv",
410         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
411         cmp_attr  => 'return attr_a->value != attr_b->value;',
412         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
413         emit      => '. sub %D0, %S0, %C',
414 },
415
416 Rsb => {
417         irn_flags => "R",
418         comment   => "construct Rsb: Rsb(a, b) = b - a",
419         attr      => "arm_shift_modifier mod, tarval *shf",
420         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
421         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
422         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
423         emit      => '. rsb %D0, %S0, %S1%X'
424 },
425
426 Rsb_i => {
427         irn_flags => "R",
428         comment   => "construct Rsb: Rsb(a, const) = const - a",
429         attr      => "tarval *tv",
430         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
431         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
432         emit      => '. rsb %D0, %S0, %C',
433         cmp_attr  => 'return attr_a->value != attr_b->value;'
434 },
435
436 Shl => {
437         irn_flags => "R",
438         comment   => "construct Shl: Shl(a, b) = a << b",
439         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
440         emit      => '. mov %D0, %S0, lsl %S1'
441 },
442
443 Shr => {
444         irn_flags => "R",
445         comment   => "construct Shr: Shr(a, b) = a >> b",
446         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
447         emit      => '. mov %D0, %S0, lsr %S1'
448 },
449
450 Shrs => {
451         irn_flags => "R",
452         comment   => "construct Shrs: Shrs(a, b) = a >> b",
453         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
454         emit      => '. mov %D0, %S0, asr %S1'
455 },
456
457 #RotR => {
458 #       irn_flags => "R",
459 #       comment   => "construct RotR: RotR(a, b) = a ROTR b",
460 #       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
461 #       emit      => '. mov %D0, %S0, ror %S1 /* RotR(%S0, %S1) -> %D0, (%A1, %A2) */'
462 ##      emit      => '. ror %S0, %S1, %D0'
463 #},
464
465 #RotL => {
466 #  irn_flags => "R",
467 #  comment   => "construct RotL: RotL(a, b) = a ROTL b",
468 #  reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
469 #  emit      => '. rol %S0, %S1, %D0'
470 #},
471
472 #RotL_i => {
473 #       irn_flags => "R",
474 #       comment   => "construct RotL: RotL(a, const) = a ROTL const",
475 #       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
476 #       emit      => '. rol %S0, %C, %D0'
477 #},
478
479 Mov => {
480         irn_flags => "R",
481         comment   => "construct Mov: a = b",
482         attr      => "arm_shift_modifier mod, tarval *shf",
483         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
484         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
485         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
486         emit      => '. mov %D0, %S0%X'
487 },
488
489 Mov_i => {
490         irn_flags => "R",
491         comment   => "represents an integer constant",
492         attr      => "tarval *tv",
493         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
494         reg_req   => { "out" => [ "gp" ] },
495         emit      => '. mov %D0, %C',
496         cmp_attr  => 'return attr_a->value != attr_b->value;'
497 },
498
499 Mvn => {
500         irn_flags => "R",
501         comment   => "construct Not: Not(a) = !a",
502         attr      => "arm_shift_modifier mod, tarval *shf",
503         init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
504         cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
505         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
506         emit      => '. mvn %D0, %S0%X'
507 },
508
509 Mvn_i => {
510         irn_flags => "R",
511         comment   => "represents a negated integer constant",
512         attr      => "tarval *tv",
513         init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
514         cmp_attr  => 'return attr_a->value != attr_b->value;',
515         reg_req   => { "out" => [ "gp" ] },
516         emit      => '. mvn %D0, %C',
517 },
518
519 Abs => {
520         irn_flags => "R",
521         comment   => "construct Abs: Abs(a) = |a|",
522         reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
523         emit      =>
524 '. movs %S0, %S0, #0
525 . rsbmi %D0, %S0, #0'
526 },
527
528 # other operations
529
530 #
531 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
532 #
533 EmptyReg => {
534         op_flags  => "c",
535         irn_flags => "R",
536         comment   => "allocate an empty register for calculations",
537         reg_req   => { "out" => [ "gp" ] },
538         emit      => '. /* %D0 now available for calculations */',
539         cmp_attr  => 'return 1;'
540 },
541
542 Copy => {
543         comment  => "implements a register copy",
544         reg_req  => { "in" => [ "gp" ], "out" => [ "gp" ] },
545 },
546
547 CopyB => {
548         op_flags  => "F|H",
549         state     => "pinned",
550         comment   => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
551         attr      => "tarval *tv",
552         init_attr => 'attr->value = tv;',
553         reg_req   => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
554         outs      => [ "M" ],
555 },
556
557 SymConst => {
558         op_flags  => "c",
559         irn_flags => "R",
560         comment   => "represents a symbolic constant",
561         attr      => "ident *id",
562         init_attr => "\tset_arm_symconst_id(res, id);",
563         reg_req   => { "out" => [ "gp" ] },
564         attr_type   => "arm_SymConst_attr_t",
565 },
566
567 CondJmp => {
568         op_flags  => "L|X|Y",
569         state     => "pinned",
570         comment   => "construct conditional jump: CMP A, B && JMPxx LABEL",
571         mode      => "mode_T",
572         attr      => "int proj_num",
573         init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
574         reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
575         attr_type => "arm_CondJmp_attr_t",
576 },
577
578 SwitchJmp => {
579         op_flags  => "L|X|Y",
580         state     => "pinned",
581         comment   => "construct switch",
582         mode      => "mode_T",
583         attr      => "int n_projs, long def_proj_num",
584         init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
585                      "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
586         reg_req   => { "in" => [ "gp" ], "out" => [ "none" ] },
587         attr_type => "arm_SwitchJmp_attr_t",
588 },
589
590 # Load / Store
591
592 Load => {
593         op_flags  => "L|F",
594         irn_flags => "R",
595         state     => "exc_pinned",
596         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
597         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
598         emit      => '. ldr %D0, [%S0, #0]',
599         outs      => [ "res", "M" ],
600 },
601
602 Loadb => {
603         op_flags  => "L|F",
604         irn_flags => "R",
605         state     => "exc_pinned",
606         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
607         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
608         emit      => '. ldrb %D0, [%S0, #0]',
609         outs      => [ "res", "M" ],
610 },
611
612 Loadbs => {
613         op_flags  => "L|F",
614         irn_flags => "R",
615         state     => "exc_pinned",
616         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
617         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
618         emit      => '. ldrsb %D0, [%S0, #0]',
619         outs      => [ "res", "M" ],
620 },
621
622 Loadh => {
623         op_flags  => "L|F",
624         irn_flags => "R",
625         state     => "exc_pinned",
626         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
627         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
628         emit      => '. ldrh %D0, [%S0, #0]',
629         outs      => [ "res", "M" ],
630 },
631
632 Loadhs => {
633         op_flags  => "L|F",
634         irn_flags => "R",
635         state     => "exc_pinned",
636         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
637         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
638         emit      => '. ldrsh %D0, [%S0, #0]',
639         outs      => [ "res", "M" ],
640 },
641
642 Storeb => {
643         op_flags  => "L|F",
644         irn_flags => "R",
645         state     => "exc_pinned",
646         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
647         reg_req   => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
648         emit      => '. strb %S1, [%S0, #0]',
649         mode      => "mode_M",
650 },
651
652 Storeh => {
653         op_flags  => "L|F",
654         irn_flags => "R",
655         state     => "exc_pinned",
656         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
657         reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
658         emit      => '. strh %S1, [%S0, #0]',
659         mode      => "mode_M",
660 },
661
662 Store => {
663         op_flags  => "L|F",
664         irn_flags => "R",
665         state     => "exc_pinned",
666         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
667         reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
668         emit      => '. str %S1, [%S0, #0]',
669         mode      => "mode_M",
670 },
671
672 StoreStackM4Inc => {
673         op_flags  => "L|F",
674         irn_flags => "R",
675         state     => "exc_pinned",
676         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
677         reg_req   => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
678         emit      => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
679         outs      => [ "ptr", "M" ],
680 },
681
682 LoadStackM3 => {
683         op_flags  => "L|F",
684         irn_flags => "R",
685         state     => "exc_pinned",
686         comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
687         reg_req   => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] },
688         emit      => '. ldmfd %S0, {%D0, %D1, %D2}',
689         outs      => [ "res0", "res1", "res2", "M" ],
690 },
691
692
693 #---------------------------------------------------#
694 #    __                               _             #
695 #   / _|                             | |            #
696 #  | |_ _ __   __ _   _ __   ___   __| | ___  ___   #
697 #  |  _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __|  #
698 #  | | | |_) | (_| | | | | | (_) | (_| |  __/\__ \  #
699 #  |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/  #
700 #      | |                                          #
701 #      |_|                                          #
702 #---------------------------------------------------#
703
704 # commutative operations
705
706 fpaAdd => {
707         op_flags  => "C",
708         irn_flags => "R",
709         comment   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
710         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
711         emit      => '. adf%M %D0, %S0, %S1',
712 },
713
714 fpaMul => {
715         op_flags  => "C",
716         comment   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
717         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
718         emit      =>'. muf%M %D0, %S0, %S1',
719 },
720
721 fpaFMul => {
722         op_flags  => "C",
723         comment   => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
724         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
725         emit      =>'. fml%M %D0, %S0, %S1',
726 },
727
728 fpaMax => {
729         op_flags  => "C",
730         irn_flags => "R",
731         comment   => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
732         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
733         emit      =>'. fmax %S0, %S1, %D0',
734 },
735
736 fpaMin => {
737         op_flags  => "C",
738         irn_flags => "R",
739         comment   => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
740         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
741         emit      =>'. fmin %S0, %S1, %D0',
742 },
743
744 # not commutative operations
745
746 fpaSub => {
747         irn_flags => "R",
748         comment   => "construct FPA Sub: Sub(a, b) = a - b",
749         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
750         emit      => '. suf%M %D0, %S0, %S1'
751 },
752
753 fpaRsb => {
754         irn_flags => "R",
755         comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
756         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
757         emit      => '. rsf%M %D0, %S0, %S1'
758 },
759
760 fpaDiv => {
761         comment   => "construct FPA 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      =>'. dvf%M %D0, %S0, %S1',
766         outs      => [ "res", "M" ],
767 },
768
769 fpaRdv => {
770         comment   => "construct FPA reverse Div: Div(a, b) = b / a",
771         attr      => "ir_mode *op_mode",
772         init_attr => "attr->op_mode = op_mode;",
773         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
774         emit      =>'. rdf%M %D0, %S0, %S1',
775         outs      => [ "res", "M" ],
776 },
777
778 fpaFDiv => {
779         comment   => "construct FPA Fast Div: Div(a, b) = a / b",
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      =>'. fdv%M %D0, %S0, %S1',
784         outs      => [ "res", "M" ],
785 },
786
787 fpaFRdv => {
788         comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
789         attr      => "ir_mode *op_mode",
790         init_attr => "attr->op_mode = op_mode;",
791         reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
792         emit      =>'. frd%M %D0, %S0, %S1',
793         outs      => [ "res", "M" ],
794 },
795
796 fpaMov => {
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 fpaMnv => {
804         irn_flags => "R",
805         comment   => "construct FPA Move Negated: b = -a",
806         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
807         emit      => '. mnf%M %S0, %D0',
808 },
809
810 fpaAbs => {
811         irn_flags => "R",
812         comment   => "construct FPA Absolute value: fAbsd(a) = |a|",
813         reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
814         emit      => '. abs%M %D0, %S0',
815 },
816
817 # other operations
818
819 fpaFlt => {
820         irn_flags => "R",
821         comment   => "construct a FPA integer->float conversion",
822         reg_req   => { "in" => ["gp"], "out" => [ "fpa" ] },
823         emit      => '. flt%M %D0, %S0',
824 },
825
826 fpaFix => {
827         irn_flags => "R",
828         comment   => "construct a FPA float->integer conversion",
829         reg_req   => { "in" => ["fpa"], "out" => [ "gp" ] },
830         emit      => '. fix %D0, %S0',
831 },
832
833 # Load / Store
834
835 fpaLdf => {
836         op_flags  => "L|F",
837         irn_flags => "R",
838         state     => "exc_pinned",
839         comment   => "construct FPA Load: Load(ptr, mem) = LD ptr",
840         attr      => "ir_mode *op_mode",
841         init_attr => "attr->op_mode = op_mode;",
842         reg_req   => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
843         emit      => '. ldf%M %D0, [%S0]',
844         outs      => [ "res", "M" ],
845 },
846
847 fpaStf => {
848         op_flags  => "L|F",
849         irn_flags => "R",
850         state     => "exc_pinned",
851         comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
852         attr      => "ir_mode *op_mode",
853         init_attr => "attr->op_mode = op_mode;",
854         reg_req   => { "in" => [ "gp", "fpa", "none" ], "out" => [ "none" ] },
855         emit      => '. stf%M %S1, [%S0]',
856         mode      => "mode_M",
857 },
858
859 fpaDbl2GP => {
860         op_flags  => "L|F",
861         irn_flags => "R",
862         comment   => "construct fp double to 2 gp register transfer",
863         reg_req   => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] },
864         outs      => [ "low", "high", "M" ],
865 },
866
867 AddSP => {
868         irn_flags => "I",
869         comment   => "construct Add to stack pointer",
870         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] },
871         emit      => '. add %D0, %S0, %S1',
872         outs      => [ "stack:S", "M" ],
873 },
874
875 SubSP => {
876         irn_flags => "I",
877         comment   => "construct Sub from stack pointer",
878         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] },
879         emit      => '. sub %D0, %S0, %S1',
880         outs      => [ "stack:S", "M" ],
881 },
882
883 LdTls => {
884         irn_flags => "R",
885         comment   => "load the TLS address",
886         reg_req   => { out => [ "gp" ] },
887 },
888
889
890 #
891 # floating point constants
892 #
893 fpaConst => {
894         op_flags  => "c",
895         irn_flags => "R",
896         comment   => "construct a floating point constant",
897         attr      => "tarval *tv",
898         init_attr => "attr->value = tv;",
899         mode      => "get_tarval_mode(tv)",
900         reg_req   => { "out" => [ "fpa" ] },
901 }
902
903 #---------------------------------------------------#
904 #          __                         _             #
905 #         / _|                       | |            #
906 #  __   _| |_ _ __    _ __   ___   __| | ___  ___   #
907 #  \ \ / /  _| '_ \  | '_ \ / _ \ / _` |/ _ \/ __|  #
908 #   \ V /| | | |_) | | | | | (_) | (_| |  __/\__ \  #
909 #    \_/ |_| | .__/  |_| |_|\___/ \__,_|\___||___/  #
910 #            | |                                    #
911 #            |_|                                    #
912 #---------------------------------------------------#
913
914 ); # end of %nodes