1 /***************************** comp/mcode.c ************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 This file is an include file for "compiler.c" . It contains (mostly)
8 architecture independent functions for writing instructions into the
9 code area and constants into the data area.
11 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
12 Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
13 Changes: Micheal Gschwind EMAIL: cacao@complang.tuwien.ac.at
15 Last Change: 1997/04/13
18 All functions assume the following code area / data area layout:
22 | code area | code area grows to higher addresses
24 +-----------+ <-- start of procedure
26 | data area | data area grows to lower addresses
30 The functions first write into a temporary code/data area allocated by
31 "mcode_init". "mcode_finish" copies the code and data area into permanent
32 memory. All functions writing values into the data area return the offset
33 relative the begin of the code area (start of procedure).
35 *******************************************************************************/
40 #define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
41 #define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
43 static u1* mcodebase = NULL; /* base pointer of code area */
44 static int mcodesize; /* complete size of code area (bytes) */
45 static int mcodelen; /* used size of code area (bytes) */
47 static u1* dsegtop = NULL; /* pointer to top (end) of data area */
48 static int dsegsize; /* complete size of data area (bytes) */
49 static int dseglen; /* used size of data area (bytes) */
50 /* data area grows from top to bottom */
52 static list mcodereferences; /* list of branch instruction adresses */
53 /* and of jumptable target addresses */
55 static void mcode_init(); /* allocates code and data area */
56 static void mcode_close(); /* releases temporary storage */
57 static void mcode_finish(); /* makes code and data area permanent and */
58 /* updates branch references to code/data */
59 static void mcode_adds4(s4 code); /* adds an instruction to code area */
61 static s4 dseg_adds4(s4 value); /* adds an int to data area */
62 static s4 dseg_adds8(s8 value); /* adds an long to data area */
63 static s4 dseg_addfloat (float value); /* adds an float to data area */
64 static s4 dseg_adddouble(double value); /* adds an double to data area */
66 /* s4 dseg_addaddress(void* value); */
67 static s4 dseg_addtarget(basicblock *target);
68 static void mcode_addreference(basicblock *target);
69 static void dseg_display();
71 /* mcode_init allocates and initialises code area, data area and references */
73 static void mcode_init()
76 mcodebase = MNEW (u1, MCODEINITSIZE);
77 mcodesize = MCODEINITSIZE;
81 dsegtop = MNEW (u1, DSEGINITSIZE);
82 dsegsize = DSEGINITSIZE;
89 list_init (&mcodereferences, OFFSET(mcodereference, linkage) );
93 /* mcode_close releases temporary code and data area */
95 static void mcode_close()
98 MFREE (mcodebase, u1, mcodesize);
102 MFREE (dsegtop - dsegsize, u1, dsegsize);
108 /* mcode_adds4_increase doubles code area and adds instruction */
110 static void mcode_adds4_increase(s4 code)
112 mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
114 *((s4 *) (mcodebase + mcodelen - 4)) = code;
118 /* mcode_adds4 checks code area size and adds instruction */
120 static void mcode_adds4(s4 code)
124 codeptr = (s4 *) (mcodebase + mcodelen);
126 if (mcodelen <= mcodesize)
129 mcode_adds4_increase(code);
133 /* desg_increase doubles data area */
135 static void dseg_increase() {
136 u1 *newstorage = MNEW (u1, dsegsize * 2);
137 memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
138 MFREE (dsegtop - dsegsize, u1, dsegsize);
139 dsegtop = newstorage;
145 static s4 dseg_adds4_increase(s4 value)
148 *((s4 *) (dsegtop - dseglen)) = value;
153 static s4 dseg_adds4(s4 value)
158 dataptr = (s4 *) (dsegtop - dseglen);
159 if (dseglen > dsegsize)
160 return dseg_adds4_increase(value);
166 static s4 dseg_adds8_increase(s8 value)
169 *((s8 *) (dsegtop - dseglen)) = value;
174 static s4 dseg_adds8(s8 value)
178 dseglen = ALIGN (dseglen + 8, 8);
179 dataptr = (s8 *) (dsegtop - dseglen);
180 if (dseglen > dsegsize)
181 return dseg_adds8_increase(value);
187 static s4 dseg_addfloat_increase(float value)
190 *((float *) (dsegtop - dseglen)) = value;
195 static s4 dseg_addfloat(float value)
200 dataptr = (float *) (dsegtop - dseglen);
201 if (dseglen > dsegsize)
202 return dseg_addfloat_increase(value);
208 static s4 dseg_adddouble_increase(double value)
211 *((double *) (dsegtop - dseglen)) = value;
216 static s4 dseg_adddouble(double value)
220 dseglen = ALIGN (dseglen + 8, 8);
221 dataptr = (double *) (dsegtop - dseglen);
222 if (dseglen > dsegsize)
223 return dseg_adddouble_increase(value);
230 #define dseg_addaddress(value) dseg_adds8((s8)(value))
232 #define dseg_addaddress(value) dseg_adds4((s4)(value))
236 static s4 dseg_addtarget(basicblock *target)
238 mcodereference *cr = DNEW(mcodereference);
240 dseglen = ALIGN (dseglen + sizeof(void*), sizeof(void*));
241 if (dseglen > dsegsize)
244 cr -> incode = false;
245 cr -> msourcepos = -dseglen;
246 cr -> target = target;
248 list_addlast (&mcodereferences, cr);
254 static void mcode_addreference(basicblock *target)
256 mcodereference *cr = DNEW(mcodereference);
259 cr -> msourcepos = mcodelen;
260 cr -> target = target;
262 list_addlast (&mcodereferences, cr);
267 static void mcode_blockstart (basicblock *b)
274 static void gen_resolvebranch(void* mcodepiece, s4 sourcepos, s4 targetpos);
276 static void mcode_finish()
280 count_code_len += mcodelen;
281 count_data_len += dseglen;
283 dseglen = ALIGN(dseglen, MAX_ALIGN);
285 method->mcodelength = mcodelen + dseglen;
286 method->mcode = CNEW(u1, mcodelen + dseglen);
288 memcpy ( method->mcode, dsegtop - dseglen, dseglen);
289 memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
291 method -> entrypoint = (u1*) (method->mcode + dseglen);
293 cr = list_first (&mcodereferences);
296 if (cr->incode) { /* branch resolving */
297 gen_resolvebranch ( ((u1*)(method->entrypoint)) + cr->msourcepos,
301 else { /* jump table resolving */
303 p = (void**) ( ((u1*)(method->entrypoint)) + cr->msourcepos);
305 *p = ((u1*)(method->entrypoint)) + cr->target->mpc;
308 cr = list_next (&mcodereferences, cr);
311 #ifdef CACHE_FLUSH_BLOCK
312 synchronize_caches(method->mcode, (mcodelen>>2));
318 static void dseg_display()
321 printf (" --- dump of datasegment\n");
322 for (i = dseglen - 4; i >= 0 ; i -= 4) {
323 printf ("%6x: %8x\n", i, (int)(*((s4*)(dsegtop - i))));