From 4684cd5bacba09a00a05645f7344250a33fd3974 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 14 Dec 2014 19:41:11 -0800 Subject: [PATCH] Add opcodes for sign-extending integers. --- public/jit/x86/assembler-x86.h | 19 ++++++++++++++ sourcepawn/compiler/sc6.cpp | 4 +-- sourcepawn/include/smx/smx-v1-opcodes.h | 4 +-- sourcepawn/jit/x86/jit_x86.cpp | 35 +++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/public/jit/x86/assembler-x86.h b/public/jit/x86/assembler-x86.h index b766bb54a..5e6e5e23c 100644 --- a/public/jit/x86/assembler-x86.h +++ b/public/jit/x86/assembler-x86.h @@ -367,6 +367,7 @@ class AssemblerX86 : public Assembler void movb(Register dest, const Operand &src) { emit1(0x8a, dest.code, src); } + void movzxb(Register dest, const Operand &src) { emit2(0x0f, 0xb6, dest.code, src); } @@ -380,6 +381,24 @@ class AssemblerX86 : public Assembler emit2(0x0f, 0xb7, dest.code, src.code); } + void movsxb(Register dest, const Operand &src) { + emit2(0x0f, 0xbe, dest.code, src); + } + void movsxb(Register dest, const Register src) { + emit2(0x0f, 0xbe, dest.code, src.code); + } + void movsxw(Register dest, const Operand &src) { + emit2(0x0f, 0xbf, dest.code, src); + } + void movsxw(Register dest, const Register src) { + emit2(0x0f, 0xbf, dest.code, src.code); + } + + // Sign extend eax -> edx. + void cdq() { + emit1(0x99); + } + void lea(Register dest, const Operand &src) { emit1(0x8d, dest.code, src); } diff --git a/sourcepawn/compiler/sc6.cpp b/sourcepawn/compiler/sc6.cpp index 5e73e7ddd..db6eff10e 100644 --- a/sourcepawn/compiler/sc6.cpp +++ b/sourcepawn/compiler/sc6.cpp @@ -432,8 +432,8 @@ static OPCODEC opcodelist[] = { { 66, "shr", sIN_CSEG, parm0 }, { 71, "shr.c.alt", sIN_CSEG, parm1 }, { 70, "shr.c.pri", sIN_CSEG, parm1 }, - { 94, "sign.alt", sIN_CSEG, parm0 }, - { 93, "sign.pri", sIN_CSEG, parm0 }, + { 94, "sign.alt", sIN_CSEG, parm1 }, + { 93, "sign.pri", sIN_CSEG, parm1 }, {102, "sleq", sIN_CSEG, parm0 }, {101, "sless", sIN_CSEG, parm0 }, { 72, "smul", sIN_CSEG, parm0 }, diff --git a/sourcepawn/include/smx/smx-v1-opcodes.h b/sourcepawn/include/smx/smx-v1-opcodes.h index 4be5ae393..b4eaa26e1 100644 --- a/sourcepawn/include/smx/smx-v1-opcodes.h +++ b/sourcepawn/include/smx/smx-v1-opcodes.h @@ -161,8 +161,8 @@ namespace sp { _(ZERO_ALT, "zero.alt") \ _(ZERO, "zero") \ _(ZERO_S, "zero.s") \ - _(UNGEN_SIGN_PRI, "sign.pri") \ - _(UNGEN_SIGN_ALT, "sign.alt") \ + _(SIGN_PRI, "sign.pri") \ + _(SIGN_ALT, "sign.alt") \ _(EQ, "eq") \ _(NEQ, "neq") \ _(LESS, "less") \ diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 21700596b..60f859c7b 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -980,6 +980,41 @@ Compiler::emitOp(OPCODE op) __ sarl(pri, 2); break; + // Sign extend an [8,16] bit value to a 32-bit value, or a 32-bit value + // to a 64-bit value. + case OP_SIGN_PRI: + case OP_SIGN_ALT: + { + Register reg = (op == OP_SIGN_PRI) ? pri : alt; + size_t bits = readCell(); + switch (bits) { + case 8: + __ movsxb(reg, reg); + break; + case 16: + __ movsxw(reg, reg); + break; + case 32: + // Address is in |reg|. We have to save pri/alt because cdq needs + // to destroy both. We move the sign-extended reg to ecx and then + // write it back after. + emitCheckAddress(reg); + __ push(eax); + __ push(edx); + __ movl(tmp, Operand(reg, 0)); + __ cdq(); + __ movl(tmp, edx); + __ pop(edx); + __ pop(eax); + __ movl(Operand(reg, 4), tmp); + break; + default: + error_= SP_ERROR_INVALID_INSTRUCTION; + return false; + } + break; + } + case OP_ABS_F32: __ movl(pri, Operand(stk, 0)); __ andl(pri, 0x7fffffff);