diff options
author | Thilo Schulz <arny@ats.s.bawue.de> | 2011-05-16 17:55:07 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-09 22:29:01 +0000 |
commit | 24d967c48660c3e98ef6d49b757c5ffb3e22f50c (patch) | |
tree | 5d6bc2a9967264588b60ab4f4bf31f81894b56f4 /src/qcommon/vm_x86_64_assembler.c | |
parent | a794d38bda1b44bf4232cf6196919eab1321ff60 (diff) |
- Fix SEGV in while loop getop() after t = b = 0 - Fix iss8, iss16 and iss32 which would not correctly detect 32-bit signed integer range - Add support for "addb", "subb" etc. assembler mnemonic - Change opStack protection for x86_64 VM: No overflow checks necessary anymore as offset register is 1 byte long only
Diffstat (limited to 'src/qcommon/vm_x86_64_assembler.c')
-rw-r--r-- | src/qcommon/vm_x86_64_assembler.c | 118 |
1 files changed, 65 insertions, 53 deletions
diff --git a/src/qcommon/vm_x86_64_assembler.c b/src/qcommon/vm_x86_64_assembler.c index 10280be2..5047977a 100644 --- a/src/qcommon/vm_x86_64_assembler.c +++ b/src/qcommon/vm_x86_64_assembler.c @@ -160,6 +160,7 @@ typedef enum { R_R15 = 0x0F | R_64, R_AL = R_EAX | R_8, R_AX = R_EAX | R_16, + R_BL = R_EBX | R_8, R_CL = R_ECX | R_8, R_XMM0 = 0x00 | R_XMM, R_MGP = 0x0F, // mask for general purpose registers @@ -215,6 +216,32 @@ typedef struct { u8 rcode; // opcode for reg/mem } opparam_t; +static opparam_t params_add = { subcode: 0, rmcode: 0x01, }; +static opparam_t params_or = { subcode: 1, rmcode: 0x09, }; +static opparam_t params_and = { subcode: 4, rmcode: 0x21, }; +static opparam_t params_sub = { subcode: 5, rmcode: 0x29, }; +static opparam_t params_xor = { subcode: 6, rmcode: 0x31, }; +static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, }; +static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, }; +static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, }; +static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, }; +static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, }; +static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, }; + +static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a }; +static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c }; +static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 }; +static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e }; +static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 }; +static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 }; +static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c }; +static opparam_t params_ucomiss = { mrcode: 0x2e }; + /* ************************* */ static unsigned hashkey(const char *string, unsigned len) { @@ -316,9 +343,9 @@ static const char* argtype2str(argtype_t t) /* ************************* */ -static inline int iss8(u64 v) +static inline int iss8(int64_t v) { - return (llabs(v) <= 0x80); //llabs instead of labs required for __WIN64 + return (v >= -0x80 && v <= 0x7f); } static inline int isu8(u64 v) @@ -326,9 +353,9 @@ static inline int isu8(u64 v) return (v <= 0xff); } -static inline int iss16(u64 v) +static inline int iss16(int64_t v) { - return (llabs(v) <= 0x8000); + return (v >= -0x8000 && v <= 0x7fff); } static inline int isu16(u64 v) @@ -336,9 +363,9 @@ static inline int isu16(u64 v) return (v <= 0xffff); } -static inline int iss32(u64 v) +static inline int iss32(int64_t v) { - return (llabs(v) <= 0x80000000); + return (v >= -0x80000000L && v <= 0x7fffffff); } static inline int isu32(u64 v) @@ -597,7 +624,7 @@ static void emit_mov(const char* mnemonic, arg_t arg1, arg_t arg2, void* data) if(arg2.v.reg & R_8) { - if(!isu8(arg1.v.imm)) + if(!iss8(arg1.v.imm)) crap("value too large for 8bit register"); op = 0xb0; @@ -713,19 +740,23 @@ static void emit_subaddand(const char* mnemonic, arg_t arg1, arg_t arg2, void* d } compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2); - modrm |= params->subcode << 3; if(rex) emit1(rex); -#if 0 - if(isu8(arg1.v.imm)) + + if(arg2.v.reg & R_8) + { + emit1(0x80); // sub reg8/mem8, imm8 + emit1(modrm); + emit1(arg1.v.imm & 0xFF); + } + else if(iss8(arg1.v.imm)) { emit1(0x83); // sub reg/mem, imm8 emit1(modrm); - emit1(arg1.v.imm&0xFF); + emit1(arg1.v.imm & 0xFF); } else -#endif { emit1(0x81); // sub reg/mem, imm32 emit1(modrm); @@ -895,42 +926,19 @@ static void emit_twobyte(const char* mnemonic, arg_t arg1, arg_t arg2, void* dat CRAP_INVALID_ARGS; } -static opparam_t params_add = { subcode: 0, rmcode: 0x01, }; -static opparam_t params_or = { subcode: 1, rmcode: 0x09, }; -static opparam_t params_and = { subcode: 4, rmcode: 0x21, }; -static opparam_t params_sub = { subcode: 5, rmcode: 0x29, }; -static opparam_t params_xor = { subcode: 6, rmcode: 0x31, }; -static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, }; -static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, }; -static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, }; -static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, }; -static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, }; -static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, }; - -static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a }; -static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c }; -static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 }; -static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e }; -static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 }; -static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 }; -static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c }; -static opparam_t params_ucomiss = { mrcode: 0x2e }; - static int ops_sorted = 0; static op_t ops[] = { + { "addb", emit_subaddand, ¶ms_add }, { "addl", emit_subaddand, ¶ms_add }, { "addq", emit_subaddand, ¶ms_add }, { "addss", emit_twobyte, ¶ms_addss }, + { "andb", emit_subaddand, ¶ms_and }, { "andl", emit_subaddand, ¶ms_and }, { "andq", emit_subaddand, ¶ms_and }, { "callq", emit_call, NULL }, { "cbw", emit_opsingle16, (void*)0x98 }, { "cdq", emit_opsingle, (void*)0x99 }, + { "cmpb", emit_subaddand, ¶ms_cmp }, { "cmpl", emit_subaddand, ¶ms_cmp }, { "cmpq", emit_subaddand, ¶ms_cmp }, { "cvtsi2ss", emit_twobyte, ¶ms_cvtsi2ss }, @@ -976,18 +984,21 @@ static op_t ops[] = { { "nop", emit_opsingle, (void*)0x90 }, { "notl", emit_op_rm, ¶ms_not }, { "notq", emit_op_rm, ¶ms_not }, - { "or", emit_subaddand, ¶ms_or }, + { "orb", emit_subaddand, ¶ms_or }, { "orl", emit_subaddand, ¶ms_or }, + { "orq", emit_subaddand, ¶ms_or }, { "pop", emit_opreg, (void*)0x58 }, { "push", emit_opreg, (void*)0x50 }, { "ret", emit_opsingle, (void*)0xc3 }, { "sarl", emit_op_rm_cl, ¶ms_sar }, { "shl", emit_op_rm_cl, ¶ms_shl }, { "shrl", emit_op_rm_cl, ¶ms_shr }, + { "subb", emit_subaddand, ¶ms_sub }, { "subl", emit_subaddand, ¶ms_sub }, { "subq", emit_subaddand, ¶ms_sub }, { "subss", emit_twobyte, ¶ms_subss }, { "ucomiss", emit_twobyte, ¶ms_ucomiss }, + { "xorb", emit_subaddand, ¶ms_xor }, { "xorl", emit_subaddand, ¶ms_xor }, { "xorq", emit_subaddand, ¶ms_xor }, { NULL, NULL, NULL } @@ -1012,27 +1023,24 @@ static op_t* getop(const char* n) } #else - unsigned m, t, b; + unsigned int m, t, b; int r; t = ARRAY_LEN(ops)-1; - b = 0; - while(b <= t) + r = m = -1; + + do { - m = ((t-b)>>1) + b; - if((r = strcmp(ops[m].mnemonic, n)) == 0) - { - return &ops[m]; - } - else if(r < 0) - { + if(r < 0) b = m + 1; - } else - { t = m - 1; - } - } + + m = ((t - b) >> 1) + b; + + if((r = strcmp(ops[m].mnemonic, n)) == 0) + return &ops[m]; + } while(b <= t && t); #endif return NULL; @@ -1049,6 +1057,10 @@ static reg_t parsereg(const char* str) { return R_AX; } + if(*s == 'b' && s[1] == 'l' && !s[2]) + { + return R_BL; + } if(*s == 'c' && s[1] == 'l' && !s[2]) { return R_CL; |