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