2 * Regular Pattern Analyzer (RPA)
3 * Copyright (c) 2009-2010 Martin Stoilov
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * Martin Stoilov <martin@rpasearch.com>
21 #include "rlib/rmem.h"
22 #include "rvm/rvmcodegen.h"
23 #include "rvm/rvmcpu.h"
26 rvm_codegen_t *rvm_codegen_create()
30 cg = (rvm_codegen_t *)r_malloc(sizeof(*cg));
33 r_memset(cg, 0, sizeof(*cg));
34 cg->code = r_array_create(sizeof(rvm_asmins_t));
35 cg->staticdata = r_array_create(sizeof(ruint8));
36 cg->dynamicdata = r_carray_create(sizeof(rvmreg_t));
37 cg->codemap = rvm_codemap_create();
38 cg->relocmap = rvm_relocmap_create();
39 cg->sourceidx = r_array_create(sizeof(unsigned long));
44 void rvm_codegen_destroy(rvm_codegen_t *cg)
46 rvm_codemap_destroy(cg->codemap);
47 rvm_relocmap_destroy(cg->relocmap);
48 r_array_destroy(cg->staticdata);
49 r_array_destroy(cg->code);
50 r_array_destroy(cg->sourceidx);
51 r_carray_destroy(cg->dynamicdata);
56 void rvm_codegen_clear(rvm_codegen_t *cg)
58 r_array_setlength(cg->code, 0);
59 r_array_setlength(cg->staticdata, 0);
60 rvm_codemap_clear(cg->codemap);
61 rvm_relocmap_clear(cg->relocmap);
65 void rvm_codegen_setsource(rvm_codegen_t *cg, unsigned long srcidx)
67 cg->cursrcidx = srcidx;
71 long rvm_codegen_getsource(rvm_codegen_t *cg, unsigned long codeidx)
73 if (codeidx >= r_array_length(cg->sourceidx))
75 return r_array_index(cg->sourceidx, codeidx, long);
79 rvm_asmins_t *rvm_codegen_getcode(rvm_codegen_t *cg, unsigned int index)
81 return (rvm_asmins_t *)r_array_slot(cg->code, index);
85 unsigned long rvm_codegen_getcodesize(rvm_codegen_t *cg)
87 return r_array_length(cg->code);
90 void rvm_codegen_setcodesize(rvm_codegen_t *cg, unsigned int size)
92 r_array_setlength(cg->code, size);
96 unsigned long rvm_codegen_addins(rvm_codegen_t *cg, rvm_asmins_t ins)
98 unsigned long codeidx;
100 codeidx = r_array_add(cg->code, &ins);
101 r_array_replace(cg->sourceidx, codeidx, &cg->cursrcidx);
106 long rvm_codegen_redefinelabel(rvm_codegen_t *cg, long index, unsigned long offset)
108 long codeidx = rvm_codemap_lookupadd_s(cg->codemap, ".code");
109 rvm_codelabel_t *label = rvm_codemap_label(cg->codemap, index);
113 rvm_codelabel_setoffset(label, codeidx, RVM_CODE2BYTE_OFFSET(offset));
118 long rvm_codegen_redefinelabel_default(rvm_codegen_t *cg, long index)
120 return rvm_codegen_redefinelabel(cg, index, rvm_codegen_getcodesize(cg));
124 long rvm_codegen_validlabel(rvm_codegen_t *cg, long index)
126 return rvm_codemap_validindex(cg->codemap, index);
130 long rvm_codegen_redefinepointer(rvm_codegen_t *cg, long index, rpointer data)
132 rvm_codelabel_t *label = rvm_codemap_label(cg->codemap, index);
136 // return rvm_codemap_addpointer(cg->codemap, label->name->str, label->name->size, data);
137 rvm_codelabel_setpointer(label, data);
142 long rvm_codegen_addlabel(rvm_codegen_t *cg, const char* name, unsigned int namesize, unsigned long offset)
144 return rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), RVM_CODE2BYTE_OFFSET(offset));
148 long rvm_codegen_addlabel_s(rvm_codegen_t *cg, const char* name, unsigned long offset)
150 return rvm_codegen_addlabel(cg, name, r_strlen(name), offset);
154 long rvm_codegen_addlabel_default(rvm_codegen_t *cg, const char* name, unsigned int namesize)
156 return rvm_codegen_addlabel(cg, name, namesize, rvm_codegen_getcodesize(cg));
160 long rvm_codegen_addlabel_default_s(rvm_codegen_t *cg, const char* name)
162 return rvm_codegen_addlabel_default(cg, name, r_strlen(name));
166 long rvm_codegen_invalid_addlabel(rvm_codegen_t *cg, const char* name, unsigned int namesize)
168 return rvm_codemap_invalid_add(cg->codemap, name, namesize);
172 long rvm_codegen_invalid_addlabel_s(rvm_codegen_t *cg, const char* name)
174 return rvm_codegen_invalid_addlabel(cg, name, r_strlen(name));
178 unsigned long rvm_codegen_addlabelins(rvm_codegen_t *cg, const char* name, unsigned int namesize, rvm_asmins_t ins)
180 rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), RVM_CODE2BYTE_OFFSET(rvm_codegen_getcodesize(cg)));
181 return rvm_codegen_addins(cg, ins);
185 unsigned long rvm_codegen_addlabelins_s(rvm_codegen_t *cg, const char* name, rvm_asmins_t ins)
187 return rvm_codegen_addlabelins(cg, name, r_strlen(name), ins);
191 unsigned long rvm_codegen_index_addrelocins(rvm_codegen_t *cg, rvm_reloctype_t type, unsigned long index, rvm_asmins_t ins)
193 rvm_relocmap_add(cg->relocmap, RVM_RELOC_CODE, type, rvm_codegen_getcodesize(cg), index);
194 return rvm_codegen_addins(cg, ins);
198 unsigned long rvm_codegen_addrelocins(rvm_codegen_t *cg, rvm_reloctype_t type, const char* name, unsigned int namesize, rvm_asmins_t ins)
200 return rvm_codegen_index_addrelocins(cg, type, rvm_codemap_lookupadd(cg->codemap, name, namesize), ins);
204 unsigned long rvm_codegen_addrelocins_s(rvm_codegen_t *cg, rvm_reloctype_t type, const char* name, rvm_asmins_t ins)
206 return rvm_codegen_addrelocins(cg, type, name, r_strlen(name), ins);
210 int rvm_codegen_relocate(rvm_codegen_t *cg, rvm_codelabel_t **err)
212 rvm_codemap_addpointer_s(cg->codemap, ".code", r_array_slot(cg->code, 0));
213 rvm_codemap_addpointer_s(cg->codemap, ".data", r_array_slot(cg->staticdata, 0));
214 return rvm_relocmap_relocate(cg->relocmap, cg->codemap, (rvm_asmins_t *)r_array_slot(cg->code, 0), err);
218 unsigned long rvm_codegen_insertins(rvm_codegen_t *cg, unsigned int index, rvm_asmins_t ins)
220 return r_array_insert(cg->code, index, &ins);
224 unsigned long rvm_codegen_replaceins(rvm_codegen_t *cg, unsigned int index, rvm_asmins_t ins)
226 return r_array_replace(cg->code, index, &ins);
231 unsigned int rvm_codegen_funcstart(rvm_codegen_t *cg, const char* name, unsigned int namesize, unsigned int args)
234 rvm_codegen_addins(cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
235 start = rvm_codegen_addlabelins(cg, name, namesize, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(FP)|BIT(SP)|BIT(LR)));
236 rvm_codegen_addins(cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
237 rvm_codegen_addins(cg, rvm_asm(RVM_ADD, SP, SP, DA, args));
238 // rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), start);
243 unsigned int rvm_codegen_funcstart_s(rvm_codegen_t *cg, const char* name, unsigned int args)
245 return rvm_codegen_funcstart(cg, name, r_strlen(name), args);
249 unsigned int rvm_codegen_vargs_funcstart(rvm_codegen_t *cg, const char* name, unsigned int namesize)
252 rvm_codegen_addins(cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
253 start = rvm_codegen_addlabelins(cg, name, namesize, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(FP)|BIT(SP)|BIT(LR)));
254 rvm_codegen_addins(cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
255 rvm_codegen_addins(cg, rvm_asm(RVM_ADD, SP, SP, R0, 0));
256 // rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), start);
261 unsigned int rvm_codegen_vargs_funcstart_s(rvm_codegen_t *cg, const char* name)
263 return rvm_codegen_vargs_funcstart(cg, name, r_strlen(name));
267 void rvm_codegen_funcend(rvm_codegen_t *cg)
269 rvm_codegen_addins(cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
270 rvm_codegen_addins(cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(FP)|BIT(SP)|BIT(LR)));
271 rvm_codegen_addins(cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
274 long rvm_codegen_adddata(rvm_codegen_t *cg, const char *name, unsigned int namesize, rconstpointer data, unsigned long size)
277 unsigned long cursize = R_SIZE_ALIGN(r_array_length(cg->staticdata), sizeof(ruword));
279 r_array_setlength(cg->staticdata, cursize + size + sizeof(ruword) + 1);
280 buffer = r_array_slot(cg->staticdata, cursize);
281 r_memset(buffer, 0, size + sizeof(ruword));
282 r_memmove(buffer, data, size);
283 return rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".data"), cursize);
287 long rvm_codegen_adddata_s(rvm_codegen_t *cg, const char *name, rconstpointer data, unsigned long size)
289 return rvm_codegen_adddata(cg, name, r_strlen(name), data, size);
293 long rvm_codegen_addstring(rvm_codegen_t *cg, const char *name, unsigned int namesize, const char* data)
295 return rvm_codegen_adddata(cg, name, namesize, data, r_strlen(data) + 1);
299 long rvm_codegen_addstring_s(rvm_codegen_t *cg, const char *name, const char* data)
301 return rvm_codegen_addstring(cg, name, r_strlen(name), data);
305 long rvm_codegen_add_numlabel_s(rvm_codegen_t *cg, const char *alphaname, long numname)
309 r_memset(label, 0, sizeof(label));
310 r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
311 return rvm_codegen_addlabel_default_s(cg, label);
315 long rvm_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const char *alphaname, long numname)
319 r_memset(label, 0, sizeof(label));
320 r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
321 return rvm_codegen_invalid_addlabel_s(cg, label);