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