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