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