/* Process the arguments */ int process_args(int argc, char **argv) { int ch; g_title = NULL; g_filename = NULL; g_empty = 0; ch = getopt_long(argc, argv, "ed:s:", arg_opts, NULL); while(ch != -1) { switch(ch) { case 'd' : if(!add_dword(optarg)) { return 0; } break; case 's' : if(!add_string(optarg)) { } break; default : break; }; ch = getopt_long(argc, argv, "ed:s:", arg_opts, NULL); } argc -= optind; argv += optind; if(argc < 1) { return 0; } if(!g_empty) { g_title = argv[0]; argc--; argv++; } if(argc < 1) { return 0; } g_filename = argv[0]; return 1; }
void emit_mcode(Mcode *mc, u32 opcode, u32 operand_size, Arg left, Arg right) { bool is_simd = IS_SIMD_OPCODE(opcode); bool jump_opcode = JUMP_OPCODE(opcode); bool set_byte_opcode = SET_BYTE_OPCODE(opcode); bool muldiv_opcode = opcode == MUL || opcode == DIV; assert(!is_simd || operand_size == DWORD || operand_size == QWORD); assert(!jump_opcode || operand_size == BYTE || operand_size == DWORD); assert(!set_byte_opcode || operand_size == BYTE); assert(!(set_byte_opcode || muldiv_opcode) || left.type == REGISTER || left.type == STACK); assert(!jump_opcode || left.type == JUMP); assert(jump_opcode || set_byte_opcode || muldiv_opcode || right.type != UNDEFINED); u8 multibyte_operands = (operand_size == BYTE) ? 0 : 1; if (is_simd) { if (operand_size == DWORD) add_word(mc, 0x0ff3); else if (operand_size == QWORD) add_word(mc, 0x0ff2); } else { if (operand_size == WORD) add_byte(mc, 0x66); else if (operand_size == QWORD) add_byte(mc, 0x48); } if (jump_opcode || set_byte_opcode || muldiv_opcode) { if (set_byte_opcode) { add_byte(mc, 0x0f); add_byte(mc, opcode); if (left.type == REGISTER) add_byte(mc, REG_ADDRESSING << 6 | left.reg); else { if (size_of_int(left.offset) == BYTE) { add_byte(mc, BYTE_OFFSET << 6 | left.reg); add_byte(mc, left.offset); } else { add_byte(mc, DWORD_OFFSET << 6 | left.reg); add_dword(mc, left.offset); } } } else if (jump_opcode) { if (size_of_int(left.offset) == BYTE) { add_byte(mc, opcode); add_byte(mc, left.offset - 2); } else { add_byte(mc, 0x0f); add_byte(mc, opcode + 0x10); add_dword(mc, left.offset - 6); } } else { add_byte(mc, 0xf7); if (left.type == REGISTER) add_byte(mc, REG_ADDRESSING << 6 | opcode << 3 | left.reg); else if (left.type == STACK) { if (size_of_int(left.offset) == BYTE) { add_byte(mc, BYTE_OFFSET << 6 | opcode << 3 | left.reg); add_byte(mc, left.offset); } else { add_byte(mc, DWORD_OFFSET << 6 | opcode << 3 | left.reg); add_dword(mc, left.offset); } } } } else if (left.type == REGISTER && right.type == REGISTER) { if (is_simd) { add_byte(mc, opcode); add_byte(mc, REG_ADDRESSING << 6 | right.reg << 3 | left.reg); } else { add_byte(mc, opcode << 3 | multibyte_operands); add_byte(mc, REG_ADDRESSING << 6 | left.reg << 3 | right.reg); } } else if (left.type == REGISTER && right.type == STACK) { if (is_simd) { assert(opcode == MOVS); add_byte(mc, opcode | 0x1); } else add_byte(mc, opcode << 3 | multibyte_operands); if (size_of_int(right.offset) == BYTE) { add_byte(mc, BYTE_OFFSET << 6 | left.reg << 3 | right.reg); add_byte(mc, right.offset); } else { add_byte(mc, DWORD_OFFSET << 6 | left.reg << 3 | right.reg); add_dword(mc, right.offset); } } else if (left.type == STACK && right.type == REGISTER) { if (is_simd) add_byte(mc, opcode); else add_byte(mc, opcode << 3 | 0x2 | multibyte_operands); if (size_of_int(left.offset) == BYTE) { add_byte(mc, BYTE_OFFSET << 6 | right.reg << 3 | left.reg); add_byte(mc, left.offset); } else { add_byte(mc, DWORD_OFFSET << 6 | right.reg << 3 | left.reg); add_dword(mc, left.offset); } } else if (left.type == IMMEDIATE) { u8 immediate_size = size_of_int(left.immediate); u8 byte_immediate = (immediate_size == BYTE) ? 0x2 : 0x0; assert(!is_simd || right.type != REGISTER); assert(immediate_size != QWORD || opcode == MOV && right.type == REGISTER); if (right.type == REGISTER) { if (opcode == MOV) { if (operand_size == BYTE) add_byte(mc, 0xb0 | right.reg); else add_byte(mc, 0xb8 | right.reg); } else { if (operand_size == BYTE && right.reg == AX) add_byte(mc, 0x04 | opcode << 3 | AX); else { add_byte(mc, 0x80 | byte_immediate | multibyte_operands); add_byte(mc, REG_ADDRESSING << 6 | opcode << 3 | right.reg); } } } else if (right.type == STACK) { u8 opcode_part = 0x0; if (opcode == MOV) add_byte(mc, 0xc6 | multibyte_operands); else { opcode_part = opcode << 3; if (operand_size == BYTE) add_byte(mc, 0x80); else add_byte(mc, 0x80 | byte_immediate | multibyte_operands); } if (size_of_int(right.offset) == BYTE) { add_byte(mc, BYTE_OFFSET << 6 | opcode_part | right.reg); add_byte(mc, right.offset); } else { add_byte(mc, DWORD_OFFSET << 6 | opcode_part | right.reg); add_dword(mc, right.offset); } } switch ((opcode == MOV) ? operand_size : immediate_size) { case BYTE: add_byte(mc, left.immediate); break; case WORD: add_word(mc, left.immediate); break; case DWORD: add_dword(mc, left.immediate); break; case QWORD: add_qword(mc, left.immediate); break; } } else assert(false); /* emit: unhandled arg combo */ }
void push(Mcode *mc) { add_dword(mc, 0xe5894855); }