void genword(char * buffer, int begin, int size, int curcar, char result[SIZE+1]) { int i = 0; char tmp1, tmp2, tmp3; if (size == 1) { assert(curcar < NBCAR && curcar >= 0); buffer[begin] = C[curcar]; /*printf("%s\n", buffer);*/ tmp1 = buffer[0], tmp2 = buffer[1], tmp3 = buffer[2]; if (decode(result, buffer) == 1) { printf("%s:%s\n\n", buffer, result); } assert(tmp1 == buffer[0] && tmp2 == buffer[1] && tmp3 == buffer[2]); if (curcar >= NBCAR -1) { return; } genword(buffer, begin, size, curcar+1, result); } else { for (i = 0; i < NBCAR; i++) { buffer[begin] = C[i]; genword(buffer, begin+1, size-1, 0, result); } } }
int main(void) { //printf("%d\n", XOR(65, 42)); //printf("%d\n", XOR(107, 42)); char buffer[4] = {0, 0, 0, 0}, result[SIZE+1] = ""; genword(buffer, 0, 3, 0, result); return 0; }
void dumplits(void) /* * dump the string literal pool. */ { while( strtab != 0) { cseg(); nl(); put_label(strtab->label); genstring(strtab->str,strtab->type); if (strtab->type) genword(0); else genbyte(0); strtab = strtab->next; } nl(); }
int genstring(char *str, int uselong) /* * Generate a string literal */ { if (uselong) { while (*(short *)str) { genword(*((short *)str)); str+=2; } return pstrlen(str)*2; } else { while (*str) genbyte(*str++); return strlen(str); } }
void gcode(void) { int i, n, t, r, stacksize, addr, pc, disp, rel, errs, more, func_start; Branch *b, *bn; // Generate function prolog func_start = cur_text_section->data_offset; if (!func_naked) { // Align local size to word stacksize = (-loc + 3) & -4; if (stacksize >= 4096) { // Generate stack guard since parameters can cross page boundary Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); gen(0xb8); // mov stacksize, %eax genword(stacksize); gen(0xe8); // call __chkstk, (does the stackframe too) put_reloc(cur_text_section, sym, cur_text_section->data_offset, R_386_PC32); genword(-4); } else { if (do_debug || loc || !func_noargs) { gen(0x55); // push %ebp gen(0x89); // mov %esp, %ebp gen(0xe5); } if (stacksize > 0) { if (stacksize == (char) stacksize) { gen(0x83); // sub esp, stacksize gen(0xec); gen(stacksize); } else { gen(0x81); // sub esp, stacksize gen(0xec); genword(stacksize); } } } // Save callee-saved registers used by function. for (r = 0; r < NB_REGS; ++r) { if ((reg_classes[r] & RC_SAVE) && (regs_used & (1 << r))) { gen(0x50 + r); // push r } } } // Optimize jumps more = 1; while (more) { more = 0; for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeLabel) b->target = 0; if (b->type != CodeJump) continue; t = skip_nops(b->target, 1); if (branch[t].type == CodeJump && !branch[t].param && b->target != branch[t].target) { // Eliminate jump to jump b->target = branch[t].target; more = 1; continue; } // Find next non-nop n = i + 1; while (branch[n].type == CodeNop || branch[n].type == CodeLine) n++; bn = branch + n; if (b->ind != bn->ind) continue; if (!b->param && bn->type == CodeJump) { // Eliminate dead jump instruction bn->type = CodeNop; more = 1; continue; } if (b->target > i && b->target <= n) { // Eliminate jump to next instruction b->type = CodeNop; more = 1; continue; } t = skip_nops(n + 1, 0); if (bn->type == CodeJump && !bn->param && b->target == t && bn->ind == branch[t].ind) { // Optimize inverted jump if (b->param) b->param ^= 1; b->target = bn->target; bn->type = CodeNop; more = 1; continue; } } // Eliminate unused labels for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeJump) branch[b->target].target++; } for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeLabel && !b->target && !b->sym) { // Remove label with no references b->type = CodeNop; more = 1; } } } // Assign addresses to branch points, assuming only long jumps addr = cur_text_section->data_offset; pc = 0; for (i = 0; i < br; ++i) { b = branch + i; addr += b->ind - pc; b->addr = addr; switch (b->type) { case CodeJump: addr += 5; if (b->param != 0) addr++; break; case CodeAlign: // Use convervative estimate for short/long jump estimation addr += b->param - 1; break; } pc = b->ind; } // Find jumps which can be encoded as short jumps for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeJump) { disp = branch[b->target].addr - b->addr - 2; if (b->param) disp--; if (disp == (char) disp) b->type = CodeShortJump; } } // Assign final addresses to branch points addr = cur_text_section->data_offset; pc = 0; for (i = 0; i < br; ++i) { b = branch + i; addr += b->ind - pc; b->addr = addr; switch (b->type) { case CodeJump: addr += 5; if (b->param) addr++; break; case CodeShortJump: addr += 2; break; case CodeAlign: addr = (addr + b->param - 1) & -b->param; break; } pc = b->ind; } // Generate code blocks pc = 0; errs = 0; for (i = 0; i < br; ++i) { b = branch + i; // Output code block before branch point if (b->ind != pc) { genblk(code + pc, b->ind - pc); pc = b->ind; } switch (b->type) { case CodeLabel: // Export label if symbol defined if (b->sym) { put_extern_sym_ex(b->sym, cur_text_section, b->addr, 0, 0); sym_free(b->sym); } break; case CodeJump: // Generate long jump instruction if (branch[b->target].type != CodeLabel) { printf("internal error: jump %d to non-label %d\n", i, b->target); errs++; } if (b->param > 0xff) error("invalid displacement"); if (b->param == 0) { gen(0xe9); genword(branch[b->target].addr - (b->addr + 5)); } else { gen(0x0f); gen(b->param - 0x10); genword(branch[b->target].addr - (b->addr + 6)); } break; case CodeShortJump: // Generate short jump instruction if (branch[b->target].type != CodeLabel) { printf("internal error: jump %d to non-label %d\n", i, b->target); errs++; } if (b->param == 0) { gen(0xeb); } else { gen(b->param - 0x20); } gen(branch[b->target].addr - (b->addr + 2)); break; case CodeReloc: if (b->param) { rel = R_386_PC32; } else { rel = R_386_32; } put_elf_reloc(symtab_section, cur_text_section, b->addr, rel, b->target); break; case CodeAlign: i = addr; while (i & (b->param - 1)) { gen(b->target); i++; } break; case CodeLine: put_stabn(N_SLINE, 0, b->target, b->addr - func_start); break; } } // Generate function epilog if (!func_naked) { // Restore callee-saved registers used by function. for (r = NB_REGS; r >= 0; --r) { if ((reg_classes[r] & RC_SAVE) && (regs_used & (1 << r))) { gen(0x58 + r); // pop r } } if (do_debug || loc || !func_noargs) gen(0xc9); // leave // Generate return if (func_ret_sub == 0) { gen(0xc3); // ret } else { gen(0xc2); // ret n gen(func_ret_sub); gen(func_ret_sub >> 8); } } #ifdef DEBUG_BRANCH printf("\nbranch table for %s\n", func_name); printf(" # t targ parm ind addr\n"); printf("---- - ---- ----- -------- --------\n"); for (i = 0; i < br; ++i) { b = branch + i; printf("%04d %c %04d %04x %08x %08x", i, "SLJjRANlE"[b->type], b->target, b->param, b->ind, b->addr); if (branch[i].sym) { printf(" sym=%s", get_tok_str(b->sym->v, NULL)); } printf("\n"); } printf("\n"); #endif if (errs) error("internal error: code generation"); }