static void emit_alu_x86reg_immediate(int aluop, int x86reg, int imm) { if (imm >= -0x80 && imm < 0x80) { emit_byte(0x83); emit_modrm_x86reg(aluop, x86reg); emit_byte(imm); } else if (x86reg == EAX) { emit_byte(0x05 | aluop << 3); emit_dword(imm); } else { emit_byte(0x81); emit_modrm_x86reg(aluop, x86reg); emit_dword(imm); } }
static inline void emit_jump(uintptr_t target) { emit_byte(0xE9); int64_t diff = target - ((uintptr_t) out + 4); if(diff > INT32_MAX || diff < INT32_MIN) assert(false); emit_dword(diff); }
/*This is a hack: * -regs not saved * -stack not aligned */ static inline void emit_call_nosave(uintptr_t target) { emit_byte(0xE8); int64_t diff = target - ((uintptr_t) out + 4); if(diff > INT32_MAX || diff < INT32_MIN) assert(false); //Distance doesn't fit into immediate emit_dword(diff); }
static void emit_modrm_base_offset(int r, int basex86reg, int offset) { if (offset == 0) { emit_byte(basex86reg | r << 3); } else if (offset >= -0x80 && offset < 0x80) { emit_byte(0x40 | basex86reg | r << 3); emit_byte(offset); } else { emit_byte(0x80 | basex86reg | r << 3); emit_dword(offset); } }
static void emit_alu_armreg_immediate(int aluop, int armreg, int imm) { if (imm >= -0x80 && imm < 0x80) { emit_byte(0x83); emit_modrm_armreg(aluop, armreg); emit_byte(imm); } else { emit_byte(0x81); emit_modrm_armreg(aluop, armreg); emit_dword(imm); } }
int main(int argc,char *argv[]) { int i,opsize=sizeof(opcode_table)/sizeof(opcode_desc), pushsize=sizeof(push_table)/sizeof(opcode_desc), popsize=sizeof(pop_table)/sizeof(opcode_desc), compsize=sizeof(compiler_table)/sizeof(char*); int label; const char **func_table = bg_intrinsic_table; int funsize = bg_intrinsic_size; int findex = 1; // Index in argv of 1st filename. unsigned int opcodetype; indata=codesize=datasize=0; /* printf("Wody's Usecode Compiler v0.009\nCopyright (c) 1999 Wody " "Dragon (a.k.a. Wouter Dijkslag)\n");*/ if (argc<3) { printf("syntax: %s [-s] infile outfile\n", argv[0]); exit(0); } // Serpent Isle? if (strcmp(argv[1], "-s") == 0) { findex++; func_table = si_intrinsic_table; funsize = si_intrinsic_size; } lindex=0; for (pass=0;pass<2;pass++) { // printf("Pass %d\n",pass+1); if ((fi=fopen(argv[findex],"r"))==NULL) { printf("Can't open infile for reading\n"); exit(0); } if ((fo=fopen(argv[findex + 1],"wb"))==NULL) { printf("Can't open outfile for writing\n"); exit(0); } while (!feof(fi)) { read_token(fi); if (strlen(token)>1 && token[strlen(token)-1]==':') { token[strlen(token)-1]=0; // remove trailing ':' if (pass == 0) add_label(); strcpy(curlabel, token); } else if (!strcmp(token,".code")) { indata=0; offset=0; } else if (!strcmp(token,".data")) { if (extended == 0) { emit_word(funcnum); emit_word(0); emit_word(0); codesize = 2; } else { emit_word(-1); emit_word(funcnum); emit_dword(0); emit_dword(0); codesize = 4; } indata=1; offset=0; } else if (!strcmp(token,".funcnumber")) { read_token(fi); sscanf(token,"%x",&funcnum); printf("Function %04X\n", funcnum); // codesize=2; extended = 0; } else if (!strcmp(token,".ext32")) { extended = 1; } else if (token[0]=='.') { indata=0; for (i=0;i<compsize;i++) if (!strcasecmp(compiler_table[i],token)) { read_token(fi); sscanf(token,"%x",&word); emit_word(word); } } else if (!strcmp(token,"db")) { read_token(fi); if (token[0]==39) for (i=1;i<strlen(token);i++) emit_byte(token[i]); else { sscanf(token,"%x",&byte); emit_byte(byte); } } else if (!strcasecmp(token,"dw")) { read_token(fi); sscanf(token,"%x",&word); emit_word(word); } else for (i=0;i<opsize;i++) { if (!opcode_table[i].mnemonic) continue; if (!strcasecmp(opcode_table[i].mnemonic,token)) { if (opcode_table[i].nbytes==0 && opcode_table[i].type==0) emit_byte(i); else { opcodetype = opcode_table[i].type; if (i == 0x21) opcodetype = PUSH; if (i == 0x12) opcodetype = POP; switch (opcodetype) { case BYTE: emit_byte(i); read_token(fi); sscanf(token,"%x",&word); emit_byte(word); break; case CALL: emit_byte(i); read_token(fi); if ((token2=strchr(token,'@'))!=NULL) { token2++; read_token(fi); sscanf(token, "(%x)", &word); emit_word(word); sscanf(token2,"%d",&word); } else { sscanf(token,"%x",&word); emit_word(word); read_token(fi); sscanf(token,"%d",&word); } emit_byte(word); break; case DATA_STRING: emit_byte(i); read_token(fi); label = get_label(); check_data_label_16(label); emit_word(label); break; case DATA_STRING32: emit_byte(i); read_token(fi); emit_dword(get_label()); break; case EXTCALL: case VARREF: emit_byte(i); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); break; case FLGREF: emit_byte(i); read_token(fi); sscanf(token,"flag:[%x]",&word); emit_word(word); break; case PUSH: read_token(fi); for (i=0;i<pushsize;i++) { if (!strcasecmp(push_table[i].mnemonic,token)) { emit_byte(push_table[i].type); break; } } if (i==pushsize) { emit_byte(0x21); sscanf(token,"[%x]",&word); emit_word(word); } break; case POP: read_token(fi); for (i=0;i<popsize;i++) { if (!strcasecmp(pop_table[i].mnemonic,token)) { emit_byte(pop_table[i].type); break; } } if (i==popsize) { emit_byte(0x12); sscanf(token,"[%x]",&word); emit_word(word); } break; case IMMED: emit_byte(i); read_token(fi); sscanf(token,"%x",&word); emit_word(word); break; case IMMED32: emit_byte(i); read_token(fi); sscanf(token,"%x",&word); emit_dword(word); break; case RELATIVE_JUMP: emit_byte(i); read_token(fi); if (pass==1) { // printf("%x, %x, %x\n", get_label(), offset, get_label() - offset-2); label = get_label() - offset - 2; check_jump_label_16(label); emit_word(label); } else emit_word(-1); break; case RELATIVE_JUMP32: emit_byte(i); read_token(fi); if (pass==1) { // printf("%x, %x, %x\n", get_label(), offset, get_label() - offset-2); emit_dword(get_label()-offset-4); } else emit_dword(-1); break; case IMMED_AND_RELATIVE_JUMP: emit_byte(i); read_token(fi); sscanf(token,"%x",&word); emit_word(word); read_token(fi); if (pass==1) { label = get_label() - offset - 2; check_jump_label_16(label); emit_word(label); } else emit_word(-1); break; case IMMED_RELJUMP32: emit_byte(i); read_token(fi); sscanf(token,"%x",&word); emit_word(word); read_token(fi); if (pass==1) emit_dword(get_label()-offset-4); else emit_dword(-1); break; case SLOOP: #if 0 emit_byte(0x2E); if (pass == 0) { sscanf(curlabel, "%x:",&word); sprintf(token,"%04X:",word+1); printf("adding sloop label %s (curlabel=%s)\n", token, curlabel); add_label(); } #endif emit_byte(0x02); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"%x",&word); if (pass==1) { label = get_label() - offset - 2; check_jump_label_16(label); emit_word(label); } else emit_word(-1); break; case SLOOP32: #if 0 emit_byte(0xAE); if (pass == 0) { sscanf(curlabel, "%x:",&word); sprintf(token,"%04X:",word+1); printf("adding sloop label %s (curlabel=%s)\n", token, curlabel); add_label(); } #endif emit_byte(0x82); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"[%x]",&word); emit_word(word); read_token(fi); sscanf(token,"%x",&word); if (pass==1) emit_dword(get_label()-offset-2); else emit_dword(-1); break; default: break; } } } } } if (extended == 0) { fseek(fo,2,SEEK_SET); indata=0; i=codesize; if (codesize > 65535) { printf("Error: code size > 64Kb and not in ext32 mode!\n"); } emit_word(i); if (datasize > 65535) { printf("Error: data size > 64Kb and not in ext32 mode!\n"); } emit_word(datasize); } else { fseek(fo,4,SEEK_SET); indata=0; i=codesize; emit_dword(i); emit_dword(datasize); } fclose(fo); fclose(fi); } return 0; }
static inline void emit_test_armreg_immediate(int armreg, int imm) { emit_byte(0xF7); emit_modrm_armreg(0, armreg); emit_dword(imm); }
static void emit_mov_armreg_immediate(int armreg, int imm) { emit_byte(0xC7); emit_modrm_armreg(0, armreg); emit_dword(imm); }
static void emit_mov_x86reg_immediate(int x86reg, int imm) { emit_byte(0xB8 | x86reg); emit_dword(imm); }
static inline void emit_jump(u32 target) { emit_byte(0xE9); emit_dword(target - ((u32)out + 4)); }
static inline void emit_call(u32 target) { emit_byte(0xE8); emit_dword(target - ((u32)out + 4)); }