2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Interface for machine code output
9 * @author Matthias Braun
17 #include "beemitter_binary.h"
22 static code_fragment_t *first_fragment;
23 static code_fragment_t *last_fragment;
24 static const unsigned CODE_FRAGMENT_MAGIC = 0x4643414d; /* "CFMA" */
26 struct obstack code_fragment_obst;
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)
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);
39 /** allocates a new fragment on the obstack (warning: address is only valid
41 static void alloc_fragment(void)
43 code_fragment_t *fragment;
45 /* shouldn't have any growing fragments */
46 assert(obstack_object_size(&code_fragment_obst) == 0);
48 obstack_blank(&code_fragment_obst, sizeof(*fragment));
49 fragment = (code_fragment_t*)obstack_base(&code_fragment_obst);
50 memset(fragment, 0, sizeof(*fragment));
52 fragment->magic = CODE_FRAGMENT_MAGIC;
55 fragment->alignment = 1;
57 fragment->max_offset = UINT_MAX;
60 static code_fragment_t *finish_fragment(void)
62 code_fragment_t *fragment = be_get_current_fragment();
64 = obstack_object_size(&code_fragment_obst) - sizeof(*fragment);
66 fragment = (code_fragment_t*) obstack_finish(&code_fragment_obst);
67 last_fragment = fragment;
69 if (first_fragment == NULL)
70 first_fragment = fragment;
75 void be_start_code_emitter(void)
77 obstack_init(&code_fragment_obst);
78 first_fragment = NULL;
82 void be_start_new_fragment(void)
88 static void emit(FILE *file, const unsigned char *buffer, size_t len)
91 for (i = 0; i < len; ++i) {
93 fputs("\t.byte ", file);
94 for (i2 = i; i2 < i + 30 && i2 < len; ++i2) {
95 fprintf(file, "0x%02X", (unsigned)buffer[i2]);
102 static unsigned align(unsigned offset, unsigned alignment)
104 if (offset % alignment != 0) {
105 offset += alignment - (offset % alignment);
110 static bool determine_jumpsize_iteration(
111 const binary_emiter_interface_t *interface)
114 unsigned max_offset = 0;
115 bool changed = false;
116 code_fragment_t *fragment;
118 for (fragment = first_fragment; fragment != NULL;
119 fragment = fragment->next) {
120 unsigned alignment = fragment->alignment;
122 /* assure alignment */
123 offset = align(offset, alignment);
124 max_offset = align(max_offset, alignment);
126 if (offset != fragment->offset) {
128 fragment->offset = offset;
130 fragment->max_offset = max_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;
143 static void determine_offsets(const binary_emiter_interface_t *interface)
147 assert(first_fragment->alignment == 1);
148 first_fragment->offset = 0;
149 first_fragment->max_offset = 0;
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. */
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... */
165 void be_emit_entity(ir_entity *entity, bool entity_sign, int offset,
172 panic("not implemented yet");
175 void be_emit_code(FILE *output, const binary_emiter_interface_t *interface)
179 code_fragment_t *fragment;
183 /* determine near/far jumps */
184 determine_offsets(interface);
188 for (fragment = first_fragment; fragment != NULL;
189 fragment = fragment->next) {
190 unsigned char *jmpbuffer;
193 /* assure alignment by emitting nops */
194 assert(fragment->offset >= offset);
195 nops = fragment->offset - offset;
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);
204 /* emit the fragment */
205 emit(output, fragment->data, fragment->len);
206 offset += fragment->len;
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);