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