Added beinsn.c
[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 # comment: OPTIONAL comment for the node constructor
72 #
73 # rd_constructor: for every operation there will be a
74 #      new_rd_<arch>_<op-name> function with the arguments from above
75 #      which creates the ir_node corresponding to the defined operation
76 #      you can either put the complete source code of this function here
77 #
78 #      This key is OPTIONAL. If omitted, the following constructor will
79 #      be created:
80 #      if (!op_<arch>_<op-name>) assert(0);
81 #      for i = 1 to arity
82 #         set in[i] = op_i
83 #      done
84 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
85 #      return res
86 #
87 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
88
89 # register types:
90 #   0 - no special type
91 #   1 - caller save (register must be saved by the caller of a function)
92 #   2 - callee save (register must be saved by the called function)
93 #   4 - ignore (do not assign this register)
94 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
95 %reg_classes = (
96   "gp" => [
97                          { "name" => "r0", "type" => 1 },
98                          { "name" => "r1", "type" => 1 },
99                          { "name" => "r2", "type" => 1 },
100                          { "name" => "r3", "type" => 1 },
101                          { "name" => "r4", "type" => 2 },
102                          { "name" => "r5", "type" => 2 },
103                          { "name" => "r6", "type" => 2 },
104                          { "name" => "r7", "type" => 2 },
105                          { "name" => "r8", "type" => 2 },
106                          { "name" => "r9", "type" => 2 },
107                          { "name" => "r10", "type" => 2 },
108                          { "name" => "r11", "type" => 2 },
109                          { "name" => "r12", "type" => 6 }, # reserved for linker
110                          { "name" => "sp", "type" => 6 }, # this is our stack pointer
111                          { "name" => "lr", "type" => 3 }, # this is our return address
112                          { "name" => "pc", "type" => 6 }, # this is our program counter
113                          { "name" => "rxx", "type" => 6 }, # dummy register for no_mem
114                          { "mode" => "mode_Iu" }
115                        ],
116   "fp"  => [
117                          { "name" => "f0", "type" => 1 },
118                          { "name" => "f1", "type" => 1 },
119                          { "name" => "f2", "type" => 1 },
120                          { "name" => "f3", "type" => 1 },
121                          { "name" => "f4", "type" => 2 },
122                          { "name" => "f5", "type" => 2 },
123                          { "name" => "f6", "type" => 2 },
124                          { "name" => "f7", "type" => 2 },
125                          { "name" => "fxx", "type" => 6 }, # dummy register for no_mem
126                          { "mode" => "mode_D" }
127                        ]
128 ); # %reg_classes
129
130 #--------------------------------------------------#
131 #                        _                         #
132 #                       (_)                        #
133 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
134 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
135 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
136 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
137 #                                      | |         #
138 #                                      |_|         #
139 #--------------------------------------------------#
140
141 %nodes = (
142
143 #-----------------------------------------------------------------#
144 #  _       _                                         _            #
145 # (_)     | |                                       | |           #
146 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
147 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
148 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
149 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
150 #                   __/ |                                         #
151 #                  |___/                                          #
152 #-----------------------------------------------------------------#
153
154 # commutative operations
155
156 "Add" => {
157   "op_flags"  => "C",
158   "irn_flags" => "R",
159   "comment"   => "construct Add: Add(a, b) = Add(b, a) = a + b",
160   "attr"      => "arm_shift_modifier mod, tarval *shf",
161   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
162   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
163   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
164   "emit"      => '. ADD %D1, %S1, %S2%X0 /* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
165 },
166
167 "Add_i" => {
168   "irn_flags" => "R",
169   "comment"   => "construct Add: Add(a, const) = Add(const, a) = a + const",
170   "attr"      => "tarval *tv",
171   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
172   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
173   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
174   "emit"      => '. ADD %D1, %S1, %C /* Add(%C, %S1) -> %D1, (%A1, const) */'
175 },
176
177 "Mul" => {
178   #"op_flags"  => "C",
179   "irn_flags" => "R",
180   "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
181   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
182   "emit"      =>'. MUL %D1, %S1, %S2 /* Mul(%S1, %S2) -> %D1, (%A1, %A2) */'
183 },
184
185 "Mla" => {
186   #"op_flags"  => "C",
187   "irn_flags" => "R",
188   "comment"   => "construct Mla: Mla(a, b, c) = a * b + c",
189   "reg_req"   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
190   "emit"      =>'. MLA %D1, %S1, %S2, %S3 /* Mla(%S1, %S2, %S3) -> %D1, (%A1, %A2, %A3) */'
191 },
192
193 "And" => {
194   "op_flags"  => "C",
195   "irn_flags" => "R",
196   "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
197   "attr"      => "arm_shift_modifier mod, tarval *shf",
198   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
199   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
200   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
201   "emit"      => '. AND %D1, %S1, %S2%X0 /* And(%S1, %S2) -> %D1, (%A1, %A2) */'
202 },
203
204 "And_i" => {
205   "irn_flags" => "R",
206   "comment"   => "construct And: And(a, const) = And(const, a) = a AND const",
207   "attr"      => "tarval *tv",
208   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
209   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
210   "emit"      => '. AND %D1, %S1, %C /* And(%C, %S1) -> %D1, (%A1, const) */',
211   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
212 },
213
214 "Or" => {
215   "op_flags"  => "C",
216   "irn_flags" => "R",
217   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
218   "attr"      => "arm_shift_modifier mod, tarval *shf",
219   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
220   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
221   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
222   "emit"      => '. ORR %D1, %S1, %S2%X0 /* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
223 },
224
225 "Or_i" => {
226   "irn_flags" => "R",
227   "comment"   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
228   "attr"      => "tarval *tv",
229   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
230   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
231   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
232   "emit"      => '. ORR %D1, %S1, %C /* Or(%C, %S1) -> %D1, (%A1, const) */'
233 },
234
235 "Eor" => {
236   "op_flags"  => "C",
237   "irn_flags" => "R",
238   "comment"   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
239   "attr"      => "arm_shift_modifier mod, tarval *shf",
240   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
241   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
242   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
243   "emit"      => '. EOR %D1, %S1, %S2%X0 /* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
244 },
245
246 "Eor_i" => {
247   "irn_flags" => "R",
248   "comment"   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
249   "attr"      => "tarval *tv",
250   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
251   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
252   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
253   "emit"      => '. EOR %D1, %S1, %C /* Xor(%C, %S1) -> %D1, (%A1, const) */'
254 },
255
256 # not commutative operations
257
258 "Bic" => {
259   "irn_flags" => "R",
260   "comment"   => "construct Bic: Bic(a, b) = a AND ~b",
261   "attr"      => "arm_shift_modifier mod, tarval *shf",
262   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
263   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
264   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
265   "emit"      => '. BIC %D1, %S1, %S2%X0 /* AndNot(%S1, %S2) -> %D1, (%A1, %A2) */'
266 },
267
268 "Bic_i" => {
269   "irn_flags" => "R",
270   "comment"   => "construct Bic: Bic(a, const) = a AND ~const",
271   "attr"      => "tarval *tv",
272   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
273   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
274   "emit"      => '. BIC %D1, %S1, %C /* AndNot(%C, %S1) -> %D1, (%A1, const) */',
275   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
276 },
277
278 "Sub" => {
279   "irn_flags" => "R",
280   "comment"   => "construct Sub: Sub(a, b) = a - b",
281   "attr"      => "arm_shift_modifier mod, tarval *shf",
282   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
283   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
284   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
285   "emit"      => '. SUB %D1, %S1, %S2%X0 /* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
286 },
287
288 "Sub_i" => {
289   "irn_flags" => "R",
290   "comment"   => "construct Sub: Sub(a, const) = a - const",
291   "attr"      => "tarval *tv",
292   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
293   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
294   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
295   "emit"      => '. SUB %D1, %S1, %C /* Sub(%S1, %C) -> %D1, (%A1, const) */',
296 },
297
298 "Rsb" => {
299   "irn_flags" => "R",
300   "comment"   => "construct Rsb: Rsb(a, b) = b - a",
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"      => '. RSB %D1, %S1, %S2%X0 /* Rsb(%S1, %S2) -> %D1, (%A1, %A2) */'
306 },
307
308 "Rsb_i" => {
309   "irn_flags" => "R",
310   "comment"   => "construct Rsb: Rsb(a, const) = const - a",
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"      => '. RSB %D1, %S1, %C /* Rsb(%S1, %C) -> %D1, (%A1, const) */',
315   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
316 },
317
318 "Shl" => {
319   "irn_flags" => "R",
320   "comment"   => "construct Shl: Shl(a, b) = a << b",
321   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
322   "emit"      => '. MOV %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
323 },
324
325 "Shr" => {
326   "irn_flags" => "R",
327   "comment"   => "construct Shr: Shr(a, b) = a >> b",
328   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
329   "emit"      => '. MOV %D1, %S1, LSR %S2 /* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
330 },
331
332 "Shrs" => {
333   "irn_flags" => "R",
334   "comment"   => "construct Shrs: Shrs(a, b) = a >> b",
335   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
336   "emit"      => '. MOV %D1, %S1, ASR %S2\t\t /* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */'
337 },
338
339 #"RotR" => {
340 #  "irn_flags" => "R",
341 #  "comment"   => "construct RotR: RotR(a, b) = a ROTR b",
342 #  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
343 #  "emit"      => '. MOV %D1, %S1, ROR %S2 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
344 ##  "emit"      => '. ror %S1, %S2, %D1 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
345 #},
346
347 #"RotL" => {
348 #  "irn_flags" => "R",
349 #  "comment"   => "construct RotL: RotL(a, b) = a ROTL b",
350 #  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
351 #  "emit"      => '. rol %S1, %S2, %D1 /* RotL(%S1, %S2) -> %D1, (%A1, %A2) */'
352 #},
353
354 #"RotL_i" => {
355 #  "irn_flags" => "R",
356 #  "comment"   => "construct RotL: RotL(a, const) = a ROTL const",
357 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
358 #  "emit"      => '. rol %S1, %C, %D1 /* RotL(%S1, %C) -> %D1, (%A1, const) */'
359 #},
360
361 "Mov" => {
362   "irn_flags" => "R",
363   "comment"   => "construct Mov: a = b",
364   "attr"      => "arm_shift_modifier mod, tarval *shf",
365   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
366   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
367   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
368   "emit"      => '. MOV %D1, %S1%X0\t/* Mov(%S1%X0) -> %D1, (%A1) */'
369 },
370
371 "Mov_i" => {
372   "irn_flags" => "R",
373   "comment"   => "represents an integer constant",
374   "attr"      => "tarval *tv",
375   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
376   "reg_req"   => { "out" => [ "gp" ] },
377   "emit"      => '. MOV %D1, %C   /* Mov Const into register */',
378   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
379 },
380
381 "Mvn" => {
382   "irn_flags" => "R",
383   "comment"   => "construct Not: Not(a) = !a",
384   "attr"      => "arm_shift_modifier mod, tarval *shf",
385   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
386   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
387   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
388   "emit"      => '. MVN %D1, %S1%X0 /* ~(%S1%X0) -> %D1, (%A1) */'
389 },
390
391 "Mvn_i" => {
392   "irn_flags" => "R",
393   "comment"   => "represents a negated integer constant",
394   "attr"      => "tarval *tv",
395   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
396   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
397   "reg_req"   => { "out" => [ "gp" ] },
398   "emit"      => '. MVN %D1, %C   /* Mov ~Const into register */',
399 },
400
401 "Abs" => {
402   "irn_flags" => "R",
403   "comment"   => "construct Abs: Abs(a) = |a|",
404   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
405   "emit"      =>
406 '. MOVS %S1, %S1, #0 /* set condition flag */\n
407 . RSBMI %D1, %S1, #0 /* Neg(%S1) -> %D1, (%A1) */'
408 },
409
410 # other operations
411
412 "EmptyReg" => {
413   "op_flags"  => "c",
414   "irn_flags" => "R",
415   "comment"  => "just to get an empty register for calculations",
416   "reg_req"  => { "out" => [ "gp" ] },
417   "emit"      => '. /* %D1 now available for calculations */',
418   "cmp_attr"  => 'return 1;'
419 },
420
421 "Copy" => {
422   "comment"  => "implements a register copy",
423   "reg_req"  => { "in" => [ "gp" ], "out" => [ "gp" ] },
424 },
425
426 "CopyB" => {
427   "op_flags" => "F|H",
428   "state"    => "pinned",
429   "comment"  => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
430   "reg_req"  => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
431 },
432
433 "SymConst" => {
434   "op_flags"  => "c",
435   "irn_flags" => "R",
436   "comment"   => "represents a symbolic constant",
437   "attr"      => "const char *label",
438   "init_attr" => '  attr->symconst_label = label;',
439   "reg_req"   => { "out" => [ "gp" ] },
440 #  "emit"      => '. LDR %D1, %C /* Mov Const into register */',
441   "cmp_attr"  =>
442 '  /* should be identical but ...*/
443    return strcmp(attr_a->symconst_label, attr_b->symconst_label);'
444 },
445
446 "CondJmp" => {
447   "op_flags"  => "L|X|Y",
448   "comment"   => "construct conditional jump: CMP A, B && JMPxx LABEL",
449   "cmp_attr"  => "  return arm_comp_condJmp(attr_a, attr_b);\n",
450   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
451 },
452
453 "SwitchJmp" => {
454   "op_flags"  => "L|X|Y",
455   "comment"   => "construct switch",
456   "reg_req"   => { "in" => [ "gp" ], "out" => [ "none" ] },
457   "cmp_attr"  => "  return 0;\n",
458 },
459
460 # Load / Store
461
462 "Load" => {
463   "op_flags"  => "L|F",
464   "irn_flags" => "R",
465   "state"     => "exc_pinned",
466   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
467   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp" ] },
468   "emit"      => '. LDR %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */'
469 #  "emit"      => '. LDR %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */'
470 },
471
472 "Loadb" => {
473   "op_flags"  => "L|F",
474   "irn_flags" => "R",
475   "state"     => "exc_pinned",
476   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
477   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp" ] },
478   "emit"      => '. LDRB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */'
479 #  "emit"      => '. LDRB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */'
480 },
481
482 "Loadbs" => {
483   "op_flags"  => "L|F",
484   "irn_flags" => "R",
485   "state"     => "exc_pinned",
486   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
487   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp" ] },
488   "emit"      => '. LDRSB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */'
489 #  "emit"      => '. LDRSB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */'
490 },
491
492 "Loadh" => {
493   "op_flags"  => "L|F",
494   "irn_flags" => "R",
495   "state"     => "exc_pinned",
496   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
497   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp" ] },
498   "emit"      => '. LDRH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */'
499 #  "emit"      => '. LDRH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */'
500 },
501
502 "Loadhs" => {
503   "op_flags"  => "L|F",
504   "irn_flags" => "R",
505   "state"     => "exc_pinned",
506   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
507   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp" ] },
508   "emit"      => '. LDRSH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */'
509 #  "emit"      => '. LDRSH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */'
510 },
511
512 "Storeb" => {
513   "op_flags"  => "L|F",
514   "irn_flags" => "R",
515   "state"     => "exc_pinned",
516   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
517   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
518   "emit"      => '. STRB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */'
519 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */'
520 },
521
522 "Storebs" => {
523   "op_flags"  => "L|F",
524   "irn_flags" => "R",
525   "state"     => "exc_pinned",
526   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
527   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
528   "emit"      => '. STRSB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */'
529 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */'
530 },
531
532 "Storeh" => {
533   "op_flags"  => "L|F",
534   "irn_flags" => "R",
535   "state"     => "exc_pinned",
536   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
537   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
538   "emit"      => '. STRH %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */'
539 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */'
540 },
541
542 "Storehs" => {
543   "op_flags"  => "L|F",
544   "irn_flags" => "R",
545   "state"     => "exc_pinned",
546   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
547   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
548   "emit"      => '. STRSH%S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */'
549 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */'
550 },
551
552 "Store" => {
553   "op_flags"  => "L|F",
554   "irn_flags" => "R",
555   "state"     => "exc_pinned",
556   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
557   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
558   "emit"      => '. STR %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */'
559 #  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */'
560 },
561
562 "StoreStackM4Inc" => {
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" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
568   "emit"      => '. STMFD %S1!, {%S2, %S3, %S4, %S5} /* Store multiple on Stack*/'
569 },
570
571 "LoadStackM3" => {
572   "op_flags"  => "L|F",
573   "irn_flags" => "R",
574   "state"     => "exc_pinned",
575   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
576   "reg_req"   => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] },
577   "emit"      => '. LDMFD %S1, {%D1, %D2, %D3} /* Load multiple from Stack */'
578 },
579
580
581
582
583
584
585
586
587 #--------------------------------------------------------#
588 #    __ _             _                     _            #
589 #   / _| |           | |                   | |           #
590 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
591 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
592 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
593 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
594 #--------------------------------------------------------#
595
596 # commutative operations
597
598 "fAdd" => {
599   "op_flags"  => "C",
600   "irn_flags" => "R",
601   "comment"   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
602   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
603   "emit"      => '. FADD%Mx %D1, %S1, %S2 /* FP Add(%S1, %S2) -> %D1 */'
604 },
605
606 "fMul" => {
607   "op_flags"  => "C",
608   "comment"   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
609   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
610   "emit"      =>'. FMUL%Mx %D1, %S1, %S2 /* FP Mul(%S1, %S2) -> %D1 */'
611 },
612
613 "fDiv" => {
614   "comment"   => "construct FP Div: Div(a, b) = a / b",
615   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
616   "emit"      =>'. FDIV%Mx %D1, %S1, %S2 /* FP Div(%S1, %S2) -> %D1 */'
617 },
618
619 "fMax" => {
620   "op_flags"  => "C",
621   "irn_flags" => "R",
622   "comment"   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
623   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
624   "emit"      =>'. fmax %S1, %S2, %D1 /* FP Max(%S1, %S2) -> %D1 */'
625 },
626
627 "fMin" => {
628   "op_flags"  => "C",
629   "irn_flags" => "R",
630   "comment"   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
631   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
632   "emit"      =>'. fmin %S1, %S2, %D1 /* FP Min(%S1, %S2) -> %D1 */'
633 },
634
635 # not commutative operations
636
637 "fSub" => {
638   "irn_flags" => "R",
639   "comment"   => "construct FP Sub: Sub(a, b) = a - b",
640   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
641   "emit"      => '. FSUB%Mx %D1, %S1, %S2 /* FP Sub(%S1, %S2) -> %D1 */'
642 },
643
644 "fNeg" => {
645   "irn_flags" => "R",
646   "comment"   => "construct FP Neg: Neg(a) = -a",
647   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
648   "emit"      => '. fneg %S1, %D1 /* FP Neg(%S1) -> %D1 */'
649 },
650
651 "fAbs" => {
652   "irn_flags" => "R",
653   "comment"   => "construct FP Absolute value: fAbsd(a) = |a|",
654   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
655   "emit"      => '. FABS%Mx %D1, %S1 /* FP Absd(%S1) -> %D1 */'
656 },
657
658 # other operations
659
660 "fConst" => {
661   "op_flags"  => "c",
662   "irn_flags" => "R",
663   "comment"   => "represents a FP constant",
664   "attr"      => "tarval *val",
665   "init_attr" => 'attr->value = val;',
666   "reg_req"   => { "out" => [ "fp" ] },
667   "emit"      => '. FMOV %D1, %C /* Mov fConst into register */',
668   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
669 },
670
671 "fConvD2S" => {
672   "irn_flags" => "R",
673   "comment"   => "convert double to single",
674   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
675   "emit"      => '. FCVTSD %D1, %S1 /* Convert double to single */',
676 },
677
678 "fConvS2D" => {
679   "irn_flags" => "R",
680   "comment"   => "convert single to double",
681   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
682   "emit"      => '. FCVTDS %D1, %S1 /* Convert single to double */',
683 },
684
685
686 # Load / Store
687
688 "fLoad" => {
689   "op_flags"  => "L|F",
690   "irn_flags" => "R",
691   "state"     => "exc_pinned",
692   "comment"   => "construct FP Load: Load(ptr, mem) = LD ptr",
693   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "fp" ] },
694   "emit"      => '. FLD%Mx %D1, %S1 /* Load((%S1)) -> %D1 */'
695 },
696
697 "fStore" => {
698   "op_flags"  => "L|F",
699   "irn_flags" => "R",
700   "state"     => "exc_pinned",
701   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
702   "reg_req"   => { "in" => [ "gp", "fp", "none" ] },
703   "emit"      => '. FST%Mx %S2, %S1 /* Store(%S2) -> (%S1), (%A1, %A2) */'
704 },
705
706 ); # end of %nodes