void opcode_chain_serialize(opcode_chain_t oc, opcode_dict_t od, program_t p, void* dl_handle) { slist_node_t sn; opcode_chain_node_t ocn; word_t ofs = program_get_code_size(p), backup=ofs, code_sz=0, data_sz=0; /* * 1st pass : compute labels addresses and init data segment */ sn = list_head(oc); while(sn!=NULL) { ocn = node_value(opcode_chain_node_t,sn); switch(ocn->type) { case NodeLabel: ocn->lofs=ofs; program_add_label(p,ofs,ocn->name); break; case NodeData: data_sz+= 2*atoi(ocn->arg); /*vm_printf("data rep %i\n",atoi(ocn->arg));*/ break; case NodeOpcode: ofs+=2; /* two words per instruction */ code_sz+=2; break; case NodeLangPlug: case NodeLangDef: default:; }; sn=sn->next; } /* reserve segments sizes */ program_reserve_code(p, code_sz); program_reserve_data(p, data_sz?2+data_sz:0); /* * 2nd pass : serialize opcodes */ ofs=backup; sn = list_head(oc); while(sn!=NULL) { ocn = node_value(opcode_chain_node_t,sn); if(ocn->type==NodeOpcode) { opcode_serialize(od,oc,ofs,ocn,p,dl_handle); ofs+=2; } else if(ocn->type==NodeData) { long rep = atoi(ocn->arg); word_t dat = str2data(p,(vm_data_type_t)ocn->arg_type,ocn->name); dynarray_t data_seg = &p->data; while(rep>0) { dynarray_set(data_seg,dynarray_size(data_seg), ocn->arg_type); dynarray_set(data_seg,dynarray_size(data_seg), dat); rep-=1; } } sn=sn->next; } }
dynarray_t *dynarray_set(dynarray_t *da, int i, da_numeric_t val) { assert(i >= 0); if (!da) { da = malloc(sizeof(dynarray_t)); da->next = NULL; da->n = 0; } if (i+1 > da->n) da->n = i+1; if (i >= DYNARRAY_ALEN) da->next = dynarray_set(da->next, i-DYNARRAY_ALEN, val); else da->a[i] = val; return da; }
void opcode_dict_add(opcode_dict_t od, opcode_arg_t arg_type, const char* name, opcode_stub_t stub) { word_t ofs = dynarray_size(&od->stub_by_index[arg_type]); /* should check for duplicates in arg_type:name AND in stub */ const char* common_key; if(!stub) { vm_printerrf("[VM:ERR] Tried to load NULL opcode %s:%i\n", name, arg_type); return; } if(opcode_stub_by_name(od, arg_type, name)) { return; } common_key = strdup(name); hash_addelem(&od->stub_by_name[arg_type], (hash_key)common_key, (hash_elem)stub); hash_addelem(&od->wordcode_by_stub, (hash_key)stub, (hash_elem) MAKE_WC(arg_type,ofs)); hash_addelem(&od->name_by_stub, (hash_key)stub, (hash_elem) common_key); dynarray_set(&od->stub_by_index[arg_type],ofs,(word_t)stub); }
dynarray_t *dynarray_set_from_matc(dynarray_t *da, char type, const char *var) { char *p; int i; da_numeric_t val; p = MTC_DOMATH(var); if (p == NULL || strncmp(p, "MATC ERROR: Undeclared identifier", 33) == 0) return da; i = 0; while (*p) { if (isspace(*p)) { p++; continue; } assert(isdigit(*p) || *p == '-' || *p == '+' || *p == '.'); switch (type) { case 'i': val.i = strtol(p, &p, 10); break; case 'r': val.r = strtod(p, &p); break; default: assert(FALSE); } da = dynarray_set(da, i++, val); } return da; }