ucell load_dictionary(const char *data, ucell len) { u32 checksum=0; const char *checksum_walk; ucell *walk, *reloc_table; dictionary_header_t *header=(dictionary_header_t *)data; /* assertions */ if (len <= (sizeof(dictionary_header_t)) || strncmp(DICTID, data, 8)) return 0; #ifdef CONFIG_DEBUG_DICTIONARY dump_header(header); #endif checksum_walk=data; while (checksum_walk<data+len) { checksum+=read_long(checksum_walk); checksum_walk+=sizeof(u32); } if(checksum) { printk("Checksum invalid (%08x)!\n", checksum); return 0; } data += sizeof(dictionary_header_t); dicthead = target_long(header->length); memcpy(dict, data, dicthead); reloc_table=(ucell *)(data+dicthead); #ifdef CONFIG_DEBUG_DICTIONARY printk("\nmoving dictionary (%x bytes) to %x\n", (ucell)dicthead, (ucell)dict); printk("\ndynamic relocation..."); #endif for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead); walk++) { int pos, bit, l; l=(walk-(ucell *)dict); pos=l/BITS; bit=l&~(-BITS); if (reloc_table[pos] & target_ucell((ucell)1ULL << bit)) { // printk("%lx, pos %x, bit %d\n",*walk, pos, bit); write_ucell(walk, read_ucell(walk)+pointer2cell(dict)); } } #ifdef CONFIG_DEBUG_DICTIONARY printk(" done.\n"); #endif last = (ucell *)(dict + target_ucell(header->last)); return -1; }
void init_trampoline(ucell *tramp) { tramp[0] = DOCOL; tramp[1] = 0; tramp[2] = target_ucell(pointer2cell(tramp) + 3 * sizeof(ucell)); tramp[3] = 0; }
static void execute(void) { /* EXECUTE */ ucell address = POP(); dbg_interp_printk("execute: %x\n", address); PUSHR(PC); trampoline[1] = target_ucell(address); PC = pointer2cell(trampoline); }
/* * Compare two dictionaries constructed at different addresses. When * the cells don't match, a need for relocation is detected and the * corresponding bit in reloc_table bitmap is set. */ static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length) { ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two; ucell *reloc_table; int pos, bit; int l=(length+(sizeof(cell)-1))/sizeof(ucell), i; /* prepare relocation table */ relocation_length=(length+BITS-1)/BITS; reloc_table = malloc(relocation_length*sizeof(cell)); memset(reloc_table,0,relocation_length*sizeof(cell)); for (i=0; i<l; i++) { pos=i/BITS; bit=i&~(-BITS); if(d1[i]==d2[i]) { reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit)); // This check might bring false positives in data. //if(d1[i] >= pointer2cell(dict_one) && // d1[i] <= pointer2cell(dict_one+length)) // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]); } else { /* This is a pointer, it needs relocation, d2==dict */ reloc_table[pos] |= target_ucell((ucell)1ULL << bit); d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2)); } } #ifdef CONFIG_DEBUG_DICTIONARY printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict); for (i=0; i< relocation_length ; i++) printk("reloc %d %lx\n",i+1, reloc_table[i]); #endif relocation_address=reloc_table; }
int enterforth(xt_t xt) { ucell *_cfa = (ucell*)cell2pointer(xt); cell tmp; if (read_ucell(_cfa) != DOCOL) { trampoline[1] = target_ucell(xt); _cfa = trampoline; } if (rstackcnt < 0) { rstackcnt = 0; } tmp = rstackcnt; interruptforth = FORTH_INTSTAT_CLR; PUSHR(PC); PC = pointer2cell(_cfa); while (rstackcnt > tmp && !(interruptforth & FORTH_INTSTAT_STOP)) { if (debug_xt_list->next == NULL) { while (rstackcnt > tmp && !interruptforth) { dbg_interp_printk("enterforth: NEXT\n"); next(); } } else { while (rstackcnt > tmp && !interruptforth) { dbg_interp_printk("enterforth: NEXT_DBG\n"); next_dbg(); } } /* Always clear the debug mode change flag */ interruptforth = interruptforth & (~FORTH_INTSTAT_DBG); } #if 0 /* return true if we took an exception. The caller should normally * handle exceptions by returning immediately since the throw * is supposed to abort the execution of this C-code too. */ if (rstackcnt != tmp) { printk("EXCEPTION DETECTED!\n"); } #endif return rstackcnt != tmp; }
static int build_dictionary(void) { ucell lfa = 0; unsigned int i; /* we need a temporary place for latest outside the dictionary */ latest = &lfa; /* starting a new dictionary: clear dicthead */ dicthead = 0; #ifdef CONFIG_DEBUG_DICTIONARY printk("building dictionary, %d primitives.\nbuilt words:", sizeof(wordnames) / sizeof(void *)); #endif for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) { if (strlen(wordnames[i]) != 0) { fcreate((char *) wordnames[i], i); #ifdef CONFIG_DEBUG_DICTIONARY printk(" %s", wordnames[i]); #endif } } #ifdef CONFIG_DEBUG_DICTIONARY printk(".\n"); #endif /* get last/latest and state */ state = buildvariable("state", 0); last = buildvariable("forth-last", 0); latest = buildvariable("latest", 0); *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell)); base=buildvariable("base", 10); buildconstant("/c", sizeof(u8)); buildconstant("/w", sizeof(u16)); buildconstant("/l", sizeof(u32)); buildconstant("/n", sizeof(ucell)); buildconstant("/x", sizeof(u64)); reveal(); if (verbose) { printk("Dictionary initialization finished.\n"); } return 0; }
static void fcreate(const char *word, ucell cfaval) { if (strlen(word) == 0) { printk("WARNING: tried to create unnamed word.\n"); return; } writestring(word); /* get us at least 1 byte for flags */ writebyte(0); paddict(sizeof(cell)); /* set flags high bit. */ dict[dicthead - 1] = 128; /* lfa and cfa */ writecell(read_ucell(latest)); *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell)); writecell(cfaval); }
static void write_dictionary(const char *filename) { FILE *f; unsigned char *write_data, *walk_data; int write_len; dictionary_header_t *header; u32 checksum=0; /* * get memory for dictionary */ write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell); write_data = malloc(write_len); if(!write_data) { printk("panic: can't allocate memory for output dictionary (%d" " bytes\n", write_len); exit(1); } memset(write_data, 0, write_len); /* * prepare dictionary header */ header = (dictionary_header_t *)write_data; *header = (dictionary_header_t){ .signature = DICTID, .version = 2, .cellsize = sizeof(ucell), #ifdef CONFIG_BIG_ENDIAN .endianess = -1, #else .endianess = 0, #endif .checksum = 0, .compression = 0, .relocation = -1, .length = target_ulong((uint32_t)dicthead), .last = target_ucell((ucell)((unsigned long)last - (unsigned long)dict)), }; /* * prepare dictionary data */ walk_data=write_data+sizeof(dictionary_header_t); memcpy (walk_data, dict, dicthead); /* * prepare relocation data. * relocation_address is zero when writing a dictionary core. */ if (relocation_address) { #ifdef CONFIG_DEBUG_DICTIONARY printk("writing %d reloc cells \n",relocation_length); #endif walk_data += dicthead; memcpy(walk_data, relocation_address, relocation_length*sizeof(cell)); /* free relocation information */ free(relocation_address); relocation_address=NULL; } else { header->relocation=0; } /* * Calculate Checksum */ walk_data=write_data; while (walk_data<write_data+write_len) { checksum+=read_long(walk_data); walk_data+=sizeof(u32); } checksum=(u32)-checksum; header->checksum=target_long(checksum); if (verbose) { dump_header(header); } f = fopen(filename, "w"); if (!f) { printk("panic: can't write to dictionary '%s'.\n", filename); exit(1); } fwrite(write_data, write_len, 1, f); free(write_data); fclose(f); #ifdef CONFIG_DEBUG_DICTIONARY printk("wrote dictionary to file %s.\n", filename); #endif } /* * Write dictionary as a list of ucell hex values to filename. Array * header and end lines are not generated. * * Cells with relocations are output using the expression * DICTIONARY_BASE + value. * * Define some helpful constants. */ static void write_dictionary_hex(const char *filename) { FILE *f; ucell *walk; f = fopen(filename, "w"); if (!f) { printk("panic: can't write to dictionary '%s'.\n", filename); exit(1); } for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) { int pos, bit, l; ucell val; l = (walk - (ucell *)dict); pos = l / BITS; bit = l & ~(-BITS); val = read_ucell(walk); if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) { fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x ",\n", val); } else { fprintf(f, "0x%" FMT_CELL_x",\n", val); } } fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n", (ucell)((unsigned long)last - (unsigned long)dict)); fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n", (ucell)dicthead); fclose(f); #ifdef CONFIG_DEBUG_DICTIONARY printk("wrote dictionary to file %s.\n", filename); #endif }