8701dd27542446342065914c2e1c1e26d0a59560
[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
9 # $comment_string = 'WIRHABENKEINEKOMMENTARE';
10 $comment_string = '/*';
11
12 # the number of additional opcodes you want to register
13 #$additional_opcodes = 0;
14
15 # The node description is done as a perl hash initializer with the
16 # following structure:
17 #
18 # %nodes = (
19 #
20 # <op-name> => {
21 #   "op_flags"  => "N|L|C|X|I|F|Y|H|c|K",
22 #   "irn_flags" => "R|N|I"
23 #   "arity"     => "0|1|2|3 ... |variable|dynamic|any",
24 #   "state"     => "floats|pinned|mem_pinned|exc_pinned",
25 #   "args"      => [
26 #                    { "type" => "type 1", "name" => "name 1" },
27 #                    { "type" => "type 2", "name" => "name 2" },
28 #                    ...
29 #                  ],
30 #   "comment"   => "any comment for constructor",
31 #   "reg_req"   => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] },
32 #   "cmp_attr"  => "c source code for comparing node attributes",
33 #   "emit"      => "emit code with templates",
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", "type" => 6 }, # this is our stack pointer
114                          { "name" => "lr", "type" => 3 }, # this is our return address
115                          { "name" => "pc", "type" => 6 }, # this is our program counter
116                          { "mode" => "mode_Iu" }
117                        ],
118   "fp"  => [
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_D" }
128                        ]
129 ); # %reg_classes
130
131 #--------------------------------------------------#
132 #                        _                         #
133 #                       (_)                        #
134 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
135 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
136 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
137 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
138 #                                      | |         #
139 #                                      |_|         #
140 #--------------------------------------------------#
141
142 %nodes = (
143
144 #-----------------------------------------------------------------#
145 #  _       _                                         _            #
146 # (_)     | |                                       | |           #
147 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
148 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
149 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
150 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
151 #                   __/ |                                         #
152 #                  |___/                                          #
153 #-----------------------------------------------------------------#
154
155 # commutative operations
156
157 "Add" => {
158   "op_flags"  => "C",
159   "irn_flags" => "R",
160   "comment"   => "construct Add: Add(a, b) = Add(b, a) = a + b",
161   "attr"      => "arm_shift_modifier mod, tarval *shf",
162   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
163   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
164   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
165   "emit"      => '. ADD %D1, %S1, %S2%X0 /* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
166 },
167
168 "Add_i" => {
169   "irn_flags" => "R",
170   "comment"   => "construct Add: Add(a, const) = Add(const, a) = a + const",
171   "attr"      => "tarval *tv",
172   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
173   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
174   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
175   "emit"      => '. ADD %D1, %S1, %C /* Add(%C, %S1) -> %D1, (%A1, const) */'
176 },
177
178 "Mul" => {
179   #"op_flags"  => "C",
180   "irn_flags" => "R",
181   "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
182   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
183   "emit"      =>'. MUL %D1, %S1, %S2 /* Mul(%S1, %S2) -> %D1, (%A1, %A2) */'
184 },
185
186 "Mla" => {
187   #"op_flags"  => "C",
188   "irn_flags" => "R",
189   "comment"   => "construct Mla: Mla(a, b, c) = a * b + c",
190   "reg_req"   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
191   "emit"      =>'. MLA %D1, %S1, %S2, %S3 /* Mla(%S1, %S2, %S3) -> %D1, (%A1, %A2, %A3) */'
192 },
193
194 "And" => {
195   "op_flags"  => "C",
196   "irn_flags" => "R",
197   "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
198   "attr"      => "arm_shift_modifier mod, tarval *shf",
199   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
200   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
201   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
202   "emit"      => '. AND %D1, %S1, %S2%X0 /* And(%S1, %S2) -> %D1, (%A1, %A2) */'
203 },
204
205 "And_i" => {
206   "irn_flags" => "R",
207   "comment"   => "construct And: And(a, const) = And(const, a) = a AND const",
208   "attr"      => "tarval *tv",
209   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
210   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
211   "emit"      => '. AND %D1, %S1, %C /* And(%C, %S1) -> %D1, (%A1, const) */',
212   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
213 },
214
215 "Or" => {
216   "op_flags"  => "C",
217   "irn_flags" => "R",
218   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
219   "attr"      => "arm_shift_modifier mod, tarval *shf",
220   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
221   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
222   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
223   "emit"      => '. ORR %D1, %S1, %S2%X0 /* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
224 },
225
226 "Or_i" => {
227   "irn_flags" => "R",
228   "comment"   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
229   "attr"      => "tarval *tv",
230   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
231   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
232   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
233   "emit"      => '. ORR %D1, %S1, %C /* Or(%C, %S1) -> %D1, (%A1, const) */'
234 },
235
236 "Eor" => {
237   "op_flags"  => "C",
238   "irn_flags" => "R",
239   "comment"   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
240   "attr"      => "arm_shift_modifier mod, tarval *shf",
241   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
242   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
243   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
244   "emit"      => '. EOR %D1, %S1, %S2%X0 /* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
245 },
246
247 "Eor_i" => {
248   "irn_flags" => "R",
249   "comment"   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
250   "attr"      => "tarval *tv",
251   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
252   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
253   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
254   "emit"      => '. EOR %D1, %S1, %C /* Xor(%C, %S1) -> %D1, (%A1, const) */'
255 },
256
257 # not commutative operations
258
259 "Bic" => {
260   "irn_flags" => "R",
261   "comment"   => "construct Bic: Bic(a, b) = a AND ~b",
262   "attr"      => "arm_shift_modifier mod, tarval *shf",
263   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
264   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
265   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
266   "emit"      => '. BIC %D1, %S1, %S2%X0 /* AndNot(%S1, %S2) -> %D1, (%A1, %A2) */'
267 },
268
269 "Bic_i" => {
270   "irn_flags" => "R",
271   "comment"   => "construct Bic: Bic(a, const) = a AND ~const",
272   "attr"      => "tarval *tv",
273   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
274   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
275   "emit"      => '. BIC %D1, %S1, %C /* AndNot(%C, %S1) -> %D1, (%A1, const) */',
276   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
277 },
278
279 "Sub" => {
280   "irn_flags" => "R",
281   "comment"   => "construct Sub: Sub(a, b) = a - b",
282   "attr"      => "arm_shift_modifier mod, tarval *shf",
283   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
284   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
285   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
286   "emit"      => '. SUB %D1, %S1, %S2%X0 /* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
287 },
288
289 "Sub_i" => {
290   "irn_flags" => "R",
291   "comment"   => "construct Sub: Sub(a, const) = a - const",
292   "attr"      => "tarval *tv",
293   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
294   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
295   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
296   "emit"      => '. SUB %D1, %S1, %C /* Sub(%S1, %C) -> %D1, (%A1, const) */',
297 },
298
299 "Rsb" => {
300   "irn_flags" => "R",
301   "comment"   => "construct Rsb: Rsb(a, b) = b - a",
302   "attr"      => "arm_shift_modifier mod, tarval *shf",
303   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
304   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
305   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
306   "emit"      => '. RSB %D1, %S1, %S2%X0 /* Rsb(%S1, %S2) -> %D1, (%A1, %A2) */'
307 },
308
309 "Rsb_i" => {
310   "irn_flags" => "R",
311   "comment"   => "construct Rsb: Rsb(a, const) = const - a",
312   "attr"      => "tarval *tv",
313   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
314   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
315   "emit"      => '. RSB %D1, %S1, %C /* Rsb(%S1, %C) -> %D1, (%A1, const) */',
316   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
317 },
318
319 "Shl" => {
320   "irn_flags" => "R",
321   "comment"   => "construct Shl: Shl(a, b) = a << b",
322   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
323   "emit"      => '. MOV %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
324 },
325
326 "Shr" => {
327   "irn_flags" => "R",
328   "comment"   => "construct Shr: Shr(a, b) = a >> b",
329   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
330   "emit"      => '. MOV %D1, %S1, LSR %S2 /* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
331 },
332
333 "Shrs" => {
334   "irn_flags" => "R",
335   "comment"   => "construct Shrs: Shrs(a, b) = a >> b",
336   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
337   "emit"      => '. MOV %D1, %S1, ASR %S2\t\t /* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */'
338 },
339
340 #"RotR" => {
341 #  "irn_flags" => "R",
342 #  "comment"   => "construct RotR: RotR(a, b) = a ROTR b",
343 #  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
344 #  "emit"      => '. MOV %D1, %S1, ROR %S2 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
345 ##  "emit"      => '. ror %S1, %S2, %D1 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
346 #},
347
348 #"RotL" => {
349 #  "irn_flags" => "R",
350 #  "comment"   => "construct RotL: RotL(a, b) = a ROTL b",
351 #  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
352 #  "emit"      => '. rol %S1, %S2, %D1 /* RotL(%S1, %S2) -> %D1, (%A1, %A2) */'
353 #},
354
355 #"RotL_i" => {
356 #  "irn_flags" => "R",
357 #  "comment"   => "construct RotL: RotL(a, const) = a ROTL const",
358 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
359 #  "emit"      => '. rol %S1, %C, %D1 /* RotL(%S1, %C) -> %D1, (%A1, const) */'
360 #},
361
362 "Mov" => {
363   "irn_flags" => "R",
364   "comment"   => "construct Mov: a = b",
365   "attr"      => "arm_shift_modifier mod, tarval *shf",
366   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
367   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
368   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
369   "emit"      => '. MOV %D1, %S1%X0\t/* Mov(%S1%X0) -> %D1, (%A1) */'
370 },
371
372 "Mov_i" => {
373   "irn_flags" => "R",
374   "comment"   => "represents an integer constant",
375   "attr"      => "tarval *tv",
376   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
377   "reg_req"   => { "out" => [ "gp" ] },
378   "emit"      => '. MOV %D1, %C   /* Mov Const into register */',
379   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
380 },
381
382 "Mvn" => {
383   "irn_flags" => "R",
384   "comment"   => "construct Not: Not(a) = !a",
385   "attr"      => "arm_shift_modifier mod, tarval *shf",
386   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
387   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
388   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
389   "emit"      => '. MVN %D1, %S1%X0 /* ~(%S1%X0) -> %D1, (%A1) */'
390 },
391
392 "Mvn_i" => {
393   "irn_flags" => "R",
394   "comment"   => "represents a negated integer constant",
395   "attr"      => "tarval *tv",
396   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
397   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
398   "reg_req"   => { "out" => [ "gp" ] },
399   "emit"      => '. MVN %D1, %C   /* Mov ~Const into register */',
400 },
401
402 "Abs" => {
403   "irn_flags" => "R",
404   "comment"   => "construct Abs: Abs(a) = |a|",
405   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
406   "emit"      =>
407 '. MOVS %S1, %S1, #0 /* set condition flag */\n
408 . RSBMI %D1, %S1, #0 /* Neg(%S1) -> %D1, (%A1) */'
409 },
410
411 # other operations
412
413 "EmptyReg" => {
414   "op_flags"  => "c",
415   "irn_flags" => "R",
416   "comment"  => "just to get an empty register for calculations",
417   "reg_req"  => { "out" => [ "gp" ] },
418   "emit"      => '. /* %D1 now available for calculations */',
419   "cmp_attr"  => 'return 1;'
420 },
421
422 "Copy" => {
423   "comment"  => "implements a register copy",
424   "reg_req"  => { "in" => [ "gp" ], "out" => [ "gp" ] },
425 },
426
427 "CopyB" => {
428   "op_flags" => "F|H",
429   "state"    => "pinned",
430   "comment"  => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
431   "reg_req"  => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
432 },
433
434 "SymConst" => {
435   "op_flags"  => "c",
436   "irn_flags" => "R",
437   "comment"   => "represents a symbolic constant",
438   "attr"      => "const char *label",
439   "init_attr" => '  attr->symconst_label = label;',
440   "reg_req"   => { "out" => [ "gp" ] },
441 #  "emit"      => '. LDR %D1, %C /* Mov Const into register */',
442   "cmp_attr"  =>
443 '  /* should be identical but ...*/
444    return strcmp(attr_a->symconst_label, attr_b->symconst_label);'
445 },
446
447 "CondJmp" => {
448   "op_flags"  => "L|X|Y",
449   "comment"   => "construct conditional jump: CMP A, B && JMPxx LABEL",
450   "cmp_attr"  => "  return arm_comp_condJmp(attr_a, attr_b);\n",
451   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
452 },
453
454 "SwitchJmp" => {
455   "op_flags"  => "L|X|Y",
456   "comment"   => "construct switch",
457   "reg_req"   => { "in" => [ "gp" ], "out" => [ "none" ] },
458   "cmp_attr"  => "  return 0;\n",
459 },
460
461 # Load / Store
462
463 "Load" => {
464   "op_flags"  => "L|F",
465   "irn_flags" => "R",
466   "state"     => "exc_pinned",
467   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
468   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
469   "emit"      => '. LDR %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
470 #  "emit"      => '. LDR %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
471   "outs"      => [ "res", "M" ],
472 },
473
474 "Loadb" => {
475   "op_flags"  => "L|F",
476   "irn_flags" => "R",
477   "state"     => "exc_pinned",
478   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
479   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
480   "emit"      => '. LDRB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
481 #  "emit"      => '. LDRB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
482   "outs"      => [ "res", "M" ],
483 },
484
485 "Loadbs" => {
486   "op_flags"  => "L|F",
487   "irn_flags" => "R",
488   "state"     => "exc_pinned",
489   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
490   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
491   "emit"      => '. LDRSB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
492 #  "emit"      => '. LDRSB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
493   "outs"      => [ "res", "M" ],
494 },
495
496 "Loadh" => {
497   "op_flags"  => "L|F",
498   "irn_flags" => "R",
499   "state"     => "exc_pinned",
500   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
501   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
502   "emit"      => '. LDRH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
503 #  "emit"      => '. LDRH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
504   "outs"      => [ "res", "M" ],
505 },
506
507 "Loadhs" => {
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"      => '. LDRSH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
514 #  "emit"      => '. LDRSH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
515   "outs"      => [ "res", "M" ],
516 },
517
518 "Storeb" => {
519   "op_flags"  => "L|F",
520   "irn_flags" => "R",
521   "state"     => "exc_pinned",
522   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
523   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
524   "emit"      => '. STRB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
525 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
526   "outs"      => [ "M" ],
527 },
528
529 "Storebs" => {
530   "op_flags"  => "L|F",
531   "irn_flags" => "R",
532   "state"     => "exc_pinned",
533   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
534   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
535   "emit"      => '. STRSB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
536 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
537   "outs"      => [ "M" ],
538 },
539
540 "Storeh" => {
541   "op_flags"  => "L|F",
542   "irn_flags" => "R",
543   "state"     => "exc_pinned",
544   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
545   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
546   "emit"      => '. STRH %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
547 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
548   "outs"      => [ "M" ],
549 },
550
551 "Storehs" => {
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"      => '. STRSH%S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
558 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
559   "outs"      => [ "M" ],
560 },
561
562 "Store" => {
563   "op_flags"  => "L|F",
564   "irn_flags" => "R",
565   "state"     => "exc_pinned",
566   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
567   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
568   "emit"      => '. STR %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
569 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
570   "outs"      => [ "M" ],
571 },
572
573 "StoreStackM4Inc" => {
574   "op_flags"  => "L|F",
575   "irn_flags" => "R",
576   "state"     => "exc_pinned",
577   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
578   "reg_req"   => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
579   "emit"      => '. STMFD %S1!, {%S2, %S3, %S4, %S5} /* Store multiple on Stack*/',
580   "outs"      => [ "ptr", "M" ],
581 },
582
583 "LoadStackM3" => {
584   "op_flags"  => "L|F",
585   "irn_flags" => "R",
586   "state"     => "exc_pinned",
587   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
588   "reg_req"   => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] },
589   "emit"      => '. LDMFD %S1, {%D1, %D2, %D3} /* Load multiple from Stack */',
590   "outs"      => [ "res0", "res1", "res2", "M" ],
591 },
592
593
594
595
596
597
598
599
600 #--------------------------------------------------------#
601 #    __ _             _                     _            #
602 #   / _| |           | |                   | |           #
603 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
604 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
605 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
606 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
607 #--------------------------------------------------------#
608
609 # commutative operations
610
611 "fAdd" => {
612   "op_flags"  => "C",
613   "irn_flags" => "R",
614   "comment"   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
615   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
616   "emit"      => '. FADD%Mx %D1, %S1, %S2 /* FP Add(%S1, %S2) -> %D1 */',
617 },
618
619 "fMul" => {
620   "op_flags"  => "C",
621   "comment"   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
622   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
623   "emit"      =>'. FMUL%Mx %D1, %S1, %S2 /* FP Mul(%S1, %S2) -> %D1 */',
624 },
625
626 "fDiv" => {
627   "comment"   => "construct FP Div: Div(a, b) = a / b",
628   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
629   "emit"      =>'. FDIV%Mx %D1, %S1, %S2 /* FP Div(%S1, %S2) -> %D1 */',
630 },
631
632 "fMax" => {
633   "op_flags"  => "C",
634   "irn_flags" => "R",
635   "comment"   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
636   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
637   "emit"      =>'. fmax %S1, %S2, %D1 /* FP Max(%S1, %S2) -> %D1 */',
638 },
639
640 "fMin" => {
641   "op_flags"  => "C",
642   "irn_flags" => "R",
643   "comment"   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
644   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
645   "emit"      =>'. fmin %S1, %S2, %D1 /* FP Min(%S1, %S2) -> %D1 */',
646 },
647
648 # not commutative operations
649
650 "fSub" => {
651   "irn_flags" => "R",
652   "comment"   => "construct FP Sub: Sub(a, b) = a - b",
653   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
654   "emit"      => '. FSUB%Mx %D1, %S1, %S2 /* FP Sub(%S1, %S2) -> %D1 */'
655 },
656
657 "fNeg" => {
658   "irn_flags" => "R",
659   "comment"   => "construct FP Neg: Neg(a) = -a",
660   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
661   "emit"      => '. fneg %S1, %D1 /* FP Neg(%S1) -> %D1 */',
662 },
663
664 "fAbs" => {
665   "irn_flags" => "R",
666   "comment"   => "construct FP Absolute value: fAbsd(a) = |a|",
667   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
668   "emit"      => '. FABS%Mx %D1, %S1 /* FP Absd(%S1) -> %D1 */',
669 },
670
671 # other operations
672
673 "fConst" => {
674   "op_flags"  => "c",
675   "irn_flags" => "R",
676   "comment"   => "represents a FP constant",
677   "attr"      => "tarval *val",
678   "init_attr" => 'attr->value = val;',
679   "reg_req"   => { "out" => [ "fp" ] },
680   "emit"      => '. FMOV %D1, %C /* Mov fConst into register */',
681   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
682 },
683
684 "fConvD2S" => {
685   "irn_flags" => "R",
686   "comment"   => "convert double to single",
687   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
688   "emit"      => '. FCVTSD %D1, %S1 /* Convert double to single */',
689 },
690
691 "fConvS2D" => {
692   "irn_flags" => "R",
693   "comment"   => "convert single to double",
694   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
695   "emit"      => '. FCVTDS %D1, %S1 /* Convert single to double */',
696 },
697
698
699 # Load / Store
700
701 "fLoad" => {
702   "op_flags"  => "L|F",
703   "irn_flags" => "R",
704   "state"     => "exc_pinned",
705   "comment"   => "construct FP Load: Load(ptr, mem) = LD ptr",
706   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "fp", "none" ] },
707   "emit"      => '. FLD%Mx %D1, %S1 /* Load((%S1)) -> %D1 */',
708   "outs"      => [ "res", "M" ],
709 },
710
711 "fStore" => {
712   "op_flags"  => "L|F",
713   "irn_flags" => "R",
714   "state"     => "exc_pinned",
715   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
716   "reg_req"   => { "in" => [ "gp", "fp", "none" ] },
717   "emit"      => '. FST%Mx %S2, %S1 /* Store(%S2) -> (%S1), (%A1, %A2) */',
718   "outs"      => [ "M" ],
719 },
720
721 ); # end of %nodes