becopyopt: Use the set of admissible registers from bechordal.
[libfirm] / ir / be / beemitter_binary.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief       Interface for machine code output
9  * @author      Matthias Braun
10  * @date        12.03.2007
11  */
12 #include "config.h"
13
14 #include <assert.h>
15 #include <limits.h>
16
17 #include "beemitter_binary.h"
18 #include "obst.h"
19 #include "pdeq.h"
20 #include "error.h"
21
22 static code_fragment_t *first_fragment;
23 static code_fragment_t *last_fragment;
24 static const unsigned CODE_FRAGMENT_MAGIC = 0x4643414d;  /* "CFMA" */
25
26 struct obstack code_fragment_obst;
27
28 /** returns current fragment (the address stays only valid until the next
29     be_emit(8/16/32/entity) call!) */
30 code_fragment_t *be_get_current_fragment(void)
31 {
32         code_fragment_t *fragment = (code_fragment_t*)obstack_base(&code_fragment_obst);
33         assert(obstack_object_size(&code_fragment_obst) >= sizeof(code_fragment_t));
34         assert(fragment->magic == CODE_FRAGMENT_MAGIC);
35
36         return fragment;
37 }
38
39 /** allocates a new fragment on the obstack (warning: address is only valid
40     till next be_emit */
41 static void alloc_fragment(void)
42 {
43         code_fragment_t *fragment;
44
45         /* shouldn't have any growing fragments */
46         assert(obstack_object_size(&code_fragment_obst) == 0);
47
48         obstack_blank(&code_fragment_obst, sizeof(*fragment));
49         fragment = (code_fragment_t*)obstack_base(&code_fragment_obst);
50         memset(fragment, 0, sizeof(*fragment));
51 #ifndef NDEBUG
52         fragment->magic = CODE_FRAGMENT_MAGIC;
53 #endif
54         fragment->len        = 0;
55         fragment->alignment  = 1;
56         fragment->offset     = 0;
57         fragment->max_offset = UINT_MAX;
58 }
59
60 static code_fragment_t *finish_fragment(void)
61 {
62         code_fragment_t *fragment = be_get_current_fragment();
63         fragment->len
64                 = obstack_object_size(&code_fragment_obst) - sizeof(*fragment);
65
66         fragment      = (code_fragment_t*) obstack_finish(&code_fragment_obst);
67         last_fragment = fragment;
68
69         if (first_fragment == NULL)
70                 first_fragment = fragment;
71
72         return fragment;
73 }
74
75 void be_start_code_emitter(void)
76 {
77         obstack_init(&code_fragment_obst);
78         first_fragment = NULL;
79         alloc_fragment();
80 }
81
82 void be_start_new_fragment(void)
83 {
84         finish_fragment();
85         alloc_fragment();
86 }
87
88 static void emit(FILE *file, const unsigned char *buffer, size_t len)
89 {
90         size_t i;
91         for (i = 0; i < len; ++i) {
92                 size_t i2;
93                 fputs("\t.byte ", file);
94                 for (i2 = i; i2 < i + 30 && i2 < len; ++i2) {
95                         fprintf(file, "0x%02X", (unsigned)buffer[i2]);
96                 }
97                 i = i2;
98                 fputs("\n", file);
99         }
100 }
101
102 static unsigned align(unsigned offset, unsigned alignment)
103 {
104         if (offset % alignment != 0) {
105                 offset += alignment - (offset % alignment);
106         }
107         return offset;
108 }
109
110 static bool determine_jumpsize_iteration(
111                 const binary_emiter_interface_t *interface)
112 {
113         unsigned         offset     = 0;
114         unsigned         max_offset = 0;
115         bool             changed    = false;
116         code_fragment_t *fragment;
117
118         for (fragment = first_fragment; fragment != NULL;
119              fragment = fragment->next) {
120             unsigned alignment = fragment->alignment;
121
122             /* assure alignment */
123             offset     = align(offset, alignment);
124             max_offset = align(max_offset, alignment);
125
126                 if (offset != fragment->offset) {
127                         changed          = true;
128                         fragment->offset = offset;
129                 }
130             fragment->max_offset = max_offset;
131
132                 /* advance offset */
133                 offset     += fragment->len;
134                 max_offset += fragment->len;
135                 interface->determine_jumpsize(fragment);
136                 offset     += fragment->jumpsize_min;
137                 max_offset += fragment->jumpsize_max;
138         }
139
140         return changed;
141 }
142
143 static void determine_offsets(const binary_emiter_interface_t *interface)
144 {
145         bool changed;
146
147         assert(first_fragment->alignment == 1);
148         first_fragment->offset     = 0;
149         first_fragment->max_offset = 0;
150
151         /* The algorithm calculates a lower and upper bound for the offset of each
152          * fragment. With this information we can calculate a lower and upper bound
153          * for the size of each jump instruction.
154          * A single iteration updates the offset bounds for all fragments and jump
155          * sizes for each fragment. We iterate until we had an iteration where
156          * none of the minimum offsets changed. */
157         do {
158                 changed = determine_jumpsize_iteration(interface);
159                 /* TODO: we should have an abort mode for the case when the offsets
160                    don't converge fast enough. We could simply use a pessimistic
161                    solution after a few iterations... */
162         } while (changed);
163 }
164
165 void be_emit_entity(ir_entity *entity, bool entity_sign, int offset,
166                     bool is_relative)
167 {
168         (void) entity;
169         (void) entity_sign;
170         (void) offset;
171         (void) is_relative;
172         panic("not implemented yet");
173 }
174
175 void be_emit_code(FILE *output, const binary_emiter_interface_t *interface)
176 {
177         unsigned offset;
178
179         code_fragment_t *fragment;
180
181         finish_fragment();
182
183         /* determine near/far jumps */
184         determine_offsets(interface);
185
186         /* emit code */
187         offset = 0;
188         for (fragment = first_fragment; fragment != NULL;
189              fragment = fragment->next) {
190             unsigned char *jmpbuffer;
191                 unsigned nops;
192
193             /* assure alignment by emitting nops */
194             assert(fragment->offset >= offset);
195             nops = fragment->offset - offset;
196             if (nops > 0) {
197                         unsigned char *nopbuffer = (unsigned char*)obstack_alloc(&code_fragment_obst, nops);
198                         interface->create_nops(nopbuffer, nops);
199                         emit(output, nopbuffer, nops);
200                         offset = fragment->offset;
201                         obstack_free(&code_fragment_obst, nopbuffer);
202                 }
203
204                 /* emit the fragment */
205                 emit(output, fragment->data, fragment->len);
206                 offset += fragment->len;
207
208                 /* emit the jump */
209                 jmpbuffer = (unsigned char*)obstack_alloc(&code_fragment_obst, fragment->jumpsize_min);
210                 interface->emit_jump(fragment, jmpbuffer);
211                 emit(output, jmpbuffer, fragment->jumpsize_min);
212                 offset += fragment->jumpsize_min;
213                 obstack_free(&code_fragment_obst, jmpbuffer);
214         }
215 }