f9bb46a289673e779c8937db1b6827e0f5e5bf96
[libfirm] / ir / be / arm / bearch_arm.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /* The main arm backend driver file. */
21 /* $Id$ */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <libcore/lc_opts.h>
28 #include <libcore/lc_opts_enum.h>
29
30 #include "pseudo_irg.h"
31 #include "irgwalk.h"
32 #include "irprog.h"
33 #include "irprintf.h"
34 #include "ircons.h"
35 #include "irgmod.h"
36 #include "lower_intrinsics.h"
37
38 #include "bitset.h"
39 #include "debug.h"
40
41 #include "../bearch_t.h"                /* the general register allocator interface */
42 #include "../benode_t.h"
43 #include "../belower.h"
44 #include "../besched_t.h"
45 #include "../be.h"
46 #include "../beabi.h"
47 #include "../bemachine.h"
48 #include "../beilpsched.h"
49 #include "../bemodule.h"
50 #include "../beirg_t.h"
51
52 #include "bearch_arm_t.h"
53
54 #include "arm_new_nodes.h"           /* arm nodes interface */
55 #include "gen_arm_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
56 #include "arm_gen_decls.h"           /* interface declaration emitter */
57 #include "arm_transform.h"
58 #include "arm_emitter.h"
59 #include "arm_map_regs.h"
60
61 #define DEBUG_MODULE "firm.be.arm.isa"
62
63 /* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
64 static set *cur_reg_set = NULL;
65
66 /**************************************************
67  *                         _ _              _  __
68  *                        | | |            (_)/ _|
69  *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
70  * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
71  * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
72  * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
73  *            __/ |
74  *           |___/
75  **************************************************/
76
77 /**
78  * Return register requirements for a arm node.
79  * If the node returns a tuple (mode_T) then the proj's
80  * will be asked for this information.
81  */
82 static const
83 arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node,
84                                          int pos) {
85         long               node_pos = pos == -1 ? 0 : pos;
86         ir_mode           *mode     = get_irn_mode(node);
87         FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
88
89         if (is_Block(node) || mode == mode_X || mode == mode_M) {
90                 DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", node));
91                 return arch_no_register_req;
92         }
93
94         if (mode == mode_T && pos < 0) {
95                 DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", node));
96                 return arch_no_register_req;
97         }
98
99         DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, node));
100
101         if (is_Proj(node)) {
102                 /* in case of a proj, we need to get the correct OUT slot */
103                 /* of the node corresponding to the proj number */
104                 if (pos == -1) {
105                         node_pos = arm_translate_proj_pos(node);
106                 }
107                 else {
108                         node_pos = pos;
109                 }
110
111                 node = skip_Proj_const(node);
112
113                 DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", node, node_pos));
114         }
115
116         /* get requirements for our own nodes */
117         if (is_arm_irn(node)) {
118                 const arch_register_req_t *req;
119                 if (pos >= 0) {
120                         req = get_arm_in_req(node, pos);
121                 } else {
122                         req = get_arm_out_req(node, node_pos);
123                 }
124
125                 DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", node, pos));
126                 return req;
127         }
128
129         /* unknown should be tranformed by now */
130         assert(!is_Unknown(node));
131         DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", node));
132
133         return arch_no_register_req;
134 }
135
136 static void arm_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
137         int pos = 0;
138
139         if (is_Proj(irn)) {
140
141                 if (get_irn_mode(irn) == mode_X) {
142                         return;
143                 }
144
145                 pos = arm_translate_proj_pos(irn);
146                 irn = skip_Proj(irn);
147         }
148
149         if (is_arm_irn(irn)) {
150                 const arch_register_t **slots;
151
152                 slots      = get_arm_slots(irn);
153                 slots[pos] = reg;
154         }
155         else {
156                 /* here we set the registers for the Phi nodes */
157                 arm_set_firm_reg(irn, reg, cur_reg_set);
158         }
159 }
160
161 static const arch_register_t *arm_get_irn_reg(const void *self, const ir_node *irn) {
162         int pos = 0;
163         const arch_register_t *reg = NULL;
164
165         if (is_Proj(irn)) {
166
167                 if (get_irn_mode(irn) == mode_X) {
168                         return NULL;
169                 }
170
171                 pos = arm_translate_proj_pos(irn);
172                 irn = skip_Proj_const(irn);
173         }
174
175         if (is_arm_irn(irn)) {
176                 const arch_register_t **slots;
177                 slots = get_arm_slots(irn);
178                 reg   = slots[pos];
179         }
180         else {
181                 reg = arm_get_firm_reg(irn, cur_reg_set);
182         }
183
184         return reg;
185 }
186
187 static arch_irn_class_t arm_classify(const void *self, const ir_node *irn) {
188         irn = skip_Proj_const(irn);
189
190         if (is_cfop(irn)) {
191                 return arch_irn_class_branch;
192         }
193         else if (is_arm_irn(irn)) {
194                 return arch_irn_class_normal;
195         }
196
197         return 0;
198 }
199
200 static arch_irn_flags_t arm_get_flags(const void *self, const ir_node *irn) {
201         irn = skip_Proj_const(irn);
202
203         if (is_arm_irn(irn)) {
204                 return get_arm_flags(irn);
205         }
206         else if (is_Unknown(irn)) {
207                 return arch_irn_flags_ignore;
208         }
209
210         return 0;
211 }
212
213 static ir_entity *arm_get_frame_entity(const void *self, const ir_node *irn) {
214         /* TODO: return the entity assigned to the frame */
215         return NULL;
216 }
217
218 static void arm_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent) {
219         /* TODO: set the entity assigned to the frame */
220 }
221
222 /**
223  * This function is called by the generic backend to correct offsets for
224  * nodes accessing the stack.
225  */
226 static void arm_set_stack_bias(const void *self, ir_node *irn, int bias) {
227         /* TODO: correct offset if irn accesses the stack */
228 }
229
230 static int arm_get_sp_bias(const void *self, const ir_node *irn) {
231         return 0;
232 }
233
234 /* fill register allocator interface */
235
236 static const arch_irn_ops_if_t arm_irn_ops_if = {
237         arm_get_irn_reg_req,
238         arm_set_irn_reg,
239         arm_get_irn_reg,
240         arm_classify,
241         arm_get_flags,
242         arm_get_frame_entity,
243         arm_set_frame_entity,
244         arm_set_stack_bias,
245         arm_get_sp_bias,
246         NULL,    /* get_inverse             */
247         NULL,    /* get_op_estimated_cost   */
248         NULL,    /* possible_memory_operand */
249         NULL,    /* perform_memory_operand  */
250 };
251
252 arm_irn_ops_t arm_irn_ops = {
253         &arm_irn_ops_if,
254         NULL
255 };
256
257
258
259 /**************************************************
260  *                _                         _  __
261  *               | |                       (_)/ _|
262  *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
263  *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
264  * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
265  *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
266  *                        __/ |
267  *                       |___/
268  **************************************************/
269
270 /**
271  * Transforms the standard Firm graph into
272  * a ARM firm graph.
273  */
274 static void arm_prepare_graph(void *self) {
275         arm_code_gen_t *cg = self;
276
277         arm_register_transformers();
278         irg_walk_blkwise_graph(cg->irg, arm_move_consts, arm_transform_node, cg);
279 }
280
281
282
283 /**
284  * Called immediately before emit phase.
285  */
286 static void arm_finish_irg(void *self) {
287         /* TODO: - fix offsets for nodes accessing stack
288                          - ...
289         */
290 }
291
292
293 /**
294  * These are some hooks which must be filled but are probably not needed.
295  */
296 static void arm_before_sched(void *self) {
297         /* Some stuff you need to do after scheduling but before register allocation */
298 }
299
300 static void arm_before_ra(void *self) {
301         /* Some stuff you need to do immediately after register allocation */
302 }
303
304
305 /**
306  * Emits the code, closes the output file and frees
307  * the code generator interface.
308  */
309 static void arm_emit_and_done(void *self) {
310         arm_code_gen_t *cg = self;
311         ir_graph           *irg = cg->irg;
312         FILE               *out = cg->isa->out;
313
314         if (cg->emit_decls) {
315                 arm_gen_decls(out);
316                 cg->emit_decls = 0;
317         }
318
319         dump_ir_block_graph_sched(irg, "-arm-finished");
320         arm_gen_routine(out, irg, cg);
321
322         cur_reg_set = NULL;
323
324         /* de-allocate code generator */
325         del_set(cg->reg_set);
326         free(self);
327 }
328
329 /**
330  * Move a double floating point value into an integer register.
331  * Place the move operation into block bl.
332  *
333  * Handle some special cases here:
334  * 1.) A constant: simply split into two
335  * 2.) A load: siply split into two
336  */
337 static ir_node *convert_dbl_to_int(ir_node *bl, ir_node *arg, ir_node *mem,
338                                    ir_node **resH, ir_node **resL) {
339         if (is_Const(arg)) {
340                 tarval *tv = get_Const_tarval(arg);
341                 unsigned v;
342
343                 /* get the upper 32 bits */
344                 v =            get_tarval_sub_bits(tv, 7);
345                 v = (v << 8) | get_tarval_sub_bits(tv, 6);
346                 v = (v << 8) | get_tarval_sub_bits(tv, 5);
347                 v = (v << 8) | get_tarval_sub_bits(tv, 4);
348                 *resH = new_Const_long(mode_Is, v);
349
350                 /* get the lower 32 bits */
351                 v =            get_tarval_sub_bits(tv, 3);
352                 v = (v << 8) | get_tarval_sub_bits(tv, 2);
353                 v = (v << 8) | get_tarval_sub_bits(tv, 1);
354                 v = (v << 8) | get_tarval_sub_bits(tv, 0);
355                 *resL = new_Const_long(mode_Is, v);
356         }
357         else if (get_irn_op(skip_Proj(arg)) == op_Load) {
358                 /* FIXME: handling of low/high depends on LE/BE here */
359                 assert(0);
360         }
361         else {
362                 ir_graph *irg = current_ir_graph;
363                 ir_node *conv;
364
365                 conv = new_rd_arm_fpaDbl2GP(NULL, irg, bl, arg, mem);
366                 /* move high/low */
367                 *resL = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_low);
368                 *resH = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_high);
369                 mem   = new_r_Proj(irg, bl, conv, mode_M,  pn_arm_fpaDbl2GP_M);
370         }
371         return mem;
372 }
373
374 /**
375  * Move a single floating point value into an integer register.
376  * Place the move operation into block bl.
377  *
378  * Handle some special cases here:
379  * 1.) A constant: simply move
380  * 2.) A load: siply load
381  */
382 static ir_node *convert_sng_to_int(ir_node *bl, ir_node *arg) {
383         if (is_Const(arg)) {
384                 tarval *tv = get_Const_tarval(arg);
385                 unsigned v;
386
387                 /* get the lower 32 bits */
388                 v =            get_tarval_sub_bits(tv, 3);
389                 v = (v << 8) | get_tarval_sub_bits(tv, 2);
390                 v = (v << 8) | get_tarval_sub_bits(tv, 1);
391                 v = (v << 8) | get_tarval_sub_bits(tv, 0);
392                 return new_Const_long(mode_Is, v);
393         }
394         else if (get_irn_op(skip_Proj(arg)) == op_Load) {
395                 ir_node *load;
396
397                 load = skip_Proj(arg);
398         }
399         assert(0);
400         return NULL;
401 }
402
403 /**
404  * Convert the arguments of a call to support the
405  * ARM calling convention of general purpose AND floating
406  * point arguments.
407  */
408 static void handle_calls(ir_node *call, void *env)
409 {
410         arm_code_gen_t *cg = env;
411         int i, j, n, size, idx, flag, n_param, n_res;
412         ir_type *mtp, *new_mtd, *new_tp[5];
413         ir_node *new_in[5], **in;
414         ir_node *bl;
415
416         if (! is_Call(call))
417                 return;
418
419         /* check, if we need conversions */
420         n = get_Call_n_params(call);
421         mtp = get_Call_type(call);
422         assert(get_method_n_params(mtp) == n);
423
424         /* it's always enough to handle the first 4 parameters */
425         if (n > 4)
426                 n = 4;
427         flag = size = idx = 0;
428         bl = get_nodes_block(call);
429         for (i = 0; i < n; ++i) {
430                 ir_type *param_tp = get_method_param_type(mtp, i);
431
432                 if (is_compound_type(param_tp)) {
433                         /* an aggregate parameter: bad case */
434                         assert(0);
435                 }
436                 else {
437                         /* a primitive parameter */
438                         ir_mode *mode = get_type_mode(param_tp);
439
440                         if (mode_is_float(mode)) {
441                                 if (get_mode_size_bits(mode) > 32) {
442                                         ir_node *mem = get_Call_mem(call);
443
444                                         /* Beware: ARM wants the high part first */
445                                         size += 2 * 4;
446                                         new_tp[idx]   = cg->int_tp;
447                                         new_tp[idx+1] = cg->int_tp;
448                                         mem = convert_dbl_to_int(bl, get_Call_param(call, i), mem, &new_in[idx], &new_in[idx+1]);
449                                         idx += 2;
450                                         set_Call_mem(call, mem);
451                                 }
452                                 else {
453                                         size += 4;
454                                         new_tp[idx] = cg->int_tp;
455                                         new_in[idx] = convert_sng_to_int(bl, get_Call_param(call, i));
456                                         ++idx;
457                                 }
458                                 flag = 1;
459                         }
460                         else {
461                                 size += 4;
462                                 new_tp[idx] = param_tp;
463                                 new_in[idx] = get_Call_param(call, i);
464                                 ++idx;
465                         }
466                 }
467
468                 if (size >= 16)
469                         break;
470         }
471
472         /* if flag is NOT set, no need to translate the method type */
473         if (! flag)
474                 return;
475
476         /* construct a new method type */
477         n       = i;
478         n_param = get_method_n_params(mtp) - n + idx;
479         n_res   = get_method_n_ress(mtp);
480         new_mtd = new_d_type_method(get_type_ident(mtp), n_param, n_res, get_type_dbg_info(mtp));
481
482         for (i = 0; i < idx; ++i)
483                 set_method_param_type(new_mtd, i, new_tp[i]);
484         for (i = n, j = idx; i < get_method_n_params(mtp); ++i)
485                 set_method_param_type(new_mtd, j++, get_method_param_type(mtp, i));
486         for (i = 0; i < n_res; ++i)
487                 set_method_res_type(new_mtd, i, get_method_res_type(mtp, i));
488
489         set_method_calling_convention(new_mtd, get_method_calling_convention(mtp));
490         set_method_first_variadic_param_index(new_mtd, get_method_first_variadic_param_index(mtp));
491
492         if (is_lowered_type(mtp)) {
493                 mtp = get_associated_type(mtp);
494         }
495         set_lowered_type(mtp, new_mtd);
496
497         set_Call_type(call, new_mtd);
498
499         /* calculate new in array of the Call */
500         NEW_ARR_A(ir_node *, in, n_param + 2);
501         for (i = 0; i < idx; ++i)
502                 in[2 + i] = new_in[i];
503         for (i = n, j = idx; i < get_method_n_params(mtp); ++i)
504                 in[2 + j++] = get_Call_param(call, i);
505
506         in[0] = get_Call_mem(call);
507         in[1] = get_Call_ptr(call);
508
509         /* finally, change the call inputs */
510         set_irn_in(call, n_param + 2, in);
511 }
512
513 /**
514  * Handle graph transformations before the abi converter does its work.
515  */
516 static void arm_before_abi(void *self) {
517         arm_code_gen_t *cg = self;
518
519         irg_walk_graph(cg->irg, NULL, handle_calls, cg);
520 }
521
522 static void *arm_cg_init(be_irg_t *birg);
523
524 static const arch_code_generator_if_t arm_code_gen_if = {
525         arm_cg_init,
526         arm_before_abi,     /* before abi introduce */
527         arm_prepare_graph,
528         NULL,               /* spill */
529         arm_before_sched,   /* before scheduling hook */
530         arm_before_ra,      /* before register allocation hook */
531         NULL,               /* after register allocation */
532         arm_finish_irg,
533         arm_emit_and_done,
534 };
535
536 /**
537  * Initializes the code generator.
538  */
539 static void *arm_cg_init(be_irg_t *birg) {
540         static ir_type *int_tp = NULL;
541         arm_isa_t      *isa = (arm_isa_t *)birg->main_env->arch_env->isa;
542         arm_code_gen_t *cg;
543
544         if (! int_tp) {
545                 /* create an integer type with machine size */
546                 int_tp = new_type_primitive(new_id_from_chars("int", 3), mode_Is);
547         }
548
549         cg = xmalloc(sizeof(*cg));
550         cg->impl     = &arm_code_gen_if;
551         cg->irg      = birg->irg;
552         cg->reg_set  = new_set(arm_cmp_irn_reg_assoc, 1024);
553         cg->arch_env = birg->main_env->arch_env;
554         cg->isa      = isa;
555         cg->birg     = birg;
556         cg->int_tp   = int_tp;
557         cg->have_fp  = 0;
558
559         FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
560
561         isa->num_codegens++;
562
563         if (isa->num_codegens > 1)
564                 cg->emit_decls = 0;
565         else
566                 cg->emit_decls = 1;
567
568         cur_reg_set = cg->reg_set;
569
570         arm_irn_ops.cg = cg;
571
572         /* enter the current code generator */
573         isa->cg = cg;
574
575         return (arch_code_generator_t *)cg;
576 }
577
578
579 /**
580  * Maps all intrinsic calls that the backend support
581  * and map all instructions the backend did not support
582  * to runtime calls.
583  */
584 static void arm_handle_intrinsics(void) {
585   ir_type *tp, *int_tp, *uint_tp;
586   i_record records[8];
587   int n_records = 0;
588
589 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
590
591   int_tp  = new_type_primitive(ID("int"), mode_Is);
592   uint_tp = new_type_primitive(ID("uint"), mode_Iu);
593
594         /* ARM has neither a signed div instruction ... */
595   {
596     runtime_rt rt_Div;
597     i_instr_record *map_Div = &records[n_records++].i_instr;
598
599     tp = new_type_method(ID("rt_iDiv"), 2, 1);
600     set_method_param_type(tp, 0, int_tp);
601     set_method_param_type(tp, 1, int_tp);
602     set_method_res_type(tp, 0, int_tp);
603
604     rt_Div.ent             = new_entity(get_glob_type(), ID("__divsi3"), tp);
605     rt_Div.mode            = mode_T;
606     rt_Div.mem_proj_nr     = pn_Div_M;
607     rt_Div.exc_proj_nr     = pn_Div_X_except;
608     rt_Div.exc_mem_proj_nr = pn_Div_M;
609     rt_Div.res_proj_nr     = pn_Div_res;
610
611     set_entity_visibility(rt_Div.ent, visibility_external_allocated);
612
613     map_Div->kind     = INTRINSIC_INSTR;
614     map_Div->op       = op_Div;
615     map_Div->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
616     map_Div->ctx      = &rt_Div;
617   }
618         /* ... nor a signed div instruction ... */
619   {
620     runtime_rt rt_Div;
621     i_instr_record *map_Div = &records[n_records++].i_instr;
622
623     tp = new_type_method(ID("rt_uDiv"), 2, 1);
624     set_method_param_type(tp, 0, uint_tp);
625     set_method_param_type(tp, 1, uint_tp);
626     set_method_res_type(tp, 0, uint_tp);
627
628     rt_Div.ent             = new_entity(get_glob_type(), ID("__udivsi3"), tp);
629     rt_Div.mode            = mode_T;
630     rt_Div.mem_proj_nr     = pn_Div_M;
631     rt_Div.exc_proj_nr     = pn_Div_X_except;
632     rt_Div.exc_mem_proj_nr = pn_Div_M;
633     rt_Div.res_proj_nr     = pn_Div_res;
634
635     set_entity_visibility(rt_Div.ent, visibility_external_allocated);
636
637     map_Div->kind     = INTRINSIC_INSTR;
638     map_Div->op       = op_Div;
639     map_Div->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
640     map_Div->ctx      = &rt_Div;
641   }
642         /* ... nor a signed mod instruction ... */
643   {
644     runtime_rt rt_Mod;
645     i_instr_record *map_Mod = &records[n_records++].i_instr;
646
647     tp = new_type_method(ID("rt_iMod"), 2, 1);
648     set_method_param_type(tp, 0, int_tp);
649     set_method_param_type(tp, 1, int_tp);
650     set_method_res_type(tp, 0, int_tp);
651
652     rt_Mod.ent             = new_entity(get_glob_type(), ID("__modsi3"), tp);
653     rt_Mod.mode            = mode_T;
654     rt_Mod.mem_proj_nr     = pn_Mod_M;
655     rt_Mod.exc_proj_nr     = pn_Mod_X_except;
656     rt_Mod.exc_mem_proj_nr = pn_Mod_M;
657     rt_Mod.res_proj_nr     = pn_Mod_res;
658
659     set_entity_visibility(rt_Mod.ent, visibility_external_allocated);
660
661     map_Mod->kind     = INTRINSIC_INSTR;
662     map_Mod->op       = op_Mod;
663     map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
664     map_Mod->ctx      = &rt_Mod;
665   }
666         /* ... nor a unsigned mod. */
667   {
668     runtime_rt rt_Mod;
669     i_instr_record *map_Mod = &records[n_records++].i_instr;
670
671     tp = new_type_method(ID("rt_uMod"), 2, 1);
672     set_method_param_type(tp, 0, uint_tp);
673     set_method_param_type(tp, 1, uint_tp);
674     set_method_res_type(tp, 0, uint_tp);
675
676     rt_Mod.ent             = new_entity(get_glob_type(), ID("__umodsi3"), tp);
677     rt_Mod.mode            = mode_T;
678     rt_Mod.mem_proj_nr     = pn_Mod_M;
679     rt_Mod.exc_proj_nr     = pn_Mod_X_except;
680     rt_Mod.exc_mem_proj_nr = pn_Mod_M;
681     rt_Mod.res_proj_nr     = pn_Mod_res;
682
683     set_entity_visibility(rt_Mod.ent, visibility_external_allocated);
684
685     map_Mod->kind     = INTRINSIC_INSTR;
686     map_Mod->op       = op_Mod;
687     map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
688     map_Mod->ctx      = &rt_Mod;
689   }
690
691   if (n_records > 0)
692     lower_intrinsics(records, n_records);
693 }
694
695 /*****************************************************************
696  *  ____             _                  _   _____  _____
697  * |  _ \           | |                | | |_   _|/ ____|  /\
698  * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
699  * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
700  * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
701  * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
702  *
703  *****************************************************************/
704
705 static arm_isa_t arm_isa_template = {
706         &arm_isa_if,           /* isa interface */
707         &arm_gp_regs[REG_SP],  /* stack pointer */
708         &arm_gp_regs[REG_R11], /* base pointer */
709         -1,                    /* stack direction */
710         0,                     /* number of codegenerator objects */
711         0,                     /* use generic register names instead of SP, LR, PC */
712         NULL,                  /* current code generator */
713         NULL,                  /* output file */
714         ARM_FPU_ARCH_FPE,      /* FPU architecture */
715 };
716
717 /**
718  * Initializes the backend ISA and opens the output file.
719  */
720 static void *arm_init(FILE *file_handle) {
721         static int inited = 0;
722         arm_isa_t *isa;
723
724         if(inited)
725                 return NULL;
726
727         isa = xmalloc(sizeof(*isa));
728         memcpy(isa, &arm_isa_template, sizeof(*isa));
729
730         arm_register_init(isa);
731
732         isa->cg  = NULL;
733         isa->out = file_handle;
734
735         arm_create_opcodes();
736         arm_handle_intrinsics();
737         arm_switch_section(NULL, NO_SECTION);
738
739         inited = 1;
740         return isa;
741 }
742
743
744
745 /**
746  * frees the ISA structure.
747  */
748 static void arm_done(void *self) {
749         free(self);
750 }
751
752
753 /**
754  * Report the number of register classes.
755  * If we don't have fp instructions, report only GP
756  * here to speed up register allocation (and makes dumps
757  * smaller and more readable).
758  */
759 static int arm_get_n_reg_class(const void *self) {
760         const arm_isa_t *isa = self;
761
762         return isa->cg->have_fp ? 2 : 1;
763 }
764
765 /**
766  * Return the register class with requested index.
767  */
768 static const arch_register_class_t *arm_get_reg_class(const void *self, int i) {
769         return i == 0 ? &arm_reg_classes[CLASS_arm_gp] : &arm_reg_classes[CLASS_arm_fpa];
770 }
771
772 /**
773  * Get the register class which shall be used to store a value of a given mode.
774  * @param self The this pointer.
775  * @param mode The mode in question.
776  * @return A register class which can hold values of the given mode.
777  */
778 const arch_register_class_t *arm_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
779         if (mode_is_float(mode))
780                 return &arm_reg_classes[CLASS_arm_fpa];
781         else
782                 return &arm_reg_classes[CLASS_arm_gp];
783 }
784
785 /**
786  * Produces the type which sits between the stack args and the locals on the stack.
787  * it will contain the return address and space to store the old base pointer.
788  * @return The Firm type modelling the ABI between type.
789  */
790 static ir_type *arm_get_between_type(void *self) {
791         static ir_type *between_type = NULL;
792         static ir_entity *old_bp_ent = NULL;
793
794         if(!between_type) {
795                 ir_entity *ret_addr_ent;
796                 ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);
797                 ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);
798
799                 between_type           = new_type_class(new_id_from_str("arm_between_type"));
800                 old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
801                 ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);
802
803                 set_entity_offset(old_bp_ent, 0);
804                 set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
805                 set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
806         }
807
808         return between_type;
809 }
810
811
812 typedef struct {
813         be_abi_call_flags_bits_t flags;
814         const arch_env_t *arch_env;
815         const arch_isa_t *isa;
816         ir_graph *irg;
817 } arm_abi_env_t;
818
819 static void *arm_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg)
820 {
821         arm_abi_env_t *env     = xmalloc(sizeof(env[0]));
822         be_abi_call_flags_t fl = be_abi_call_get_flags(call);
823         env->flags    = fl.bits;
824         env->irg      = irg;
825         env->arch_env = arch_env;
826         env->isa      = arch_env->isa;
827         return env;
828 }
829
830 static void arm_abi_dont_save_regs(void *self, pset *s)
831 {
832         arm_abi_env_t *env = self;
833         if (env->flags.try_omit_fp)
834                 pset_insert_ptr(s, env->isa->bp);
835 }
836
837
838
839 /**
840  * Build the ARM prolog
841  */
842 static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *reg_map) {
843         ir_node *keep, *store;
844         arm_abi_env_t *env = self;
845         ir_graph *irg = env->irg;
846         ir_node *block = get_irg_start_block(irg);
847 //      ir_node *regs[16];
848 //      int n_regs = 0;
849         arch_register_class_t *gp = &arm_reg_classes[CLASS_arm_gp];
850
851         ir_node *fp = be_abi_reg_map_get(reg_map, env->isa->bp);
852         ir_node *ip = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R12]);
853         ir_node *sp = be_abi_reg_map_get(reg_map, env->isa->sp);
854         ir_node *lr = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_LR]);
855         ir_node *pc = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_PC]);
856 //      ir_node *r0 = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R0]);
857 //      ir_node *r1 = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R1]);
858 //      ir_node *r2 = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R2]);
859 //      ir_node *r3 = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R3]);
860
861         if(env->flags.try_omit_fp)
862                 return env->isa->sp;
863
864         ip = be_new_Copy(gp, irg, block, sp );
865         arch_set_irn_register(env->arch_env, ip, &arm_gp_regs[REG_R12]);
866         be_set_constr_single_reg(ip, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
867
868 //      if (r0) regs[n_regs++] = r0;
869 //      if (r1) regs[n_regs++] = r1;
870 //      if (r2) regs[n_regs++] = r2;
871 //      if (r3) regs[n_regs++] = r3;
872 //      sp = new_r_arm_StoreStackMInc(irg, block, *mem, sp, n_regs, regs, get_irn_mode(sp));
873 //              set_arm_req_out(sp, &arm_default_req_arm_gp_sp, 0);
874 //              arch_set_irn_register(env->arch_env, sp, env->isa->sp);
875         store = new_rd_arm_StoreStackM4Inc(NULL, irg, block, sp, fp, ip, lr, pc, *mem);
876         // TODO
877         // set_arm_req_out(store, &arm_default_req_arm_gp_sp, 0);
878         // arch_set_irn_register(env->arch_env, store, env->isa->sp);
879
880         sp = new_r_Proj(irg, block, store, env->isa->sp->reg_class->mode, pn_arm_StoreStackM4Inc_ptr);
881         arch_set_irn_register(env->arch_env, sp, env->isa->sp);
882         *mem = new_r_Proj(irg, block, store, mode_M, pn_arm_StoreStackM4Inc_M);
883
884         keep = be_new_CopyKeep_single(gp, irg, block, ip, sp, get_irn_mode(ip));
885         be_node_set_reg_class(keep, 1, gp);
886         arch_set_irn_register(env->arch_env, keep, &arm_gp_regs[REG_R12]);
887         be_set_constr_single_reg(keep, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
888
889         fp = new_rd_arm_Sub_i(NULL, irg, block, keep, get_irn_mode(fp),
890                               new_tarval_from_long(4, get_irn_mode(fp)));
891         // TODO...
892         //set_arm_req_out_all(fp, fp_req);
893         //set_arm_req_out(fp, &arm_default_req_arm_gp_r11, 0);
894         arch_set_irn_register(env->arch_env, fp, env->isa->bp);
895
896 //      be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R0], r0);
897 //      be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R1], r1);
898 //      be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R2], r2);
899 //      be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R3], r3);
900         be_abi_reg_map_set(reg_map, env->isa->bp, fp);
901         be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R12], keep);
902         be_abi_reg_map_set(reg_map, env->isa->sp, sp);
903         be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_LR], lr);
904         be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_PC], pc);
905
906         return env->isa->bp;
907 }
908
909 static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map) {
910         arm_abi_env_t *env = self;
911         ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->isa->sp);
912         ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->isa->bp);
913         ir_node *curr_pc = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_PC]);
914         ir_node *curr_lr = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_LR]);
915
916         // TODO: Activate Omit fp in epilogue
917         if(env->flags.try_omit_fp) {
918                 curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK);
919                 add_irn_dep(curr_sp, *mem);
920
921                 curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr, curr_sp, get_irn_mode(curr_lr));
922                 be_node_set_reg_class(curr_lr, 1, &arm_reg_classes[CLASS_arm_gp]);
923                 arch_set_irn_register(env->arch_env, curr_lr, &arm_gp_regs[REG_LR]);
924                 be_set_constr_single_reg(curr_lr, BE_OUT_POS(0), &arm_gp_regs[REG_LR] );
925
926                 curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr );
927                 arch_set_irn_register(env->arch_env, curr_pc, &arm_gp_regs[REG_PC]);
928                 be_set_constr_single_reg(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC] );
929         } else {
930                 ir_node *sub12_node;
931                 ir_node *load_node;
932                 tarval *tv = new_tarval_from_long(12,mode_Iu);
933                 sub12_node = new_rd_arm_Sub_i(NULL, env->irg, bl, curr_bp, mode_Iu, tv);
934                 // FIXME
935                 //set_arm_req_out_all(sub12_node, sub12_req);
936                 arch_set_irn_register(env->arch_env, sub12_node, env->isa->sp);
937                 load_node = new_rd_arm_LoadStackM3( NULL, env->irg, bl, sub12_node, *mem );
938                 // FIXME
939                 //set_arm_req_out(load_node, &arm_default_req_arm_gp_r11, 0);
940                 //set_arm_req_out(load_node, &arm_default_req_arm_gp_sp, 1);
941                 //set_arm_req_out(load_node, &arm_default_req_arm_gp_pc, 2);
942                 curr_bp = new_r_Proj(env->irg, bl, load_node, env->isa->bp->reg_class->mode, pn_arm_LoadStackM3_res0);
943                 curr_sp = new_r_Proj(env->irg, bl, load_node, env->isa->sp->reg_class->mode, pn_arm_LoadStackM3_res1);
944                 curr_pc = new_r_Proj(env->irg, bl, load_node, mode_Iu, pn_arm_LoadStackM3_res2);
945                 *mem    = new_r_Proj(env->irg, bl, load_node, mode_M, pn_arm_LoadStackM3_M);
946                 arch_set_irn_register(env->arch_env, curr_bp, env->isa->bp);
947                 arch_set_irn_register(env->arch_env, curr_sp, env->isa->sp);
948                 arch_set_irn_register(env->arch_env, curr_pc, &arm_gp_regs[REG_PC]);
949         }
950         be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
951         be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
952         be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_LR], curr_lr);
953         be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_PC], curr_pc);
954 }
955
956 static const be_abi_callbacks_t arm_abi_callbacks = {
957         arm_abi_init,
958         free,
959         arm_get_between_type,
960         arm_abi_dont_save_regs,
961         arm_abi_prologue,
962         arm_abi_epilogue,
963 };
964
965
966 /**
967  * Get the ABI restrictions for procedure calls.
968  * @param self        The this pointer.
969  * @param method_type The type of the method (procedure) in question.
970  * @param abi         The abi object to be modified
971  */
972 void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
973         ir_type  *tp;
974         ir_mode  *mode;
975         int       i;
976         int       n = get_method_n_params(method_type);
977         be_abi_call_flags_t flags = {
978                 {
979                         0, /* store from left to right */
980                         0, /* store arguments sequential */
981                         1, /* try to omit the frame pointer */
982                         1, /* the function can use any register as frame pointer */
983                         1  /* a call can take the callee's address as an immediate */
984                 }
985         };
986
987         /* set stack parameter passing style */
988         be_abi_call_set_flags(abi, flags, &arm_abi_callbacks);
989
990         for (i = 0; i < n; i++) {
991                 /* reg = get reg for param i;          */
992                 /* be_abi_call_param_reg(abi, i, reg); */
993                 if (i < 4)
994
995                         be_abi_call_param_reg(abi, i, arm_get_RegParam_reg(i));
996                 else
997                         be_abi_call_param_stack(abi, i, 4, 0, 0);
998         }
999
1000         /* default: return value is in R0 resp. F0 */
1001         assert(get_method_n_ress(method_type) < 2);
1002         if (get_method_n_ress(method_type) > 0) {
1003                 tp   = get_method_res_type(method_type, 0);
1004                 mode = get_type_mode(tp);
1005
1006                 be_abi_call_res_reg(abi, 0,
1007                         mode_is_float(mode) ? &arm_fpa_regs[REG_F0] : &arm_gp_regs[REG_R0]);
1008         }
1009 }
1010
1011 static const void *arm_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
1012         return &arm_irn_ops;
1013 }
1014
1015 const arch_irn_handler_t arm_irn_handler = {
1016         arm_get_irn_ops
1017 };
1018
1019 const arch_irn_handler_t *arm_get_irn_handler(const void *self) {
1020         return &arm_irn_handler;
1021 }
1022
1023 int arm_to_appear_in_schedule(void *block_env, const ir_node *irn) {
1024         return is_arm_irn(irn);
1025 }
1026
1027 /**
1028  * Initializes the code generator interface.
1029  */
1030 static const arch_code_generator_if_t *arm_get_code_generator_if(void *self) {
1031         return &arm_code_gen_if;
1032 }
1033
1034 list_sched_selector_t arm_sched_selector;
1035
1036 /**
1037  * Returns the reg_pressure scheduler with to_appear_in_schedule() over\loaded
1038  */
1039 static const list_sched_selector_t *arm_get_list_sched_selector(const void *self, list_sched_selector_t *selector) {
1040         memcpy(&arm_sched_selector, reg_pressure_selector, sizeof(list_sched_selector_t));
1041         arm_sched_selector.to_appear_in_schedule = arm_to_appear_in_schedule;
1042         return &arm_sched_selector;
1043 }
1044
1045 static const ilp_sched_selector_t *arm_get_ilp_sched_selector(const void *self) {
1046         return NULL;
1047 }
1048
1049 /**
1050  * Returns the necessary byte alignment for storing a register of given class.
1051  */
1052 static int arm_get_reg_class_alignment(const void *self, const arch_register_class_t *cls) {
1053         ir_mode *mode = arch_register_class_mode(cls);
1054         return get_mode_size_bytes(mode);
1055 }
1056
1057 static const be_execution_unit_t ***arm_get_allowed_execution_units(const void *self, const ir_node *irn) {
1058         /* TODO */
1059         assert(0);
1060         return NULL;
1061 }
1062
1063 static const be_machine_t *arm_get_machine(const void *self) {
1064         /* TODO */
1065         assert(0);
1066         return NULL;
1067 }
1068
1069 /**
1070  * Return irp irgs in the desired order.
1071  */
1072 static ir_graph **arm_get_irg_list(const void *self, ir_graph ***irg_list) {
1073         return NULL;
1074 }
1075
1076 /**
1077  * Returns the libFirm configuration parameter for this backend.
1078  */
1079 static const backend_params *arm_get_libfirm_params(void) {
1080         static arch_dep_params_t ad = {
1081                 1,  /* allow subs */
1082                 0,      /* Muls are fast enough on ARM */
1083                 31, /* shift would be ok */
1084                 0,  /* SMUL is needed, only in Arch M*/
1085                 0,  /* UMUL is needed, only in Arch M */
1086                 32, /* SMUL & UMUL available for 32 bit */
1087         };
1088         static backend_params p = {
1089                 NULL,  /* no additional opcodes */
1090                 NULL,  /* will be set later */
1091                 1,     /* need dword lowering */
1092                 NULL,  /* but yet no creator function */
1093                 NULL,  /* context for create_intrinsic_fkt */
1094         };
1095
1096         p.dep_param = &ad;
1097         return &p;
1098 }
1099
1100 /* fpu set architectures. */
1101 static const lc_opt_enum_int_items_t arm_fpu_items[] = {
1102         { "softfloat", ARM_FPU_ARCH_SOFTFLOAT },
1103         { "fpe",       ARM_FPU_ARCH_FPE },
1104         { "fpa",       ARM_FPU_ARCH_FPA },
1105         { "vfp1xd",    ARM_FPU_ARCH_VFP_V1xD },
1106         { "vfp1",      ARM_FPU_ARCH_VFP_V1 },
1107         { "vfp2",      ARM_FPU_ARCH_VFP_V2 },
1108         { NULL,        0 }
1109 };
1110
1111 static lc_opt_enum_int_var_t arch_fpu_var = {
1112         &arm_isa_template.fpu_arch, arm_fpu_items
1113 };
1114
1115 static const lc_opt_table_entry_t arm_options[] = {
1116         LC_OPT_ENT_ENUM_INT("fpunit",    "select the floating point unit", &arch_fpu_var),
1117         LC_OPT_ENT_BOOL("gen_reg_names", "use generic register names", &arm_isa_template.gen_reg_names),
1118         { NULL }
1119 };
1120
1121 const arch_isa_if_t arm_isa_if = {
1122         arm_init,
1123         arm_done,
1124         arm_get_n_reg_class,
1125         arm_get_reg_class,
1126         arm_get_reg_class_for_mode,
1127         arm_get_call_abi,
1128         arm_get_irn_handler,
1129         arm_get_code_generator_if,
1130         arm_get_list_sched_selector,
1131         arm_get_ilp_sched_selector,
1132         arm_get_reg_class_alignment,
1133         arm_get_libfirm_params,
1134         arm_get_allowed_execution_units,
1135         arm_get_machine,
1136         arm_get_irg_list,
1137 };
1138
1139 void be_init_arch_arm(void)
1140 {
1141         lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
1142         lc_opt_entry_t *arm_grp = lc_opt_get_grp(be_grp, "arm");
1143
1144         lc_opt_add_table(arm_grp, arm_options);
1145
1146         be_register_isa_if("arm", &arm_isa_if);
1147 }
1148
1149 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm);