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