Fixed some ugly "const" code
[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", "realname" => "r13", "type" => 6 }, # this is our stack pointer
127                          { "name" => "lr", "realname" => "r14", "type" => 3 }, # this is our return address
128                          { "name" => "pc", "realname" => "r15", "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" => 2 },
137                          { "name" => "f5", "type" => 2 },
138                          { "name" => "f6", "type" => 2 },
139                          { "name" => "f7", "type" => 2 },
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 %nodes = (
187
188 #-----------------------------------------------------------------#
189 #  _       _                                         _            #
190 # (_)     | |                                       | |           #
191 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
192 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
193 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
194 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
195 #                   __/ |                                         #
196 #                  |___/                                          #
197 #-----------------------------------------------------------------#
198
199 # commutative operations
200
201 Add => {
202   op_flags  => "C",
203   irn_flags => "R",
204   comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
205   attr      => "arm_shift_modifier mod, tarval *shf",
206   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
207   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
208   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
209   emit      => '. add %D0, %S0, %S1%X'
210 },
211
212 Add_i => {
213   irn_flags => "R",
214   comment   => "construct Add: Add(a, const) = Add(const, a) = a + const",
215   attr      => "tarval *tv",
216   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
217   cmp_attr  => 'return attr_a->value != attr_b->value;',
218   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
219   emit      => '. add %D0, %S0, %C'
220 },
221
222 Mul => {
223   #op_flags  => "C",
224   irn_flags => "R",
225   comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
226   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
227   emit      =>'. mul %D0, %S0, %S1'
228 },
229
230 Smull => {
231   #op_flags  => "C",
232   irn_flags => "R",
233   comment   => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
234   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
235   emit      =>'. smull %D0, %D1, %S0, %S1',
236   outs      => [ "low", "high" ],
237 },
238
239 Umull => {
240   #op_flags  => "C",
241   irn_flags => "R",
242   comment   => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
243   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
244   emit      =>'. umull %D0, %D1, %S0, %S1',
245   outs      => [ "low", "high" ],
246 },
247
248 Mla => {
249   #op_flags  => "C",
250   irn_flags => "R",
251   comment   => "construct Mla: Mla(a, b, c) = a * b + c",
252   reg_req   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
253   emit      =>'. mla %D0, %S0, %S1, %S2'
254 },
255
256 And => {
257   op_flags  => "C",
258   irn_flags => "R",
259   comment   => "construct And: And(a, b) = And(b, a) = a AND 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      => '. and %D0, %S0, %S1%X'
265 },
266
267 And_i => {
268   irn_flags => "R",
269   comment   => "construct And: And(a, const) = And(const, a) = a AND const",
270   attr      => "tarval *tv",
271   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
272   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
273   emit      => '. and %D0, %S0, %C',
274   cmp_attr  => 'return attr_a->value != attr_b->value;'
275 },
276
277 Or => {
278   op_flags  => "C",
279   irn_flags => "R",
280   comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
281   attr      => "arm_shift_modifier mod, tarval *shf",
282   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
283   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
284   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
285   emit      => '. orr %D0, %S0, %S1%X'
286 },
287
288 Or_i => {
289   irn_flags => "R",
290   comment   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
291   attr      => "tarval *tv",
292   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
293   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
294   cmp_attr  => 'return attr_a->value != attr_b->value;',
295   emit      => '. orr %D0, %S0, %C'
296 },
297
298 Eor => {
299   op_flags  => "C",
300   irn_flags => "R",
301   comment   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
302   attr      => "arm_shift_modifier mod, tarval *shf",
303   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
304   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
305   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
306   emit      => '. eor %D0, %S0, %S1%X'
307 },
308
309 Eor_i => {
310   irn_flags => "R",
311   comment   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
312   attr      => "tarval *tv",
313   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
314   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
315   cmp_attr  => 'return attr_a->value != attr_b->value;',
316   emit      => '. eor %D0, %S0, %C'
317 },
318
319 # not commutative operations
320
321 Bic => {
322   irn_flags => "R",
323   comment   => "construct Bic: Bic(a, b) = a AND ~b",
324   attr      => "arm_shift_modifier mod, tarval *shf",
325   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
326   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
327   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
328   emit      => '. bic %D0, %S0, %S1%X'
329 },
330
331 Bic_i => {
332   irn_flags => "R",
333   comment   => "construct Bic: Bic(a, const) = a AND ~const",
334   attr      => "tarval *tv",
335   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
336   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
337   emit      => '. bic %D0, %S0, %C',
338   cmp_attr  => 'return attr_a->value != attr_b->value;'
339 },
340
341 Sub => {
342   irn_flags => "R",
343   comment   => "construct Sub: Sub(a, b) = a - b",
344   attr      => "arm_shift_modifier mod, tarval *shf",
345   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
346   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
347   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
348   emit      => '. sub %D0, %S0, %S1%X'
349 },
350
351 Sub_i => {
352   irn_flags => "R",
353   comment   => "construct Sub: Sub(a, const) = a - const",
354   attr      => "tarval *tv",
355   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
356   cmp_attr  => 'return attr_a->value != attr_b->value;',
357   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
358   emit      => '. sub %D0, %S0, %C',
359 },
360
361 Rsb => {
362   irn_flags => "R",
363   comment   => "construct Rsb: Rsb(a, b) = b - a",
364   attr      => "arm_shift_modifier mod, tarval *shf",
365   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
366   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
367   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
368   emit      => '. rsb %D0, %S0, %S1%X'
369 },
370
371 Rsb_i => {
372   irn_flags => "R",
373   comment   => "construct Rsb: Rsb(a, const) = const - a",
374   attr      => "tarval *tv",
375   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
376   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
377   emit      => '. rsb %D0, %S0, %C',
378   cmp_attr  => 'return attr_a->value != attr_b->value;'
379 },
380
381 Shl => {
382   irn_flags => "R",
383   comment   => "construct Shl: Shl(a, b) = a << b",
384   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
385   emit      => '. mov %D0, %S0, lsl %S1'
386 },
387
388 Shr => {
389   irn_flags => "R",
390   comment   => "construct Shr: Shr(a, b) = a >> b",
391   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
392   emit      => '. mov %D0, %S0, lsr %S1'
393 },
394
395 Shrs => {
396   irn_flags => "R",
397   comment   => "construct Shrs: Shrs(a, b) = a >> b",
398   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
399   emit      => '. mov %D0, %S0, asr %S1'
400 },
401
402 #RotR => {
403 #  irn_flags => "R",
404 #  comment   => "construct RotR: RotR(a, b) = a ROTR b",
405 #  reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
406 #  emit      => '. mov %D0, %S0, ror %S1 /* RotR(%S0, %S1) -> %D0, (%A1, %A2) */'
407 ##  emit      => '. ror %S0, %S1, %D0'
408 #},
409
410 #RotL => {
411 #  irn_flags => "R",
412 #  comment   => "construct RotL: RotL(a, b) = a ROTL b",
413 #  reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
414 #  emit      => '. rol %S0, %S1, %D0'
415 #},
416
417 #RotL_i => {
418 #  irn_flags => "R",
419 #  comment   => "construct RotL: RotL(a, const) = a ROTL const",
420 #  reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
421 #  emit      => '. rol %S0, %C, %D0'
422 #},
423
424 Mov => {
425   irn_flags => "R",
426   comment   => "construct Mov: a = b",
427   attr      => "arm_shift_modifier mod, tarval *shf",
428   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
429   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
430   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
431   emit      => '. mov %D0, %S0%X'
432 },
433
434 Mov_i => {
435   irn_flags => "R",
436   comment   => "represents an integer constant",
437   attr      => "tarval *tv",
438   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
439   reg_req   => { "out" => [ "gp" ] },
440   emit      => '. mov %D0, %C',
441   cmp_attr  => 'return attr_a->value != attr_b->value;'
442 },
443
444 Mvn => {
445   irn_flags => "R",
446   comment   => "construct Not: Not(a) = !a",
447   attr      => "arm_shift_modifier mod, tarval *shf",
448   init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
449   cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
450   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
451   emit      => '. mvn %D0, %S0%X'
452 },
453
454 Mvn_i => {
455   irn_flags => "R",
456   comment   => "represents a negated integer constant",
457   attr      => "tarval *tv",
458   init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
459   cmp_attr  => 'return attr_a->value != attr_b->value;',
460   reg_req   => { "out" => [ "gp" ] },
461   emit      => '. mvn %D0, %C',
462 },
463
464 Abs => {
465   irn_flags => "R",
466   comment   => "construct Abs: Abs(a) = |a|",
467   reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
468   emit      =>
469 '. movs %S0, %S0, #0
470 . rsbmi %D0, %S0, #0'
471 },
472
473 # other operations
474
475 EmptyReg => {
476   op_flags  => "c",
477   irn_flags => "R",
478   comment   => "allocate an empty register for calculations",
479   reg_req   => { "out" => [ "gp" ] },
480   emit      => '. /* %D0 now available for calculations */',
481   cmp_attr  => 'return 1;'
482 },
483
484 Copy => {
485   comment  => "implements a register copy",
486   reg_req  => { "in" => [ "gp" ], "out" => [ "gp" ] },
487 },
488
489 CopyB => {
490   op_flags => "F|H",
491   state    => "pinned",
492   comment  => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
493   reg_req  => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
494 },
495
496 SymConst => {
497   op_flags  => "c",
498   irn_flags => "R",
499   comment   => "represents a symbolic constant",
500   attr      => "ident *id",
501   init_attr => "\tset_arm_symconst_id(res, id);",
502   reg_req   => { "out" => [ "gp" ] },
503   attr_type   => "arm_SymConst_attr_t",
504 },
505
506 CondJmp => {
507   op_flags  => "L|X|Y",
508   comment   => "construct conditional jump: CMP A, B && JMPxx LABEL",
509   mode      => "mode_T",
510   attr      => "int proj_num",
511   init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
512   reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
513   attr_type => "arm_CondJmp_attr_t",
514 },
515
516 SwitchJmp => {
517   op_flags  => "L|X|Y",
518   comment   => "construct switch",
519   mode      => "mode_T",
520   attr      => "int n_projs, long def_proj_num",
521   init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
522                  "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
523   reg_req   => { "in" => [ "gp" ], "out" => [ "none" ] },
524   attr_type => "arm_SwitchJmp_attr_t",
525 },
526
527 # Load / Store
528
529 Load => {
530   op_flags  => "L|F",
531   irn_flags => "R",
532   state     => "exc_pinned",
533   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
534   reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
535   emit      => '. ldr %D0, [%S0, #0]',
536   outs      => [ "res", "M" ],
537 },
538
539 Loadb => {
540   op_flags  => "L|F",
541   irn_flags => "R",
542   state     => "exc_pinned",
543   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
544   reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
545   emit      => '. ldrb %D0, [%S0, #0]',
546   outs      => [ "res", "M" ],
547 },
548
549 Loadbs => {
550   op_flags  => "L|F",
551   irn_flags => "R",
552   state     => "exc_pinned",
553   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
554   reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
555   emit      => '. ldrsb %D0, [%S0, #0]',
556   outs      => [ "res", "M" ],
557 },
558
559 Loadh => {
560   op_flags  => "L|F",
561   irn_flags => "R",
562   state     => "exc_pinned",
563   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
564   reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
565   emit      => '. ldrh %D0, [%S0, #0]',
566   outs      => [ "res", "M" ],
567 },
568
569 Loadhs => {
570   op_flags  => "L|F",
571   irn_flags => "R",
572   state     => "exc_pinned",
573   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
574   reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
575   emit      => '. ldrsh %D0, [%S0, #0]',
576   outs      => [ "res", "M" ],
577 },
578
579 Storeb => {
580   op_flags  => "L|F",
581   irn_flags => "R",
582   state     => "exc_pinned",
583   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
584   reg_req   => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
585   emit      => '. strb %S1, [%S0, #0]',
586   outs      => [ "M" ],
587 },
588
589 Storebs => {
590   op_flags  => "L|F",
591   irn_flags => "R",
592   state     => "exc_pinned",
593   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
594   reg_req   => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
595   emit      => '. strsb %S1, [%S0, #0]',
596   outs      => [ "M" ],
597 },
598
599 Storeh => {
600   op_flags  => "L|F",
601   irn_flags => "R",
602   state     => "exc_pinned",
603   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
604   reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
605   emit      => '. strh %S1, [%S0, #0]',
606   outs      => [ "M" ],
607 },
608
609 Storehs => {
610   op_flags  => "L|F",
611   irn_flags => "R",
612   state     => "exc_pinned",
613   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
614   reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
615   emit      => '. strhs %S1, [%S0, #0]',
616   outs      => [ "M" ],
617 },
618
619 Store => {
620   op_flags  => "L|F",
621   irn_flags => "R",
622   state     => "exc_pinned",
623   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
624   reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
625   emit      => '. str %S1, [%S0, #0]',
626   outs      => [ "M" ],
627 },
628
629 StoreStackM4Inc => {
630   op_flags  => "L|F",
631   irn_flags => "R",
632   state     => "exc_pinned",
633   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
634   reg_req   => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
635   emit      => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
636   outs      => [ "ptr", "M" ],
637 },
638
639 LoadStackM3 => {
640   op_flags  => "L|F",
641   irn_flags => "R",
642   state     => "exc_pinned",
643   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
644   reg_req   => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] },
645   emit      => '. ldmfd %S0, {%D0, %D1, %D2}',
646   outs      => [ "res0", "res1", "res2", "M" ],
647 },
648
649
650 #---------------------------------------------------#
651 #    __                               _             #
652 #   / _|                             | |            #
653 #  | |_ _ __   __ _   _ __   ___   __| | ___  ___   #
654 #  |  _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __|  #
655 #  | | | |_) | (_| | | | | | (_) | (_| |  __/\__ \  #
656 #  |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/  #
657 #      | |                                          #
658 #      |_|                                          #
659 #---------------------------------------------------#
660
661 # commutative operations
662
663 fpaAdd => {
664   op_flags  => "C",
665   irn_flags => "R",
666   comment   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
667   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
668   emit      => '. adf%M %D0, %S0, %S1',
669 },
670
671 fpaMul => {
672   op_flags  => "C",
673   comment   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
674   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
675   emit      =>'. muf%M %D0, %S0, %S1',
676 },
677
678 fpaFMul => {
679   op_flags  => "C",
680   comment   => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
681   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
682   emit      =>'. fml%M %D0, %S0, %S1',
683 },
684
685 fpaMax => {
686   op_flags  => "C",
687   irn_flags => "R",
688   comment   => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
689   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
690   emit      =>'. fmax %S0, %S1, %D0',
691 },
692
693 fpaMin => {
694   op_flags  => "C",
695   irn_flags => "R",
696   comment   => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
697   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
698   emit      =>'. fmin %S0, %S1, %D0',
699 },
700
701 # not commutative operations
702
703 fpaSub => {
704   irn_flags => "R",
705   comment   => "construct FPA Sub: Sub(a, b) = a - b",
706   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
707   emit      => '. suf%M %D0, %S0, %S1'
708 },
709
710 fpaRsb => {
711   irn_flags => "R",
712   comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
713   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
714   emit      => '. rsf%M %D0, %S0, %S1'
715 },
716
717 fpaDiv => {
718   comment   => "construct FPA Div: Div(a, b) = a / b",
719   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
720   emit      =>'. dvf%M %D0, %S0, %S1',
721 },
722
723 fpaRdv => {
724   comment   => "construct FPA reverse Div: Div(a, b) = b / a",
725   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
726   emit      =>'. rdf%M %D0, %S0, %S1',
727 },
728
729 fpaFDiv => {
730   comment   => "construct FPA Fast Div: Div(a, b) = a / b",
731   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
732   emit      =>'. fdv%M %D0, %S0, %S1',
733 },
734
735 fpaFRdv => {
736   comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
737   reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
738   emit      =>'. frd%M %D0, %S0, %S1',
739 },
740
741 fpaMov => {
742   irn_flags => "R",
743   comment   => "construct FPA Move: b = a",
744   reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
745   emit      => '. mvf%M %S0, %D0',
746 },
747
748 fpaMnv => {
749   irn_flags => "R",
750   comment   => "construct FPA Move Negated: b = -a",
751   reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
752   emit      => '. mnf%M %S0, %D0',
753 },
754
755 fpaAbs => {
756   irn_flags => "R",
757   comment   => "construct FPA Absolute value: fAbsd(a) = |a|",
758   reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
759   emit      => '. abs%M %D0, %S0',
760 },
761
762 # other operations
763
764 fpaConst => {
765   op_flags  => "c",
766   irn_flags => "R",
767   comment   => "represents a FPA constant",
768   attr      => "tarval *val",
769   init_attr => 'attr->value = val;',
770   reg_req   => { "out" => [ "fpa" ] },
771   emit      => '. fmov %D0, %C',
772   cmp_attr  => 'return attr_a->value != attr_b->value;',
773 },
774
775 fpaFlt => {
776   irn_flags => "R",
777   comment   => "construct a FPA integer->float conversion",
778   reg_req   => { "in" => ["gp"], "out" => [ "fpa" ] },
779   emit      => '. flt%M %D0, %S0',
780 },
781
782 fpaFix => {
783   irn_flags => "R",
784   comment   => "construct a FPA float->integer conversion",
785   reg_req   => { "in" => ["fpa"], "out" => [ "gp" ] },
786   emit      => '. fix %D0, %S0',
787 },
788
789 # Load / Store
790
791 fpaLdf => {
792   op_flags  => "L|F",
793   irn_flags => "R",
794   state     => "exc_pinned",
795   comment   => "construct FPA Load: Load(ptr, mem) = LD ptr",
796   attr      => "ir_mode *op_mode",
797   init_attr => "attr->op_mode = op_mode;",
798   reg_req   => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
799   emit      => '. ldf%M %D0, [%S0, #0]',
800   outs      => [ "res", "M" ],
801 },
802
803 fpaStf => {
804   op_flags  => "L|F",
805   irn_flags => "R",
806   state     => "exc_pinned",
807   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
808   attr      => "ir_mode *op_mode",
809   init_attr => "attr->op_mode = op_mode;",
810   reg_req   => { "in" => [ "gp", "fpa", "none" ], "out" => [ "none" ] },
811   emit      => '. stf%M [%S1, #0], %S0',
812   outs      => [ "M" ],
813 },
814
815 fpaDbl2GP => {
816   op_flags  => "L|F",
817   irn_flags => "R",
818   state     => "exc_pinned",
819   comment   => "construct fp double to 2 gp register transfer",
820   reg_req   => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] },
821   outs      => [ "low", "high", "M" ],
822 },
823
824
825 #---------------------------------------------------#
826 #          __                         _             #
827 #         / _|                       | |            #
828 #  __   _| |_ _ __    _ __   ___   __| | ___  ___   #
829 #  \ \ / /  _| '_ \  | '_ \ / _ \ / _` |/ _ \/ __|  #
830 #   \ V /| | | |_) | | | | | (_) | (_| |  __/\__ \  #
831 #    \_/ |_| | .__/  |_| |_|\___/ \__,_|\___||___/  #
832 #            | |                                    #
833 #            |_|                                    #
834 #---------------------------------------------------#
835
836 ); # end of %nodes