2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief Interface for machine code output
23 * @author Matthias Braun
31 #include "beemitter_binary.h"
36 static code_fragment_t *first_fragment;
37 static code_fragment_t *last_fragment;
38 static const unsigned CODE_FRAGMENT_MAGIC = 0x4643414d; /* "CFMA" */
40 struct obstack code_fragment_obst;
42 /** returns current fragment (the address stays only valid until the next
43 be_emit(8/16/32/entity) call!) */
44 code_fragment_t *be_get_current_fragment(void)
46 code_fragment_t *fragment = (code_fragment_t*)obstack_base(&code_fragment_obst);
47 assert(obstack_object_size(&code_fragment_obst) >= sizeof(code_fragment_t));
48 assert(fragment->magic == CODE_FRAGMENT_MAGIC);
53 /** allocates a new fragment on the obstack (warning: address is only valid
55 static void alloc_fragment(void)
57 code_fragment_t *fragment;
59 /* shouldn't have any growing fragments */
60 assert(obstack_object_size(&code_fragment_obst) == 0);
62 obstack_blank(&code_fragment_obst, sizeof(*fragment));
63 fragment = (code_fragment_t*)obstack_base(&code_fragment_obst);
64 memset(fragment, 0, sizeof(*fragment));
66 fragment->magic = CODE_FRAGMENT_MAGIC;
69 fragment->alignment = 1;
71 fragment->max_offset = UINT_MAX;
74 static code_fragment_t *finish_fragment(void)
76 code_fragment_t *fragment = be_get_current_fragment();
78 = obstack_object_size(&code_fragment_obst) - sizeof(*fragment);
80 fragment = (code_fragment_t*) obstack_finish(&code_fragment_obst);
81 last_fragment = fragment;
83 if (first_fragment == NULL)
84 first_fragment = fragment;
89 void be_start_code_emitter(void)
91 obstack_init(&code_fragment_obst);
92 first_fragment = NULL;
96 void be_start_new_fragment(void)
102 static void emit(FILE *file, const unsigned char *buffer, size_t len)
105 for (i = 0; i < len; ++i) {
107 fputs("\t.byte ", file);
108 for (i2 = i; i2 < i + 30 && i2 < len; ++i2) {
109 fprintf(file, "0x%02X", (unsigned)buffer[i2]);
116 static unsigned align(unsigned offset, unsigned alignment)
118 if (offset % alignment != 0) {
119 offset += alignment - (offset % alignment);
124 static bool determine_jumpsize_iteration(
125 const binary_emiter_interface_t *interface)
128 unsigned max_offset = 0;
129 bool changed = false;
130 code_fragment_t *fragment;
132 for (fragment = first_fragment; fragment != NULL;
133 fragment = fragment->next) {
134 unsigned alignment = fragment->alignment;
136 /* assure alignment */
137 offset = align(offset, alignment);
138 max_offset = align(max_offset, alignment);
140 if (offset != fragment->offset) {
142 fragment->offset = offset;
144 fragment->max_offset = max_offset;
147 offset += fragment->len;
148 max_offset += fragment->len;
149 interface->determine_jumpsize(fragment);
150 offset += fragment->jumpsize_min;
151 max_offset += fragment->jumpsize_max;
157 static void determine_offsets(const binary_emiter_interface_t *interface)
161 assert(first_fragment->alignment == 1);
162 first_fragment->offset = 0;
163 first_fragment->max_offset = 0;
165 /* The algorithm calculates a lower and upper bound for the offset of each
166 * fragment. With this information we can calculate a lower and upper bound
167 * for the size of each jump instruction.
168 * A single iteration updates the offset bounds for all fragments and jump
169 * sizes for each fragment. We iterate until we had an iteration where
170 * none of the minimum offsets changed. */
172 changed = determine_jumpsize_iteration(interface);
173 /* TODO: we should have an abort mode for the case when the offsets
174 don't converge fast enough. We could simply use a pessimistic
175 solution after a few iterations... */
179 void be_emit_entity(ir_entity *entity, bool entity_sign, int offset,
186 panic("not implemented yet");
189 void be_emit_code(FILE *output, const binary_emiter_interface_t *interface)
193 code_fragment_t *fragment;
197 /* determine near/far jumps */
198 determine_offsets(interface);
202 for (fragment = first_fragment; fragment != NULL;
203 fragment = fragment->next) {
204 unsigned char *jmpbuffer;
207 /* assure alignment by emitting nops */
208 assert(fragment->offset >= offset);
209 nops = fragment->offset - offset;
211 unsigned char *nopbuffer = (unsigned char*)obstack_alloc(&code_fragment_obst, nops);
212 interface->create_nops(nopbuffer, nops);
213 emit(output, nopbuffer, nops);
214 offset = fragment->offset;
215 obstack_free(&code_fragment_obst, nopbuffer);
218 /* emit the fragment */
219 emit(output, fragment->data, fragment->len);
220 offset += fragment->len;
223 jmpbuffer = (unsigned char*)obstack_alloc(&code_fragment_obst, fragment->jumpsize_min);
224 interface->emit_jump(fragment, jmpbuffer);
225 emit(output, jmpbuffer, fragment->jumpsize_min);
226 offset += fragment->jumpsize_min;
227 obstack_free(&code_fragment_obst, jmpbuffer);