Refactor the JIT to use a newer, simpler macro assembler. (bug 5827, r=ann)
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/public/jit/assembler.h Thu Aug 08 09:41:24 2013 -0700
1.3 @@ -0,0 +1,294 @@
1.4 +/**
1.5 + * vim: set ts=8 sts=2 sw=2 tw=99 et:
1.6 + * =============================================================================
1.7 + * SourcePawn JIT SDK
1.8 + * Copyright (C) 2004-2013 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +#ifndef _include_sourcepawn_assembler_h__
1.35 +#define _include_sourcepawn_assembler_h__
1.36 +
1.37 +#include <assert.h>
1.38 +#include <stdlib.h>
1.39 +#include <stddef.h>
1.40 +#include <stdint.h>
1.41 +#include <limits.h>
1.42 +
1.43 +class Assembler
1.44 +{
1.45 + public:
1.46 + static const size_t kMinBufferSize = 4096;
1.47 + static const size_t kMaxInstructionSize = 32;
1.48 + static const size_t kMaxBufferSize = INT_MAX / 2;
1.49 +
1.50 + public:
1.51 + Assembler() {
1.52 + buffer_ = (uint8_t *)malloc(kMinBufferSize);
1.53 + pos_ = buffer_;
1.54 + end_ = buffer_ + kMinBufferSize;
1.55 + outOfMemory_ = !buffer_;
1.56 + }
1.57 + ~Assembler() {
1.58 + free(buffer_);
1.59 + }
1.60 +
1.61 + bool outOfMemory() const {
1.62 + return outOfMemory_;
1.63 + }
1.64 +
1.65 + // Amount needed to allocate for executable code.
1.66 + size_t length() const {
1.67 + return pos_ - buffer_;
1.68 + }
1.69 +
1.70 + protected:
1.71 + void writeByte(uint8_t byte) {
1.72 + write<uint8_t>(byte);
1.73 + }
1.74 + void writeInt32(int32_t word) {
1.75 + write<int32_t>(word);
1.76 + }
1.77 + void writeUint32(uint32_t word) {
1.78 + write<uint32_t>(word);
1.79 + }
1.80 + void writePointer(void *ptr) {
1.81 + write<void *>(ptr);
1.82 + }
1.83 +
1.84 + template <typename T>
1.85 + void write(const T &t) {
1.86 + assertCanWrite(sizeof(T));
1.87 + *reinterpret_cast<T *>(pos_) = t;
1.88 + pos_ += sizeof(T);
1.89 + }
1.90 +
1.91 + // Normally this does not need to be checked, but it must be called before
1.92 + // emitting any instruction.
1.93 + bool ensureSpace() {
1.94 + if (pos_ + kMaxInstructionSize <= end_)
1.95 + return true;
1.96 +
1.97 + if (outOfMemory())
1.98 + return false;
1.99 +
1.100 + size_t oldlength = size_t(end_ - buffer_);
1.101 +
1.102 + if (oldlength * 2 > kMaxBufferSize) {
1.103 + // See comment when if realloc() fails.
1.104 + pos_ = buffer_;
1.105 + outOfMemory_ = true;
1.106 + return false;
1.107 + }
1.108 +
1.109 + size_t oldpos = size_t(pos_ - buffer_);
1.110 + uint8_t *newbuf = (uint8_t *)realloc(buffer_, oldlength * 2);
1.111 + if (!newbuf) {
1.112 + // Writes will be safe, though we'll corrupt the instruction stream, so
1.113 + // actually using the buffer will be invalid and compilation should be
1.114 + // aborted when possible.
1.115 + pos_ = buffer_;
1.116 + outOfMemory_ = true;
1.117 + return false;
1.118 + }
1.119 + buffer_ = newbuf;
1.120 + end_ = newbuf + oldlength * 2;
1.121 + pos_ = buffer_ + oldpos;
1.122 + return true;
1.123 + }
1.124 +
1.125 + // Position will never be negative, but it's nice to have signed results
1.126 + // for relative address calculation.
1.127 + int32_t position() const {
1.128 + return int32_t(pos_ - buffer_);
1.129 + }
1.130 +
1.131 + // pc is the unsigned version of position().
1.132 + uint32_t pc() const {
1.133 + return uint32_t(pos_ - buffer_);
1.134 + }
1.135 +
1.136 + protected:
1.137 + void assertCanWrite(size_t bytes) {
1.138 + assert(pos_ + bytes <= end_);
1.139 + }
1.140 + uint8_t *buffer() const {
1.141 + return buffer_;
1.142 + }
1.143 +
1.144 + private:
1.145 + uint8_t *buffer_;
1.146 + uint8_t *end_;
1.147 +
1.148 + protected:
1.149 + uint8_t *pos_;
1.150 + bool outOfMemory_;
1.151 +};
1.152 +
1.153 +class ExternalAddress
1.154 +{
1.155 + public:
1.156 + explicit ExternalAddress(void *p)
1.157 + : p_(p)
1.158 + {
1.159 + }
1.160 +
1.161 + void *address() const {
1.162 + return p_;
1.163 + }
1.164 + uintptr_t value() const {
1.165 + return uintptr_t(p_);
1.166 + }
1.167 +
1.168 + private:
1.169 + void *p_;
1.170 +};
1.171 +
1.172 +// A label is a lightweight object to assist in managing relative jumps. It
1.173 +// exists in three states:
1.174 +// * Unbound, Unused: The label has no incoming jumps, and its position has
1.175 +// not yet been fixed in the instruction stream.
1.176 +// * Unbound, Used: The label has not yet been fixed at a position in the
1.177 +// instruction stream, but it has incoming jumps.
1.178 +// * Bound: The label has been fixed at a position in the instruction stream.
1.179 +//
1.180 +// When a label is unbound and used, the offset stored in the Label is a linked
1.181 +// list threaded through each individual jump. When the label is bound, each
1.182 +// jump instruction in this list is immediately patched with the correctly
1.183 +// computed relative distance to the label.
1.184 +//
1.185 +// We keep sizeof(Label) == 4 to make it embeddable within code streams if
1.186 +// need be (for example, SourcePawn mirrors the source code to maintain jump
1.187 +// maps).
1.188 +class Label
1.189 +{
1.190 + // If set on status_, the label is bound.
1.191 + static const int32_t kBound = (1 << 0);
1.192 +
1.193 + public:
1.194 + Label()
1.195 + : status_(0)
1.196 + {
1.197 + }
1.198 + ~Label()
1.199 + {
1.200 + assert(!used() || bound());
1.201 + }
1.202 +
1.203 + static inline bool More(uint32_t status) {
1.204 + return status != 0;
1.205 + }
1.206 + static inline uint32_t ToOffset(uint32_t status) {
1.207 + return status >> 1;
1.208 + }
1.209 +
1.210 + bool used() const {
1.211 + return bound() || !!(status_ >> 1);
1.212 + }
1.213 + bool bound() const {
1.214 + return !!(status_ & kBound);
1.215 + }
1.216 + uint32_t offset() const {
1.217 + assert(bound());
1.218 + return ToOffset(status_);
1.219 + }
1.220 + uint32_t status() const {
1.221 + assert(!bound());
1.222 + return status_;
1.223 + }
1.224 + uint32_t addPending(uint32_t pc) {
1.225 + assert(pc <= INT_MAX / 2);
1.226 + uint32_t prev = status_;
1.227 + status_ = pc << 1;
1.228 + return prev;
1.229 + }
1.230 + void bind(uint32_t offset) {
1.231 + assert(!bound());
1.232 + status_ = (offset << 1) | kBound;
1.233 + assert(this->offset() == offset);
1.234 + }
1.235 +
1.236 + private:
1.237 + // Note that 0 as an invalid offset is okay, because the offset we save for
1.238 + // pending jumps are after the jump opcode itself, and therefore 0 is never
1.239 + // valid, since there are no 0-byte jumps.
1.240 + uint32_t status_;
1.241 +};
1.242 +
1.243 +// A DataLabel is a special form of Label intended for absolute addresses that
1.244 +// are within the code buffer, and thus aren't known yet, and will be
1.245 +// automatically fixed up when calling emitToExecutableMemory().
1.246 +//
1.247 +// Unlike normal Labels, these do not store a list of incoming uses.
1.248 +class DataLabel
1.249 +{
1.250 + // If set on status_, the label is bound.
1.251 + static const int32_t kBound = (1 << 0);
1.252 +
1.253 + public:
1.254 + DataLabel()
1.255 + : status_(0)
1.256 + {
1.257 + }
1.258 + ~DataLabel()
1.259 + {
1.260 + assert(!used() || bound());
1.261 + }
1.262 +
1.263 + static inline uint32_t ToOffset(uint32_t status) {
1.264 + return status >> 1;
1.265 + }
1.266 +
1.267 + bool used() const {
1.268 + return bound() || !!(status_ >> 1);
1.269 + }
1.270 + bool bound() const {
1.271 + return !!(status_ & kBound);
1.272 + }
1.273 + uint32_t offset() const {
1.274 + assert(bound());
1.275 + return ToOffset(status_);
1.276 + }
1.277 + uint32_t status() const {
1.278 + assert(!bound());
1.279 + return status_;
1.280 + }
1.281 + void use(uint32_t pc) {
1.282 + assert(!used());
1.283 + status_ = (pc << 1);
1.284 + assert(ToOffset(status_) == pc);
1.285 + }
1.286 + void bind(uint32_t offset) {
1.287 + assert(!bound());
1.288 + status_ = (offset << 1) | kBound;
1.289 + assert(this->offset() == offset);
1.290 + }
1.291 +
1.292 + private:
1.293 + uint32_t status_;
1.294 +};
1.295 +
1.296 +#endif // _include_sourcepawn_assembler_h__
1.297 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/public/jit/x86/assembler-x86.h Thu Aug 08 09:41:24 2013 -0700
2.3 @@ -0,0 +1,842 @@
2.4 +/**
2.5 + * vim: set ts=8 sts=2 sw=2 tw=99 et:
2.6 + * =============================================================================
2.7 + * SourcePawn JIT SDK
2.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
2.9 + * =============================================================================
2.10 + *
2.11 + * This program is free software; you can redistribute it and/or modify it under
2.12 + * the terms of the GNU General Public License, version 3.0, as published by the
2.13 + * Free Software Foundation.
2.14 + *
2.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
2.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2.18 + * details.
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License along with
2.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
2.22 + *
2.23 + * As a special exception, AlliedModders LLC gives you permission to link the
2.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
2.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
2.26 + * by the Valve Corporation. You must obey the GNU General Public License in
2.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
2.28 + * this exception to all derivative works. AlliedModders LLC defines further
2.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
2.30 + * or <http://www.sourcemod.net/license.php>.
2.31 + *
2.32 + * Version: $Id$
2.33 + */
2.34 +#ifndef _include_sourcepawn_assembler_x86_h__
2.35 +#define _include_sourcepawn_assembler_x86_h__
2.36 +
2.37 +#include <assembler.h>
2.38 +#include <ke_vector.h>
2.39 +#include <string.h>
2.40 +
2.41 +struct Register
2.42 +{
2.43 + const char *name() const {
2.44 + static const char *names[] = {
2.45 + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
2.46 + };
2.47 + return names[code];
2.48 + }
2.49 +
2.50 + int code;
2.51 +
2.52 + bool operator == (const Register &other) const {
2.53 + return code == other.code;
2.54 + }
2.55 + bool operator != (const Register &other) const {
2.56 + return code != other.code;
2.57 + }
2.58 +};
2.59 +
2.60 +// X86 has an ancient FPU (called x87) which has a stack of registers
2.61 +// numbered st0 through st7.
2.62 +struct FpuRegister
2.63 +{
2.64 + const char *name() const {
2.65 + static const char *names[] = {
2.66 + "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
2.67 + };
2.68 + return names[code];
2.69 + }
2.70 +
2.71 + int code;
2.72 +
2.73 + bool operator == (const FpuRegister &other) const {
2.74 + return code == other.code;
2.75 + }
2.76 + bool operator != (const FpuRegister &other) const {
2.77 + return code != other.code;
2.78 + }
2.79 +};
2.80 +
2.81 +struct FloatRegister
2.82 +{
2.83 + const char *name() const {
2.84 + static const char *names[] = {
2.85 + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
2.86 + };
2.87 + return names[code];
2.88 + }
2.89 +
2.90 + int code;
2.91 +
2.92 + bool operator == (const FloatRegister &other) const {
2.93 + return code == other.code;
2.94 + }
2.95 + bool operator != (const FloatRegister &other) const {
2.96 + return code != other.code;
2.97 + }
2.98 +};
2.99 +
2.100 +const Register eax = { 0 };
2.101 +const Register ecx = { 1 };
2.102 +const Register edx = { 2 };
2.103 +const Register ebx = { 3 };
2.104 +const Register esp = { 4 };
2.105 +const Register ebp = { 5 };
2.106 +const Register esi = { 6 };
2.107 +const Register edi = { 7 };
2.108 +
2.109 +const Register r8_al = { 0 };
2.110 +const Register r8_cl = { 1 };
2.111 +const Register r8_dl = { 2 };
2.112 +const Register r8_bl = { 3 };
2.113 +const Register r8_ah = { 4 };
2.114 +const Register r8_ch = { 5 };
2.115 +const Register r8_dh = { 6 };
2.116 +const Register r8_bh = { 7 };
2.117 +
2.118 +const FpuRegister st0 = { 0 };
2.119 +const FpuRegister st1 = { 1 };
2.120 +const FpuRegister st2 = { 2 };
2.121 +const FpuRegister st3 = { 3 };
2.122 +const FpuRegister st4 = { 4 };
2.123 +const FpuRegister st5 = { 5 };
2.124 +const FpuRegister st6 = { 6 };
2.125 +const FpuRegister st7 = { 7 };
2.126 +
2.127 +const FloatRegister xmm0 = { 0 };
2.128 +const FloatRegister xmm1 = { 1 };
2.129 +const FloatRegister xmm2 = { 2 };
2.130 +const FloatRegister xmm3 = { 3 };
2.131 +const FloatRegister xmm4 = { 4 };
2.132 +const FloatRegister xmm5 = { 5 };
2.133 +const FloatRegister xmm6 = { 6 };
2.134 +const FloatRegister xmm7 = { 7 };
2.135 +
2.136 +static const uint8_t kModeDisp0 = 0;
2.137 +static const uint8_t kModeDisp8 = 1;
2.138 +static const uint8_t kModeDisp32 = 2;
2.139 +static const uint8_t kModeReg = 3;
2.140 +static const uint8_t kNoIndex = 4;
2.141 +static const uint8_t kSIB = 4;
2.142 +static const uint8_t kRIP = 5;
2.143 +
2.144 +enum ConditionCode {
2.145 + overflow,
2.146 + no_overflow,
2.147 + below,
2.148 + not_below,
2.149 + equal,
2.150 + not_equal,
2.151 + not_above,
2.152 + above,
2.153 + negative,
2.154 + not_negative,
2.155 + even_parity,
2.156 + odd_parity,
2.157 + less,
2.158 + not_less,
2.159 + not_greater,
2.160 + greater,
2.161 +
2.162 + zero = equal,
2.163 + not_zero = not_equal,
2.164 + less_equal = not_greater,
2.165 + greater_equal = not_less
2.166 +};
2.167 +
2.168 +enum Scale {
2.169 + NoScale,
2.170 + ScaleTwo,
2.171 + ScaleFour,
2.172 + ScaleEight,
2.173 + ScalePointer = ScaleFour
2.174 +};
2.175 +
2.176 +struct Operand
2.177 +{
2.178 + friend class AssemblerX86;
2.179 +
2.180 + public:
2.181 + Operand(Register reg, int32_t disp) {
2.182 + if (reg == esp) {
2.183 + // If the reg is esp, we need a SIB encoding.
2.184 + if (disp == 0)
2.185 + sib_disp0(NoScale, kNoIndex, reg.code);
2.186 + else if (disp >= SCHAR_MIN && disp <= SCHAR_MAX)
2.187 + sib_disp8(NoScale, kNoIndex, reg.code, disp);
2.188 + else
2.189 + sib_disp32(NoScale, kNoIndex, reg.code, disp);
2.190 + } else if (disp == 0 && reg != ebp) {
2.191 + // note, [ebp+0] is disp32/rip
2.192 + modrm_disp0(reg.code);
2.193 + } else if (disp >= SCHAR_MIN && disp <= SCHAR_MAX) {
2.194 + modrm_disp8(reg.code, disp);
2.195 + } else {
2.196 + modrm_disp32(reg.code, disp);
2.197 + }
2.198 + }
2.199 +
2.200 + Operand(Register base, Scale scale, int32_t disp = 0) {
2.201 + if (disp == 0 && base != ebp)
2.202 + sib_disp0(scale, kNoIndex, base.code);
2.203 + else if (disp >= SCHAR_MIN && disp <= SCHAR_MAX)
2.204 + sib_disp8(scale, kNoIndex, base.code, disp);
2.205 + else
2.206 + sib_disp32(scale, kNoIndex, base.code, disp);
2.207 + }
2.208 +
2.209 + Operand(Register base, Register index, Scale scale, int32_t disp = 0) {
2.210 + assert(index.code != kNoIndex);
2.211 + if (disp == 0 && base != ebp)
2.212 + sib_disp0(scale, index.code, base.code);
2.213 + else if (disp >= SCHAR_MIN && disp <= SCHAR_MAX)
2.214 + sib_disp8(scale, index.code, base.code, disp);
2.215 + else
2.216 + sib_disp32(scale, index.code, base.code, disp);
2.217 + }
2.218 +
2.219 + explicit Operand(ExternalAddress address) {
2.220 + modrm(kModeDisp0, kRIP);
2.221 + *reinterpret_cast<const void **>(bytes_ + 1) = address.address();
2.222 + }
2.223 +
2.224 + bool isRegister() const {
2.225 + return mode() == kModeReg;
2.226 + }
2.227 + bool isRegister(Register r) const {
2.228 + return mode() == kModeReg && rm() == r.code;
2.229 + }
2.230 + int registerCode() const {
2.231 + return rm();
2.232 + }
2.233 +
2.234 + uint8_t getByte(size_t index) const {
2.235 + assert(index < length());
2.236 + return bytes_[index];
2.237 + }
2.238 +
2.239 + size_t length() const {
2.240 + if (mode() == kModeDisp0 && rm() == kRIP)
2.241 + return 5;
2.242 + size_t sib = (mode() != kModeReg && rm() == kSIB);
2.243 + if (mode() == kModeDisp32)
2.244 + return 5 + sib;
2.245 + if (mode() == kModeDisp8)
2.246 + return 2 + sib;
2.247 + return 1 + sib;
2.248 + }
2.249 +
2.250 + private:
2.251 + explicit Operand(Register reg) {
2.252 + modrm(kModeReg, reg.code);
2.253 + }
2.254 +
2.255 + void modrm(uint8_t mode, uint8_t rm) {
2.256 + assert(mode <= 3);
2.257 + assert(rm <= 7);
2.258 + bytes_[0] = (mode << 6) | rm;
2.259 + }
2.260 + void modrm_disp0(uint8_t rm) {
2.261 + modrm(kModeDisp0, rm);
2.262 + }
2.263 + void modrm_disp8(uint8_t rm, int8_t disp) {
2.264 + modrm(kModeDisp8, rm);
2.265 + bytes_[1] = disp;
2.266 + }
2.267 + void modrm_disp32(uint8_t rm, int32_t disp) {
2.268 + modrm(kModeDisp32, rm);
2.269 + *reinterpret_cast<int32_t *>(bytes_ + 1) = disp;
2.270 + }
2.271 + void sib(uint8_t mode, Scale scale, uint8_t index, uint8_t base) {
2.272 + modrm(mode, kSIB);
2.273 +
2.274 + assert(scale <= 3);
2.275 + assert(index <= 7);
2.276 + assert(base <= 7);
2.277 + bytes_[1] = (uint8_t(scale) << 6) | (index << 3) | base;
2.278 + }
2.279 + void sib_disp0(Scale scale, uint8_t index, uint8_t base) {
2.280 + sib(kModeDisp0, scale, index, base);
2.281 + }
2.282 + void sib_disp8(Scale scale, uint8_t index, uint8_t base, int8_t disp) {
2.283 + sib(kModeDisp8, scale, index, base);
2.284 + bytes_[2] = disp;
2.285 + }
2.286 + void sib_disp32(Scale scale, uint8_t index, uint8_t base, int32_t disp) {
2.287 + sib(kModeDisp32, scale, index, base);
2.288 + *reinterpret_cast<int32_t *>(bytes_ + 2) = disp;
2.289 + }
2.290 +
2.291 + private:
2.292 + uint8_t rm() const {
2.293 + return bytes_[0] & 7;
2.294 + }
2.295 + uint8_t mode() const {
2.296 + return bytes_[0] >> 6;
2.297 + }
2.298 +
2.299 + private:
2.300 + uint8_t bytes_[6];
2.301 +};
2.302 +
2.303 +class AssemblerX86 : public Assembler
2.304 +{
2.305 + public:
2.306 + void movl(Register dest, Register src) {
2.307 + emit1(0x89, src.code, dest.code);
2.308 + }
2.309 + void movl(Register dest, const Operand &src) {
2.310 + emit1(0x8b, dest.code, src);
2.311 + }
2.312 + void movl(const Operand &dest, Register src) {
2.313 + emit1(0x89, src.code, dest);
2.314 + }
2.315 + void movl(Register dest, int32_t imm) {
2.316 + emit1(0xb8 + dest.code);
2.317 + writeInt32(imm);
2.318 + }
2.319 + void movl(const Operand &dest, int32_t imm) {
2.320 + if (dest.isRegister())
2.321 + emit1(0xb8 + dest.registerCode());
2.322 + else
2.323 + emit1(0xc7, 0, dest);
2.324 + writeInt32(imm);
2.325 + }
2.326 + void movw(const Operand &dest, Register src) {
2.327 + emit1(0x89, src.code, dest);
2.328 + }
2.329 + void movw(Register dest, const Operand &src) {
2.330 + emit1(0x8b, dest.code, src);
2.331 + }
2.332 + void movb(const Operand &dest, Register src) {
2.333 + emit1(0x88, src.code, dest);
2.334 + }
2.335 + void movb(Register dest, const Operand &src) {
2.336 + emit1(0x8a, dest.code, src);
2.337 + }
2.338 + void movzxb(Register dest, const Operand &src) {
2.339 + emit2(0x0f, 0xb6, dest.code, src);
2.340 + }
2.341 + void movzxb(Register dest, const Register src) {
2.342 + emit2(0x0f, 0xb6, dest.code, src.code);
2.343 + }
2.344 + void movzxw(Register dest, const Operand &src) {
2.345 + emit2(0x0f, 0xb7, dest.code, src);
2.346 + }
2.347 + void movzxw(Register dest, const Register src) {
2.348 + emit2(0x0f, 0xb7, dest.code, src.code);
2.349 + }
2.350 +
2.351 + void lea(Register dest, const Operand &src) {
2.352 + emit1(0x8d, dest.code, src);
2.353 + }
2.354 +
2.355 + void xchgl(Register dest, Register src) {
2.356 + if (src == eax)
2.357 + emit1(0x90 + dest.code);
2.358 + else if (dest == eax)
2.359 + emit1(0x90 + src.code);
2.360 + else
2.361 + emit1(0x87, src.code, dest.code);
2.362 + }
2.363 +
2.364 + void shll_cl(Register dest) {
2.365 + shift_cl(dest.code, 4);
2.366 + }
2.367 + void shll(Register dest, uint8_t imm) {
2.368 + shift_imm(dest.code, 4, imm);
2.369 + }
2.370 + void shll(const Operand &dest, uint8_t imm) {
2.371 + shift_imm(dest, 4, imm);
2.372 + }
2.373 + void shrl_cl(Register dest) {
2.374 + shift_cl(dest.code, 5);
2.375 + }
2.376 + void shrl(Register dest, uint8_t imm) {
2.377 + shift_imm(dest.code, 5, imm);
2.378 + }
2.379 + void shrl(const Operand &dest, uint8_t imm) {
2.380 + shift_imm(dest, 5, imm);
2.381 + }
2.382 + void sarl_cl(Register dest) {
2.383 + shift_cl(dest.code, 7);
2.384 + }
2.385 + void sarl(Register dest, uint8_t imm) {
2.386 + shift_imm(dest.code, 7, imm);
2.387 + }
2.388 + void sarl(const Operand &dest, uint8_t imm) {
2.389 + shift_imm(dest, 7, imm);
2.390 + }
2.391 +
2.392 + void cmpl(Register left, int32_t imm) {
2.393 + alu_imm(7, imm, Operand(left));
2.394 + }
2.395 + void cmpl(const Operand &left, int32_t imm) {
2.396 + alu_imm(7, imm, left);
2.397 + }
2.398 + void cmpl(Register left, Register right) {
2.399 + emit1(0x39, right.code, left.code);
2.400 + }
2.401 + void cmpl(const Operand &left, Register right) {
2.402 + emit1(0x39, right.code, left);
2.403 + }
2.404 + void cmpl(Register left, const Operand &right) {
2.405 + emit1(0x3b, left.code, right);
2.406 + }
2.407 + void andl(Register dest, int32_t imm) {
2.408 + alu_imm(4, imm, Operand(dest));
2.409 + }
2.410 + void andl(const Operand &dest, int32_t imm) {
2.411 + alu_imm(4, imm, dest);
2.412 + }
2.413 + void andl(Register dest, Register src) {
2.414 + emit1(0x21, src.code, dest.code);
2.415 + }
2.416 + void andl(const Operand &dest, Register src) {
2.417 + emit1(0x21, src.code, dest);
2.418 + }
2.419 + void andl(Register dest, const Operand &src) {
2.420 + emit1(0x23, dest.code, src);
2.421 + }
2.422 + void orl(Register dest, Register src) {
2.423 + emit1(0x09, src.code, dest.code);
2.424 + }
2.425 + void orl(const Operand &dest, Register src) {
2.426 + emit1(0x09, src.code, dest);
2.427 + }
2.428 + void orl(Register dest, const Operand &src) {
2.429 + emit1(0x0b, dest.code, src);
2.430 + }
2.431 + void xorl(Register dest, Register src) {
2.432 + emit1(0x31, src.code, dest.code);
2.433 + }
2.434 + void xorl(const Operand &dest, Register src) {
2.435 + emit1(0x31, src.code, dest);
2.436 + }
2.437 + void xorl(Register dest, const Operand &src) {
2.438 + emit1(0x33, dest.code, src);
2.439 + }
2.440 +
2.441 + void subl(Register dest, Register src) {
2.442 + emit1(0x29, src.code, dest.code);
2.443 + }
2.444 + void subl(const Operand &dest, Register src) {
2.445 + emit1(0x29, src.code, dest);
2.446 + }
2.447 + void subl(Register dest, const Operand &src) {
2.448 + emit1(0x2b, dest.code, src);
2.449 + }
2.450 + void subl(Register dest, int32_t imm) {
2.451 + alu_imm(5, imm, Operand(dest));
2.452 + }
2.453 + void subl(const Operand &dest, int32_t imm) {
2.454 + alu_imm(5, imm, dest);
2.455 + }
2.456 + void addl(Register dest, Register src) {
2.457 + emit1(0x01, src.code, dest.code);
2.458 + }
2.459 + void addl(const Operand &dest, Register src) {
2.460 + emit1(0x01, src.code, dest);
2.461 + }
2.462 + void addl(Register dest, const Operand &src) {
2.463 + emit1(0x03, dest.code, src);
2.464 + }
2.465 + void addl(Register dest, int32_t imm) {
2.466 + alu_imm(0, imm, Operand(dest));
2.467 + }
2.468 + void addl(const Operand &dest, int32_t imm) {
2.469 + alu_imm(0, imm, dest);
2.470 + }
2.471 +
2.472 + void imull(Register dest, const Operand &src) {
2.473 + emit2(0x0f, 0xaf, dest.code, src);
2.474 + }
2.475 + void imull(Register dest, Register src) {
2.476 + emit2(0x0f, 0xaf, dest.code, src.code);
2.477 + }
2.478 + void imull(Register dest, const Operand &src, int32_t imm) {
2.479 + if (imm >= SCHAR_MIN && imm <= SCHAR_MAX) {
2.480 + emit1(0x6b, dest.code, src);
2.481 + *pos_++ = imm;
2.482 + } else {
2.483 + emit1(0x69, dest.code, src);
2.484 + writeInt32(imm);
2.485 + }
2.486 + }
2.487 + void imull(Register dest, Register src, int32_t imm) {
2.488 + imull(dest, Operand(src), imm);
2.489 + }
2.490 +
2.491 + void testl(const Operand &op1, Register op2) {
2.492 + emit1(0x85, op2.code, op1);
2.493 + }
2.494 + void testl(Register op1, Register op2) {
2.495 + emit1(0x85, op2.code, op1.code);
2.496 + }
2.497 + void set(ConditionCode cc, const Operand &dest) {
2.498 + emit2(0x0f, 0x90 + uint8_t(cc), 0, dest);
2.499 + }
2.500 + void set(ConditionCode cc, Register dest) {
2.501 + emit2(0x0f, 0x90 + uint8_t(cc), 0, dest.code);
2.502 + }
2.503 + void negl(Register srcdest) {
2.504 + emit1(0xf7, 3, srcdest.code);
2.505 + }
2.506 + void negl(const Operand &srcdest) {
2.507 + emit1(0xf7, 3, srcdest);
2.508 + }
2.509 + void notl(Register srcdest) {
2.510 + emit1(0xf7, 2, srcdest.code);
2.511 + }
2.512 + void notl(const Operand &srcdest) {
2.513 + emit1(0xf7, 2, srcdest);
2.514 + }
2.515 + void idivl(Register dividend) {
2.516 + emit1(0xf7, 7, dividend.code);
2.517 + }
2.518 + void idivl(const Operand ÷nd) {
2.519 + emit1(0xf7, 7, dividend);
2.520 + }
2.521 +
2.522 + void ret() {
2.523 + emit1(0xc3);
2.524 + }
2.525 + void cld() {
2.526 + emit1(0xfc);
2.527 + }
2.528 + void push(Register reg) {
2.529 + emit1(0x50 + reg.code);
2.530 + }
2.531 + void push(const Operand &src) {
2.532 + if (src.isRegister())
2.533 + emit1(0x50 + src.registerCode());
2.534 + else
2.535 + emit1(0xff, 6, src);
2.536 + }
2.537 + void push(int32_t imm) {
2.538 + emit1(0x68);
2.539 + writeInt32(imm);
2.540 + }
2.541 + void pop(Register reg) {
2.542 + emit1(0x58 + reg.code);
2.543 + }
2.544 + void pop(const Operand &src) {
2.545 + if (src.isRegister())
2.546 + emit1(0x58 + src.registerCode());
2.547 + else
2.548 + emit1(0x8f, 0, src);
2.549 + }
2.550 +
2.551 + void rep_movsb() {
2.552 + emit2(0xf3, 0xa4);
2.553 + }
2.554 + void rep_movsd() {
2.555 + emit2(0xf3, 0xa5);
2.556 + }
2.557 + void rep_stosd() {
2.558 + emit2(0xf3, 0xab);
2.559 + }
2.560 + void breakpoint() {
2.561 + emit1(0xcc);
2.562 + }
2.563 +
2.564 + void fld32(const Operand &src) {
2.565 + emit1(0xd9, 0, src);
2.566 + }
2.567 + void fild32(const Operand &src) {
2.568 + emit1(0xdb, 0, src);
2.569 + }
2.570 + void fistp32(const Operand &dest) {
2.571 + emit1(0xdb, 3, dest);
2.572 + }
2.573 + void fadd32(const Operand &src) {
2.574 + emit1(0xd8, 0, src);
2.575 + }
2.576 + void fsub32(const Operand &src) {
2.577 + emit1(0xd8, 4, src);
2.578 + }
2.579 + void fmul32(const Operand &src) {
2.580 + emit1(0xd8, 1, src);
2.581 + }
2.582 + void fdiv32(const Operand &src) {
2.583 + emit1(0xd8, 6, src);
2.584 + }
2.585 + void fstp32(const Operand &dest) {
2.586 + emit1(0xd9, 3, dest);
2.587 + }
2.588 + void fstp(FpuRegister src) {
2.589 + emit2(0xdd, 0xd8 + src.code);
2.590 + }
2.591 + void fldcw(const Operand &src) {
2.592 + emit1(0xd9, 5, src);
2.593 + }
2.594 + void fstcw(const Operand &dest) {
2.595 + emit2(0x9b, 0xd9, 7, dest);
2.596 + }
2.597 + void fsubr32(const Operand &src) {
2.598 + emit1(0xd8, 5, src);
2.599 + }
2.600 +
2.601 + // Compare st0 with stN.
2.602 + void fucomip(FpuRegister other) {
2.603 + emit2(0xdf, 0xe8 + other.code);
2.604 + }
2.605 +
2.606 + // At least one argument of these forms must be st0.
2.607 + void fadd32(FpuRegister dest, FpuRegister src) {
2.608 + assert(dest == st0 || src == st0);
2.609 + if (dest == st0)
2.610 + emit2(0xd8, 0xc0 + dest.code);
2.611 + else
2.612 + emit2(0xdc, 0xc0 + src.code);
2.613 + }
2.614 +
2.615 + void jmp(Label *dest) {
2.616 + int8_t d8;
2.617 + if (canEmitSmallJump(dest, &d8)) {
2.618 + emit2(0xeb, d8);
2.619 + } else {
2.620 + emit1(0xe9);
2.621 + emitJumpTarget(dest);
2.622 + }
2.623 + }
2.624 + void jmp(Register target) {
2.625 + emit1(0xff, 4, target.code);
2.626 + }
2.627 + void jmp(const Operand &target) {
2.628 + emit1(0xff, 4, target);
2.629 + }
2.630 + void j(ConditionCode cc, Label *dest) {
2.631 + int8_t d8;
2.632 + if (canEmitSmallJump(dest, &d8)) {
2.633 + emit2(0x70 + uint8_t(cc), d8);
2.634 + } else {
2.635 + emit2(0x0f, 0x80 + uint8_t(cc));
2.636 + emitJumpTarget(dest);
2.637 + }
2.638 + }
2.639 + void call(Label *dest) {
2.640 + emit1(0xe8);
2.641 + emitJumpTarget(dest);
2.642 + }
2.643 + void bind(Label *target) {
2.644 + if (outOfMemory()) {
2.645 + // If we ran out of memory, the code stream is potentially invalid and
2.646 + // we cannot use the embedded linked list.
2.647 + target->bind(pc());
2.648 + return;
2.649 + }
2.650 +
2.651 + assert(!target->bound());
2.652 + uint32_t status = target->status();
2.653 + while (Label::More(status)) {
2.654 + // Grab the offset. It should be at least a 1byte op + rel32.
2.655 + uint32_t offset = Label::ToOffset(status);
2.656 + assert(offset >= 5);
2.657 +
2.658 + // Grab the delta from target to pc.
2.659 + ptrdiff_t delta = pos_ - (buffer() + offset);
2.660 + assert(delta >= INT_MIN && delta <= INT_MAX);
2.661 +
2.662 + int32_t *p = reinterpret_cast<int32_t *>(buffer() + offset - 4);
2.663 + status = *p;
2.664 + *p = delta;
2.665 + }
2.666 + target->bind(pc());
2.667 + }
2.668 +
2.669 + void bind(DataLabel *address) {
2.670 + if (outOfMemory())
2.671 + return;
2.672 + if (address->used()) {
2.673 + uint32_t offset = DataLabel::ToOffset(address->status());
2.674 + *reinterpret_cast<int32_t *>(buffer() + offset - 4) = position() - int32_t(offset);
2.675 + }
2.676 + address->bind(pc());
2.677 + }
2.678 + void movl(Register dest, DataLabel *src) {
2.679 + emit1(0xb8 + dest.code);
2.680 + if (src->bound()) {
2.681 + writeInt32(int32_t(src->offset()) - (position() + 4));
2.682 + } else {
2.683 + writeInt32(0xabcdef0);
2.684 + src->use(pc());
2.685 + }
2.686 + if (!local_refs_.append(pc()))
2.687 + outOfMemory_ = true;
2.688 + }
2.689 + void emit_absolute_address(Label *address) {
2.690 + if (address->bound())
2.691 + writeUint32(int32_t(address->offset()) - (position() + 4));
2.692 + else
2.693 + writeUint32(address->addPending(position() + 4));
2.694 + if (!local_refs_.append(pc()))
2.695 + outOfMemory_ = true;
2.696 + }
2.697 +
2.698 + void call(Register target) {
2.699 + emit1(0xff, 2, target.code);
2.700 + }
2.701 + void call(const Operand &target) {
2.702 + emit1(0xff, 2, target);
2.703 + }
2.704 + void call(ExternalAddress address) {
2.705 + emit1(0xe8);
2.706 + writeInt32(address.value());
2.707 + if (!external_refs_.append(pc()))
2.708 + outOfMemory_ = true;
2.709 + }
2.710 + void jmp(ExternalAddress address) {
2.711 + assert(sizeof(address) == sizeof(int32_t));
2.712 + emit1(0xe9);
2.713 + writeInt32(address.value());
2.714 + if (!external_refs_.append(pc()))
2.715 + outOfMemory_ = true;
2.716 + }
2.717 +
2.718 + static void PatchRel32Absolute(uint8_t *ip, void *ptr) {
2.719 + int32_t delta = uint32_t(ptr) - uint32_t(ip);
2.720 + *reinterpret_cast<int32_t *>(ip - 4) = delta;
2.721 + }
2.722 +
2.723 + void emitToExecutableMemory(void *code) {
2.724 + assert(!outOfMemory());
2.725 +
2.726 + // Relocate anything we emitted as rel32 with an external pointer.
2.727 + uint8_t *base = reinterpret_cast<uint8_t *>(code);
2.728 + memcpy(base, buffer(), length());
2.729 + for (size_t i = 0; i < external_refs_.length(); i++) {
2.730 + size_t offset = external_refs_[i];
2.731 + PatchRel32Absolute(base + offset, *reinterpret_cast<void **>(base + offset - 4));
2.732 + }
2.733 +
2.734 + // Relocate everything we emitted as an abs32 with an internal offset. Note
2.735 + // that in the code stream, we use relative offsets so we can use both Label
2.736 + // and DataLabel.
2.737 + for (size_t i = 0; i < local_refs_.length(); i++) {
2.738 + size_t offset = local_refs_[i];
2.739 + int32_t delta = *reinterpret_cast<int32_t *>(base + offset - 4);
2.740 + *reinterpret_cast<void **>(base + offset - 4) = base + offset + delta;
2.741 + }
2.742 + }
2.743 +
2.744 + void align(uint32_t bytes) {
2.745 + int32_t delta = (pc() & ~(bytes - 1)) + bytes - pc();
2.746 + for (int32_t i = 0; i < delta; i++)
2.747 + emit1(0xcc);
2.748 + }
2.749 +
2.750 + private:
2.751 + bool canEmitSmallJump(Label *dest, int8_t *deltap) {
2.752 + if (!dest->bound())
2.753 + return false;
2.754 +
2.755 + // All small jumps are assumed to be 2 bytes.
2.756 + ptrdiff_t delta = ptrdiff_t(dest->offset()) - (position() + 2);
2.757 + if (delta < SCHAR_MIN || delta > SCHAR_MAX)
2.758 + return false;
2.759 + *deltap = delta;
2.760 + return true;
2.761 + }
2.762 + void emitJumpTarget(Label *dest) {
2.763 + if (dest->bound()) {
2.764 + ptrdiff_t delta = ptrdiff_t(dest->offset()) - (position() + 4);
2.765 + assert(delta >= INT_MIN && delta <= INT_MAX);
2.766 + writeInt32(delta);
2.767 + } else {
2.768 + writeUint32(dest->addPending(position() + 4));
2.769 + }
2.770 + }
2.771 +
2.772 + void emit(uint8_t reg, const Operand &operand) {
2.773 + *pos_++ = operand.getByte(0) | (reg << 3);
2.774 + size_t length = operand.length();
2.775 + for (size_t i = 1; i < length; i++)
2.776 + *pos_++ = operand.getByte(i);
2.777 + }
2.778 +
2.779 + void emit1(uint8_t opcode) {
2.780 + ensureSpace();
2.781 + *pos_++ = opcode;
2.782 + }
2.783 + void emit1(uint8_t opcode, uint8_t reg, uint8_t opreg) {
2.784 + ensureSpace();
2.785 + assert(reg <= 7);
2.786 + assert(opreg <= 7);
2.787 + *pos_++ = opcode;
2.788 + *pos_++ = (kModeReg << 6) | (reg << 3) | opreg;
2.789 + }
2.790 + void emit1(uint8_t opcode, uint8_t reg, const Operand &operand) {
2.791 + ensureSpace();
2.792 + assert(reg <= 7);
2.793 + *pos_++ = opcode;
2.794 + emit(reg, operand);
2.795 + }
2.796 +
2.797 + void emit2(uint8_t prefix, uint8_t opcode) {
2.798 + ensureSpace();
2.799 + *pos_++ = prefix;
2.800 + *pos_++ = opcode;
2.801 + }
2.802 + void emit2(uint8_t prefix, uint8_t opcode, uint8_t reg, uint8_t opreg) {
2.803 + emit2(prefix, opcode);
2.804 + assert(reg <= 7);
2.805 + *pos_++ = (kModeReg << 6) | (reg << 3) | opreg;
2.806 + }
2.807 + void emit2(uint8_t prefix, uint8_t opcode, uint8_t reg, const Operand &operand) {
2.808 + emit2(prefix, opcode);
2.809 + emit(reg, operand);
2.810 + }
2.811 +
2.812 + template <typename T>
2.813 + void shift_cl(const T &t, uint8_t r) {
2.814 + emit1(0xd3, r, t);
2.815 + }
2.816 +
2.817 + template <typename T>
2.818 + void shift_imm(const T &t, uint8_t r, int32_t imm) {
2.819 + if (imm == 1) {
2.820 + emit1(0xd1, r, t);
2.821 + } else {
2.822 + emit1(0xc1, r, t);
2.823 + *pos_++ = imm & 0x1F;
2.824 + }
2.825 + }
2.826 + void alu_imm(uint8_t r, int32_t imm, const Operand &operand) {
2.827 + if (imm >= SCHAR_MIN && imm <= SCHAR_MAX) {
2.828 + emit1(0x83, r, operand);
2.829 + *pos_++ = uint8_t(imm & 0xff);
2.830 + } else if (operand.isRegister(eax)) {
2.831 + emit1(0x05 | (r << 3));
2.832 + writeInt32(imm);
2.833 + } else {
2.834 + emit1(0x81, r, operand);
2.835 + writeInt32(imm);
2.836 + }
2.837 + }
2.838 +
2.839 + private:
2.840 + ke::Vector<uint32_t> external_refs_;
2.841 + ke::Vector<uint32_t> local_refs_;
2.842 +};
2.843 +
2.844 +#endif // _include_sourcepawn_assembler_x86_h__
2.845 +
3.1 --- a/public/jit/x86/x86_macros.h Thu Aug 08 09:40:23 2013 -0700
3.2 +++ b/public/jit/x86/x86_macros.h Thu Aug 08 09:41:24 2013 -0700
3.3 @@ -32,6 +32,10 @@
3.4 #ifndef _INCLUDE_JIT_X86_MACROS_H
3.5 #define _INCLUDE_JIT_X86_MACROS_H
3.6
3.7 +// :XXX:
3.8 +// :XXX: This file is deprecated. For new code, use assembler-x86.h.
3.9 +// :XXX:
3.10 +
3.11 #include <limits.h>
3.12
3.13 //MOD R/M
3.14 @@ -83,120 +87,38 @@
3.15 #define CC_G 0xF
3.16 #define CC_NLE CC_G
3.17
3.18 -//Opcodes with encoding information
3.19 -#define IA32_XOR_RM_REG 0x31 // encoding is /r
3.20 -#define IA32_XOR_REG_RM 0x33 // encoding is /r
3.21 -#define IA32_XOR_EAX_IMM32 0x35 // encoding is /r
3.22 -#define IA32_XOR_RM_IMM32 0x81 // encoding is /6
3.23 -#define IA32_XOR_RM_IMM8 0x83 // encoding is /6
3.24 -#define IA32_ADD_RM_REG 0x01 // encoding is /r
3.25 -#define IA32_ADD_REG_RM 0x03 // encoding is /r
3.26 -#define IA32_ADD_RM_IMM32 0x81 // encoding is /0
3.27 -#define IA32_ADD_RM_IMM8 0x83 // encoding is /0
3.28 -#define IA32_ADD_EAX_IMM32 0x05 // no extra encoding
3.29 -#define IA32_SUB_RM_REG 0x29 // encoding is /r
3.30 -#define IA32_SUB_REG_RM 0x2B // encoding is /r
3.31 -#define IA32_SUB_RM_IMM8 0x83 // encoding is /5 <imm8>
3.32 -#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 <imm32>
3.33 -#define IA32_SBB_REG_RM 0x1B // encoding is /r
3.34 -#define IA32_SBB_RM_IMM8 0x83 // encoding is <imm32>
3.35 -#define IA32_JMP_IMM32 0xE9 // encoding is imm32
3.36 -#define IA32_JMP_IMM8 0xEB // encoding is imm8
3.37 -#define IA32_JMP_RM 0xFF // encoding is /4
3.38 -#define IA32_CALL_IMM32 0xE8 // relative call, <imm32>
3.39 -#define IA32_CALL_RM 0xFF // encoding is /2
3.40 -#define IA32_MOV_REG_IMM 0xB8 // encoding is +r <imm32>
3.41 -#define IA32_MOV_RM8_REG 0x88 // encoding is /r
3.42 -#define IA32_MOV_RM_REG 0x89 // encoding is /r
3.43 -#define IA32_MOV_REG_RM 0x8B // encoding is /r
3.44 -#define IA32_MOV_REG8_RM8 0x8A // encoding is /r
3.45 -#define IA32_MOV_RM8_REG8 0x88 // encoding is /r
3.46 -#define IA32_MOV_RM_IMM32 0xC7 // encoding is /0
3.47 -#define IA32_MOV_EAX_MEM 0xA1 // encoding is <imm32>
3.48 -#define IA32_CMP_RM_IMM32 0x81 // encoding is /7 <imm32>
3.49 -#define IA32_CMP_RM_IMM8 0x83 // encoding is /7 <imm8>
3.50 -#define IA32_CMP_AL_IMM32 0x3C // no extra encoding
3.51 -#define IA32_CMP_EAX_IMM32 0x3D // no extra encoding
3.52 -#define IA32_CMP_RM_REG 0x39 // encoding is /r
3.53 -#define IA32_CMP_REG_RM 0x3B // encoding is /r
3.54 -#define IA32_CMPSB 0xA6 // no extra encoding
3.55 -#define IA32_TEST_RM_REG 0x85 // encoding is /r
3.56 -#define IA32_JCC_IMM 0x70 // encoding is +cc <imm8>
3.57 -#define IA32_JCC_IMM32_1 0x0F // opcode part 1
3.58 -#define IA32_JCC_IMM32_2 0x80 // encoding is +cc <imm32>
3.59 -#define IA32_RET 0xC3 // no extra encoding
3.60 -#define IA32_RETN 0xC2 // encoding is <imm16>
3.61 -#define IA32_NEG_RM 0xF7 // encoding is /3
3.62 -#define IA32_INC_REG 0x40 // encoding is +r
3.63 -#define IA32_INC_RM 0xFF // encoding is /0
3.64 -#define IA32_DEC_REG 0x48 // encoding is +r
3.65 -#define IA32_DEC_RM 0xFF // encoding is /1
3.66 -#define IA32_OR_REG_RM 0x0B // encoding is /r
3.67 -#define IA32_AND_REG_RM 0x23 // encoding is /r
3.68 -#define IA32_AND_EAX_IMM32 0x25 // encoding is <imm32>
3.69 -#define IA32_AND_RM_IMM32 0x81 // encoding is /4
3.70 -#define IA32_AND_RM_IMM8 0x83 // encoding is /4
3.71 -#define IA32_NOT_RM 0xF7 // encoding is /2
3.72 -#define IA32_DIV_RM 0xF7 // encoding is /6
3.73 -#define IA32_MUL_RM 0xF7 // encoding is /4
3.74 -#define IA32_IDIV_RM 0xF7 // encoding is /7
3.75 -#define IA32_IMUL_RM 0xF7 // encoding is /5
3.76 -#define IA32_IMUL_REG_IMM32 0x69 // encoding is /r
3.77 -#define IA32_IMUL_REG_IMM8 0x6B // encoding is /r
3.78 -#define IA32_IMUL_REG_RM_1 0x0F // encoding is _2
3.79 -#define IA32_IMUL_REG_RM_2 0xAF // encoding is /r
3.80 -#define IA32_SHR_RM_IMM8 0xC1 // encoding is /5 <ib>
3.81 -#define IA32_SHR_RM_1 0xD1 // encoding is /5
3.82 -#define IA32_SHL_RM_IMM8 0xC1 // encoding is /4 <ib>
3.83 -#define IA32_SHL_RM_1 0xD1 // encoding is /4
3.84 -#define IA32_SAR_RM_CL 0xD3 // encoding is /7
3.85 -#define IA32_SAR_RM_1 0xD1 // encoding is /7
3.86 -#define IA32_SHR_RM_CL 0xD3 // encoding is /5
3.87 -#define IA32_SHL_RM_CL 0xD3 // encoding is /4
3.88 -#define IA32_SAR_RM_IMM8 0xC1 // encoding is /7 <ib>
3.89 -#define IA32_SETCC_RM8_1 0x0F // opcode part 1
3.90 -#define IA32_SETCC_RM8_2 0x90 // encoding is +cc /0 (8bits)
3.91 -#define IA32_CMOVCC_RM_1 0x0F // opcode part 1
3.92 -#define IA32_CMOVCC_RM_2 0x40 // encoding is +cc /r
3.93 -#define IA32_XCHG_EAX_REG 0x90 // encoding is +r
3.94 -#define IA32_LEA_REG_MEM 0x8D // encoding is /r
3.95 +#define IA32_MOVZX_R32_RM8_1 0x0F // opcode part 1
3.96 +#define IA32_MOVZX_R32_RM16_1 0x0F // opcode part 1
3.97 +#define IA32_PUSH_REG 0x50 // encoding is +r
3.98 #define IA32_POP_REG 0x58 // encoding is +r
3.99 -#define IA32_PUSH_REG 0x50 // encoding is +r
3.100 -#define IA32_PUSH_RM 0xFF // encoding is /6
3.101 #define IA32_PUSH_IMM32 0x68 // encoding is <imm32>
3.102 #define IA32_PUSH_IMM8 0x6A // encoding is <imm8>
3.103 -#define IA32_REP 0xF3 // no extra encoding
3.104 -#define IA32_MOVSD 0xA5 // no extra encoding
3.105 +#define IA32_ADD_RM_IMM32 0x81 // encoding is /0
3.106 +#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 <imm32>
3.107 +#define IA32_ADD_RM_IMM8 0x83 // encoding is /0
3.108 +#define IA32_AND_RM_IMM8 0x83 // encoding is /4
3.109 +#define IA32_SUB_RM_IMM8 0x83 // encoding is /5 <imm8>
3.110 +#define IA32_MOV_RM8_REG8 0x88 // encoding is /r
3.111 +#define IA32_MOV_RM_REG 0x89 // encoding is /r
3.112 +#define IA32_MOV_REG8_RM8 0x8A // encoding is /r
3.113 +#define IA32_MOV_REG_RM 0x8B // encoding is /r
3.114 +#define IA32_LEA_REG_MEM 0x8D // encoding is /r
3.115 #define IA32_MOVSB 0xA4 // no extra encoding
3.116 -#define IA32_STOSD 0xAB // no extra encoding
3.117 -#define IA32_CLD 0xFC // no extra encoding
3.118 -#define IA32_PUSHAD 0x60 // no extra encoding
3.119 -#define IA32_POPAD 0x61 // no extra encoding
3.120 -#define IA32_NOP 0x90 // no extra encoding
3.121 -#define IA32_INT3 0xCC // no extra encoding
3.122 +#define IA32_MOVSD 0xA5 // no extra encoding
3.123 +#define IA32_MOVZX_R32_RM8_2 0xB6 // encoding is /r
3.124 +#define IA32_MOVZX_R32_RM16_2 0xB7 // encoding is /r
3.125 +#define IA32_MOV_REG_IMM 0xB8 // encoding is +r <imm32>
3.126 +#define IA32_FLD_MEM32 0xD9 // encoding is /0
3.127 #define IA32_FSTP_MEM32 0xD9 // encoding is /3
3.128 -#define IA32_FSTP_MEM64 0xDD // encoding is /3
3.129 -#define IA32_FLD_MEM32 0xD9 // encoding is /0
3.130 #define IA32_FLD_MEM64 0xDD // encoding is /0
3.131 -#define IA32_FILD_MEM32 0xDB // encoding is /0
3.132 -#define IA32_FADD_MEM32 0xD8 // encoding is /0
3.133 -#define IA32_FADD_FPREG_ST0_1 0xDC // opcode part 1
3.134 -#define IA32_FADD_FPREG_ST0_2 0xC0 // encoding is +r
3.135 -#define IA32_FSUB_MEM32 0xD8 // encoding is /4
3.136 -#define IA32_FMUL_MEM32 0xD8 // encoding is /1
3.137 -#define IA32_FDIV_MEM32 0xD8 // encoding is /6
3.138 -#define IA32_FSTCW_MEM16_1 0x9B // opcode part 1
3.139 -#define IA32_FSTCW_MEM16_2 0xD9 // encoding is /7
3.140 -#define IA32_FLDCW_MEM16 0xD9 // encoding is /5
3.141 -#define IA32_FISTP_MEM32 0xDB // encoding is /3
3.142 -#define IA32_FUCOMIP_1 0xDF // opcode part 1
3.143 -#define IA32_FUCOMIP_2 0xE8 // encoding is +r
3.144 -#define IA32_FSTP_FPREG_1 0xDD // opcode part 1
3.145 -#define IA32_FSTP_FPREG_2 0xD8 // encoding is +r
3.146 -#define IA32_MOVZX_R32_RM8_1 0x0F // opcode part 1
3.147 -#define IA32_MOVZX_R32_RM8_2 0xB6 // encoding is /r
3.148 -#define IA32_MOVZX_R32_RM16_1 0x0F // opcode part 1
3.149 -#define IA32_MOVZX_R32_RM16_2 0xB7 // encoding is /r
3.150 +#define IA32_FSTP_MEM64 0xDD // encoding is /3
3.151 +#define IA32_CALL_IMM32 0xE8 // relative call, <imm32>
3.152 +#define IA32_JMP_IMM32 0xE9 // encoding is imm32
3.153 +#define IA32_RETN 0xC2 // encoding is <imm16>
3.154 +#define IA32_RET 0xC3 // no extra encoding
3.155 +#define IA32_REP 0xF3 // no extra encoding
3.156 +#define IA32_CLD 0xFC // no extra encoding
3.157 +#define IA32_CALL_RM 0xFF // encoding is /2
3.158
3.159 inline jit_uint8_t ia32_modrm(jit_uint8_t mode, jit_uint8_t reg, jit_uint8_t rm)
3.160 {
3.161 @@ -221,574 +143,9 @@
3.162 return sib;
3.163 }
3.164
3.165 -/***********************
3.166 - * INCREMENT/DECREMENT *
3.167 - ***********************/
3.168 -
3.169 -inline void IA32_Inc_Reg(JitWriter *jit, jit_uint8_t reg)
3.170 -{
3.171 - jit->write_ubyte(IA32_INC_REG+reg);
3.172 -}
3.173 -
3.174 -inline void IA32_Inc_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp)
3.175 -{
3.176 - jit->write_ubyte(IA32_INC_RM);
3.177 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, reg));
3.178 - jit->write_byte(disp);
3.179 -}
3.180 -
3.181 -inline void IA32_Inc_Rm_Disp32(JitWriter *jit, jit_uint8_t reg, jit_int32_t disp)
3.182 -{
3.183 - jit->write_ubyte(IA32_INC_RM);
3.184 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, reg));
3.185 - jit->write_int32(disp);
3.186 -}
3.187 -
3.188 -inline void IA32_Inc_Rm_Disp_Reg(JitWriter *jit, jit_uint8_t base, jit_uint8_t reg, jit_uint8_t scale)
3.189 -{
3.190 - jit->write_ubyte(IA32_INC_RM);
3.191 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, REG_SIB));
3.192 - jit->write_ubyte(ia32_sib(scale, reg, base));
3.193 -}
3.194 -
3.195 -inline void IA32_Dec_Reg(JitWriter *jit, jit_uint8_t reg)
3.196 -{
3.197 - jit->write_ubyte(IA32_DEC_REG+reg);
3.198 -}
3.199 -
3.200 -inline void IA32_Dec_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp)
3.201 -{
3.202 - jit->write_ubyte(IA32_DEC_RM);
3.203 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 1, reg));
3.204 - jit->write_byte(disp);
3.205 -}
3.206 -
3.207 -inline void IA32_Dec_Rm_Disp32(JitWriter *jit, jit_uint8_t reg, jit_int32_t disp)
3.208 -{
3.209 - jit->write_ubyte(IA32_DEC_RM);
3.210 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 1, reg));
3.211 - jit->write_int32(disp);
3.212 -}
3.213 -
3.214 -inline void IA32_Dec_Rm_Disp_Reg(JitWriter *jit, jit_uint8_t base, jit_uint8_t reg, jit_uint8_t scale)
3.215 -{
3.216 - jit->write_ubyte(IA32_DEC_RM);
3.217 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 1, REG_SIB));
3.218 - jit->write_ubyte(ia32_sib(scale, reg, base));
3.219 -}
3.220 -
3.221 -/****************
3.222 - * BINARY LOGIC *
3.223 - ****************/
3.224 -
3.225 -inline void IA32_Xor_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t dest_mode)
3.226 -{
3.227 - jit->write_ubyte(IA32_XOR_RM_REG);
3.228 - jit->write_ubyte(ia32_modrm(dest_mode, src, dest));
3.229 -}
3.230 -
3.231 -inline void IA32_Xor_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t dest_mode)
3.232 -{
3.233 - jit->write_ubyte(IA32_XOR_REG_RM);
3.234 - jit->write_ubyte(ia32_modrm(dest_mode, dest, src));
3.235 -}
3.236 -
3.237 -inline void IA32_Xor_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value)
3.238 -{
3.239 - jit->write_ubyte(IA32_XOR_RM_IMM8);
3.240 - jit->write_ubyte(ia32_modrm(mode, 6, reg));
3.241 - jit->write_byte(value);
3.242 -}
3.243 -
3.244 -inline void IA32_Xor_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int32_t value)
3.245 -{
3.246 - jit->write_ubyte(IA32_XOR_RM_IMM32);
3.247 - jit->write_ubyte(ia32_modrm(mode, 6, reg));
3.248 - jit->write_int32(value);
3.249 -}
3.250 -
3.251 -inline void IA32_Xor_Eax_Imm32(JitWriter *jit, jit_int32_t value)
3.252 -{
3.253 - jit->write_ubyte(IA32_XOR_EAX_IMM32);
3.254 - jit->write_int32(value);
3.255 -}
3.256 -
3.257 -inline void IA32_Neg_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.258 -{
3.259 - jit->write_ubyte(IA32_NEG_RM);
3.260 - jit->write_ubyte(ia32_modrm(mode, 3, reg));
3.261 -}
3.262 -
3.263 -inline void IA32_Or_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.264 -{
3.265 - jit->write_ubyte(IA32_OR_REG_RM);
3.266 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.267 -}
3.268 -
3.269 -inline void IA32_And_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.270 -{
3.271 - jit->write_ubyte(IA32_AND_REG_RM);
3.272 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.273 -}
3.274 -
3.275 -inline void IA32_And_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int32_t value)
3.276 -{
3.277 - jit->write_ubyte(IA32_AND_RM_IMM32);
3.278 - jit->write_ubyte(ia32_modrm(mode, 4, reg));
3.279 - jit->write_int32(value);
3.280 -}
3.281 -
3.282 -inline void IA32_And_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value)
3.283 -{
3.284 - jit->write_ubyte(IA32_AND_RM_IMM8);
3.285 - jit->write_ubyte(ia32_modrm(mode, 4, reg));
3.286 - jit->write_byte(value);
3.287 -}
3.288 -
3.289 -inline void IA32_And_Eax_Imm32(JitWriter *jit, jit_int32_t value)
3.290 -{
3.291 - jit->write_ubyte(IA32_AND_EAX_IMM32);
3.292 - jit->write_int32(value);
3.293 -}
3.294 -
3.295 -inline void IA32_Not_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.296 -{
3.297 - jit->write_ubyte(IA32_NOT_RM);
3.298 - jit->write_ubyte(ia32_modrm(mode, 2, reg));
3.299 -}
3.300 -
3.301 -inline void IA32_Shr_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t value, jit_uint8_t mode)
3.302 -{
3.303 - jit->write_ubyte(IA32_SHR_RM_IMM8);
3.304 - jit->write_ubyte(ia32_modrm(mode, 5, dest));
3.305 - jit->write_ubyte(value);
3.306 -}
3.307 -
3.308 -inline void IA32_Shr_Rm_1(JitWriter *jit, jit_uint8_t dest, jit_uint8_t mode)
3.309 -{
3.310 - jit->write_ubyte(IA32_SHR_RM_1);
3.311 - jit->write_ubyte(ia32_modrm(mode, 5, dest));
3.312 -}
3.313 -
3.314 -inline void IA32_Shl_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t value, jit_uint8_t mode)
3.315 -{
3.316 - jit->write_ubyte(IA32_SHL_RM_IMM8);
3.317 - jit->write_ubyte(ia32_modrm(mode, 4, dest));
3.318 - jit->write_ubyte(value);
3.319 -}
3.320 -
3.321 -inline void IA32_Shl_Rm_1(JitWriter *jit, jit_uint8_t dest, jit_uint8_t mode)
3.322 -{
3.323 - jit->write_ubyte(IA32_SHL_RM_1);
3.324 - jit->write_ubyte(ia32_modrm(mode, 4, dest));
3.325 -}
3.326 -
3.327 -inline void IA32_Sar_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t value, jit_uint8_t mode)
3.328 -{
3.329 - jit->write_ubyte(IA32_SAR_RM_IMM8);
3.330 - jit->write_ubyte(ia32_modrm(mode, 7, dest));
3.331 - jit->write_ubyte(value);
3.332 -}
3.333 -
3.334 -inline void IA32_Sar_Rm_CL(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.335 -{
3.336 - jit->write_ubyte(IA32_SAR_RM_CL);
3.337 - jit->write_ubyte(ia32_modrm(mode, 7, reg));
3.338 -}
3.339 -
3.340 -inline void IA32_Sar_Rm_1(JitWriter *jit, jit_uint8_t dest, jit_uint8_t mode)
3.341 -{
3.342 - jit->write_ubyte(IA32_SAR_RM_1);
3.343 - jit->write_ubyte(ia32_modrm(mode, 7, dest));
3.344 -}
3.345 -
3.346 -inline void IA32_Shr_Rm_CL(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.347 -{
3.348 - jit->write_ubyte(IA32_SHR_RM_CL);
3.349 - jit->write_ubyte(ia32_modrm(mode, 5, reg));
3.350 -}
3.351 -
3.352 -inline void IA32_Shl_Rm_CL(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.353 -{
3.354 - jit->write_ubyte(IA32_SHL_RM_CL);
3.355 - jit->write_ubyte(ia32_modrm(mode, 4, reg));
3.356 -}
3.357 -
3.358 -inline void IA32_Xchg_Eax_Reg(JitWriter *jit, jit_uint8_t reg)
3.359 -{
3.360 - jit->write_ubyte(IA32_XCHG_EAX_REG+reg);
3.361 -}
3.362 -
3.363 -/**********************
3.364 - * ARITHMETIC (BASIC) *
3.365 - **********************/
3.366 -
3.367 -inline void IA32_Add_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.368 -{
3.369 - jit->write_ubyte(IA32_ADD_RM_REG);
3.370 - jit->write_ubyte(ia32_modrm(mode, src, dest));
3.371 -}
3.372 -
3.373 -inline void IA32_Add_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.374 -{
3.375 - jit->write_ubyte(IA32_ADD_REG_RM);
3.376 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.377 -}
3.378 -
3.379 -inline void IA32_Add_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t value, jit_uint8_t mode)
3.380 -{
3.381 - jit->write_ubyte(IA32_ADD_RM_IMM8);
3.382 - jit->write_ubyte(ia32_modrm(mode, 0, reg));
3.383 - jit->write_byte(value);
3.384 -}
3.385 -
3.386 -inline void IA32_Add_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t value, jit_uint8_t mode)
3.387 -{
3.388 - jit->write_ubyte(IA32_ADD_RM_IMM32);
3.389 - jit->write_ubyte(ia32_modrm(mode, 0, reg));
3.390 - jit->write_int32(value);
3.391 -}
3.392 -
3.393 -inline void IA32_Add_Eax_Imm32(JitWriter *jit, jit_int32_t value)
3.394 -{
3.395 - jit->write_ubyte(IA32_ADD_EAX_IMM32);
3.396 - jit->write_int32(value);
3.397 -}
3.398 -
3.399 -inline void IA32_Sub_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.400 -{
3.401 - jit->write_ubyte(IA32_SUB_RM_REG);
3.402 - jit->write_ubyte(ia32_modrm(mode, src, dest));
3.403 -}
3.404 -
3.405 -inline void IA32_Sub_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.406 -{
3.407 - jit->write_ubyte(IA32_SUB_REG_RM);
3.408 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.409 -}
3.410 -
3.411 -inline void IA32_Sub_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp8)
3.412 -{
3.413 - jit->write_ubyte(IA32_SUB_REG_RM);
3.414 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
3.415 - jit->write_byte(disp8);
3.416 -}
3.417 -
3.418 -inline void IA32_Sub_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp8)
3.419 -{
3.420 - jit->write_ubyte(IA32_SUB_RM_REG);
3.421 - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest));
3.422 - jit->write_byte(disp8);
3.423 -}
3.424 -
3.425 -inline void IA32_Sub_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t val, jit_uint8_t mode)
3.426 -{
3.427 - jit->write_ubyte(IA32_SUB_RM_IMM8);
3.428 - jit->write_ubyte(ia32_modrm(mode, 5, reg));
3.429 - jit->write_byte(val);
3.430 -}
3.431 -
3.432 -inline void IA32_Sub_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t val, jit_uint8_t mode)
3.433 -{
3.434 - jit->write_ubyte(IA32_SUB_RM_IMM32);
3.435 - jit->write_ubyte(ia32_modrm(mode, 5, reg));
3.436 - jit->write_int32(val);
3.437 -}
3.438 -
3.439 -inline void IA32_Sbb_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.440 -{
3.441 - jit->write_ubyte(IA32_SBB_REG_RM);
3.442 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.443 -}
3.444 -
3.445 -inline void IA32_Sbb_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_int8_t value, jit_uint8_t mode)
3.446 +inline void IA32_Return(JitWriter *jit)
3.447 {
3.448 - jit->write_ubyte(IA32_SBB_RM_IMM8);
3.449 - jit->write_ubyte(ia32_modrm(mode, 3, dest));
3.450 - jit->write_byte(value);
3.451 -}
3.452 -
3.453 -inline void IA32_Div_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.454 -{
3.455 - jit->write_ubyte(IA32_DIV_RM);
3.456 - jit->write_ubyte(ia32_modrm(mode, 6, reg));
3.457 -}
3.458 -
3.459 -inline void IA32_IDiv_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.460 -{
3.461 - jit->write_ubyte(IA32_IDIV_RM);
3.462 - jit->write_ubyte(ia32_modrm(mode, 7, reg));
3.463 -}
3.464 -
3.465 -inline void IA32_Mul_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.466 -{
3.467 - jit->write_ubyte(IA32_MUL_RM);
3.468 - jit->write_ubyte(ia32_modrm(mode, 4, reg));
3.469 -}
3.470 -
3.471 -inline void IA32_IMul_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.472 -{
3.473 - jit->write_ubyte(IA32_IMUL_RM);
3.474 - jit->write_ubyte(ia32_modrm(mode, 5, reg));
3.475 -}
3.476 -
3.477 -inline void IA32_IMul_Reg_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value)
3.478 -{
3.479 - jit->write_ubyte(IA32_IMUL_REG_IMM8);
3.480 - jit->write_ubyte(ia32_modrm(mode, 0, reg));
3.481 - jit->write_byte(value);
3.482 -}
3.483 -
3.484 -inline void IA32_IMul_Reg_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int32_t value)
3.485 -{
3.486 - jit->write_ubyte(IA32_IMUL_REG_IMM32);
3.487 - jit->write_ubyte(ia32_modrm(mode, 0, reg));
3.488 - jit->write_int32(value);
3.489 -}
3.490 -
3.491 -inline void IA32_IMul_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.492 -{
3.493 - jit->write_ubyte(IA32_IMUL_REG_RM_1);
3.494 - jit->write_ubyte(IA32_IMUL_REG_RM_2);
3.495 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.496 -}
3.497 -
3.498 -inline void IA32_Add_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.499 -{
3.500 - jit->write_ubyte(IA32_ADD_RM_REG);
3.501 - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest));
3.502 - jit->write_byte(disp);
3.503 -}
3.504 -
3.505 -inline void IA32_Add_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.506 -{
3.507 - jit->write_ubyte(IA32_ADD_REG_RM);
3.508 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
3.509 - jit->write_byte(disp);
3.510 -}
3.511 -
3.512 -inline void IA32_Add_Rm_Imm8_Disp8(JitWriter *jit,
3.513 - jit_uint8_t dest,
3.514 - jit_int8_t val,
3.515 - jit_int8_t disp8)
3.516 -{
3.517 - jit->write_ubyte(IA32_ADD_RM_IMM8);
3.518 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest));
3.519 - jit->write_byte(disp8);
3.520 - jit->write_byte(val);
3.521 -}
3.522 -
3.523 -inline void IA32_Add_Rm_Imm32_Disp8(JitWriter *jit,
3.524 - jit_uint8_t dest,
3.525 - jit_int32_t val,
3.526 - jit_int8_t disp8)
3.527 -{
3.528 - jit->write_ubyte(IA32_ADD_RM_IMM32);
3.529 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest));
3.530 - jit->write_byte(disp8);
3.531 - jit->write_int32(val);
3.532 -}
3.533 -
3.534 -inline jitoffs_t IA32_Add_Rm_Imm32_Later(JitWriter *jit,
3.535 - jit_uint8_t dest,
3.536 - jit_uint8_t mode)
3.537 -{
3.538 - jit->write_ubyte(IA32_ADD_RM_IMM32);
3.539 - jit->write_ubyte(ia32_modrm(mode, 0, dest));
3.540 - jitoffs_t ptr = jit->get_outputpos();
3.541 - jit->write_int32(0);
3.542 - return ptr;
3.543 -}
3.544 -
3.545 -inline void IA32_Add_Rm_Imm8_Disp32(JitWriter *jit,
3.546 - jit_uint8_t dest,
3.547 - jit_int8_t val,
3.548 - jit_int32_t disp32)
3.549 -{
3.550 - jit->write_ubyte(IA32_ADD_RM_IMM8);
3.551 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, dest));
3.552 - jit->write_int32(disp32);
3.553 - jit->write_byte(val);
3.554 -}
3.555 -
3.556 -inline void IA32_Add_RmEBP_Imm8_Disp_Reg(JitWriter *jit,
3.557 - jit_uint8_t dest_base,
3.558 - jit_uint8_t dest_index,
3.559 - jit_uint8_t dest_scale,
3.560 - jit_int8_t val)
3.561 -{
3.562 - jit->write_ubyte(IA32_ADD_RM_IMM8);
3.563 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB));
3.564 - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
3.565 - jit->write_byte(0);
3.566 - jit->write_byte(val);
3.567 -}
3.568 -
3.569 -inline void IA32_Sub_Rm_Imm8_Disp8(JitWriter *jit,
3.570 - jit_uint8_t dest,
3.571 - jit_int8_t val,
3.572 - jit_int8_t disp8)
3.573 -{
3.574 - jit->write_ubyte(IA32_SUB_RM_IMM8);
3.575 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 5, dest));
3.576 - jit->write_byte(disp8);
3.577 - jit->write_byte(val);
3.578 -}
3.579 -
3.580 -inline void IA32_Sub_Rm_Imm8_Disp32(JitWriter *jit,
3.581 - jit_uint8_t dest,
3.582 - jit_int8_t val,
3.583 - jit_int32_t disp32)
3.584 -{
3.585 - jit->write_ubyte(IA32_SUB_RM_IMM8);
3.586 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 5, dest));
3.587 - jit->write_int32(disp32);
3.588 - jit->write_byte(val);
3.589 -}
3.590 -
3.591 -inline void IA32_Sub_RmEBP_Imm8_Disp_Reg(JitWriter *jit,
3.592 - jit_uint8_t dest_base,
3.593 - jit_uint8_t dest_index,
3.594 - jit_uint8_t dest_scale,
3.595 - jit_int8_t val)
3.596 -{
3.597 - jit->write_ubyte(IA32_SUB_RM_IMM8);
3.598 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 5, REG_SIB));
3.599 - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
3.600 - jit->write_byte(0);
3.601 - jit->write_byte(val);
3.602 -}
3.603 -
3.604 -/**
3.605 -* Memory Instructions
3.606 -*/
3.607 -
3.608 -inline void IA32_Lea_Reg_DispRegMult(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_uint8_t src_index, jit_uint8_t scale)
3.609 -{
3.610 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.611 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_SIB));
3.612 - jit->write_ubyte(ia32_sib(scale, src_index, src_base));
3.613 -}
3.614 -
3.615 -inline void IA32_Lea_Reg_DispEBPRegMult(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_uint8_t src_index, jit_uint8_t scale)
3.616 -{
3.617 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.618 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB));
3.619 - jit->write_ubyte(ia32_sib(scale, src_index, src_base));
3.620 - jit->write_byte(0);
3.621 -}
3.622 -
3.623 -inline void IA32_Lea_Reg_DispRegMultImm8(JitWriter *jit,
3.624 - jit_uint8_t dest,
3.625 - jit_uint8_t src_base,
3.626 - jit_uint8_t src_index,
3.627 - jit_uint8_t scale,
3.628 - jit_int8_t val)
3.629 -{
3.630 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.631 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB));
3.632 - jit->write_ubyte(ia32_sib(scale, src_index, src_base));
3.633 - jit->write_byte(val);
3.634 -}
3.635 -
3.636 -inline void IA32_Lea_Reg_DispRegMultImm32(JitWriter *jit,
3.637 - jit_uint8_t dest,
3.638 - jit_uint8_t src_base,
3.639 - jit_uint8_t src_index,
3.640 - jit_uint8_t scale,
3.641 - jit_int32_t val)
3.642 -{
3.643 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.644 - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, REG_SIB));
3.645 - jit->write_ubyte(ia32_sib(scale, src_index, src_base));
3.646 - jit->write_int32(val);
3.647 -}
3.648 -
3.649 -inline void IA32_Lea_Reg_RegMultImm32(JitWriter *jit,
3.650 - jit_uint8_t dest,
3.651 - jit_uint8_t src_index,
3.652 - jit_uint8_t scale,
3.653 - jit_int32_t val)
3.654 -{
3.655 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.656 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_SIB));
3.657 - jit->write_ubyte(ia32_sib(scale, src_index, REG_IMM_BASE));
3.658 - jit->write_int32(val);
3.659 -}
3.660 -
3.661 -inline void IA32_Lea_DispRegImm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int8_t val)
3.662 -{
3.663 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.664 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src_base));
3.665 - jit->write_byte(val);
3.666 -}
3.667 -
3.668 -inline void IA32_Lea_DispRegImm32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int32_t val)
3.669 -{
3.670 - jit->write_ubyte(IA32_LEA_REG_MEM);
3.671 - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src_base));
3.672 - jit->write_int32(val);
3.673 -}
3.674 -
3.675 -/**
3.676 -* Stack Instructions
3.677 -*/
3.678 -
3.679 -inline void IA32_Pop_Reg(JitWriter *jit, jit_uint8_t reg)
3.680 -{
3.681 - jit->write_ubyte(IA32_POP_REG+reg);
3.682 -}
3.683 -
3.684 -inline void IA32_Push_Reg(JitWriter *jit, jit_uint8_t reg)
3.685 -{
3.686 - jit->write_ubyte(IA32_PUSH_REG+reg);
3.687 -}
3.688 -
3.689 -inline void IA32_Push_Imm8(JitWriter *jit, jit_int8_t val)
3.690 -{
3.691 - jit->write_ubyte(IA32_PUSH_IMM8);
3.692 - jit->write_byte(val);
3.693 -}
3.694 -
3.695 -inline void IA32_Push_Imm32(JitWriter *jit, jit_int32_t val)
3.696 -{
3.697 - jit->write_ubyte(IA32_PUSH_IMM32);
3.698 - jit->write_int32(val);
3.699 -}
3.700 -
3.701 -inline void IA32_Pushad(JitWriter *jit)
3.702 -{
3.703 - jit->write_ubyte(IA32_PUSHAD);
3.704 -}
3.705 -
3.706 -inline void IA32_Popad(JitWriter *jit)
3.707 -{
3.708 - jit->write_ubyte(IA32_POPAD);
3.709 -}
3.710 -
3.711 -inline void IA32_Push_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp8)
3.712 -{
3.713 - jit->write_ubyte(IA32_PUSH_RM);
3.714 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, reg));
3.715 - jit->write_byte(disp8);
3.716 -}
3.717 -
3.718 -inline void IA32_Push_Rm_Disp8_ESP(JitWriter *jit, jit_int8_t disp8)
3.719 -{
3.720 - jit->write_ubyte(IA32_PUSH_RM);
3.721 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, REG_SIB));
3.722 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.723 - jit->write_byte(disp8);
3.724 -}
3.725 -
3.726 -/**
3.727 - * Moving from REGISTER/MEMORY to REGISTER
3.728 - */
3.729 -
3.730 -inline void IA32_Mov_Eax_Mem(JitWriter *jit, jit_uint32_t mem)
3.731 -{
3.732 - jit->write_ubyte(IA32_MOV_EAX_MEM);
3.733 - jit->write_uint32(mem);
3.734 + jit->write_ubyte(IA32_RET);
3.735 }
3.736
3.737 inline void IA32_Mov_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.738 @@ -797,432 +154,6 @@
3.739 jit->write_ubyte(ia32_modrm(mode, dest, src));
3.740 }
3.741
3.742 -inline void IA32_Mov_Reg8_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.743 -{
3.744 - jit->write_ubyte(IA32_MOV_REG8_RM8);
3.745 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.746 -}
3.747 -
3.748 -inline void IA32_Mov_Reg_RmESP(JitWriter *jit, jit_uint8_t dest)
3.749 -{
3.750 - jit->write_ubyte(IA32_MOV_REG_RM);
3.751 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_ESP));
3.752 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.753 -}
3.754 -
3.755 -inline void IA32_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.756 -{
3.757 - jit->write_ubyte(IA32_MOV_REG_RM);
3.758 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
3.759 - jit->write_byte(disp);
3.760 -}
3.761 -
3.762 -inline void IA32_Mov_Reg8_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.763 -{
3.764 - jit->write_ubyte(IA32_MOV_REG8_RM8);
3.765 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
3.766 - jit->write_byte(disp);
3.767 -}
3.768 -
3.769 -inline void IA32_Mov_Reg_Esp_Disp8(JitWriter *jit, jit_uint8_t dest, jit_int8_t disp)
3.770 -{
3.771 - jit->write_ubyte(IA32_MOV_REG_RM);
3.772 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB));
3.773 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.774 - jit->write_byte(disp);
3.775 -}
3.776 -
3.777 -inline void IA32_Mov_Reg_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
3.778 -{
3.779 - jit->write_ubyte(IA32_MOV_REG_RM);
3.780 - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src));
3.781 - jit->write_int32(disp);
3.782 -}
3.783 -
3.784 -inline void IA32_Mov_Reg8_Rm8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
3.785 -{
3.786 - jit->write_ubyte(IA32_MOV_REG8_RM8);
3.787 - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src));
3.788 - jit->write_int32(disp);
3.789 -}
3.790 -
3.791 -inline void IA32_Mov_Reg_Rm_Disp_Reg(JitWriter *jit,
3.792 - jit_uint8_t dest,
3.793 - jit_uint8_t src_base,
3.794 - jit_uint8_t src_index,
3.795 - jit_uint8_t src_scale)
3.796 -{
3.797 - jit->write_ubyte(IA32_MOV_REG_RM);
3.798 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_SIB));
3.799 - jit->write_ubyte(ia32_sib(src_scale, src_index, src_base));
3.800 -}
3.801 -
3.802 -inline void IA32_Mov_Reg_Rm_Disp_Reg_Disp8(JitWriter *jit,
3.803 - jit_uint8_t dest,
3.804 - jit_uint8_t src_base,
3.805 - jit_uint8_t src_index,
3.806 - jit_uint8_t src_scale,
3.807 - jit_int8_t disp8)
3.808 -{
3.809 - jit->write_ubyte(IA32_MOV_REG_RM);
3.810 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB));
3.811 - jit->write_ubyte(ia32_sib(src_scale, src_index, src_base));
3.812 - jit->write_byte(disp8);
3.813 -}
3.814 -
3.815 -inline void IA32_Mov_Reg_RmEBP_Disp_Reg(JitWriter *jit,
3.816 - jit_uint8_t dest,
3.817 - jit_uint8_t src_base,
3.818 - jit_uint8_t src_index,
3.819 - jit_uint8_t src_scale)
3.820 -{
3.821 - jit->write_ubyte(IA32_MOV_REG_RM);
3.822 - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB));
3.823 - jit->write_ubyte(ia32_sib(src_scale, src_index, src_base));
3.824 - jit->write_byte(0);
3.825 -}
3.826 -
3.827 -/**
3.828 - * Moving from REGISTER to REGISTER/MEMORY
3.829 - */
3.830 -
3.831 -inline void IA32_Mov_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.832 -{
3.833 - jit->write_ubyte(IA32_MOV_RM_REG);
3.834 - jit->write_ubyte(ia32_modrm(mode, src, dest));
3.835 -}
3.836 -
3.837 -inline void IA32_Mov_Rm8_Reg8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.838 -{
3.839 - jit->write_ubyte(IA32_MOV_RM8_REG8);
3.840 - jit->write_ubyte(ia32_modrm(mode, src, dest));
3.841 -}
3.842 -
3.843 -inline void IA32_Mov_RmESP_Reg(JitWriter *jit, jit_uint8_t src)
3.844 -{
3.845 - jit->write_ubyte(IA32_MOV_RM_REG);
3.846 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src, REG_ESP));
3.847 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.848 -}
3.849 -
3.850 -inline void IA32_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.851 -{
3.852 - jit->write_ubyte(IA32_MOV_RM_REG);
3.853 - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest));
3.854 - jit->write_byte(disp);
3.855 -}
3.856 -
3.857 -inline void IA32_Mov_Rm_Reg_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
3.858 -{
3.859 - jit->write_ubyte(IA32_MOV_RM_REG);
3.860 - jit->write_ubyte(ia32_modrm(MOD_DISP32, src, dest));
3.861 - jit->write_int32(disp);
3.862 -}
3.863 -
3.864 -inline void IA32_Mov_RmEBP_Reg_Disp_Reg(JitWriter *jit,
3.865 - jit_uint8_t dest_base,
3.866 - jit_uint8_t dest_index,
3.867 - jit_uint8_t dest_scale,
3.868 - jit_uint8_t src)
3.869 -{
3.870 - jit->write_ubyte(IA32_MOV_RM_REG);
3.871 - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, REG_SIB));
3.872 - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
3.873 - jit->write_byte(0);
3.874 -}
3.875 -
3.876 -inline void IA32_Mov_Rm8EBP_Reg_Disp_Reg(JitWriter *jit,
3.877 - jit_uint8_t dest_base,
3.878 - jit_uint8_t dest_index,
3.879 - jit_uint8_t dest_scale,
3.880 - jit_uint8_t src)
3.881 -{
3.882 - jit->write_ubyte(IA32_MOV_RM8_REG);
3.883 - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, REG_SIB));
3.884 - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
3.885 - jit->write_byte(0);
3.886 -}
3.887 -
3.888 -inline void IA32_Mov_Rm16EBP_Reg_Disp_Reg(JitWriter *jit,
3.889 - jit_uint8_t dest_base,
3.890 - jit_uint8_t dest_index,
3.891 - jit_uint8_t dest_scale,
3.892 - jit_uint8_t src)
3.893 -{
3.894 - jit->write_ubyte(IA32_16BIT_PREFIX);
3.895 - jit->write_ubyte(IA32_MOV_RM_REG);
3.896 - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, REG_SIB));
3.897 - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
3.898 - jit->write_byte(0);
3.899 -}
3.900 -
3.901 -/**
3.902 - * Moving from IMMEDIATE to REGISTER
3.903 - */
3.904 -
3.905 -inline jitoffs_t IA32_Mov_Reg_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t num)
3.906 -{
3.907 - jitoffs_t offs;
3.908 - jit->write_ubyte(IA32_MOV_REG_IMM+dest);
3.909 - offs = jit->get_outputpos();
3.910 - jit->write_int32(num);
3.911 - return offs;
3.912 -}
3.913 -
3.914 -inline void IA32_Mov_Rm_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t val, jit_uint8_t mode)
3.915 -{
3.916 - jit->write_ubyte(IA32_MOV_RM_IMM32);
3.917 - jit->write_ubyte(ia32_modrm(mode, 0, dest));
3.918 - jit->write_int32(val);
3.919 -}
3.920 -
3.921 -inline void IA32_Mov_Rm_Imm32_Disp8(JitWriter *jit,
3.922 - jit_uint8_t dest,
3.923 - jit_int32_t val,
3.924 - jit_int8_t disp8)
3.925 -{
3.926 - jit->write_ubyte(IA32_MOV_RM_IMM32);
3.927 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest));
3.928 - jit->write_byte(disp8);
3.929 - jit->write_int32(val);
3.930 -}
3.931 -
3.932 -inline void IA32_Mov_Rm_Imm32_Disp32(JitWriter *jit,
3.933 - jit_uint8_t dest,
3.934 - jit_int32_t val,
3.935 - jit_int32_t disp32)
3.936 -{
3.937 - jit->write_ubyte(IA32_MOV_RM_IMM32);
3.938 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, dest));
3.939 - jit->write_int32(disp32);
3.940 - jit->write_int32(val);
3.941 -}
3.942 -
3.943 -inline void IA32_Mov_Rm_Imm32_SIB(JitWriter *jit,
3.944 - jit_uint8_t dest,
3.945 - jit_int32_t val,
3.946 - jit_int32_t disp,
3.947 - jit_uint8_t index,
3.948 - jit_uint8_t scale)
3.949 -{
3.950 - jit->write_ubyte(IA32_MOV_RM_IMM32);
3.951 -
3.952 - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX)
3.953 - {
3.954 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB));
3.955 - }
3.956 - else
3.957 - {
3.958 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, REG_SIB));
3.959 - }
3.960 -
3.961 - jit->write_ubyte(ia32_sib(scale, index, dest));
3.962 -
3.963 - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX)
3.964 - {
3.965 - jit->write_byte((jit_int8_t)disp);
3.966 - }
3.967 - else
3.968 - {
3.969 - jit->write_int32(disp);
3.970 - }
3.971 -
3.972 - jit->write_int32(val);
3.973 -}
3.974 -
3.975 -inline void IA32_Mov_RmEBP_Imm32_Disp_Reg(JitWriter *jit,
3.976 - jit_uint8_t dest_base,
3.977 - jit_uint8_t dest_index,
3.978 - jit_uint8_t dest_scale,
3.979 - jit_int32_t val)
3.980 -{
3.981 - jit->write_ubyte(IA32_MOV_RM_IMM32);
3.982 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB));
3.983 - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
3.984 - jit->write_byte(0);
3.985 - jit->write_int32(val);
3.986 -}
3.987 -
3.988 -inline void IA32_Mov_ESP_Disp8_Imm32(JitWriter *jit, jit_int8_t disp8, jit_int32_t val)
3.989 -{
3.990 - jit->write_ubyte(IA32_MOV_RM_IMM32);
3.991 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB));
3.992 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.993 - jit->write_byte(disp8);
3.994 - jit->write_int32(val);
3.995 -}
3.996 -
3.997 -/**
3.998 -* Floating Point Instructions
3.999 -*/
3.1000 -
3.1001 -inline void IA32_Fstcw_Mem16_ESP(JitWriter *jit)
3.1002 -{
3.1003 - jit->write_ubyte(IA32_FSTCW_MEM16_1);
3.1004 - jit->write_ubyte(IA32_FSTCW_MEM16_2);
3.1005 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 7, REG_SIB));
3.1006 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1007 -}
3.1008 -
3.1009 -inline void IA32_Fldcw_Mem16_ESP(JitWriter *jit)
3.1010 -{
3.1011 - jit->write_ubyte(IA32_FLDCW_MEM16);
3.1012 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 5, REG_SIB));
3.1013 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1014 -}
3.1015 -
3.1016 -inline void IA32_Fldcw_Mem16_Disp8_ESP(JitWriter *jit, jit_int8_t disp8)
3.1017 -{
3.1018 - jit->write_ubyte(IA32_FLDCW_MEM16);
3.1019 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 5, REG_SIB));
3.1020 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1021 - jit->write_byte(disp8);
3.1022 -}
3.1023 -
3.1024 -inline void IA32_Fistp_Mem32_ESP(JitWriter *jit)
3.1025 -{
3.1026 - jit->write_ubyte(IA32_FISTP_MEM32);
3.1027 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
3.1028 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1029 -}
3.1030 -
3.1031 -inline void IA32_Fistp_Mem32_Disp8_Esp(JitWriter *jit, jit_int8_t disp8)
3.1032 -{
3.1033 - jit->write_ubyte(IA32_FISTP_MEM32);
3.1034 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 3, REG_SIB));
3.1035 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1036 - jit->write_byte(disp8);
3.1037 -}
3.1038 -
3.1039 -inline void IA32_Fucomip_ST0_FPUreg(JitWriter *jit, jit_uint8_t reg)
3.1040 -{
3.1041 - jit->write_ubyte(IA32_FUCOMIP_1);
3.1042 - jit->write_ubyte(IA32_FUCOMIP_2+reg);
3.1043 -}
3.1044 -
3.1045 -inline void IA32_Fadd_FPUreg_ST0(JitWriter *jit, jit_uint8_t reg)
3.1046 -{
3.1047 - jit->write_ubyte(IA32_FADD_FPREG_ST0_1);
3.1048 - jit->write_ubyte(IA32_FADD_FPREG_ST0_2+reg);
3.1049 -}
3.1050 -
3.1051 -inline void IA32_Fadd_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1052 -{
3.1053 - jit->write_ubyte(IA32_FADD_MEM32);
3.1054 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src));
3.1055 - jit->write_byte(val);
3.1056 -}
3.1057 -
3.1058 -inline void IA32_Fadd_Mem32_ESP(JitWriter *jit)
3.1059 -{
3.1060 - jit->write_ubyte(IA32_FADD_MEM32);
3.1061 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, REG_SIB));
3.1062 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1063 -}
3.1064 -
3.1065 -inline void IA32_Fsub_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1066 -{
3.1067 - jit->write_ubyte(IA32_FSUB_MEM32);
3.1068 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 4, src));
3.1069 - jit->write_byte(val);
3.1070 -}
3.1071 -
3.1072 -inline void IA32_Fmul_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1073 -{
3.1074 - jit->write_ubyte(IA32_FMUL_MEM32);
3.1075 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 1, src));
3.1076 - jit->write_byte(val);
3.1077 -}
3.1078 -
3.1079 -inline void IA32_Fdiv_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1080 -{
3.1081 - jit->write_ubyte(IA32_FDIV_MEM32);
3.1082 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, src));
3.1083 - jit->write_byte(val);
3.1084 -}
3.1085 -
3.1086 -inline void IA32_Fild_Mem32(JitWriter *jit, jit_uint8_t src)
3.1087 -{
3.1088 - jit->write_ubyte(IA32_FILD_MEM32);
3.1089 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src));
3.1090 -}
3.1091 -
3.1092 -inline void IA32_Fstp_Mem32(JitWriter *jit, jit_uint8_t dest)
3.1093 -{
3.1094 - jit->write_ubyte(IA32_FSTP_MEM32);
3.1095 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, dest));
3.1096 -}
3.1097 -
3.1098 -inline void IA32_Fstp_Mem64(JitWriter *jit, jit_uint8_t dest)
3.1099 -{
3.1100 - jit->write_ubyte(IA32_FSTP_MEM64);
3.1101 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, dest));
3.1102 -}
3.1103 -
3.1104 -inline void IA32_Fstp_Mem32_ESP(JitWriter *jit)
3.1105 -{
3.1106 - jit->write_ubyte(IA32_FSTP_MEM32);
3.1107 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
3.1108 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1109 -}
3.1110 -
3.1111 -inline void IA32_Fstp_Mem64_ESP(JitWriter *jit)
3.1112 -{
3.1113 - jit->write_ubyte(IA32_FSTP_MEM64);
3.1114 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
3.1115 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1116 -}
3.1117 -
3.1118 -inline void IA32_Fstp_FPUreg(JitWriter *jit, jit_uint8_t reg)
3.1119 -{
3.1120 - jit->write_ubyte(IA32_FSTP_FPREG_1);
3.1121 - jit->write_ubyte(IA32_FSTP_FPREG_2+reg);
3.1122 -}
3.1123 -
3.1124 -inline void IA32_Fld_Mem32(JitWriter *jit, jit_uint8_t src)
3.1125 -{
3.1126 - jit->write_ubyte(IA32_FLD_MEM32);
3.1127 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src));
3.1128 -}
3.1129 -
3.1130 -inline void IA32_Fld_Mem64(JitWriter *jit, jit_uint8_t src)
3.1131 -{
3.1132 - jit->write_ubyte(IA32_FLD_MEM64);
3.1133 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src));
3.1134 -}
3.1135 -
3.1136 -inline void IA32_Fld_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1137 -{
3.1138 - jit->write_ubyte(IA32_FLD_MEM32);
3.1139 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src));
3.1140 - jit->write_byte(val);
3.1141 -}
3.1142 -
3.1143 -inline void IA32_Fld_Mem64_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1144 -{
3.1145 - jit->write_ubyte(IA32_FLD_MEM64);
3.1146 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src));
3.1147 - jit->write_byte(val);
3.1148 -}
3.1149 -
3.1150 -inline void IA32_Fld_Mem32_Disp32(JitWriter *jit, jit_uint8_t src, jit_int32_t val)
3.1151 -{
3.1152 - jit->write_ubyte(IA32_FLD_MEM32);
3.1153 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, src));
3.1154 - jit->write_int32(val);
3.1155 -}
3.1156 -
3.1157 -inline void IA32_Fld_Mem64_Disp32(JitWriter *jit, jit_uint8_t src, jit_int32_t val)
3.1158 -{
3.1159 - jit->write_ubyte(IA32_FLD_MEM64);
3.1160 - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, src));
3.1161 - jit->write_int32(val);
3.1162 -}
3.1163 -
3.1164 -/**
3.1165 -* Move data with zero extend
3.1166 -*/
3.1167 -
3.1168 inline void IA32_Movzx_Reg32_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.1169 {
3.1170 jit->write_ubyte(IA32_MOVZX_R32_RM8_1);
3.1171 @@ -1269,57 +200,76 @@
3.1172 jit->write_int32(disp);
3.1173 }
3.1174
3.1175 -/**
3.1176 - * Branching/Jumping
3.1177 - */
3.1178 -
3.1179 -inline jitoffs_t IA32_Jump_Cond_Imm8(JitWriter *jit, jit_uint8_t cond, jit_int8_t disp)
3.1180 +inline void IA32_Push_Reg(JitWriter *jit, jit_uint8_t reg)
3.1181 {
3.1182 - jitoffs_t ptr;
3.1183 - jit->write_ubyte(IA32_JCC_IMM+cond);
3.1184 - ptr = jit->get_outputpos();
3.1185 - jit->write_byte(disp);
3.1186 - return ptr;
3.1187 + jit->write_ubyte(IA32_PUSH_REG+reg);
3.1188 +}
3.1189 +
3.1190 +inline void IA32_Pop_Reg(JitWriter *jit, jit_uint8_t reg)
3.1191 +{
3.1192 + jit->write_ubyte(IA32_POP_REG+reg);
3.1193 }
3.1194
3.1195 -inline jitoffs_t IA32_Jump_Imm32(JitWriter *jit, jit_int32_t disp)
3.1196 +inline void IA32_Lea_DispRegImm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int8_t val)
3.1197 +{
3.1198 + jit->write_ubyte(IA32_LEA_REG_MEM);
3.1199 + jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src_base));
3.1200 + jit->write_byte(val);
3.1201 +}
3.1202 +
3.1203 +inline void IA32_Lea_DispRegImm32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int32_t val)
3.1204 {
3.1205 - jitoffs_t ptr;
3.1206 - jit->write_ubyte(IA32_JMP_IMM32);
3.1207 - ptr = jit->get_outputpos();
3.1208 - jit->write_int32(disp);
3.1209 - return ptr;
3.1210 + jit->write_ubyte(IA32_LEA_REG_MEM);
3.1211 + jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src_base));
3.1212 + jit->write_int32(val);
3.1213 +}
3.1214 +
3.1215 +inline void IA32_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.1216 +{
3.1217 + jit->write_ubyte(IA32_MOV_REG_RM);
3.1218 + jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
3.1219 + jit->write_byte(disp);
3.1220 }
3.1221
3.1222 -inline jitoffs_t IA32_Jump_Imm8(JitWriter *jit, jit_int8_t disp)
3.1223 +inline void IA32_Mov_Reg_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
3.1224 {
3.1225 - jitoffs_t ptr;
3.1226 - jit->write_ubyte(IA32_JMP_IMM8);
3.1227 - ptr = jit->get_outputpos();
3.1228 - jit->write_byte(disp);
3.1229 - return ptr;
3.1230 + jit->write_ubyte(IA32_MOV_REG_RM);
3.1231 + jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src));
3.1232 + jit->write_int32(disp);
3.1233 +}
3.1234 +
3.1235 +inline void IA32_Sub_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t val, jit_uint8_t mode)
3.1236 +{
3.1237 + jit->write_ubyte(IA32_SUB_RM_IMM8);
3.1238 + jit->write_ubyte(ia32_modrm(mode, 5, reg));
3.1239 + jit->write_byte(val);
3.1240 }
3.1241
3.1242 -inline jitoffs_t IA32_Jump_Cond_Imm32(JitWriter *jit, jit_uint8_t cond, jit_int32_t disp)
3.1243 +inline void IA32_Sub_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t val, jit_uint8_t mode)
3.1244 {
3.1245 - jitoffs_t ptr;
3.1246 - jit->write_ubyte(IA32_JCC_IMM32_1);
3.1247 - jit->write_ubyte(IA32_JCC_IMM32_2+cond);
3.1248 - ptr = jit->get_outputpos();
3.1249 - jit->write_int32(disp);
3.1250 - return ptr;
3.1251 + jit->write_ubyte(IA32_SUB_RM_IMM32);
3.1252 + jit->write_ubyte(ia32_modrm(mode, 5, reg));
3.1253 + jit->write_int32(val);
3.1254 +}
3.1255 +
3.1256 +inline void IA32_Cld(JitWriter *jit)
3.1257 +{
3.1258 + jit->write_ubyte(IA32_CLD);
3.1259 }
3.1260
3.1261 -inline void IA32_Jump_Reg(JitWriter *jit, jit_uint8_t reg)
3.1262 +inline void IA32_Rep(JitWriter *jit)
3.1263 {
3.1264 - jit->write_ubyte(IA32_JMP_RM);
3.1265 - jit->write_ubyte(ia32_modrm(MOD_REG, 4, reg));
3.1266 + jit->write_ubyte(IA32_REP);
3.1267 }
3.1268
3.1269 -inline void IA32_Jump_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
3.1270 +inline void IA32_Movsd(JitWriter *jit)
3.1271 {
3.1272 - jit->write_ubyte(IA32_JMP_RM);
3.1273 - jit->write_ubyte(ia32_modrm(mode, 4, reg));
3.1274 + jit->write_ubyte(IA32_MOVSD);
3.1275 +}
3.1276 +
3.1277 +inline void IA32_Movsb(JitWriter *jit)
3.1278 +{
3.1279 + jit->write_ubyte(IA32_MOVSB);
3.1280 }
3.1281
3.1282 inline jitoffs_t IA32_Call_Imm32(JitWriter *jit, jit_int32_t disp)
3.1283 @@ -1331,36 +281,16 @@
3.1284 return ptr;
3.1285 }
3.1286
3.1287 -inline void IA32_Call_Reg(JitWriter *jit, jit_uint8_t reg)
3.1288 +inline void IA32_Mov_Rm8_Reg8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.1289 {
3.1290 - jit->write_ubyte(IA32_CALL_RM);
3.1291 - jit->write_ubyte(ia32_modrm(MOD_REG, 2, reg));
3.1292 + jit->write_ubyte(IA32_MOV_RM8_REG8);
3.1293 + jit->write_ubyte(ia32_modrm(mode, src, dest));
3.1294 }
3.1295
3.1296 -inline void IA32_Write_Jump8(JitWriter *jit, jitoffs_t jmp, jitoffs_t target)
3.1297 +inline void IA32_Mov_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.1298 {
3.1299 - //save old ptr
3.1300 - jitcode_t oldptr = jit->outptr;
3.1301 - //get relative difference
3.1302 - jit_int8_t diff = (target - (jmp + 1));
3.1303 - //overwrite old value
3.1304 - jit->outptr = jit->outbase + jmp;
3.1305 - jit->write_byte(diff);
3.1306 - //restore old ptr
3.1307 - jit->outptr = oldptr;
3.1308 -}
3.1309 -
3.1310 -inline void IA32_Write_Jump32(JitWriter *jit, jitoffs_t jmp, jitoffs_t target)
3.1311 -{
3.1312 - //save old ptr
3.1313 - jitcode_t oldptr = jit->outptr;
3.1314 - //get relative difference
3.1315 - jit_int32_t diff = (target - (jmp + 4));
3.1316 - //overwrite old value
3.1317 - jit->outptr = jit->outbase + jmp;
3.1318 - jit->write_int32(diff);
3.1319 - //restore old ptr
3.1320 - jit->outptr = oldptr;
3.1321 + jit->write_ubyte(IA32_MOV_RM_REG);
3.1322 + jit->write_ubyte(ia32_modrm(mode, src, dest));
3.1323 }
3.1324
3.1325 /**
3.1326 @@ -1379,54 +309,126 @@
3.1327 jit->outptr = oldptr;
3.1328 }
3.1329
3.1330 -/* For writing and auto-calculating a relative target */
3.1331 -inline void IA32_Jump_Imm32_Rel(JitWriter *jit, jitoffs_t target)
3.1332 +inline void IA32_Fstp_Mem32(JitWriter *jit, jit_uint8_t dest)
3.1333 +{
3.1334 + jit->write_ubyte(IA32_FSTP_MEM32);
3.1335 + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, dest));
3.1336 +}
3.1337 +
3.1338 +inline void IA32_Fstp_Mem64(JitWriter *jit, jit_uint8_t dest)
3.1339 {
3.1340 - jit->write_ubyte(IA32_JMP_IMM32);
3.1341 - IA32_Write_Jump32(jit, jit->get_outputpos(), target);
3.1342 - jit->outptr += 4;
3.1343 + jit->write_ubyte(IA32_FSTP_MEM64);
3.1344 + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, dest));
3.1345 +}
3.1346 +
3.1347 +inline void IA32_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.1348 +{
3.1349 + jit->write_ubyte(IA32_MOV_RM_REG);
3.1350 + jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest));
3.1351 + jit->write_byte(disp);
3.1352 +}
3.1353 +
3.1354 +inline void IA32_Call_Reg(JitWriter *jit, jit_uint8_t reg)
3.1355 +{
3.1356 + jit->write_ubyte(IA32_CALL_RM);
3.1357 + jit->write_ubyte(ia32_modrm(MOD_REG, 2, reg));
3.1358 }
3.1359
3.1360 -/* For writing and auto-calculating an absolute target */
3.1361 -inline void IA32_Jump_Imm32_Abs(JitWriter *jit, void *target)
3.1362 +inline jitoffs_t IA32_Mov_Reg_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t num)
3.1363 +{
3.1364 + jitoffs_t offs;
3.1365 + jit->write_ubyte(IA32_MOV_REG_IMM+dest);
3.1366 + offs = jit->get_outputpos();
3.1367 + jit->write_int32(num);
3.1368 + return offs;
3.1369 +}
3.1370 +
3.1371 +inline void IA32_Add_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t value, jit_uint8_t mode)
3.1372 {
3.1373 - jitoffs_t jmp;
3.1374 + jit->write_ubyte(IA32_ADD_RM_IMM8);
3.1375 + jit->write_ubyte(ia32_modrm(mode, 0, reg));
3.1376 + jit->write_byte(value);
3.1377 +}
3.1378
3.1379 - jmp = IA32_Jump_Imm32(jit, 0);
3.1380 - IA32_Write_Jump32_Abs(jit, jmp, target);
3.1381 +inline void IA32_Add_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t value, jit_uint8_t mode)
3.1382 +{
3.1383 + jit->write_ubyte(IA32_ADD_RM_IMM32);
3.1384 + jit->write_ubyte(ia32_modrm(mode, 0, reg));
3.1385 + jit->write_int32(value);
3.1386 +}
3.1387 +
3.1388 +inline void IA32_And_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value)
3.1389 +{
3.1390 + jit->write_ubyte(IA32_AND_RM_IMM8);
3.1391 + jit->write_ubyte(ia32_modrm(mode, 4, reg));
3.1392 + jit->write_byte(value);
3.1393 }
3.1394
3.1395 -inline void IA32_Jump_Cond_Imm32_Rel(JitWriter *jit, jit_uint8_t cond, jitoffs_t target)
3.1396 +inline void IA32_Lea_Reg_DispRegMultImm8(JitWriter *jit,
3.1397 + jit_uint8_t dest,
3.1398 + jit_uint8_t src_base,
3.1399 + jit_uint8_t src_index,
3.1400 + jit_uint8_t scale,
3.1401 + jit_int8_t val)
3.1402 {
3.1403 - jit->write_ubyte(IA32_JCC_IMM32_1);
3.1404 - jit->write_ubyte(IA32_JCC_IMM32_2+cond);
3.1405 - IA32_Write_Jump32(jit, jit->get_outputpos(), target);
3.1406 - jit->outptr += 4;
3.1407 + jit->write_ubyte(IA32_LEA_REG_MEM);
3.1408 + jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB));
3.1409 + jit->write_ubyte(ia32_sib(scale, src_index, src_base));
3.1410 + jit->write_byte(val);
3.1411 }
3.1412
3.1413 -inline void IA32_Jump_Cond_Imm32_Abs(JitWriter *jit, jit_uint8_t cond, void *target)
3.1414 +inline void IA32_Fld_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1415 +{
3.1416 + jit->write_ubyte(IA32_FLD_MEM32);
3.1417 + jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src));
3.1418 + jit->write_byte(val);
3.1419 +}
3.1420 +
3.1421 +inline void IA32_Fld_Mem64_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val)
3.1422 {
3.1423 - jit->write_ubyte(IA32_JCC_IMM32_1);
3.1424 - jit->write_ubyte(IA32_JCC_IMM32_2+cond);
3.1425 - IA32_Write_Jump32_Abs(jit, jit->get_outputpos(), target);
3.1426 - jit->outptr += 4;
3.1427 + jit->write_ubyte(IA32_FLD_MEM64);
3.1428 + jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src));
3.1429 + jit->write_byte(val);
3.1430 +}
3.1431 +
3.1432 +inline void IA32_Fld_Mem32(JitWriter *jit, jit_uint8_t src)
3.1433 +{
3.1434 + jit->write_ubyte(IA32_FLD_MEM32);
3.1435 + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src));
3.1436 }
3.1437
3.1438 -inline void IA32_Send_Jump8_Here(JitWriter *jit, jitoffs_t jmp)
3.1439 +inline void IA32_Fld_Mem64(JitWriter *jit, jit_uint8_t src)
3.1440 {
3.1441 - jitoffs_t curptr = jit->get_outputpos();
3.1442 - IA32_Write_Jump8(jit, jmp, curptr);
3.1443 + jit->write_ubyte(IA32_FLD_MEM64);
3.1444 + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src));
3.1445 +}
3.1446 +
3.1447 +inline void IA32_Fld_Mem32_Disp32(JitWriter *jit, jit_uint8_t src, jit_int32_t val)
3.1448 +{
3.1449 + jit->write_ubyte(IA32_FLD_MEM32);
3.1450 + jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, src));
3.1451 + jit->write_int32(val);
3.1452 }
3.1453
3.1454 -inline void IA32_Send_Jump32_Here(JitWriter *jit, jitoffs_t jmp)
3.1455 +inline void IA32_Fld_Mem64_Disp32(JitWriter *jit, jit_uint8_t src, jit_int32_t val)
3.1456 {
3.1457 - jitoffs_t curptr = jit->get_outputpos();
3.1458 - IA32_Write_Jump32(jit, jmp, curptr);
3.1459 + jit->write_ubyte(IA32_FLD_MEM64);
3.1460 + jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, src));
3.1461 + jit->write_int32(val);
3.1462 }
3.1463
3.1464 -inline void IA32_Return(JitWriter *jit)
3.1465 +inline void IA32_Fstp_Mem32_ESP(JitWriter *jit)
3.1466 {
3.1467 - jit->write_ubyte(IA32_RET);
3.1468 + jit->write_ubyte(IA32_FSTP_MEM32);
3.1469 + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
3.1470 + jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1471 +}
3.1472 +
3.1473 +inline void IA32_Fstp_Mem64_ESP(JitWriter *jit)
3.1474 +{
3.1475 + jit->write_ubyte(IA32_FSTP_MEM64);
3.1476 + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
3.1477 + jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1478 }
3.1479
3.1480 inline void IA32_Return_Popstack(JitWriter *jit, unsigned short bytes)
3.1481 @@ -1435,130 +437,33 @@
3.1482 jit->write_ushort(bytes);
3.1483 }
3.1484
3.1485 -inline void IA32_Test_Rm_Reg(JitWriter *jit, jit_uint8_t reg1, jit_uint8_t reg2, jit_uint8_t mode)
3.1486 -{
3.1487 - jit->write_ubyte(IA32_TEST_RM_REG);
3.1488 - jit->write_ubyte(ia32_modrm(mode, reg2, reg1));
3.1489 -}
3.1490 -
3.1491 -inline void IA32_Cmp_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.1492 -{
3.1493 - jit->write_ubyte(IA32_CMP_RM_REG);
3.1494 - jit->write_ubyte(ia32_modrm(mode, src, dest));
3.1495 -}
3.1496 -
3.1497 -inline void IA32_Cmp_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
3.1498 -{
3.1499 - jit->write_ubyte(IA32_CMP_REG_RM);
3.1500 - jit->write_ubyte(ia32_modrm(mode, dest, src));
3.1501 -}
3.1502 -
3.1503 -inline void IA32_Cmp_Reg_Rm_ESP(JitWriter *jit, jit_uint8_t cmpreg)
3.1504 +inline void IA32_Push_Imm8(JitWriter *jit, jit_int8_t val)
3.1505 {
3.1506 - jit->write_ubyte(IA32_CMP_REG_RM);
3.1507 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, cmpreg, REG_SIB));
3.1508 - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP));
3.1509 -}
3.1510 -
3.1511 -inline void IA32_Cmp_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t reg1, jit_uint8_t reg2, jit_int8_t disp8)
3.1512 -{
3.1513 - jit->write_ubyte(IA32_CMP_REG_RM);
3.1514 - jit->write_ubyte(ia32_modrm(MOD_DISP8, reg1, reg2));
3.1515 - jit->write_byte(disp8);
3.1516 -}
3.1517 -
3.1518 -inline void IA32_Cmp_Rm_Imm8(JitWriter *jit, jit_uint8_t mode, jit_uint8_t rm, jit_int8_t imm8)
3.1519 -{
3.1520 - jit->write_ubyte(IA32_CMP_RM_IMM8);
3.1521 - jit->write_ubyte(ia32_modrm(mode, 7, rm));
3.1522 - jit->write_byte(imm8);
3.1523 -}
3.1524 -
3.1525 -inline void IA32_Cmp_Rm_Imm32(JitWriter *jit, jit_uint8_t mode, jit_uint8_t rm, jit_int32_t imm32)
3.1526 -{
3.1527 - jit->write_ubyte(IA32_CMP_RM_IMM32);
3.1528 - jit->write_ubyte(ia32_modrm(mode, 7, rm));
3.1529 - jit->write_int32(imm32);
3.1530 + jit->write_ubyte(IA32_PUSH_IMM8);
3.1531 + jit->write_byte(val);
3.1532 }
3.1533
3.1534 -inline void IA32_Cmp_Rm_Imm32_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp8, jit_int32_t imm32)
3.1535 -{
3.1536 - jit->write_ubyte(IA32_CMP_RM_IMM32);
3.1537 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 7, reg));
3.1538 - jit->write_byte(disp8);
3.1539 - jit->write_int32(imm32);
3.1540 -}
3.1541 -
3.1542 -inline void IA32_Cmp_Rm_Disp8_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp, jit_int8_t imm8)
3.1543 +inline void IA32_Push_Imm32(JitWriter *jit, jit_int32_t val)
3.1544 {
3.1545 - jit->write_ubyte(IA32_CMP_RM_IMM8);
3.1546 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 7, reg));
3.1547 - jit->write_byte(disp);
3.1548 - jit->write_byte(imm8);
3.1549 -}
3.1550 -
3.1551 -inline void IA32_Cmp_Al_Imm8(JitWriter *jit, jit_int8_t value)
3.1552 -{
3.1553 - jit->write_ubyte(IA32_CMP_AL_IMM32);
3.1554 - jit->write_byte(value);
3.1555 + jit->write_ubyte(IA32_PUSH_IMM32);
3.1556 + jit->write_int32(val);
3.1557 }
3.1558
3.1559 -inline void IA32_Cmp_Eax_Imm32(JitWriter *jit, jit_int32_t value)
3.1560 -{
3.1561 - jit->write_ubyte(IA32_CMP_EAX_IMM32);
3.1562 - jit->write_int32(value);
3.1563 -}
3.1564 -
3.1565 -inline void IA32_SetCC_Rm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t cond)
3.1566 +inline void IA32_Mov_Reg8_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
3.1567 {
3.1568 - jit->write_ubyte(IA32_SETCC_RM8_1);
3.1569 - jit->write_ubyte(IA32_SETCC_RM8_2+cond);
3.1570 - jit->write_ubyte(ia32_modrm(MOD_REG, 0, reg));
3.1571 -}
3.1572 -
3.1573 -inline void IA32_CmovCC_Rm(JitWriter *jit, jit_uint8_t src, jit_uint8_t cond)
3.1574 -{
3.1575 - jit->write_ubyte(IA32_CMOVCC_RM_1);
3.1576 - jit->write_ubyte(IA32_CMOVCC_RM_2+cond);
3.1577 - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src));
3.1578 -}
3.1579 -
3.1580 -inline void IA32_CmovCC_Rm_Disp8(JitWriter *jit, jit_uint8_t src, jit_uint8_t cond, jit_int8_t disp)
3.1581 -{
3.1582 - jit->write_ubyte(IA32_CMOVCC_RM_1);
3.1583 - jit->write_ubyte(IA32_CMOVCC_RM_2+cond);
3.1584 - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src));
3.1585 + jit->write_ubyte(IA32_MOV_REG8_RM8);
3.1586 + jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
3.1587 jit->write_byte(disp);
3.1588 }
3.1589
3.1590 -inline void IA32_Cmpsb(JitWriter *jit)
3.1591 -{
3.1592 - jit->write_ubyte(IA32_CMPSB);
3.1593 -}
3.1594 -
3.1595 -inline void IA32_Rep(JitWriter *jit)
3.1596 -{
3.1597 - jit->write_ubyte(IA32_REP);
3.1598 -}
3.1599 -
3.1600 -inline void IA32_Movsd(JitWriter *jit)
3.1601 +inline jitoffs_t IA32_Jump_Imm32(JitWriter *jit, jit_int32_t disp)
3.1602 {
3.1603 - jit->write_ubyte(IA32_MOVSD);
3.1604 -}
3.1605 -
3.1606 -inline void IA32_Movsb(JitWriter *jit)
3.1607 -{
3.1608 - jit->write_ubyte(IA32_MOVSB);
3.1609 -}
3.1610 -
3.1611 -inline void IA32_Stosd(JitWriter *jit)
3.1612 -{
3.1613 - jit->write_ubyte(IA32_STOSD);
3.1614 -}
3.1615 -
3.1616 -inline void IA32_Cld(JitWriter *jit)
3.1617 -{
3.1618 - jit->write_ubyte(IA32_CLD);
3.1619 + jitoffs_t ptr;
3.1620 + jit->write_ubyte(IA32_JMP_IMM32);
3.1621 + ptr = jit->get_outputpos();
3.1622 + jit->write_int32(disp);
3.1623 + return ptr;
3.1624 }
3.1625
3.1626 #endif //_INCLUDE_JIT_X86_MACROS_H
3.1627 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/public/sourcepawn/ke_allocator_policies.h Thu Aug 08 09:41:24 2013 -0700
4.3 @@ -0,0 +1,53 @@
4.4 +/* vim: set ts=2 sw=2 tw=99 et:
4.5 + *
4.6 + * Copyright (C) 2012 David Anderson
4.7 + *
4.8 + * This file is part of SourcePawn.
4.9 + *
4.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
4.11 + * the terms of the GNU General Public License as published by the Free
4.12 + * Software Foundation, either version 3 of the License, or (at your option)
4.13 + * any later version.
4.14 + *
4.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
4.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License along with
4.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
4.21 + */
4.22 +#ifndef _include_sourcepawn_allocatorpolicies_h_
4.23 +#define _include_sourcepawn_allocatorpolicies_h_
4.24 +
4.25 +#include <stdio.h>
4.26 +#include <stdlib.h>
4.27 +
4.28 +namespace ke {
4.29 +
4.30 +class SystemAllocatorPolicy
4.31 +{
4.32 + protected:
4.33 + void reportOutOfMemory() {
4.34 + fprintf(stderr, "OUT OF MEMORY\n");
4.35 + abort();
4.36 + }
4.37 + void reportAllocationOverflow() {
4.38 + fprintf(stderr, "OUT OF MEMORY\n");
4.39 + abort();
4.40 + }
4.41 +
4.42 + public:
4.43 + void free(void *memory) {
4.44 + ::free(memory);
4.45 + }
4.46 + void *malloc(size_t bytes) {
4.47 + void *ptr = ::malloc(bytes);
4.48 + if (!ptr)
4.49 + reportOutOfMemory();
4.50 + return ptr;
4.51 + }
4.52 +};
4.53 +
4.54 +}
4.55 +
4.56 +#endif // _include_sourcepawn_allocatorpolicies_h_
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/public/sourcepawn/ke_utility.h Thu Aug 08 09:41:24 2013 -0700
5.3 @@ -0,0 +1,318 @@
5.4 +/* vim: set ts=4 sw=4 tw=99 et:
5.5 + *
5.6 + * Copyright (C) 2012-2013 David Anderson
5.7 + *
5.8 + * This file is part of SourcePawn.
5.9 + *
5.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
5.11 + * the terms of the GNU General Public License as published by the Free
5.12 + * Software Foundation, either version 3 of the License, or (at your option)
5.13 + * any later version.
5.14 + *
5.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
5.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
5.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License along with
5.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
5.21 + */
5.22 +#ifndef _include_jitcraft_utility_h_
5.23 +#define _include_jitcraft_utility_h_
5.24 +
5.25 +#include <assert.h>
5.26 +#include <stddef.h>
5.27 +#include <stdlib.h>
5.28 +#if defined(_MSC_VER)
5.29 +# include <intrin.h>
5.30 +#endif
5.31 +
5.32 +#define KE_32BIT
5.33 +
5.34 +#if defined(_MSC_VER)
5.35 +# pragma warning(disable:4355)
5.36 +#endif
5.37 +
5.38 +namespace ke {
5.39 +
5.40 +static const size_t kMallocAlignment = sizeof(void *) * 2;
5.41 +
5.42 +typedef uint8_t uint8;
5.43 +typedef int32_t int32;
5.44 +typedef uint32_t uint32;
5.45 +typedef int64_t int64;
5.46 +typedef uint64_t uint64;
5.47 +
5.48 +typedef uint8 * Address;
5.49 +
5.50 +static const size_t kKB = 1024;
5.51 +static const size_t kMB = 1024 * kKB;
5.52 +static const size_t kGB = 1024 * kMB;
5.53 +
5.54 +template <typename T>
5.55 +class AutoFree
5.56 +{
5.57 + T *t_;
5.58 +
5.59 + public:
5.60 + AutoFree()
5.61 + : t_(NULL)
5.62 + {
5.63 + }
5.64 + AutoFree(T *t)
5.65 + : t_(t)
5.66 + {
5.67 + }
5.68 + ~AutoFree() {
5.69 + free(t_);
5.70 + }
5.71 + T *take() {
5.72 + T *t = t_;
5.73 + t_ = NULL;
5.74 + return t;
5.75 + }
5.76 + T *operator *() const {
5.77 + return t_;
5.78 + }
5.79 + void operator =(T *t) {
5.80 + if (t_)
5.81 + free(t_);
5.82 + t_ = t;
5.83 + }
5.84 +};
5.85 +
5.86 +// Bob Jenkin's one-at-a-time hash function[1].
5.87 +//
5.88 +// [1] http://burtleburtle.net/bob/hash/doobs.html
5.89 +class CharacterStreamHasher
5.90 +{
5.91 + uint32 hash;
5.92 +
5.93 + public:
5.94 + CharacterStreamHasher()
5.95 + : hash(0)
5.96 + { }
5.97 +
5.98 + void add(char c) {
5.99 + hash += c;
5.100 + hash += (hash << 10);
5.101 + hash ^= (hash >> 6);
5.102 + }
5.103 +
5.104 + void add(const char *s, size_t length) {
5.105 + for (size_t i = 0; i < length; i++)
5.106 + add(s[i]);
5.107 + }
5.108 +
5.109 + uint32 result() {
5.110 + hash += (hash << 3);
5.111 + hash ^= (hash >> 11);
5.112 + hash += (hash << 15);
5.113 + return hash;
5.114 + }
5.115 +};
5.116 +
5.117 +static inline uint32
5.118 +HashCharSequence(const char *s, size_t length)
5.119 +{
5.120 + CharacterStreamHasher hasher;
5.121 + hasher.add(s, length);
5.122 + return hasher.result();
5.123 +}
5.124 +
5.125 +// From http://burtleburtle.net/bob/hash/integer.html
5.126 +static inline uint32
5.127 +HashInt32(int32 a)
5.128 +{
5.129 + a = (a ^ 61) ^ (a >> 16);
5.130 + a = a + (a << 3);
5.131 + a = a ^ (a >> 4);
5.132 + a = a * 0x27d4eb2d;
5.133 + a = a ^ (a >> 15);
5.134 + return a;
5.135 +}
5.136 +
5.137 +// From http://www.cris.com/~Ttwang/tech/inthash.htm
5.138 +static inline uint32
5.139 +HashInt64(int64 key)
5.140 +{
5.141 + key = (~key) + (key << 18); // key = (key << 18) - key - 1;
5.142 + key = key ^ (uint64(key) >> 31);
5.143 + key = key * 21; // key = (key + (key << 2)) + (key << 4);
5.144 + key = key ^ (uint64(key) >> 11);
5.145 + key = key + (key << 6);
5.146 + key = key ^ (uint64(key) >> 22);
5.147 + return uint32(key);
5.148 +}
5.149 +
5.150 +static inline uint32
5.151 +HashPointer(void *p)
5.152 +{
5.153 +#if defined(KE_32BIT)
5.154 + return HashInt32(reinterpret_cast<int32>(p));
5.155 +#elif defined(KE_64BIT)
5.156 + return HashInt64(reinterpret_cast<int64>(p));
5.157 +#endif
5.158 +}
5.159 +
5.160 +static inline size_t
5.161 +Log2(size_t number)
5.162 +{
5.163 + assert(number != 0);
5.164 +
5.165 +#ifdef _MSC_VER
5.166 + unsigned long rval;
5.167 +# ifdef _M_IX86
5.168 + _BitScanReverse(&rval, number);
5.169 +# elif _M_X64
5.170 + _BitScanReverse64(&rval, number);
5.171 +# endif
5.172 + return rval;
5.173 +#else
5.174 + size_t bit;
5.175 + asm("bsr %1, %0\n"
5.176 + : "=r" (bit)
5.177 + : "rm" (number));
5.178 + return bit;
5.179 +#endif
5.180 +}
5.181 +
5.182 +static inline size_t
5.183 +FindRightmostBit(size_t number)
5.184 +{
5.185 + assert(number != 0);
5.186 +
5.187 +#ifdef _MSC_VER
5.188 + unsigned long rval;
5.189 +# ifdef _M_IX86
5.190 + _BitScanForward(&rval, number);
5.191 +# elif _M_X64
5.192 + _BitScanForward64(&rval, number);
5.193 +# endif
5.194 + return rval;
5.195 +#else
5.196 + size_t bit;
5.197 + asm("bsf %1, %0\n"
5.198 + : "=r" (bit)
5.199 + : "rm" (number));
5.200 + return bit;
5.201 +#endif
5.202 +}
5.203 +
5.204 +static inline bool
5.205 +IsPowerOfTwo(size_t value)
5.206 +{
5.207 + if (value == 0)
5.208 + return false;
5.209 + return !(value & (value - 1));
5.210 +}
5.211 +
5.212 +static inline size_t
5.213 +Align(size_t count, size_t alignment)
5.214 +{
5.215 + assert(IsPowerOfTwo(alignment));
5.216 + return count + (alignment - (count % alignment)) % alignment;
5.217 +}
5.218 +
5.219 +static inline bool
5.220 +IsUint32AddSafe(unsigned a, unsigned b)
5.221 +{
5.222 + if (!a || !b)
5.223 + return true;
5.224 + size_t log2_a = Log2(a);
5.225 + size_t log2_b = Log2(b);
5.226 + return (log2_a < sizeof(unsigned) * 8) &&
5.227 + (log2_b < sizeof(unsigned) * 8);
5.228 +}
5.229 +
5.230 +static inline bool
5.231 +IsUintPtrAddSafe(size_t a, size_t b)
5.232 +{
5.233 + if (!a || !b)
5.234 + return true;
5.235 + size_t log2_a = Log2(a);
5.236 + size_t log2_b = Log2(b);
5.237 + return (log2_a < sizeof(size_t) * 8) &&
5.238 + (log2_b < sizeof(size_t) * 8);
5.239 +}
5.240 +
5.241 +static inline bool
5.242 +IsUint32MultiplySafe(unsigned a, unsigned b)
5.243 +{
5.244 + if (a <= 1 || b <= 1)
5.245 + return true;
5.246 +
5.247 + size_t log2_a = Log2(a);
5.248 + size_t log2_b = Log2(b);
5.249 + return log2_a + log2_b <= sizeof(unsigned) * 8;
5.250 +}
5.251 +
5.252 +static inline bool
5.253 +IsUintPtrMultiplySafe(size_t a, size_t b)
5.254 +{
5.255 + if (a <= 1 || b <= 1)
5.256 + return true;
5.257 +
5.258 + size_t log2_a = Log2(a);
5.259 + size_t log2_b = Log2(b);
5.260 + return log2_a + log2_b <= sizeof(size_t) * 8;
5.261 +}
5.262 +
5.263 +#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
5.264 +#define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
5.265 +
5.266 +#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
5.267 +
5.268 +template <typename T>
5.269 +static inline bool
5.270 +IsAligned(T addr, size_t alignment)
5.271 +{
5.272 + assert(IsPowerOfTwo(alignment));
5.273 + return !(uintptr_t(addr) & (alignment - 1));
5.274 +}
5.275 +
5.276 +static inline Address
5.277 +AlignedBase(Address addr, size_t alignment)
5.278 +{
5.279 + assert(IsPowerOfTwo(alignment));
5.280 + return Address(uintptr_t(addr) & ~(alignment - 1));
5.281 +}
5.282 +
5.283 +template <typename T> static inline T
5.284 +Min(const T &t1, const T &t2)
5.285 +{
5.286 + return t1 < t2 ? t1 : t2;
5.287 +}
5.288 +
5.289 +template <typename T> static inline T
5.290 +Max(const T &t1, const T &t2)
5.291 +{
5.292 + return t1 > t2 ? t1 : t2;
5.293 +}
5.294 +
5.295 +template <typename T> T
5.296 +ReturnAndVoid(T &t)
5.297 +{
5.298 + T saved = t;
5.299 + t = T();
5.300 + return saved;
5.301 +}
5.302 +
5.303 +#define OFFSETOF(Class, Member) reinterpret_cast<size_t>(&((Class *)NULL)->Member)
5.304 +
5.305 +#if defined(_MSC_VER)
5.306 +# define KE_SIZET_FMT "%Iu"
5.307 +#elif defined(__GNUC__)
5.308 +# define KE_SIZET_FMT "%zu"
5.309 +#else
5.310 +# error "Implement format specifier string"
5.311 +#endif
5.312 +
5.313 +#if defined(__GNUC__)
5.314 +# define KE_CRITICAL_LIKELY(x) __builtin_expect(!!(x), 1)
5.315 +#else
5.316 +# define KE_CRITICAL_LIKELY(x) x
5.317 +#endif
5.318 +
5.319 +}
5.320 +
5.321 +#endif // _include_jitcraft_utility_h_
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/public/sourcepawn/ke_vector.h Thu Aug 08 09:41:24 2013 -0700
6.3 @@ -0,0 +1,166 @@
6.4 +/* vim: set ts=2 sw=2 tw=99 et:
6.5 + *
6.6 + * Copyright (C) 2012 David Anderson
6.7 + *
6.8 + * This file is part of SourcePawn.
6.9 + *
6.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
6.11 + * the terms of the GNU General Public License as published by the Free
6.12 + * Software Foundation, either version 3 of the License, or (at your option)
6.13 + * any later version.
6.14 + *
6.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
6.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License along with
6.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
6.21 + */
6.22 +#ifndef _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
6.23 +#define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
6.24 +
6.25 +#include <new>
6.26 +#include <stdlib.h>
6.27 +#include <ke_allocator_policies.h>
6.28 +#include <ke_utility.h>
6.29 +
6.30 +namespace ke {
6.31 +
6.32 +template <typename T, typename AllocPolicy = SystemAllocatorPolicy>
6.33 +class Vector : public AllocPolicy
6.34 +{
6.35 + public:
6.36 + Vector(AllocPolicy = AllocPolicy())
6.37 + : data(NULL),
6.38 + nitems(0),
6.39 + maxsize(0)
6.40 + {
6.41 + }
6.42 +
6.43 + ~Vector()
6.44 + {
6.45 + zap();
6.46 + }
6.47 +
6.48 + void steal(Vector &other) {
6.49 + zap();
6.50 + data = other.data;
6.51 + nitems = other.nitems;
6.52 + maxsize = other.maxsize;
6.53 + other.reset();
6.54 + }
6.55 +
6.56 + bool append(const T& item) {
6.57 + if (!growIfNeeded(1))
6.58 + return false;
6.59 + new (&data[nitems]) T(item);
6.60 + nitems++;
6.61 + return true;
6.62 + }
6.63 + void infallibleAppend(const T &item) {
6.64 + assert(growIfNeeded(1));
6.65 + new (&data[nitems]) T(item);
6.66 + nitems++;
6.67 + }
6.68 + T popCopy() {
6.69 + T t = at(length() - 1);
6.70 + pop();
6.71 + return t;
6.72 + }
6.73 + void pop() {
6.74 + assert(nitems);
6.75 + data[nitems - 1].~T();
6.76 + nitems--;
6.77 + }
6.78 + bool empty() const {
6.79 + return length() == 0;
6.80 + }
6.81 + size_t length() const {
6.82 + return nitems;
6.83 + }
6.84 + T& at(size_t i) {
6.85 + assert(i < length());
6.86 + return data[i];
6.87 + }
6.88 + const T& at(size_t i) const {
6.89 + assert(i < length());
6.90 + return data[i];
6.91 + }
6.92 + T& operator [](size_t i) {
6.93 + return at(i);
6.94 + }
6.95 + const T& operator [](size_t i) const {
6.96 + return at(i);
6.97 + }
6.98 + void clear() {
6.99 + nitems = 0;
6.100 + }
6.101 + const T &back() const {
6.102 + return at(length() - 1);
6.103 + }
6.104 + T &back() {
6.105 + return at(length() - 1);
6.106 + }
6.107 +
6.108 + T *buffer() const {
6.109 + return data;
6.110 + }
6.111 +
6.112 + bool ensure(size_t desired) {
6.113 + if (desired <= length())
6.114 + return true;
6.115 +
6.116 + return growIfNeeded(desired - length());
6.117 + }
6.118 +
6.119 + private:
6.120 + void zap() {
6.121 + for (size_t i = 0; i < nitems; i++)
6.122 + data[i].~T();
6.123 + this->free(data);
6.124 + }
6.125 + void reset() {
6.126 + data = NULL;
6.127 + nitems = 0;
6.128 + maxsize = 0;
6.129 + }
6.130 +
6.131 + bool growIfNeeded(size_t needed)
6.132 + {
6.133 + if (!IsUintPtrAddSafe(nitems, needed)) {
6.134 + this->reportAllocationOverflow();
6.135 + return false;
6.136 + }
6.137 + if (nitems + needed < maxsize)
6.138 + return true;
6.139 + if (maxsize == 0)
6.140 + maxsize = 8;
6.141 + while (nitems + needed > maxsize) {
6.142 + if (!IsUintPtrMultiplySafe(maxsize, 2)) {
6.143 + this->reportAllocationOverflow();
6.144 + return false;
6.145 + }
6.146 + maxsize *= 2;
6.147 + }
6.148 + T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
6.149 + if (newdata == NULL)
6.150 + return false;
6.151 + for (size_t i = 0; i < nitems; i++) {
6.152 + new (&newdata[i]) T(data[i]);
6.153 + data[i].~T();
6.154 + }
6.155 + this->free(data);
6.156 + data = newdata;
6.157 + return true;
6.158 + }
6.159 +
6.160 + private:
6.161 + T* data;
6.162 + size_t nitems;
6.163 + size_t maxsize;
6.164 +};
6.165 +
6.166 +}
6.167 +
6.168 +#endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */
6.169 +
7.1 --- a/public/sourcepawn/sp_vm_types.h Thu Aug 08 09:40:23 2013 -0700
7.2 +++ b/public/sourcepawn/sp_vm_types.h Thu Aug 08 09:41:24 2013 -0700
7.3 @@ -1,5 +1,5 @@
7.4 /**
7.5 - * vim: set ts=4 :
7.6 + * vim: set ts=4 sw=4 tw=99 noet:
7.7 * =============================================================================
7.8 * SourcePawn
7.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
7.10 @@ -85,6 +85,8 @@
7.11 #define SP_ERROR_ABORTED 25 /**< Function call was aborted */
7.12 #define SP_ERROR_CODE_TOO_OLD 26 /**< Code is too old for this VM */
7.13 #define SP_ERROR_CODE_TOO_NEW 27 /**< Code is too new for this VM */
7.14 +#define SP_ERROR_OUT_OF_MEMORY 28 /**< Out of memory */
7.15 +#define SP_ERROR_INTEGER_OVERFLOW 29 /**< Integer overflow (-INT_MIN / -1) */
7.16 //Hey you! Update the string table if you add to the end of me! */
7.17
7.18 /**********************************************
8.1 --- a/sourcepawn/jit/AMBuilder Thu Aug 08 09:40:23 2013 -0700
8.2 +++ b/sourcepawn/jit/AMBuilder Thu Aug 08 09:41:24 2013 -0700
8.3 @@ -22,8 +22,8 @@
8.4 'sp_vm_basecontext.cpp',
8.5 'sp_vm_engine.cpp',
8.6 'sp_vm_function.cpp',
8.7 + 'opcodes.cpp',
8.8 'x86/jit_x86.cpp',
8.9 - 'x86/opcode_helpers.cpp',
8.10 'zlib/adler32.c',
8.11 'zlib/compress.c',
8.12 'zlib/crc32.c',
9.1 --- a/sourcepawn/jit/BaseRuntime.cpp Thu Aug 08 09:40:23 2013 -0700
9.2 +++ b/sourcepawn/jit/BaseRuntime.cpp Thu Aug 08 09:41:24 2013 -0700
9.3 @@ -1,3 +1,4 @@
9.4 +// vim: set ts=8 sts=2 sw=2 tw=99 et:
9.5 #include <stdio.h>
9.6 #include <stdlib.h>
9.7 #include <string.h>
9.8 @@ -12,573 +13,571 @@
9.9
9.10 using namespace SourcePawn;
9.11
9.12 -BaseRuntime::BaseRuntime() : m_Debug(&m_plugin), m_pPlugin(&m_plugin), m_pCtx(NULL),
9.13 -m_PubFuncs(NULL), m_PubJitFuncs(NULL), m_pCo(NULL), m_CompSerial(0)
9.14 +static inline bool
9.15 +IsPointerCellAligned(void *p)
9.16 {
9.17 - memset(&m_plugin, 0, sizeof(m_plugin));
9.18 + return uintptr_t(p) % 4 == 0;
9.19 +}
9.20
9.21 - m_FuncCache = NULL;
9.22 - m_MaxFuncs = 0;
9.23 - m_NumFuncs = 0;
9.24 -
9.25 - memset(m_CodeHash, 0, sizeof(m_CodeHash));
9.26 - memset(m_DataHash, 0, sizeof(m_DataHash));
9.27 +BaseRuntime::BaseRuntime()
9.28 + : m_Debug(&m_plugin),
9.29 + m_pCtx(NULL),
9.30 + m_PubFuncs(NULL),
9.31 + m_PubJitFuncs(NULL),
9.32 + co_(NULL),
9.33 + m_CompSerial(0)
9.34 +{
9.35 + memset(&m_plugin, 0, sizeof(m_plugin));
9.36 +
9.37 + m_MaxFuncs = 0;
9.38 + m_NumFuncs = 0;
9.39 + float_table_ = NULL;
9.40 + function_map_ = NULL;
9.41 + alt_pcode_ = NULL;
9.42 +
9.43 + memset(m_CodeHash, 0, sizeof(m_CodeHash));
9.44 + memset(m_DataHash, 0, sizeof(m_DataHash));
9.45 }
9.46
9.47 BaseRuntime::~BaseRuntime()
9.48 {
9.49 - for (uint32_t i = 0; i < m_pPlugin->num_publics; i++)
9.50 - {
9.51 - delete m_PubFuncs[i];
9.52 - m_PubFuncs[i] = NULL;
9.53 - }
9.54 - delete [] m_PubFuncs;
9.55 - delete [] m_PubJitFuncs;
9.56 + for (uint32_t i = 0; i < m_plugin.num_publics; i++)
9.57 + delete m_PubFuncs[i];
9.58 + delete [] m_PubFuncs;
9.59 + delete [] m_PubJitFuncs;
9.60 + delete [] float_table_;
9.61 + delete [] function_map_;
9.62 + delete [] alt_pcode_;
9.63 +
9.64 + for (size_t i = 0; i < m_JitFunctions.length(); i++)
9.65 + delete m_JitFunctions[i];
9.66 +
9.67 + delete m_pCtx;
9.68 + if (co_)
9.69 + co_->Abort();
9.70 +
9.71 + free(m_plugin.base);
9.72 + delete [] m_plugin.memory;
9.73 + delete [] m_plugin.publics;
9.74 + delete [] m_plugin.pubvars;
9.75 + delete [] m_plugin.natives;
9.76 + free(m_plugin.name);
9.77 +}
9.78
9.79 - for (unsigned int i = 0; i < m_NumFuncs; i++)
9.80 - {
9.81 - delete m_FuncCache[i];
9.82 - }
9.83 - free(m_FuncCache);
9.84 +void
9.85 +BaseRuntime::SetupFloatNativeRemapping()
9.86 +{
9.87 + float_table_ = new floattbl_t[m_plugin.num_natives];
9.88 + for (size_t i = 0; i < m_plugin.num_natives; i++) {
9.89 + const char *name = m_plugin.natives[i].name;
9.90 + if (!strcmp(name, "FloatAbs")) {
9.91 + float_table_[i].found = true;
9.92 + float_table_[i].index = OP_FABS;
9.93 + } else if (!strcmp(name, "FloatAdd")) {
9.94 + float_table_[i].found = true;
9.95 + float_table_[i].index = OP_FLOATADD;
9.96 + } else if (!strcmp(name, "FloatSub")) {
9.97 + float_table_[i].found = true;
9.98 + float_table_[i].index = OP_FLOATSUB;
9.99 + } else if (!strcmp(name, "FloatMul")) {
9.100 + float_table_[i].found = true;
9.101 + float_table_[i].index = OP_FLOATMUL;
9.102 + } else if (!strcmp(name, "FloatDiv")) {
9.103 + float_table_[i].found = true;
9.104 + float_table_[i].index = OP_FLOATDIV;
9.105 + } else if (!strcmp(name, "float")) {
9.106 + float_table_[i].found = true;
9.107 + float_table_[i].index = OP_FLOAT;
9.108 + } else if (!strcmp(name, "FloatCompare")) {
9.109 + float_table_[i].found = true;
9.110 + float_table_[i].index = OP_FLOATCMP;
9.111 + } else if (!strcmp(name, "RoundToZero")) {
9.112 + float_table_[i].found = true;
9.113 + float_table_[i].index = OP_RND_TO_ZERO;
9.114 + } else if (!strcmp(name, "RoundToCeil")) {
9.115 + float_table_[i].found = true;
9.116 + float_table_[i].index = OP_RND_TO_CEIL;
9.117 + } else if (!strcmp(name, "RoundToFloor")) {
9.118 + float_table_[i].found = true;
9.119 + float_table_[i].index = OP_RND_TO_FLOOR;
9.120 + } else if (!strcmp(name, "RoundToNearest")) {
9.121 + float_table_[i].found = true;
9.122 + float_table_[i].index = OP_RND_TO_NEAREST;
9.123 + }
9.124 + }
9.125 +}
9.126
9.127 - delete m_pCtx;
9.128 - if (m_pCo != NULL)
9.129 - {
9.130 - m_pCo->Abort();
9.131 - }
9.132 +unsigned
9.133 +BaseRuntime::GetNativeReplacement(size_t index)
9.134 +{
9.135 + if (!float_table_[index].found)
9.136 + return OP_NOP;
9.137 + return float_table_[index].index;
9.138 +}
9.139
9.140 - free(m_pPlugin->base);
9.141 - delete [] m_pPlugin->memory;
9.142 - delete [] m_pPlugin->publics;
9.143 - delete [] m_pPlugin->pubvars;
9.144 - delete [] m_pPlugin->natives;
9.145 - free(m_pPlugin->name);
9.146 +void
9.147 +BaseRuntime::SetName(const char *name)
9.148 +{
9.149 + m_plugin.name = strdup(name);
9.150 }
9.151
9.152 static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
9.153 {
9.154 - return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
9.155 + return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
9.156 }
9.157
9.158 int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
9.159 {
9.160 - int set_err;
9.161 - char *nameptr;
9.162 - uint8_t sectnum = 0;
9.163 - sp_plugin_t *plugin = m_pPlugin;
9.164 - sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
9.165 + char *nameptr;
9.166 + uint8_t sectnum = 0;
9.167 + sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
9.168
9.169 - memset(plugin, 0, sizeof(sp_plugin_t));
9.170 + memset(&m_plugin, 0, sizeof(m_plugin));
9.171
9.172 - plugin->base = base;
9.173 - plugin->base_size = hdr->imagesize;
9.174 - set_err = SP_ERROR_NONE;
9.175 + m_plugin.base = base;
9.176 + m_plugin.base_size = hdr->imagesize;
9.177
9.178 - if (hdr->version == 0x0101)
9.179 - {
9.180 - plugin->debug.unpacked = true;
9.181 - }
9.182 + if (hdr->version == 0x0101)
9.183 + m_plugin.debug.unpacked = true;
9.184
9.185 - /* We have to read the name section first */
9.186 - for (sectnum = 0; sectnum < hdr->sections; sectnum++)
9.187 - {
9.188 - nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
9.189 - if (strcmp(nameptr, ".names") == 0)
9.190 - {
9.191 - plugin->stringbase = (const char *)(base + secptr[sectnum].dataoffs);
9.192 - break;
9.193 - }
9.194 - }
9.195 + /* We have to read the name section first */
9.196 + for (sectnum = 0; sectnum < hdr->sections; sectnum++) {
9.197 + nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
9.198 + if (strcmp(nameptr, ".names") == 0) {
9.199 + m_plugin.stringbase = (const char *)(base + secptr[sectnum].dataoffs);
9.200 + break;
9.201 + }
9.202 + }
9.203 +
9.204 + sectnum = 0;
9.205
9.206 - sectnum = 0;
9.207 + /* Now read the rest of the sections */
9.208 + while (sectnum < hdr->sections) {
9.209 + nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
9.210
9.211 - /* Now read the rest of the sections */
9.212 - while (sectnum < hdr->sections)
9.213 - {
9.214 - nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
9.215 + if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
9.216 + sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
9.217
9.218 - if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
9.219 - {
9.220 - sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
9.221 + if (cod->codeversion < SP_CODEVERS_JIT1)
9.222 + return SP_ERROR_CODE_TOO_OLD;
9.223 + if (cod->codeversion > SP_CODEVERS_JIT2)
9.224 + return SP_ERROR_CODE_TOO_NEW;
9.225
9.226 - if (cod->codeversion < SP_CODEVERS_JIT1)
9.227 - {
9.228 - return SP_ERROR_CODE_TOO_OLD;
9.229 - }
9.230 - else if (cod->codeversion > SP_CODEVERS_JIT2)
9.231 - {
9.232 - return SP_ERROR_CODE_TOO_NEW;
9.233 - }
9.234 + m_plugin.pcode = base + secptr->dataoffs + cod->code;
9.235 + m_plugin.pcode_size = cod->codesize;
9.236 + m_plugin.flags = cod->flags;
9.237 + m_plugin.pcode_version = cod->codeversion;
9.238 + if (!IsPointerCellAligned(m_plugin.pcode)) {
9.239 + // The JIT requires that pcode is cell-aligned, so if it's not, we
9.240 + // remap the code segment to a new address.
9.241 + alt_pcode_ = new uint8_t[m_plugin.pcode_size];
9.242 + memcpy(alt_pcode_, m_plugin.pcode, m_plugin.pcode_size);
9.243 + assert(IsPointerCellAligned(alt_pcode_));
9.244
9.245 - plugin->pcode = base + secptr->dataoffs + cod->code;
9.246 - plugin->pcode_size = cod->codesize;
9.247 - plugin->flags = cod->flags;
9.248 - plugin->pcode_version = cod->codeversion;
9.249 - }
9.250 - else if (!(plugin->data) && !strcmp(nameptr, ".data"))
9.251 - {
9.252 - sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
9.253 - plugin->data = base + secptr->dataoffs + dat->data;
9.254 - plugin->data_size = dat->datasize;
9.255 - plugin->mem_size = dat->memsize;
9.256 - plugin->memory = new uint8_t[plugin->mem_size];
9.257 - memcpy(plugin->memory, plugin->data, plugin->data_size);
9.258 - }
9.259 - else if ((plugin->publics == NULL) && !strcmp(nameptr, ".publics"))
9.260 - {
9.261 - sp_file_publics_t *publics;
9.262 + m_plugin.pcode = alt_pcode_;
9.263 + }
9.264 + } else if (!(m_plugin.data) && !strcmp(nameptr, ".data")) {
9.265 + sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
9.266 + m_plugin.data = base + secptr->dataoffs + dat->data;
9.267 + m_plugin.data_size = dat->datasize;
9.268 + m_plugin.mem_size = dat->memsize;
9.269 + m_plugin.memory = new uint8_t[m_plugin.mem_size];
9.270 + memcpy(m_plugin.memory, m_plugin.data, m_plugin.data_size);
9.271 + } else if ((m_plugin.publics == NULL) && !strcmp(nameptr, ".publics")) {
9.272 + sp_file_publics_t *publics;
9.273
9.274 - publics = (sp_file_publics_t *)(base + secptr->dataoffs);
9.275 - plugin->num_publics = secptr->size / sizeof(sp_file_publics_t);
9.276 + publics = (sp_file_publics_t *)(base + secptr->dataoffs);
9.277 + m_plugin.num_publics = secptr->size / sizeof(sp_file_publics_t);
9.278
9.279 - if (plugin->num_publics > 0)
9.280 - {
9.281 - plugin->publics = new sp_public_t[plugin->num_publics];
9.282 + if (m_plugin.num_publics > 0) {
9.283 + m_plugin.publics = new sp_public_t[m_plugin.num_publics];
9.284
9.285 - for (uint32_t i = 0; i < plugin->num_publics; i++)
9.286 - {
9.287 - plugin->publics[i].code_offs = publics[i].address;
9.288 - plugin->publics[i].funcid = (i << 1) | 1;
9.289 - plugin->publics[i].name = plugin->stringbase + publics[i].name;
9.290 - }
9.291 - }
9.292 - }
9.293 - else if ((plugin->pubvars == NULL) && !strcmp(nameptr, ".pubvars"))
9.294 - {
9.295 - sp_file_pubvars_t *pubvars;
9.296 + for (uint32_t i = 0; i < m_plugin.num_publics; i++) {
9.297 + m_plugin.publics[i].code_offs = publics[i].address;
9.298 + m_plugin.publics[i].funcid = (i << 1) | 1;
9.299 + m_plugin.publics[i].name = m_plugin.stringbase + publics[i].name;
9.300 + }
9.301 + }
9.302 + } else if ((m_plugin.pubvars == NULL) && !strcmp(nameptr, ".pubvars")) {
9.303 + sp_file_pubvars_t *pubvars;
9.304
9.305 - pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
9.306 - plugin->num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
9.307 + pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
9.308 + m_plugin.num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
9.309
9.310 - if (plugin->num_pubvars > 0)
9.311 - {
9.312 - plugin->pubvars = new sp_pubvar_t[plugin->num_pubvars];
9.313 + if (m_plugin.num_pubvars > 0) {
9.314 + m_plugin.pubvars = new sp_pubvar_t[m_plugin.num_pubvars];
9.315
9.316 - for (uint32_t i = 0; i < plugin->num_pubvars; i++)
9.317 - {
9.318 - plugin->pubvars[i].name = plugin->stringbase + pubvars[i].name;
9.319 - plugin->pubvars[i].offs = (cell_t *)(plugin->memory + pubvars[i].address);
9.320 - }
9.321 - }
9.322 - }
9.323 - else if ((plugin->natives == NULL) && !strcmp(nameptr, ".natives"))
9.324 - {
9.325 - sp_file_natives_t *natives;
9.326 + for (uint32_t i = 0; i < m_plugin.num_pubvars; i++) {
9.327 + m_plugin.pubvars[i].name = m_plugin.stringbase + pubvars[i].name;
9.328 + m_plugin.pubvars[i].offs = (cell_t *)(m_plugin.memory + pubvars[i].address);
9.329 + }
9.330 + }
9.331 + } else if ((m_plugin.natives == NULL) && !strcmp(nameptr, ".natives")) {
9.332 + sp_file_natives_t *natives;
9.333 +
9.334 + natives = (sp_file_natives_t *)(base + secptr->dataoffs);
9.335 + m_plugin.num_natives = secptr->size / sizeof(sp_file_natives_t);
9.336 +
9.337 + if (m_plugin.num_natives > 0) {
9.338 + m_plugin.natives = new sp_native_t[m_plugin.num_natives];
9.339
9.340 - natives = (sp_file_natives_t *)(base + secptr->dataoffs);
9.341 - plugin->num_natives = secptr->size / sizeof(sp_file_natives_t);
9.342 -
9.343 - if (plugin->num_natives > 0)
9.344 - {
9.345 - plugin->natives = new sp_native_t[plugin->num_natives];
9.346 + for (uint32_t i = 0; i < m_plugin.num_natives; i++) {
9.347 + m_plugin.natives[i].flags = 0;
9.348 + m_plugin.natives[i].pfn = InvalidNative;
9.349 + m_plugin.natives[i].status = SP_NATIVE_UNBOUND;
9.350 + m_plugin.natives[i].user = NULL;
9.351 + m_plugin.natives[i].name = m_plugin.stringbase + natives[i].name;
9.352 + }
9.353 + }
9.354 + } else if (!(m_plugin.debug.files) && !strcmp(nameptr, ".dbg.files")) {
9.355 + m_plugin.debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
9.356 + } else if (!(m_plugin.debug.lines) && !strcmp(nameptr, ".dbg.lines")) {
9.357 + m_plugin.debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
9.358 + } else if (!(m_plugin.debug.symbols) && !strcmp(nameptr, ".dbg.symbols")) {
9.359 + m_plugin.debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
9.360 + } else if (!(m_plugin.debug.lines_num) && !strcmp(nameptr, ".dbg.info")) {
9.361 + sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
9.362 + m_plugin.debug.files_num = inf->num_files;
9.363 + m_plugin.debug.lines_num = inf->num_lines;
9.364 + m_plugin.debug.syms_num = inf->num_syms;
9.365 + } else if (!(m_plugin.debug.stringbase) && !strcmp(nameptr, ".dbg.strings")) {
9.366 + m_plugin.debug.stringbase = (const char *)(base + secptr->dataoffs);
9.367 + } else if (strcmp(nameptr, ".dbg.natives") == 0) {
9.368 + m_plugin.debug.unpacked = false;
9.369 + }
9.370
9.371 - for (uint32_t i = 0; i < plugin->num_natives; i++)
9.372 - {
9.373 - plugin->natives[i].flags = 0;
9.374 - plugin->natives[i].pfn = InvalidNative;
9.375 - plugin->natives[i].status = SP_NATIVE_UNBOUND;
9.376 - plugin->natives[i].user = NULL;
9.377 - plugin->natives[i].name = plugin->stringbase + natives[i].name;
9.378 - }
9.379 - }
9.380 - }
9.381 - else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
9.382 - {
9.383 - plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
9.384 - }
9.385 - else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
9.386 - {
9.387 - plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
9.388 - }
9.389 - else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
9.390 - {
9.391 - plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
9.392 - }
9.393 - else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
9.394 - {
9.395 - sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
9.396 - plugin->debug.files_num = inf->num_files;
9.397 - plugin->debug.lines_num = inf->num_lines;
9.398 - plugin->debug.syms_num = inf->num_syms;
9.399 - }
9.400 - else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
9.401 - {
9.402 - plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
9.403 - }
9.404 - else if (strcmp(nameptr, ".dbg.natives") == 0)
9.405 - {
9.406 - plugin->debug.unpacked = false;
9.407 - }
9.408 + secptr++;
9.409 + sectnum++;
9.410 + }
9.411 +
9.412 + if (m_plugin.pcode == NULL || m_plugin.data == NULL)
9.413 + return SP_ERROR_FILE_FORMAT;
9.414 +
9.415 + if ((m_plugin.flags & SP_FLAG_DEBUG) && (
9.416 + !(m_plugin.debug.files) ||
9.417 + !(m_plugin.debug.lines) ||
9.418 + !(m_plugin.debug.symbols) ||
9.419 + !(m_plugin.debug.stringbase) ))
9.420 + {
9.421 + return SP_ERROR_FILE_FORMAT;
9.422 + }
9.423
9.424 - secptr++;
9.425 - sectnum++;
9.426 - }
9.427 -
9.428 - if (plugin->pcode == NULL || plugin->data == NULL)
9.429 - {
9.430 - return SP_ERROR_FILE_FORMAT;
9.431 - }
9.432 -
9.433 - if ((plugin->flags & SP_FLAG_DEBUG) && (
9.434 - !(plugin->debug.files) ||
9.435 - !(plugin->debug.lines) ||
9.436 - !(plugin->debug.symbols) ||
9.437 - !(plugin->debug.stringbase) ))
9.438 - {
9.439 - return SP_ERROR_FILE_FORMAT;
9.440 - }
9.441 + if (m_plugin.num_publics > 0) {
9.442 + m_PubFuncs = new CFunction *[m_plugin.num_publics];
9.443 + memset(m_PubFuncs, 0, sizeof(CFunction *) * m_plugin.num_publics);
9.444 + m_PubJitFuncs = new JitFunction *[m_plugin.num_publics];
9.445 + memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_plugin.num_publics);
9.446 + }
9.447
9.448 - if (m_pPlugin->num_publics > 0)
9.449 - {
9.450 - m_PubFuncs = new CFunction *[m_pPlugin->num_publics];
9.451 - memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->num_publics);
9.452 - m_PubJitFuncs = new JitFunction *[m_pPlugin->num_publics];
9.453 - memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_pPlugin->num_publics);
9.454 - }
9.455 + MD5 md5_pcode;
9.456 + md5_pcode.update(m_plugin.pcode, m_plugin.pcode_size);
9.457 + md5_pcode.finalize();
9.458 + md5_pcode.raw_digest(m_CodeHash);
9.459 +
9.460 + MD5 md5_data;
9.461 + md5_data.update(m_plugin.data, m_plugin.data_size);
9.462 + md5_data.finalize();
9.463 + md5_data.raw_digest(m_DataHash);
9.464
9.465 - MD5 md5_pcode;
9.466 - md5_pcode.update(plugin->pcode, plugin->pcode_size);
9.467 - md5_pcode.finalize();
9.468 - md5_pcode.raw_digest(m_CodeHash);
9.469 -
9.470 - MD5 md5_data;
9.471 - md5_data.update(plugin->data, plugin->data_size);
9.472 - md5_data.finalize();
9.473 - md5_data.raw_digest(m_DataHash);
9.474 + m_plugin.profiler = g_engine2.GetProfiler();
9.475 + m_pCtx = new BaseContext(this);
9.476 + co_ = g_Jit.StartCompilation(this);
9.477
9.478 - m_pPlugin->profiler = g_engine2.GetProfiler();
9.479 - m_pCtx = new BaseContext(this);
9.480 - m_pCo = g_Jit.StartCompilation(this);
9.481 + SetupFloatNativeRemapping();
9.482 + function_map_size_ = m_plugin.pcode_size / sizeof(cell_t) + 1;
9.483 + function_map_ = new JitFunction *[function_map_size_];
9.484 + memset(function_map_, 0, function_map_size_ * sizeof(JitFunction *));
9.485
9.486 - return SP_ERROR_NONE;
9.487 + return SP_ERROR_NONE;
9.488 }
9.489
9.490 -int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
9.491 +void
9.492 +BaseRuntime::AddJittedFunction(JitFunction *fn)
9.493 {
9.494 - int high;
9.495 + m_JitFunctions.append(fn);
9.496
9.497 - high = m_pPlugin->num_natives - 1;
9.498 + cell_t pcode_offset = fn->GetPCodeAddress();
9.499 + assert(pcode_offset % 4 == 0);
9.500 +
9.501 + uint32_t pcode_index = pcode_offset / 4;
9.502 + assert(pcode_index < function_map_size_);
9.503
9.504 - for (uint32_t i=0; i<m_pPlugin->num_natives; i++)
9.505 - {
9.506 - if (strcmp(m_pPlugin->natives[i].name, name) == 0)
9.507 - {
9.508 - if (index)
9.509 - {
9.510 - *index = i;
9.511 - }
9.512 - return SP_ERROR_NONE;
9.513 - }
9.514 - }
9.515 + function_map_[pcode_index] = fn;
9.516 +}
9.517
9.518 - return SP_ERROR_NOT_FOUND;
9.519 +JitFunction *
9.520 +BaseRuntime::GetJittedFunctionByOffset(cell_t pcode_offset)
9.521 +{
9.522 + assert(pcode_offset % 4 == 0);
9.523 +
9.524 + uint32_t pcode_index = pcode_offset / 4;
9.525 + assert(pcode_index < function_map_size_);
9.526 +
9.527 + return function_map_[pcode_index];
9.528 }
9.529
9.530 -int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
9.531 +int
9.532 +BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
9.533 {
9.534 - if (index >= m_pPlugin->num_natives)
9.535 - {
9.536 - return SP_ERROR_INDEX;
9.537 - }
9.538 + for (uint32_t i=0; i<m_plugin.num_natives; i++) {
9.539 + if (strcmp(m_plugin.natives[i].name, name) == 0) {
9.540 + if (index)
9.541 + *index = i;
9.542 + return SP_ERROR_NONE;
9.543 + }
9.544 + }
9.545
9.546 - if (native)
9.547 - {
9.548 - *native = &(m_pPlugin->natives[index]);
9.549 - }
9.550 + return SP_ERROR_NOT_FOUND;
9.551 +}
9.552
9.553 - return SP_ERROR_NONE;
9.554 +int
9.555 +BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
9.556 +{
9.557 + if (index >= m_plugin.num_natives)
9.558 + return SP_ERROR_INDEX;
9.559 +
9.560 + if (native)
9.561 + *native = &(m_plugin.natives[index]);
9.562 +
9.563 + return SP_ERROR_NONE;
9.564 }
9.565
9.566
9.567 -uint32_t BaseRuntime::GetNativesNum()
9.568 -{
9.569 - return m_pPlugin->num_natives;
9.570 -}
9.571 -
9.572 -int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
9.573 +uint32_t
9.574 +BaseRuntime::GetNativesNum()
9.575 {
9.576 - int diff, high, low;
9.577 - uint32_t mid;
9.578 -
9.579 - high = m_pPlugin->num_publics - 1;
9.580 - low = 0;
9.581 -
9.582 - while (low <= high)
9.583 - {
9.584 - mid = (low + high) / 2;
9.585 - diff = strcmp(m_pPlugin->publics[mid].name, name);
9.586 - if (diff == 0)
9.587 - {
9.588 - if (index)
9.589 - {
9.590 - *index = mid;
9.591 - }
9.592 - return SP_ERROR_NONE;
9.593 - } else if (diff < 0) {
9.594 - low = mid + 1;
9.595 - } else {
9.596 - high = mid - 1;
9.597 - }
9.598 - }
9.599 -
9.600 - return SP_ERROR_NOT_FOUND;
9.601 + return m_plugin.num_natives;
9.602 }
9.603
9.604 -int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
9.605 +int
9.606 +BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
9.607 {
9.608 - if (index >= m_pPlugin->num_publics)
9.609 - {
9.610 - return SP_ERROR_INDEX;
9.611 - }
9.612 + int diff, high, low;
9.613 + uint32_t mid;
9.614 +
9.615 + high = m_plugin.num_publics - 1;
9.616 + low = 0;
9.617
9.618 - if (pblic)
9.619 - {
9.620 - *pblic = &(m_pPlugin->publics[index]);
9.621 - }
9.622 + while (low <= high) {
9.623 + mid = (low + high) / 2;
9.624 + diff = strcmp(m_plugin.publics[mid].name, name);
9.625 + if (diff == 0) {
9.626 + if (index)
9.627 + *index = mid;
9.628 + return SP_ERROR_NONE;
9.629 + } else if (diff < 0) {
9.630 + low = mid + 1;
9.631 + } else {
9.632 + high = mid - 1;
9.633 + }
9.634 + }
9.635
9.636 - return SP_ERROR_NONE;
9.637 + return SP_ERROR_NOT_FOUND;
9.638 }
9.639
9.640 -uint32_t BaseRuntime::GetPublicsNum()
9.641 +int
9.642 +BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
9.643 {
9.644 - return m_pPlugin->num_publics;
9.645 + if (index >= m_plugin.num_publics)
9.646 + return SP_ERROR_INDEX;
9.647 +
9.648 + if (pblic)
9.649 + *pblic = &(m_plugin.publics[index]);
9.650 +
9.651 + return SP_ERROR_NONE;
9.652 }
9.653
9.654 -int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
9.655 +uint32_t
9.656 +BaseRuntime::GetPublicsNum()
9.657 {
9.658 - if (index >= m_pPlugin->num_pubvars)
9.659 - {
9.660 - return SP_ERROR_INDEX;
9.661 - }
9.662 + return m_plugin.num_publics;
9.663 +}
9.664
9.665 - if (pubvar)
9.666 - {
9.667 - *pubvar = &(m_pPlugin->pubvars[index]);
9.668 - }
9.669 +int
9.670 +BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
9.671 +{
9.672 + if (index >= m_plugin.num_pubvars)
9.673 + return SP_ERROR_INDEX;
9.674
9.675 - return SP_ERROR_NONE;
9.676 + if (pubvar)
9.677 + *pubvar = &(m_plugin.pubvars[index]);
9.678 +
9.679 + return SP_ERROR_NONE;
9.680 }
9.681
9.682 -int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
9.683 +int
9.684 +BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
9.685 {
9.686 - int diff, high, low;
9.687 - uint32_t mid;
9.688 + int diff, high, low;
9.689 + uint32_t mid;
9.690
9.691 - high = m_pPlugin->num_pubvars - 1;
9.692 - low = 0;
9.693 + high = m_plugin.num_pubvars - 1;
9.694 + low = 0;
9.695
9.696 - while (low <= high)
9.697 - {
9.698 - mid = (low + high) / 2;
9.699 - diff = strcmp(m_pPlugin->pubvars[mid].name, name);
9.700 - if (diff == 0)
9.701 - {
9.702 - if (index)
9.703 - {
9.704 - *index = mid;
9.705 - }
9.706 - return SP_ERROR_NONE;
9.707 - }
9.708 - else if (diff < 0)
9.709 - {
9.710 - low = mid + 1;
9.711 - }
9.712 - else
9.713 - {
9.714 - high = mid - 1;
9.715 - }
9.716 - }
9.717 + while (low <= high) {
9.718 + mid = (low + high) / 2;
9.719 + diff = strcmp(m_plugin.pubvars[mid].name, name);
9.720 + if (diff == 0) {
9.721 + if (index)
9.722 + *index = mid;
9.723 + return SP_ERROR_NONE;
9.724 + } else if (diff < 0) {
9.725 + low = mid + 1;
9.726 + } else {
9.727 + high = mid - 1;
9.728 + }
9.729 + }
9.730
9.731 - return SP_ERROR_NOT_FOUND;
9.732 + return SP_ERROR_NOT_FOUND;
9.733 }
9.734
9.735 -int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
9.736 +int
9.737 +BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
9.738 {
9.739 - if (index >= m_pPlugin->num_pubvars)
9.740 - {
9.741 - return SP_ERROR_INDEX;
9.742 - }
9.743 + if (index >= m_plugin.num_pubvars)
9.744 + return SP_ERROR_INDEX;
9.745
9.746 - *local_addr = (uint8_t *)m_pPlugin->pubvars[index].offs - m_pPlugin->memory;
9.747 - *phys_addr = m_pPlugin->pubvars[index].offs;
9.748 + *local_addr = (uint8_t *)m_plugin.pubvars[index].offs - m_plugin.memory;
9.749 + *phys_addr = m_plugin.pubvars[index].offs;
9.750
9.751 - return SP_ERROR_NONE;
9.752 + return SP_ERROR_NONE;
9.753 }
9.754
9.755 -uint32_t BaseRuntime::GetPubVarsNum()
9.756 +uint32_t
9.757 +BaseRuntime::GetPubVarsNum()
9.758 {
9.759 - return m_pPlugin->num_pubvars;
9.760 + return m_plugin.num_pubvars;
9.761 }
9.762
9.763 -IPluginContext *BaseRuntime::GetDefaultContext()
9.764 +IPluginContext *
9.765 +BaseRuntime::GetDefaultContext()
9.766 {
9.767 - return m_pCtx;
9.768 + return m_pCtx;
9.769 }
9.770
9.771 -IPluginDebugInfo *BaseRuntime::GetDebugInfo()
9.772 +IPluginDebugInfo *
9.773 +BaseRuntime::GetDebugInfo()
9.774 {
9.775 - return &m_Debug;
9.776 + return &m_Debug;
9.777 }
9.778
9.779 -IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
9.780 +IPluginFunction *
9.781 +BaseRuntime::GetFunctionById(funcid_t func_id)
9.782 {
9.783 - CFunction *pFunc = NULL;
9.784 + CFunction *pFunc = NULL;
9.785
9.786 - if (func_id & 1)
9.787 - {
9.788 - func_id >>= 1;
9.789 - if (func_id >= m_pPlugin->num_publics)
9.790 - {
9.791 - return NULL;
9.792 - }
9.793 - pFunc = m_PubFuncs[func_id];
9.794 - if (!pFunc)
9.795 - {
9.796 - m_PubFuncs[func_id] = new CFunction(this,
9.797 - (func_id << 1) | 1,
9.798 - func_id);
9.799 - pFunc = m_PubFuncs[func_id];
9.800 - }
9.801 - }
9.802 + if (func_id & 1) {
9.803 + func_id >>= 1;
9.804 + if (func_id >= m_plugin.num_publics)
9.805 + return NULL;
9.806 + pFunc = m_PubFuncs[func_id];
9.807 + if (!pFunc) {
9.808 + m_PubFuncs[func_id] = new CFunction(this,
9.809 + (func_id << 1) | 1,
9.810 + func_id);
9.811 + pFunc = m_PubFuncs[func_id];
9.812 + }
9.813 + }
9.814
9.815 - return pFunc;
9.816 + return pFunc;
9.817 }
9.818
9.819 -IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
9.820 +IPluginFunction *
9.821 +BaseRuntime::GetFunctionByName(const char *public_name)
9.822 {
9.823 - uint32_t index;
9.824 + uint32_t index;
9.825
9.826 - if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
9.827 - {
9.828 - return NULL;
9.829 - }
9.830 + if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
9.831 + return NULL;
9.832
9.833 - CFunction *pFunc = m_PubFuncs[index];
9.834 - if (!pFunc)
9.835 - {
9.836 - sp_public_t *pub = NULL;
9.837 - GetPublicByIndex(index, &pub);
9.838 - if (pub)
9.839 - {
9.840 - m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
9.841 - }
9.842 - pFunc = m_PubFuncs[index];
9.843 - }
9.844 + CFunction *pFunc = m_PubFuncs[index];
9.845 + if (!pFunc) {
9.846 + sp_public_t *pub = NULL;
9.847 + GetPublicByIndex(index, &pub);
9.848 + if (pub)
9.849 + m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
9.850 + pFunc = m_PubFuncs[index];
9.851 + }
9.852
9.853 - return pFunc;
9.854 + return pFunc;
9.855 }
9.856
9.857 bool BaseRuntime::IsDebugging()
9.858 {
9.859 - return true;
9.860 + return true;
9.861 }
9.862
9.863 void BaseRuntime::SetPauseState(bool paused)
9.864 {
9.865 - if (paused)
9.866 - {
9.867 - m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
9.868 - }
9.869 - else
9.870 - {
9.871 - m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
9.872 - }
9.873 + if (paused)
9.874 + {
9.875 + m_plugin.run_flags |= SPFLAG_PLUGIN_PAUSED;
9.876 + }
9.877 + else
9.878 + {
9.879 + m_plugin.run_flags &= ~SPFLAG_PLUGIN_PAUSED;
9.880 + }
9.881 }
9.882
9.883 bool BaseRuntime::IsPaused()
9.884 {
9.885 - return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
9.886 + return ((m_plugin.run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
9.887 }
9.888
9.889 size_t BaseRuntime::GetMemUsage()
9.890 {
9.891 - size_t mem = 0;
9.892 + size_t mem = 0;
9.893
9.894 - mem += sizeof(this);
9.895 - mem += sizeof(sp_plugin_t);
9.896 - mem += sizeof(BaseContext);
9.897 - mem += m_pPlugin->base_size;
9.898 + mem += sizeof(this);
9.899 + mem += sizeof(sp_plugin_t);
9.900 + mem += sizeof(BaseContext);
9.901 + mem += m_plugin.base_size;
9.902
9.903 - return mem;
9.904 + return mem;
9.905 }
9.906
9.907 unsigned char *BaseRuntime::GetCodeHash()
9.908 {
9.909 - return m_CodeHash;
9.910 + return m_CodeHash;
9.911 }
9.912
9.913 unsigned char *BaseRuntime::GetDataHash()
9.914 {
9.915 - return m_DataHash;
9.916 + return m_DataHash;
9.917 }
9.918
9.919 BaseContext *BaseRuntime::GetBaseContext()
9.920 {
9.921 - return m_pCtx;
9.922 + return m_pCtx;
9.923 }
9.924
9.925 -int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
9.926 +int
9.927 +BaseRuntime::ApplyCompilationOptions(ICompilation *co)
9.928 {
9.929 - if (co == NULL)
9.930 - {
9.931 - return SP_ERROR_NONE;
9.932 - }
9.933 -
9.934 - m_pCo = g_Jit.ApplyOptions(m_pCo, co);
9.935 - m_pPlugin->prof_flags = ((CompData *)m_pCo)->profile;
9.936 + if (co == NULL)
9.937 + return SP_ERROR_NONE;
9.938
9.939 - return SP_ERROR_NONE;
9.940 -}
9.941 -
9.942 -JitFunction *BaseRuntime::GetJittedFunction(uint32_t idx)
9.943 -{
9.944 - assert(idx <= m_NumFuncs);
9.945 + co_ = g_Jit.ApplyOptions(co_, co);
9.946 + m_plugin.prof_flags = ((CompData *)co_)->profile;
9.947
9.948 - if (idx == 0 || idx > m_NumFuncs)
9.949 - {
9.950 - return NULL;
9.951 - }
9.952 -
9.953 - return m_FuncCache[idx - 1];
9.954 + return SP_ERROR_NONE;
9.955 }
9.956
9.957 -uint32_t BaseRuntime::AddJittedFunction(JitFunction *fn)
9.958 +int
9.959 +BaseRuntime::CreateBlank(uint32_t heastk)
9.960 {
9.961 - if (m_NumFuncs + 1 > m_MaxFuncs)
9.962 - {
9.963 - if (m_MaxFuncs == 0)
9.964 - {
9.965 - m_MaxFuncs = 8;
9.966 - }
9.967 - else
9.968 - {
9.969 - m_MaxFuncs *= 2;
9.970 - }
9.971 + memset(&m_plugin, 0, sizeof(m_plugin));
9.972
9.973 - m_FuncCache = (JitFunction **)realloc(
9.974 - m_FuncCache,
9.975 - sizeof(JitFunction *) * m_MaxFuncs);
9.976 - }
9.977 -
9.978 - m_FuncCache[m_NumFuncs++] = fn;
9.979 + /* Align to cell_t bytes */
9.980 + heastk += sizeof(cell_t);
9.981 + heastk -= heastk % sizeof(cell_t);
9.982
9.983 - return m_NumFuncs;
9.984 -}
9.985 -
9.986 -int BaseRuntime::CreateBlank(uint32_t heastk)
9.987 -{
9.988 - memset(m_pPlugin, 0, sizeof(sp_plugin_t));
9.989 + m_plugin.mem_size = heastk;
9.990 + m_plugin.memory = new uint8_t[heastk];
9.991
9.992 - /* Align to cell_t bytes */
9.993 - heastk += sizeof(cell_t);
9.994 - heastk -= heastk % sizeof(cell_t);
9.995 -
9.996 - m_pPlugin->mem_size = heastk;
9.997 - m_pPlugin->memory = new uint8_t[heastk];
9.998 + m_plugin.profiler = g_engine2.GetProfiler();
9.999 + m_pCtx = new BaseContext(this);
9.1000 + co_ = g_Jit.StartCompilation(this);
9.1001
9.1002 - m_pPlugin->profiler = g_engine2.GetProfiler();
9.1003 - m_pCtx = new BaseContext(this);
9.1004 - m_pCo = g_Jit.StartCompilation(this);
9.1005 -
9.1006 - return SP_ERROR_NONE;
9.1007 + return SP_ERROR_NONE;
9.1008 }
10.1 --- a/sourcepawn/jit/BaseRuntime.h Thu Aug 08 09:40:23 2013 -0700
10.2 +++ b/sourcepawn/jit/BaseRuntime.h Thu Aug 08 09:41:24 2013 -0700
10.3 @@ -1,7 +1,9 @@
10.4 +// vim: set ts=8 sw=2 sts=2 tw=99 et:
10.5 #ifndef _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
10.6 #define _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
10.7
10.8 #include <sp_vm_api.h>
10.9 +#include <ke_vector.h>
10.10 #include "jit_shared.h"
10.11 #include "sp_vm_function.h"
10.12
10.13 @@ -11,65 +13,93 @@
10.14 class DebugInfo : public IPluginDebugInfo
10.15 {
10.16 public:
10.17 - DebugInfo(sp_plugin_t *plugin);
10.18 + DebugInfo(sp_plugin_t *plugin);
10.19 public:
10.20 - int LookupFile(ucell_t addr, const char **filename);
10.21 - int LookupFunction(ucell_t addr, const char **name);
10.22 - int LookupLine(ucell_t addr, uint32_t *line);
10.23 + int LookupFile(ucell_t addr, const char **filename);
10.24 + int LookupFunction(ucell_t addr, const char **name);
10.25 + int LookupLine(ucell_t addr, uint32_t *line);
10.26 private:
10.27 - sp_plugin_t *m_pPlugin;
10.28 + sp_plugin_t *m_pPlugin;
10.29 +};
10.30 +
10.31 +struct floattbl_t
10.32 +{
10.33 + floattbl_t() {
10.34 + found = false;
10.35 + index = 0;
10.36 + }
10.37 + bool found;
10.38 + unsigned int index;
10.39 };
10.40
10.41 /* Jit wants fast access to this so we expose things as public */
10.42 class BaseRuntime : public SourcePawn::IPluginRuntime
10.43 {
10.44 -public:
10.45 - BaseRuntime();
10.46 - ~BaseRuntime();
10.47 -public:
10.48 - virtual int CreateBlank(uint32_t heastk);
10.49 - virtual int CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base);
10.50 - virtual bool IsDebugging();
10.51 - virtual IPluginDebugInfo *GetDebugInfo();
10.52 - virtual int FindNativeByName(const char *name, uint32_t *index);
10.53 - virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
10.54 - virtual uint32_t GetNativesNum();
10.55 - virtual int FindPublicByName(const char *name, uint32_t *index);
10.56 - virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
10.57 - virtual uint32_t GetPublicsNum();
10.58 - virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
10.59 - virtual int FindPubvarByName(const char *name, uint32_t *index);
10.60 - virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
10.61 - virtual uint32_t GetPubVarsNum();
10.62 - virtual IPluginFunction *GetFunctionByName(const char *public_name);
10.63 - virtual IPluginFunction *GetFunctionById(funcid_t func_id);
10.64 - virtual IPluginContext *GetDefaultContext();
10.65 - virtual int ApplyCompilationOptions(ICompilation *co);
10.66 - virtual void SetPauseState(bool paused);
10.67 - virtual bool IsPaused();
10.68 - virtual size_t GetMemUsage();
10.69 - virtual unsigned char *GetCodeHash();
10.70 - virtual unsigned char *GetDataHash();
10.71 - JitFunction *GetJittedFunction(uint32_t idx);
10.72 - uint32_t AddJittedFunction(JitFunction *fn);
10.73 -public:
10.74 - BaseContext *GetBaseContext();
10.75 -private:
10.76 - sp_plugin_t m_plugin;
10.77 - unsigned int m_NumFuncs;
10.78 - unsigned int m_MaxFuncs;
10.79 - JitFunction **m_FuncCache;
10.80 -public:
10.81 - DebugInfo m_Debug;
10.82 - sp_plugin_t *m_pPlugin;
10.83 - BaseContext *m_pCtx;
10.84 - CFunction **m_PubFuncs;
10.85 - JitFunction **m_PubJitFuncs;
10.86 - ICompilation *m_pCo;
10.87 - unsigned int m_CompSerial;
10.88 -
10.89 - unsigned char m_CodeHash[16];
10.90 - unsigned char m_DataHash[16];
10.91 + public:
10.92 + BaseRuntime();
10.93 + ~BaseRuntime();
10.94 +
10.95 + public:
10.96 + virtual int CreateBlank(uint32_t heastk);
10.97 + virtual int CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base);
10.98 + virtual bool IsDebugging();
10.99 + virtual IPluginDebugInfo *GetDebugInfo();
10.100 + virtual int FindNativeByName(const char *name, uint32_t *index);
10.101 + virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
10.102 + virtual uint32_t GetNativesNum();
10.103 + virtual int FindPublicByName(const char *name, uint32_t *index);
10.104 + virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
10.105 + virtual uint32_t GetPublicsNum();
10.106 + virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
10.107 + virtual int FindPubvarByName(const char *name, uint32_t *index);
10.108 + virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
10.109 + virtual uint32_t GetPubVarsNum();
10.110 + virtual IPluginFunction *GetFunctionByName(const char *public_name);
10.111 + virtual IPluginFunction *GetFunctionById(funcid_t func_id);
10.112 + virtual IPluginContext *GetDefaultContext();
10.113 + virtual int ApplyCompilationOptions(ICompilation *co);
10.114 + virtual void SetPauseState(bool paused);
10.115 + virtual bool IsPaused();
10.116 + virtual size_t GetMemUsage();
10.117 + virtual unsigned char *GetCodeHash();
10.118 + virtual unsigned char *GetDataHash();
10.119 + JitFunction *GetJittedFunctionByOffset(cell_t pcode_offset);
10.120 + void AddJittedFunction(JitFunction *fn);
10.121 + void SetName(const char *name);
10.122 + unsigned GetNativeReplacement(size_t index);
10.123 +
10.124 + BaseContext *GetBaseContext();
10.125 + const sp_plugin_t *plugin() const {
10.126 + return &m_plugin;
10.127 + }
10.128 +
10.129 + private:
10.130 + void SetupFloatNativeRemapping();
10.131 +
10.132 + private:
10.133 + sp_plugin_t m_plugin;
10.134 + uint8_t *alt_pcode_;
10.135 + unsigned int m_NumFuncs;
10.136 + unsigned int m_MaxFuncs;
10.137 + floattbl_t *float_table_;
10.138 + JitFunction **function_map_;
10.139 + size_t function_map_size_;
10.140 + ke::Vector<JitFunction *> m_JitFunctions;
10.141 +
10.142 + public:
10.143 + DebugInfo m_Debug;
10.144 + BaseContext *m_pCtx;
10.145 + CFunction **m_PubFuncs;
10.146 + JitFunction **m_PubJitFuncs;
10.147 +
10.148 + private:
10.149 + ICompilation *co_;
10.150 +
10.151 + public:
10.152 + unsigned int m_CompSerial;
10.153 +
10.154 + unsigned char m_CodeHash[16];
10.155 + unsigned char m_DataHash[16];
10.156 };
10.157
10.158 #endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
11.1 --- a/sourcepawn/jit/Makefile Thu Aug 08 09:40:23 2013 -0700
11.2 +++ b/sourcepawn/jit/Makefile Thu Aug 08 09:41:24 2013 -0700
11.3 @@ -12,12 +12,12 @@
11.4
11.5 OBJECTS = dll_exports.cpp \
11.6 x86/jit_x86.cpp \
11.7 - x86/opcode_helpers.cpp \
11.8 sp_vm_basecontext.cpp \
11.9 sp_vm_engine.cpp \
11.10 sp_vm_function.cpp \
11.11 engine2.cpp \
11.12 BaseRuntime.cpp \
11.13 + opcodes.cpp \
11.14 jit_function.cpp \
11.15 md5/md5.cpp \
11.16 zlib/adler32.c \
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/sourcepawn/jit/Makefile.shell Thu Aug 08 09:41:24 2013 -0700
12.3 @@ -0,0 +1,111 @@
12.4 +# (C)2004-2008 SourceMod Development Team
12.5 +# Makefile written by David "BAILOPAN" Anderson
12.6 +
12.7 +SMSDK = ../..
12.8 +MMSOURCE17 = ../../../mmsource-1.7
12.9 +
12.10 +#####################################
12.11 +### EDIT BELOW FOR OTHER PROJECTS ###
12.12 +#####################################
12.13 +
12.14 +PROJECT = spshell
12.15 +
12.16 +OBJECTS = dll_exports.cpp \
12.17 + x86/jit_x86.cpp \
12.18 + sp_vm_basecontext.cpp \
12.19 + sp_vm_engine.cpp \
12.20 + sp_vm_function.cpp \
12.21 + engine2.cpp \
12.22 + BaseRuntime.cpp \
12.23 + jit_function.cpp \
12.24 + opcodes.cpp \
12.25 + md5/md5.cpp \
12.26 + zlib/adler32.c \
12.27 + zlib/compress.c \
12.28 + zlib/crc32.c \
12.29 + zlib/deflate.c \
12.30 + zlib/gzio.c \
12.31 + zlib/infback.c \
12.32 + zlib/inffast.c \
12.33 + zlib/inflate.c \
12.34 + zlib/inftrees.c \
12.35 + zlib/trees.c \
12.36 + zlib/uncompr.c \
12.37 + zlib/zutil.c \
12.38 +
12.39 +OBJECTS += ../../knight/shared/KeCodeAllocator.cpp
12.40 +
12.41 +##############################################
12.42 +### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
12.43 +##############################################
12.44 +
12.45 +C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
12.46 +C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
12.47 +C_GCC4_FLAGS = -fvisibility=hidden
12.48 +CXX_GCC4_FLAGS = -fvisibility-inlines-hidden
12.49 +CXX = c++
12.50 +CC = cc
12.51 +
12.52 +LINK = -m32 -lm
12.53 +
12.54 +INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
12.55 + -I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86
12.56 +
12.57 +CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
12.58 + -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
12.59 + -m32 -Wno-uninitialized -Werror -DSPSHELL -ggdb3 -Wno-unused
12.60 +CXXFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti -Wno-delete-non-virtual-dtor
12.61 +
12.62 +################################################
12.63 +### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
12.64 +################################################
12.65 +
12.66 +ifeq "$(DEBUG)" "true"
12.67 + BIN_DIR = Debug.shell
12.68 + CFLAGS += $(C_DEBUG_FLAGS)
12.69 +else
12.70 + BIN_DIR = Release.shell
12.71 + CFLAGS += $(C_OPT_FLAGS)
12.72 +endif
12.73 +
12.74 +GCC_VERSION := $(shell $(CXX) -dumpversion >&1 | cut -b1)
12.75 +ifeq "$(GCC_VERSION)" "4"
12.76 + CFLAGS += $(C_GCC4_FLAGS)
12.77 + CXXFLAGS += $(CXX_GCC4_FLAGS)
12.78 +endif
12.79 +
12.80 +OBJ_LINUX := $(OBJECTS:../../knight/shared/%.cpp=$(BIN_DIR)/knight/%.o)
12.81 +OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
12.82 +OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
12.83 +
12.84 +default: all
12.85 +
12.86 +$(BIN_DIR)/%.o: %.c
12.87 + $(CC) $(INCLUDE) $(CFLAGS) -o $@ -c $<
12.88 +
12.89 +$(BIN_DIR)/%.o: %.cpp
12.90 + $(CXX) $(INCLUDE) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
12.91 +
12.92 +$(BIN_DIR)/knight/%.o: ../../knight/shared/%.cpp
12.93 + $(CXX) $(INCLUDE) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
12.94 +
12.95 +all:
12.96 + mkdir -p $(BIN_DIR)/x86
12.97 + mkdir -p $(BIN_DIR)/md5
12.98 + mkdir -p $(BIN_DIR)/zlib
12.99 + mkdir -p $(BIN_DIR)/knight
12.100 + $(MAKE) -f Makefile.shell jit
12.101 +
12.102 +jit: $(OBJ_LINUX)
12.103 + $(CXX) $(INCLUDE) $(OBJ_LINUX) $(LINK) -o $(BIN_DIR)/$(PROJECT)
12.104 +
12.105 +debug:
12.106 + $(MAKE) -f Makefile.shell all DEBUG=true
12.107 +
12.108 +clean:
12.109 + rm -f $(BIN_DIR)/x86/*.o
12.110 +# rm -rf $(BIN_DIR)/zlib/*.o
12.111 +# rm -rf $(BIN_DIR)/knight/*.o
12.112 + rm -f $(BIN_DIR)/*.o
12.113 + rm -f $(BIN_DIR)/$(PROJECT)
12.114 +
13.1 --- a/sourcepawn/jit/dll_exports.cpp Thu Aug 08 09:40:23 2013 -0700
13.2 +++ b/sourcepawn/jit/dll_exports.cpp Thu Aug 08 09:41:24 2013 -0700
13.3 @@ -1,76 +1,263 @@
13.4 -/**
13.5 - * vim: set ts=4 :
13.6 - * =============================================================================
13.7 - * SourceMod
13.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
13.9 - * =============================================================================
13.10 - *
13.11 - * This program is free software; you can redistribute it and/or modify it under
13.12 - * the terms of the GNU General Public License, version 3.0, as published by the
13.13 - * Free Software Foundation.
13.14 - *
13.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
13.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13.18 - * details.
13.19 - *
13.20 - * You should have received a copy of the GNU General Public License along with
13.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
13.22 - *
13.23 - * As a special exception, AlliedModders LLC gives you permission to link the
13.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
13.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
13.26 - * by the Valve Corporation. You must obey the GNU General Public License in
13.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
13.28 - * this exception to all derivative works. AlliedModders LLC defines further
13.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
13.30 - * or <http://www.sourcemod.net/license.php>.
13.31 - *
13.32 - * Version: $Id$
13.33 - */
13.34 -
13.35 -#include <sp_vm_api.h>
13.36 -#include <stdlib.h>
13.37 -#include "x86/jit_x86.h"
13.38 -#include "dll_exports.h"
13.39 -#include "sp_vm_engine.h"
13.40 -#include "engine2.h"
13.41 -
13.42 -SourcePawnEngine2 g_engine2;
13.43 -
13.44 -EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
13.45 -{
13.46 - return &g_engine1;
13.47 -}
13.48 -
13.49 -EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
13.50 -{
13.51 - return &g_engine2;
13.52 -}
13.53 -
13.54 -#if defined __linux__ || defined __APPLE__
13.55 -extern "C" void __cxa_pure_virtual(void)
13.56 -{
13.57 -}
13.58 -
13.59 -void *operator new(size_t size)
13.60 -{
13.61 - return malloc(size);
13.62 -}
13.63 -
13.64 -void *operator new[](size_t size)
13.65 -{
13.66 - return malloc(size);
13.67 -}
13.68 -
13.69 -void operator delete(void *ptr)
13.70 -{
13.71 - free(ptr);
13.72 -}
13.73 -
13.74 -void operator delete[](void * ptr)
13.75 -{
13.76 - free(ptr);
13.77 -}
13.78 -#endif
13.79 -
13.80 +/**
13.81 + * vim: set ts=4 sts=4 sw=4 tw=99 noet:
13.82 + * =============================================================================
13.83 + * SourceMod
13.84 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
13.85 + * =============================================================================
13.86 + *
13.87 + * This program is free software; you can redistribute it and/or modify it under
13.88 + * the terms of the GNU General Public License, version 3.0, as published by the
13.89 + * Free Software Foundation.
13.90 + *
13.91 + * This program is distributed in the hope that it will be useful, but WITHOUT
13.92 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13.93 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13.94 + * details.
13.95 + *
13.96 + * You should have received a copy of the GNU General Public License along with
13.97 + * this program. If not, see <http://www.gnu.org/licenses/>.
13.98 + *
13.99 + * As a special exception, AlliedModders LLC gives you permission to link the
13.100 + * code of this program (as well as its derivative works) to "Half-Life 2," the
13.101 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
13.102 + * by the Valve Corporation. You must obey the GNU General Public License in
13.103 + * all respects for all other code used. Additionally, AlliedModders LLC grants
13.104 + * this exception to all derivative works. AlliedModders LLC defines further
13.105 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
13.106 + * or <http://www.sourcemod.net/license.php>.
13.107 + *
13.108 + * Version: $Id$
13.109 + */
13.110 +
13.111 +#include <sp_vm_api.h>
13.112 +#include <stdlib.h>
13.113 +#include <stdarg.h>
13.114 +#include "x86/jit_x86.h"
13.115 +#include "dll_exports.h"
13.116 +#include "sp_vm_engine.h"
13.117 +#include "engine2.h"
13.118 +
13.119 +using namespace SourcePawn;
13.120 +
13.121 +SourcePawnEngine2 g_engine2;
13.122 +
13.123 +#ifdef SPSHELL
13.124 +template <typename T> class AutoT
13.125 +{
13.126 +public:
13.127 + AutoT(T *t)
13.128 + : t_(t)
13.129 + {
13.130 + }
13.131 + ~AutoT()
13.132 + {
13.133 + delete t_;
13.134 + }
13.135 +
13.136 + operator T *() const {
13.137 + return t_;
13.138 + }
13.139 + bool operator !() const {
13.140 + return !t_;
13.141 + }
13.142 + T * operator ->() const {
13.143 + return t_;
13.144 + }
13.145 +private:
13.146 + T *t_;
13.147 +};
13.148 +
13.149 +class ShellDebugListener : public IDebugListener
13.150 +{
13.151 +public:
13.152 + void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error) {
13.153 + int n_err = error->GetErrorCode();
13.154 +
13.155 + if (n_err != SP_ERROR_NATIVE)
13.156 + {
13.157 + fprintf(stderr, "plugin error: %s\n", error->GetErrorString());
13.158 + }
13.159 +
13.160 + if (const char *lastname = error->GetLastNative(NULL))
13.161 + {
13.162 + if (const char *custerr = error->GetCustomErrorString())
13.163 + {
13.164 + fprintf(stderr, "Native \"%s\" reported: %s", lastname, custerr);
13.165 + } else {
13.166 + fprintf(stderr, "Native \"%s\" encountered a generic error.", lastname);
13.167 + }
13.168 + }
13.169 +
13.170 + if (!error->DebugInfoAvailable())
13.171 + {
13.172 + fprintf(stderr, "Debug info not available!\n");
13.173 + return;
13.174 + }
13.175 +
13.176 + CallStackInfo stk_info;
13.177 + int i = 0;
13.178 + fprintf(stderr, "Displaying call stack trace:\n");
13.179 + while (error->GetTraceInfo(&stk_info))
13.180 + {
13.181 + fprintf(stderr,
13.182 + " [%d] Line %d, %s::%s()",
13.183 + i++,
13.184 + stk_info.line,
13.185 + stk_info.filename,
13.186 + stk_info.function);
13.187 + }
13.188 + }
13.189 +
13.190 + void OnDebugSpew(const char *msg, ...) {
13.191 +#if !defined(NDEBUG) && defined(DEBUG)
13.192 + va_list ap;
13.193 + va_start(ap, msg);
13.194 + vfprintf(stderr, msg, ap);
13.195 + va_end(ap);
13.196 +#endif
13.197 + }
13.198 +};
13.199 +
13.200 +static cell_t Print(IPluginContext *cx, const cell_t *params)
13.201 +{
13.202 + char *p;
13.203 + cx->LocalToString(params[1], &p);
13.204 +
13.205 + return printf("%s", p);
13.206 +}
13.207 +
13.208 +static cell_t PrintNum(IPluginContext *cx, const cell_t *params)
13.209 +{
13.210 + return printf("%d\n", params[1]);
13.211 +}
13.212 +
13.213 +static cell_t PrintNums(IPluginContext *cx, const cell_t *params)
13.214 +{
13.215 + for (size_t i = 1; i <= size_t(params[0]); i++) {
13.216 + int err;
13.217 + cell_t *addr;
13.218 + if ((err = cx->LocalToPhysAddr(params[i], &addr)) != SP_ERROR_NONE)
13.219 + return cx->ThrowNativeErrorEx(err, "Could not read argument");
13.220 + fprintf(stdout, "%d", *addr);
13.221 + if (i != size_t(params[0]))
13.222 + fprintf(stdout, ", ");
13.223 + }
13.224 + fprintf(stdout, "\n");
13.225 + return 1;
13.226 +}
13.227 +
13.228 +static void BindNative(IPluginRuntime *rt, const char *name, SPVM_NATIVE_FUNC fn)
13.229 +{
13.230 + int err;
13.231 + uint32_t index;
13.232 + if ((err = rt->FindNativeByName(name, &index)) != SP_ERROR_NONE)
13.233 + return;
13.234 +
13.235 + sp_native_t *native;
13.236 + if (rt->GetNativeByIndex(index, &native) != SP_ERROR_NONE)
13.237 + return;
13.238 +
13.239 + native->pfn = fn;
13.240 + native->status = SP_NATIVE_BOUND;
13.241 +}
13.242 +
13.243 +static cell_t PrintFloat(IPluginContext *cx, const cell_t *params)
13.244 +{
13.245 + return printf("%f\n", sp_ctof(params[1]));
13.246 +}
13.247 +
13.248 +static int Execute(const char *file)
13.249 +{
13.250 + ICompilation *co = g_engine2.StartCompilation();
13.251 + if (!co) {
13.252 + fprintf(stderr, "Could not create a compilation context\n");
13.253 + return 1;
13.254 + }
13.255 +
13.256 + int err;
13.257 + AutoT<IPluginRuntime> rt(g_engine2.LoadPlugin(co, file, &err));
13.258 + if (!rt) {
13.259 + fprintf(stderr, "Could not load plugin: %s\n", g_engine1.GetErrorString(err));
13.260 + return 1;
13.261 + }
13.262 +
13.263 + BindNative(rt, "print", Print);
13.264 + BindNative(rt, "printnum", PrintNum);
13.265 + BindNative(rt, "printnums", PrintNums);
13.266 + BindNative(rt, "printfloat", PrintFloat);
13.267 +
13.268 + IPluginFunction *fun = rt->GetFunctionByName("main");
13.269 + if (!fun)
13.270 + return 0;
13.271 +
13.272 + IPluginContext *cx = rt->GetDefaultContext();
13.273 +
13.274 + int result = fun->Execute2(cx, &err);
13.275 + if (err != SP_ERROR_NONE) {
13.276 + fprintf(stderr, "Error executing main(): %s\n", g_engine1.GetErrorString(err));
13.277 + return 1;
13.278 + }
13.279 +
13.280 + return result;
13.281 +}
13.282 +
13.283 +int main(int argc, char **argv)
13.284 +{
13.285 + if (argc != 2) {
13.286 + fprintf(stderr, "Usage: <file>\n");
13.287 + return 1;
13.288 + }
13.289 +
13.290 + if (!g_engine2.Initialize()) {
13.291 + fprintf(stderr, "Could not initialize ISourcePawnEngine2\n");
13.292 + return 1;
13.293 + }
13.294 +
13.295 + ShellDebugListener debug;
13.296 + g_engine1.SetDebugListener(&debug);
13.297 +
13.298 + int errcode = Execute(argv[1]);
13.299 +
13.300 + g_engine1.SetDebugListener(NULL);
13.301 + g_engine2.Shutdown();
13.302 + return errcode;
13.303 +}
13.304 +
13.305 +#else
13.306 +EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
13.307 +{
13.308 + return &g_engine1;
13.309 +}
13.310 +
13.311 +EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
13.312 +{
13.313 + return &g_engine2;
13.314 +}
13.315 +#endif
13.316 +
13.317 +#if defined __linux__ || defined __APPLE__
13.318 +extern "C" void __cxa_pure_virtual(void)
13.319 +{
13.320 +}
13.321 +
13.322 +void *operator new(size_t size)
13.323 +{
13.324 + return malloc(size);
13.325 +}
13.326 +
13.327 +void *operator new[](size_t size)
13.328 +{
13.329 + return malloc(size);
13.330 +}
13.331 +
13.332 +void operator delete(void *ptr)
13.333 +{
13.334 + free(ptr);
13.335 +}
13.336 +
13.337 +void operator delete[](void * ptr)
13.338 +{
13.339 + free(ptr);
13.340 +}
13.341 +#endif
13.342 +
14.1 --- a/sourcepawn/jit/engine2.cpp Thu Aug 08 09:40:23 2013 -0700
14.2 +++ b/sourcepawn/jit/engine2.cpp Thu Aug 08 09:41:24 2013 -0700
14.3 @@ -106,19 +106,19 @@
14.4 #endif
14.5 )
14.6 {
14.7 - pRuntime->m_pPlugin->name = strdup(&file[i+1]);
14.8 + pRuntime->SetName(&file[i+1]);
14.9 break;
14.10 }
14.11 }
14.12
14.13 - if (pRuntime->m_pPlugin->name == NULL)
14.14 + if (!pRuntime->plugin()->name)
14.15 {
14.16 - pRuntime->m_pPlugin->name = strdup(file);
14.17 + pRuntime->SetName(file);
14.18 }
14.19
14.20 pRuntime->ApplyCompilationOptions(co);
14.21
14.22 - fclose(fp);
14.23 + fclose(fp);
14.24
14.25 return pRuntime;
14.26
14.27 @@ -204,7 +204,7 @@
14.28 return NULL;
14.29 }
14.30
14.31 - rt->m_pPlugin->name = strdup(name != NULL ? name : "<anonymous>");
14.32 + rt->SetName(name != NULL ? name : "<anonymous>");
14.33
14.34 rt->ApplyCompilationOptions(NULL);
14.35
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/sourcepawn/jit/opcodes.cpp Thu Aug 08 09:41:24 2013 -0700
15.3 @@ -0,0 +1,137 @@
15.4 +/**
15.5 + * vim: set ts=8 sw=2 tw=99 sts=2 et:
15.6 + * =============================================================================
15.7 + * SourceMod
15.8 + * Copyright _(C) 2004-2008 AlliedModders LLC. All rights reserved.
15.9 + * =============================================================================
15.10 + *
15.11 + * This program is free software; you can redistribute it and/or modify it under
15.12 + * the terms of the GNU General Public License), version 3.0), as published by the
15.13 + * Free Software Foundation.
15.14 + *
15.15 + * This program is distributed in the hope that it will be useful), but WITHOUT
15.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15.18 + * details.
15.19 + *
15.20 + * You should have received a copy of the GNU General Public License along with
15.21 + * this program. If not), see <http://www.gnu.org/licenses/>.
15.22 + *
15.23 + * As a special exception), AlliedModders LLC gives you permission to link the
15.24 + * code of this program _(as well as its derivative works) to "Half-Life 2)," the
15.25 + * "Source Engine)," the "SourcePawn JIT)," and any Game MODs that run on software
15.26 + * by the Valve Corporation. You must obey the GNU General Public License in
15.27 + * all respects for all other code used. Additionally), AlliedModders LLC grants
15.28 + * this exception to all derivative works. AlliedModders LLC defines further
15.29 + * exceptions), found in LICENSE.txt _(as of this writing), version JULY-31-2007)),
15.30 + * or <http://www.sourcemod.net/license.php>.
15.31 + *
15.32 + * Version: $Id$
15.33 + */
15.34 +#include "opcodes.h"
15.35 +#include "jit_shared.h"
15.36 +
15.37 +using namespace SourcePawn;
15.38 +
15.39 +const char *OpcodeNames[] = {
15.40 +#define _(op, text) text,
15.41 + OPCODE_LIST(_)
15.42 +#undef _
15.43 + NULL
15.44 +};
15.45 +
15.46 +void
15.47 +SourcePawn::SpewOpcode(const sp_plugin_t *plugin, cell_t *start, cell_t *cip)
15.48 +{
15.49 + fprintf(stdout, " [%05d:%04d]", cip - (cell_t *)plugin->pcode, cip - start);
15.50 +
15.51 + if (*cip >= OPCODES_TOTAL) {
15.52 + fprintf(stdout, " unknown-opcode\n");
15.53 + return;
15.54 + }
15.55 +
15.56 + OPCODE op = (OPCODE)*cip;
15.57 + fprintf(stdout, " %s ", OpcodeNames[op]);
15.58 +
15.59 + switch (op) {
15.60 + case OP_PUSH_C:
15.61 + case OP_PUSH_ADR:
15.62 + case OP_SHL_C_PRI:
15.63 + case OP_SHL_C_ALT:
15.64 + case OP_SHR_C_PRI:
15.65 + case OP_SHR_C_ALT:
15.66 + case OP_ADD_C:
15.67 + case OP_SMUL_C:
15.68 + case OP_EQ_C_PRI:
15.69 + case OP_EQ_C_ALT:
15.70 + case OP_TRACKER_PUSH_C:
15.71 + case OP_STACK:
15.72 + case OP_PUSH_S:
15.73 + case OP_HEAP:
15.74 + case OP_GENARRAY:
15.75 + case OP_GENARRAY_Z:
15.76 + fprintf(stdout, "%d", cip[1]);
15.77 + break;
15.78 +
15.79 + case OP_JUMP:
15.80 + case OP_JZER:
15.81 + case OP_JNZ:
15.82 + case OP_JEQ:
15.83 + case OP_JNEQ:
15.84 + case OP_JSLESS:
15.85 + case OP_JSGRTR:
15.86 + case OP_JSGEQ:
15.87 + case OP_JSLEQ:
15.88 + fprintf(stdout, "%05d:%04d",
15.89 + cip[1] / 4,
15.90 + ((cell_t *)plugin->pcode + cip[1] / 4) - start);
15.91 + break;
15.92 +
15.93 + case OP_SYSREQ_C:
15.94 + case OP_SYSREQ_N:
15.95 + {
15.96 + uint32_t index = cip[1];
15.97 + if (index < plugin->num_natives)
15.98 + fprintf(stdout, "%s", plugin->natives[index].name);
15.99 + if (op == OP_SYSREQ_N)
15.100 + fprintf(stdout, " ; (%d args, index %d)", cip[2], index);
15.101 + else
15.102 + fprintf(stdout, " ; (index %d)", index);
15.103 + break;
15.104 + }
15.105 +
15.106 + case OP_PUSH2_C:
15.107 + case OP_PUSH2:
15.108 + case OP_PUSH2_S:
15.109 + case OP_PUSH2_ADR:
15.110 + fprintf(stdout, "%d, %d", cip[1], cip[2]);
15.111 + break;
15.112 +
15.113 + case OP_PUSH3_C:
15.114 + case OP_PUSH3:
15.115 + case OP_PUSH3_S:
15.116 + case OP_PUSH3_ADR:
15.117 + fprintf(stdout, "%d, %d, %d", cip[1], cip[2], cip[3]);
15.118 + break;
15.119 +
15.120 + case OP_PUSH4_C:
15.121 + case OP_PUSH4:
15.122 + case OP_PUSH4_S:
15.123 + case OP_PUSH4_ADR:
15.124 + fprintf(stdout, "%d, %d, %d, %d", cip[1], cip[2], cip[3], cip[4]);
15.125 + break;
15.126 +
15.127 + case OP_PUSH5_C:
15.128 + case OP_PUSH5:
15.129 + case OP_PUSH5_S:
15.130 + case OP_PUSH5_ADR:
15.131 + fprintf(stdout, "%d, %d, %d, %d, %d", cip[1], cip[2], cip[3], cip[4], cip[5]);
15.132 + break;
15.133 +
15.134 + default:
15.135 + break;
15.136 + }
15.137 +
15.138 + fprintf(stdout, "\n");
15.139 +}
15.140 +
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/sourcepawn/jit/opcodes.h Thu Aug 08 09:41:24 2013 -0700
16.3 @@ -0,0 +1,262 @@
16.4 +/**
16.5 + * vim: set ts=8 sw=2 tw=99 sts=2 et:
16.6 + * =============================================================================
16.7 + * SourceMod
16.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
16.9 + * =============================================================================
16.10 + *
16.11 + * This program is free software; you can redistribute it and/or modify it under
16.12 + * the terms of the GNU General Public License), version 3.0), as published by the
16.13 + * Free Software Foundation.
16.14 + *
16.15 + * This program is distributed in the hope that it will be useful), but WITHOUT
16.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16.18 + * details.
16.19 + *
16.20 + * You should have received a copy of the GNU General Public License along with
16.21 + * this program. If not), see <http://www.gnu.org/licenses/>.
16.22 + *
16.23 + * As a special exception), AlliedModders LLC gives you permission to link the
16.24 + * code of this program (as well as its derivative works) to "Half-Life 2)," the
16.25 + * "Source Engine)," the "SourcePawn JIT)," and any Game MODs that run on software
16.26 + * by the Valve Corporation. You must obey the GNU General Public License in
16.27 + * all respects for all other code used. Additionally), AlliedModders LLC grants
16.28 + * this exception to all derivative works. AlliedModders LLC defines further
16.29 + * exceptions), found in LICENSE.txt (as of this writing), version JULY-31-2007)),
16.30 + * or <http://www.sourcemod.net/license.php>.
16.31 + *
16.32 + * Version: $Id$
16.33 + */
16.34 +
16.35 +#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_
16.36 +#define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_
16.37 +
16.38 +#include <sp_vm_api.h>
16.39 +
16.40 +// Opcodes labelled "UNGEN" cannot be generated by the compiler. Quite a few,
16.41 +// if they could, make little sense in the context of a JIT and could not
16.42 +// work anyway. Opcodes technically present in sc4.c/sc7.c (respectively,
16.43 +// the code emitter and peephole optimizer) are not necessarily ever generated.
16.44 +// For example, lref.pri and lref.alt would be used if a reference could be
16.45 +// stored in the global scope; but they can't, so they are unreachable.
16.46 +//
16.47 +// Most opcodes have been manually verified. A few have not, as they are only
16.48 +// produced by the peephole optimizer, or not produced at all, or eliminated
16.49 +// during optimization. We generate them anyway, just in case, but they have
16.50 +// not been tested.
16.51 +// lref.s.alt (phopt only)
16.52 +// stor.alt (never)
16.53 +// stor.s.alt (never)
16.54 +// sref.s.alt (never)
16.55 +// lidx.b (phopt only, probably impossible)
16.56 +// idxaddr.b (phopt only, looks difficult)
16.57 +// move.pri (eliminated in phopt)
16.58 +// shl.c.pri (eliminated in phopt)
16.59 +// shl.c.alt (eliminated in phopt)
16.60 +// shr.c.pri (eliminated in phopt)
16.61 +// shr.c.alt (eliminated in phopt)
16.62 +// eq.c.alt (never)
16.63 +// inc.alt (never)
16.64 +// dec.alt (never)
16.65 +// sdiv (never)
16.66 +// nop (never in function bodies)
16.67 +//
16.68 +// Additionally, some opcodes which were supported in the earlier JIT are no
16.69 +// longer supported because of the above:
16.70 +// lref.pri/alt
16.71 +// sref.pri/alt
16.72 +// sign.pri/alt
16.73 +
16.74 +#define OPCODE_LIST(_) \
16.75 + _(NONE, "none") \
16.76 + _(LOAD_PRI, "load.pri") \
16.77 + _(LOAD_ALT, "load.alt") \
16.78 + _(LOAD_S_PRI, "load.s.pri") \
16.79 + _(LOAD_S_ALT, "load.s.alt") \
16.80 + _(UNGEN_LREF_PRI, "lref.pri") \
16.81 + _(UNGEN_LREF_ALT, "lref.alt") \
16.82 + _(LREF_S_PRI, "lref.s.pri") \
16.83 + _(LREF_S_ALT, "lref.s.alt") \
16.84 + _(LOAD_I, "load.i") \
16.85 + _(LODB_I, "lodb.i") \
16.86 + _(CONST_PRI, "const.pri") \
16.87 + _(CONST_ALT, "const.alt") \
16.88 + _(ADDR_PRI, "addr.pri") \
16.89 + _(ADDR_ALT, "addr.alt") \
16.90 + _(STOR_PRI, "stor.pri") \
16.91 + _(STOR_ALT, "stor.alt") \
16.92 + _(STOR_S_PRI, "stor.s.pri") \
16.93 + _(STOR_S_ALT, "stor.s.alt") \
16.94 + _(UNGEN_SREF_PRI, "sref.pri") \
16.95 + _(UNGEN_SREF_ALT, "sref.alt") \
16.96 + _(SREF_S_PRI, "sref.s.pri") \
16.97 + _(SREF_S_ALT, "sref.s.alt") \
16.98 + _(STOR_I, "stor.i") \
16.99 + _(STRB_I, "strb.i") \
16.100 + _(LIDX, "lidx") \
16.101 + _(LIDX_B, "lidx.b") \
16.102 + _(IDXADDR, "idxaddr") \
16.103 + _(IDXADDR_B, "idxaddr.b") \
16.104 + _(UNGEN_ALIGN_PRI,"align.pri") \
16.105 + _(UNGEN_ALIGN_ALT,"align.alt") \
16.106 + _(UNGEN_LCTRL, "lctrl") \
16.107 + _(UNGEN_SCTRL, "sctrl") \
16.108 + _(MOVE_PRI, "move.pri") \
16.109 + _(MOVE_ALT, "move.alt") \
16.110 + _(XCHG, "xchg") \
16.111 + _(PUSH_PRI, "push.pri") \
16.112 + _(PUSH_ALT, "push.alt") \
16.113 + _(UNGEN_PUSH_R, "push.r") \
16.114 + _(PUSH_C, "push.c") \
16.115 + _(PUSH, "push") \
16.116 + _(PUSH_S, "push.s") \
16.117 + _(POP_PRI, "pop.pri") \
16.118 + _(POP_ALT, "pop.alt") \
16.119 + _(STACK, "stack") \
16.120 + _(HEAP, "heap") \
16.121 + _(PROC, "proc") \
16.122 + _(UNGEN_RET, "ret") \
16.123 + _(RETN, "retn") \
16.124 + _(CALL, "call") \
16.125 + _(UNGEN_CALL_PRI, "call.pri") \
16.126 + _(JUMP, "jump") \
16.127 + _(UNGEN_JREL, "jrel") \
16.128 + _(JZER, "jzer") \
16.129 + _(JNZ, "jnz") \
16.130 + _(JEQ, "jeq") \
16.131 + _(JNEQ, "jneq") \
16.132 + _(UNGEN_JLESS, "jsless") \
16.133 + _(UNGEN_JLEQ, "jleq") \
16.134 + _(UNGEN_JGRTR, "jgrtr") \
16.135 + _(UNGEN_JGEQ, "jgeq") \
16.136 + _(JSLESS, "jsless") \
16.137 + _(JSLEQ, "jsleq") \
16.138 + _(JSGRTR, "jsgrtr") \
16.139 + _(JSGEQ, "jsgeq") \
16.140 + _(SHL, "shl") \
16.141 + _(SHR, "shr") \
16.142 + _(SSHR, "sshr") \
16.143 + _(SHL_C_PRI, "shl.c.pri") \
16.144 + _(SHL_C_ALT, "shl.c.alt") \
16.145 + _(SHR_C_PRI, "shr.c.pri") \
16.146 + _(SHR_C_ALT, "shr.c.alt") \
16.147 + _(SMUL, "smul") \
16.148 + _(SDIV, "sdiv") \
16.149 + _(SDIV_ALT, "sdiv.alt") \
16.150 + _(UNGEN_UMUL, "umul") \
16.151 + _(UNGEN_UDIV, "udiv") \
16.152 + _(UNGEN_UDIV_ALT, "udiv.alt") \
16.153 + _(ADD, "add") \
16.154 + _(SUB, "sub") \
16.155 + _(SUB_ALT, "sub.alt") \
16.156 + _(AND, "and") \
16.157 + _(OR, "or") \
16.158 + _(XOR, "xor") \
16.159 + _(NOT, "not") \
16.160 + _(NEG, "neg") \
16.161 + _(INVERT, "invert") \
16.162 + _(ADD_C, "add.c") \
16.163 + _(SMUL_C, "smul.c") \
16.164 + _(ZERO_PRI, "zero.pri") \
16.165 + _(ZERO_ALT, "zero.alt") \
16.166 + _(ZERO, "zero") \
16.167 + _(ZERO_S, "zero.s") \
16.168 + _(UNGEN_SIGN_PRI, "sign.pri") \
16.169 + _(UNGEN_SIGN_ALT, "sign.alt") \
16.170 + _(EQ, "eq") \
16.171 + _(NEQ, "neq") \
16.172 + _(UNGEN_LESS, "less") \
16.173 + _(UNGEN_LEQ, "leq") \
16.174 + _(UNGEN_GRTR, "grtr") \
16.175 + _(UNGEN_GEQ, "geq") \
16.176 + _(SLESS, "sless") \
16.177 + _(SLEQ, "sleq") \
16.178 + _(SGRTR, "sgrtr") \
16.179 + _(SGEQ, "sgeq") \
16.180 + _(EQ_C_PRI, "eq.c.pri") \
16.181 + _(EQ_C_ALT, "eq.c.alt") \
16.182 + _(INC_PRI, "inc.pri") \
16.183 + _(INC_ALT, "inc.alt") \
16.184 + _(INC, "inc") \
16.185 + _(INC_S, "inc.s") \
16.186 + _(INC_I, "inc.i") \
16.187 + _(DEC_PRI, "dec.pri") \
16.188 + _(DEC_ALT, "dec.alt") \
16.189 + _(DEC, "dec") \
16.190 + _(DEC_S, "dec.s") \
16.191 + _(DEC_I, "dec.i") \
16.192 + _(MOVS, "movs") \
16.193 + _(UNGEN_CMPS, "cmps") \
16.194 + _(FILL, "fill") \
16.195 + _(HALT, "halt") \
16.196 + _(BOUNDS, "bounds") \
16.197 + _(UNGEN_SYSREQ_PRI,"sysreq.pri") \
16.198 + _(SYSREQ_C, "sysreq.c") \
16.199 + _(UNGEN_FILE, "file") \
16.200 + _(UNGEN_LINE, "line") \
16.201 + _(UNGEN_SYMBOL, "symbol") \
16.202 + _(UNGEN_SRANGE, "srange") \
16.203 + _(UNGEN_JUMP_PRI, "jump.pri") \
16.204 + _(SWITCH, "switch") \
16.205 + _(CASETBL, "casetbl") \
16.206 + _(SWAP_PRI, "swap.pri") \
16.207 + _(SWAP_ALT, "swap.alt") \
16.208 + _(PUSH_ADR, "push.adr") \
16.209 + _(NOP, "nop") \
16.210 + _(SYSREQ_N, "sysreq.n") \
16.211 + _(UNGEN_SYMTAG, "symtag") \
16.212 + _(BREAK, "break") \
16.213 + _(PUSH2_C, "push2.c") \
16.214 + _(PUSH2, "push2") \
16.215 + _(PUSH2_S, "push2.s") \
16.216 + _(PUSH2_ADR, "push2.adr") \
16.217 + _(PUSH3_C, "push3.c") \
16.218 + _(PUSH3, "push3") \
16.219 + _(PUSH3_S, "push3.s") \
16.220 + _(PUSH3_ADR, "push3.adr") \
16.221 + _(PUSH4_C, "push4.c") \
16.222 + _(PUSH4, "push4") \
16.223 + _(PUSH4_S, "push4.s") \
16.224 + _(PUSH4_ADR, "push4.adr") \
16.225 + _(PUSH5_C, "push5.c") \
16.226 + _(PUSH5, "push5") \
16.227 + _(PUSH5_S, "push5.s") \
16.228 + _(PUSH5_ADR, "push5.adr") \
16.229 + _(LOAD_BOTH, "load.both") \
16.230 + _(LOAD_S_BOTH, "load.s.both") \
16.231 + _(CONST, "const") \
16.232 + _(CONST_S, "const.s") \
16.233 + _(UNGEN_SYSREQ_D, "sysreq.d") \
16.234 + _(UNGEB_SYSREQ_ND,"sysreq.nd") \
16.235 + _(TRACKER_PUSH_C, "trk.push.c") \
16.236 + _(TRACKER_POP_SETHEAP,"trk.pop") \
16.237 + _(GENARRAY, "genarray") \
16.238 + _(GENARRAY_Z, "genarray.z") \
16.239 + _(STRADJUST_PRI, "stradjust.pri") \
16.240 + _(UNGEN_STKADJUST,"stackadjust") \
16.241 + _(ENDPROC, "endproc") \
16.242 + _(FABS, "fabs") \
16.243 + _(FLOAT, "float") \
16.244 + _(FLOATADD, "floatadd") \
16.245 + _(FLOATSUB, "floatsub") \
16.246 + _(FLOATMUL, "floatmul") \
16.247 + _(FLOATDIV, "floatdiv") \
16.248 + _(RND_TO_NEAREST, "round") \
16.249 + _(RND_TO_FLOOR, "floor") \
16.250 + _(RND_TO_CEIL, "ceil") \
16.251 + _(RND_TO_ZERO, "rndtozero") \
16.252 + _(FLOATCMP, "floatcmp")
16.253 +
16.254 +enum OPCODE {
16.255 +#define _(op, text) OP_##op,
16.256 + OPCODE_LIST(_)
16.257 +#undef _
16.258 + OPCODES_TOTAL
16.259 +};
16.260 +
16.261 +namespace SourcePawn {
16.262 + void SpewOpcode(const sp_plugin_t *plugin, cell_t *start, cell_t *cip);
16.263 +}
16.264 +
16.265 +#endif //_INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_
17.1 --- a/sourcepawn/jit/sp_vm_basecontext.cpp Thu Aug 08 09:40:23 2013 -0700
17.2 +++ b/sourcepawn/jit/sp_vm_basecontext.cpp Thu Aug 08 09:41:24 2013 -0700
17.3 @@ -1,5 +1,5 @@
17.4 /**
17.5 - * vim: set ts=4 :
17.6 + * vim: set ts=4 sw=4 tw=99 noet:
17.7 * =============================================================================
17.8 * SourcePawn
17.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
17.10 @@ -46,7 +46,6 @@
17.11 BaseContext::BaseContext(BaseRuntime *pRuntime)
17.12 {
17.13 m_pRuntime = pRuntime;
17.14 - m_pPlugin = m_pRuntime->m_pPlugin;
17.15
17.16 m_InExec = false;
17.17 m_CustomMsg = false;
17.18 @@ -75,8 +74,8 @@
17.19 m_pNullString = NULL;
17.20 }
17.21
17.22 - m_ctx.hp = m_pPlugin->data_size;
17.23 - m_ctx.sp = m_pPlugin->mem_size - sizeof(cell_t);
17.24 + m_ctx.hp = m_pRuntime->plugin()->data_size;
17.25 + m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t);
17.26 m_ctx.frm = m_ctx.sp;
17.27 m_ctx.n_err = SP_ERROR_NONE;
17.28 m_ctx.n_idx = SP_ERROR_NONE;
17.29 @@ -204,7 +203,7 @@
17.30 return SP_ERROR_HEAPLOW;
17.31 }
17.32
17.33 - addr = (cell_t *)(m_pPlugin->memory + m_ctx.hp);
17.34 + addr = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.hp);
17.35 /* store size of allocation in cells */
17.36 *addr = (cell_t)cells;
17.37 addr++;
17.38 @@ -229,12 +228,12 @@
17.39
17.40 /* check the bounds of this address */
17.41 local_addr -= sizeof(cell_t);
17.42 - if (local_addr < (cell_t)m_pPlugin->data_size || local_addr >= m_ctx.sp)
17.43 + if (local_addr < (cell_t)m_pRuntime->plugin()->data_size || local_addr >= m_ctx.sp)
17.44 {
17.45 return SP_ERROR_INVALID_ADDRESS;
17.46 }
17.47
17.48 - addr = (cell_t *)(m_pPlugin->memory + local_addr);
17.49 + addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr);
17.50 cellcount = (*addr) * sizeof(cell_t);
17.51 /* check if this memory count looks valid */
17.52 if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr)
17.53 @@ -250,7 +249,7 @@
17.54
17.55 int BaseContext::HeapRelease(cell_t local_addr)
17.56 {
17.57 - if (local_addr < (cell_t)m_pPlugin->data_size)
17.58 + if (local_addr < (cell_t)m_pRuntime->plugin()->data_size)
17.59 {
17.60 return SP_ERROR_INVALID_ADDRESS;
17.61 }
17.62 @@ -334,14 +333,14 @@
17.63 int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
17.64 {
17.65 if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
17.66 - || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
17.67 + || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
17.68 {
17.69 return SP_ERROR_INVALID_ADDRESS;
17.70 }
17.71
17.72 if (phys_addr)
17.73 {
17.74 - *phys_addr = (cell_t *)(m_pPlugin->memory + local_addr);
17.75 + *phys_addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr);
17.76 }
17.77
17.78 return SP_ERROR_NONE;
17.79 @@ -365,11 +364,11 @@
17.80 int BaseContext::LocalToString(cell_t local_addr, char **addr)
17.81 {
17.82 if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
17.83 - || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
17.84 + || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
17.85 {
17.86 return SP_ERROR_INVALID_ADDRESS;
17.87 }
17.88 - *addr = (char *)(m_pPlugin->memory + local_addr);
17.89 + *addr = (char *)(m_pRuntime->plugin()->memory + local_addr);
17.90
17.91 return SP_ERROR_NONE;
17.92 }
17.93 @@ -385,7 +384,7 @@
17.94 size_t len;
17.95
17.96 if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
17.97 - || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
17.98 + || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
17.99 {
17.100 return SP_ERROR_INVALID_ADDRESS;
17.101 }
17.102 @@ -396,7 +395,7 @@
17.103 }
17.104
17.105 len = strlen(source);
17.106 - dest = (char *)(m_pPlugin->memory + local_addr);
17.107 + dest = (char *)(m_pRuntime->plugin()->memory + local_addr);
17.108
17.109 if (len >= bytes)
17.110 {
17.111 @@ -455,7 +454,7 @@
17.112
17.113 if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
17.114 || (local_addr < 0)
17.115 - || ((ucell_t)local_addr >= m_pPlugin->mem_size))
17.116 + || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
17.117 {
17.118 return SP_ERROR_INVALID_ADDRESS;
17.119 }
17.120 @@ -466,7 +465,7 @@
17.121 }
17.122
17.123 len = strlen(source);
17.124 - dest = (char *)(m_pPlugin->memory + local_addr);
17.125 + dest = (char *)(m_pRuntime->plugin()->memory + local_addr);
17.126
17.127 if ((size_t)len >= maxbytes)
17.128 {
17.129 @@ -586,21 +585,18 @@
17.130
17.131 /* We got this far. It's time to start profiling. */
17.132
17.133 - if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
17.134 + if ((m_pRuntime->plugin()->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
17.135 {
17.136 - serial = m_pPlugin->profiler->OnCallbackBegin(this, pubfunc);
17.137 + serial = m_pRuntime->plugin()->profiler->OnCallbackBegin(this, pubfunc);
17.138 }
17.139
17.140 /* See if we have to compile the callee. */
17.141 if ((fn = m_pRuntime->m_PubJitFuncs[public_id]) == NULL)
17.142 {
17.143 - uint32_t func_idx;
17.144 -
17.145 /* We might not have to - check pcode offset. */
17.146 - if ((func_idx = FuncLookup((CompData *)m_pRuntime->m_pCo, pubfunc->code_offs)) != 0)
17.147 + fn = m_pRuntime->GetJittedFunctionByOffset(pubfunc->code_offs);
17.148 + if (fn)
17.149 {
17.150 - fn = m_pRuntime->GetJittedFunction(func_idx);
17.151 - assert(fn != NULL);
17.152 m_pRuntime->m_PubJitFuncs[public_id] = fn;
17.153 }
17.154 else
17.155 @@ -629,7 +625,7 @@
17.156 /* Push parameters */
17.157
17.158 m_ctx.sp -= sizeof(cell_t) * (num_params + 1);
17.159 - sp = (cell_t *)(m_pPlugin->memory + m_ctx.sp);
17.160 + sp = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.sp);
17.161
17.162 sp[0] = num_params;
17.163 for (unsigned int i = 0; i < num_params; i++)
17.164 @@ -687,9 +683,9 @@
17.165 m_ctx.hp = save_hp;
17.166 m_ctx.rp = save_rp;
17.167
17.168 - if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
17.169 + if ((m_pRuntime->plugin()->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
17.170 {
17.171 - m_pPlugin->profiler->OnCallbackEnd(serial);
17.172 + m_pRuntime->plugin()->profiler->OnCallbackEnd(serial);
17.173 }
17.174
17.175 m_ctx.err_cip = save_cip;
17.176 @@ -746,7 +742,6 @@
17.177 {
17.178 uint32_t max, iter;
17.179 sp_fdbg_symbol_t *sym;
17.180 - sp_fdbg_arraydim_t *arr;
17.181 uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols);
17.182
17.183 max = m_pPlugin->debug.syms_num;
17.184 @@ -765,7 +760,6 @@
17.185 if (sym->dimcount > 0)
17.186 {
17.187 cursor += sizeof(sp_fdbg_symbol_t);
17.188 - arr = (sp_fdbg_arraydim_t *)cursor;
17.189 cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
17.190 continue;
17.191 }
17.192 @@ -779,7 +773,6 @@
17.193 {
17.194 uint32_t max, iter;
17.195 sp_u_fdbg_symbol_t *sym;
17.196 - sp_u_fdbg_arraydim_t *arr;
17.197 uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols);
17.198
17.199 max = m_pPlugin->debug.syms_num;
17.200 @@ -798,7 +791,6 @@
17.201 if (sym->dimcount > 0)
17.202 {
17.203 cursor += sizeof(sp_u_fdbg_symbol_t);
17.204 - arr = (sp_u_fdbg_arraydim_t *)cursor;
17.205 cursor += sizeof(sp_u_fdbg_arraydim_t) * sym->dimcount;
17.206 continue;
17.207 }
17.208 @@ -848,7 +840,7 @@
17.209
17.210 cell_t *BaseContext::GetLocalParams()
17.211 {
17.212 - return (cell_t *)(m_pPlugin->memory + m_ctx.frm + (2 * sizeof(cell_t)));
17.213 + return (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.frm + (2 * sizeof(cell_t)));
17.214 }
17.215
17.216 void BaseContext::SetKey(int k, void *value)
18.1 --- a/sourcepawn/jit/sp_vm_basecontext.h Thu Aug 08 09:40:23 2013 -0700
18.2 +++ b/sourcepawn/jit/sp_vm_basecontext.h Thu Aug 08 09:41:24 2013 -0700
18.3 @@ -100,7 +100,6 @@
18.4 void SetErrorMessage(const char *msg, va_list ap);
18.5 void _SetErrorMessage(const char *msg, ...);
18.6 private:
18.7 - sp_plugin_t *m_pPlugin;
18.8 cell_t *m_pNullVec;
18.9 cell_t *m_pNullString;
18.10 char m_MsgCache[1024];
19.1 --- a/sourcepawn/jit/sp_vm_engine.cpp Thu Aug 08 09:40:23 2013 -0700
19.2 +++ b/sourcepawn/jit/sp_vm_engine.cpp Thu Aug 08 09:41:24 2013 -0700
19.3 @@ -58,7 +58,7 @@
19.4
19.5 using namespace SourcePawn;
19.6
19.7 -#define ERROR_MESSAGE_MAX 25
19.8 +#define ERROR_MESSAGE_MAX 29
19.9 static const char *g_ErrorMsgTable[] =
19.10 {
19.11 NULL,
19.12 @@ -89,6 +89,8 @@
19.13 "Call was aborted",
19.14 "Plugin format is too old",
19.15 "Plugin format is too new",
19.16 + "Out of memory",
19.17 + "Integer overflow"
19.18 };
19.19
19.20 const char *SourcePawnEngine::GetErrorString(int error)
20.1 --- a/sourcepawn/jit/x86/jit_x86.cpp Thu Aug 08 09:40:23 2013 -0700
20.2 +++ b/sourcepawn/jit/x86/jit_x86.cpp Thu Aug 08 09:41:24 2013 -0700
20.3 @@ -1,5 +1,5 @@
20.4 /**
20.5 - * vim: set ts=4 :
20.6 + * vim: set ts=2 sw=2 tw=99 et:
20.7 * =============================================================================
20.8 * SourceMod
20.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
20.10 @@ -33,8 +33,6 @@
20.11 #include <stdlib.h>
20.12 #include <assert.h>
20.13 #include "jit_x86.h"
20.14 -#include "opcode_helpers.h"
20.15 -#include <x86_macros.h>
20.16 #include "../sp_vm_engine.h"
20.17 #include "../engine2.h"
20.18 #include "../BaseRuntime.h"
20.19 @@ -46,2994 +44,1971 @@
20.20 #include "ungen_opcodes.h"
20.21 #endif
20.22
20.23 +#define __ masm.
20.24 +
20.25 JITX86 g_Jit;
20.26 KeCodeCache *g_pCodeCache = NULL;
20.27 ISourcePawnEngine *engine = &g_engine1;
20.28
20.29 -inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
20.30 -{
20.31 - return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
20.32 -}
20.33 -
20.34 -inline void WriteOp_Move_Pri(JitWriter *jit)
20.35 -{
20.36 - //mov eax, edx
20.37 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.38 -}
20.39 -
20.40 -inline void WriteOp_Move_Alt(JitWriter *jit)
20.41 -{
20.42 - //mov edx, eax
20.43 - IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
20.44 -}
20.45 -
20.46 -inline void WriteOp_Xchg(JitWriter *jit)
20.47 -{
20.48 - //xchg eax, edx
20.49 - IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT);
20.50 -}
20.51 -
20.52 -inline void WriteOp_Push(JitWriter *jit)
20.53 -{
20.54 - //push stack, DAT offset based
20.55 - //sub edi, 4
20.56 - //mov ecx, [ebp+<val>]
20.57 - //mov [edi], ecx
20.58 - cell_t val = jit->read_cell();
20.59 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.60 - //optimize encoding a bit...
20.61 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.62 - {
20.63 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
20.64 - } else {
20.65 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
20.66 - }
20.67 - IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
20.68 -}
20.69 -
20.70 -inline void WriteOp_Push_C(JitWriter *jit)
20.71 -{
20.72 - //push stack
20.73 - //mov [edi-4], <val>
20.74 - //sub edi, 4
20.75 - cell_t val = jit->read_cell();
20.76 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4);
20.77 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.78 -}
20.79 -
20.80 -inline void WriteOp_Zero(JitWriter *jit)
20.81 -{
20.82 - //mov [ebp+<val>], 0
20.83 - cell_t val = jit->read_cell();
20.84 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.85 - {
20.86 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val);
20.87 - } else {
20.88 - IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val);
20.89 - }
20.90 -}
20.91 -
20.92 -inline void WriteOp_Zero_S(JitWriter *jit)
20.93 +static inline void *
20.94 +LinkCode(AssemblerX86 &masm)
20.95 {
20.96 - //mov [ebx+<val>], 0
20.97 - cell_t val = jit->read_cell();
20.98 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.99 - {
20.100 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val);
20.101 - } else {
20.102 - IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val);
20.103 - }
20.104 -}
20.105 -
20.106 -inline void WriteOp_Push_S(JitWriter *jit)
20.107 -{
20.108 - //push stack, FRM offset based
20.109 - //sub edi, 4
20.110 - //mov ecx, [ebx+<val>]
20.111 - //mov [edi], ecx
20.112 - cell_t val = jit->read_cell();
20.113 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.114 - //optimize encoding a bit...
20.115 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.116 - {
20.117 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
20.118 - } else {
20.119 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
20.120 - }
20.121 - IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
20.122 -}
20.123 -
20.124 -inline void WriteOp_Push_Pri(JitWriter *jit)
20.125 -{
20.126 - //mov [edi-4], eax
20.127 - //sub edi, 4
20.128 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4);
20.129 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.130 -}
20.131 + if (masm.outOfMemory())
20.132 + return NULL;
20.133
20.134 -inline void WriteOp_Push_Alt(JitWriter *jit)
20.135 -{
20.136 - //mov [edi-4], edx
20.137 - //sub edi, 4
20.138 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4);
20.139 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.140 -}
20.141 -
20.142 -inline void WriteOp_Push2_C(JitWriter *jit)
20.143 -{
20.144 - Macro_PushN_C(jit, 2);
20.145 -}
20.146 -
20.147 -inline void WriteOp_Push3_C(JitWriter *jit)
20.148 -{
20.149 - Macro_PushN_C(jit, 3);
20.150 -}
20.151 + void *code = Knight::KE_AllocCode(g_pCodeCache, masm.length());
20.152 + if (!code)
20.153 + return NULL;
20.154
20.155 -inline void WriteOp_Push4_C(JitWriter *jit)
20.156 -{
20.157 - Macro_PushN_C(jit, 4);
20.158 -}
20.159 -
20.160 -inline void WriteOp_Push5_C(JitWriter *jit)
20.161 -{
20.162 - Macro_PushN_C(jit, 5);
20.163 -}
20.164 -
20.165 -inline void WriteOp_Push2_Adr(JitWriter *jit)
20.166 -{
20.167 - Macro_PushN_Addr(jit, 2);
20.168 -}
20.169 -
20.170 -inline void WriteOp_Push3_Adr(JitWriter *jit)
20.171 -{
20.172 - Macro_PushN_Addr(jit, 3);
20.173 -}
20.174 -
20.175 -inline void WriteOp_Push4_Adr(JitWriter *jit)
20.176 -{
20.177 - Macro_PushN_Addr(jit, 4);
20.178 + masm.emitToExecutableMemory(code);
20.179 + return code;
20.180 }
20.181
20.182 -inline void WriteOp_Push5_Adr(JitWriter *jit)
20.183 -{
20.184 - Macro_PushN_Addr(jit, 5);
20.185 -}
20.186 -
20.187 -inline void WriteOp_Push2_S(JitWriter *jit)
20.188 -{
20.189 - Macro_PushN_S(jit, 2);
20.190 -}
20.191 -
20.192 -inline void WriteOp_Push3_S(JitWriter *jit)
20.193 -{
20.194 - Macro_PushN_S(jit, 3);
20.195 -}
20.196 -
20.197 -inline void WriteOp_Push4_S(JitWriter *jit)
20.198 -{
20.199 - Macro_PushN_S(jit, 4);
20.200 -}
20.201 -
20.202 -inline void WriteOp_Push5_S(JitWriter *jit)
20.203 -{
20.204 - Macro_PushN_S(jit, 5);
20.205 -}
20.206 -
20.207 -inline void WriteOp_Push5(JitWriter *jit)
20.208 -{
20.209 - Macro_PushN(jit, 5);
20.210 -}
20.211 -
20.212 -inline void WriteOp_Push4(JitWriter *jit)
20.213 -{
20.214 - Macro_PushN(jit, 4);
20.215 -}
20.216 -
20.217 -inline void WriteOp_Push3(JitWriter *jit)
20.218 -{
20.219 - Macro_PushN(jit, 3);
20.220 -}
20.221 -
20.222 -inline void WriteOp_Push2(JitWriter *jit)
20.223 -{
20.224 - Macro_PushN(jit, 2);
20.225 -}
20.226 -
20.227 -inline void WriteOp_Zero_Pri(JitWriter *jit)
20.228 -{
20.229 - //xor eax, eax
20.230 - IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
20.231 -}
20.232 -
20.233 -inline void WriteOp_Zero_Alt(JitWriter *jit)
20.234 -{
20.235 - //xor edx, edx
20.236 - IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
20.237 -}
20.238 -
20.239 -inline void WriteOp_Add(JitWriter *jit)
20.240 -{
20.241 - //add eax, edx
20.242 - IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.243 -}
20.244 -
20.245 -inline void WriteOp_Sub(JitWriter *jit)
20.246 -{
20.247 - //sub eax, edx
20.248 - IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.249 -}
20.250 -
20.251 -inline void WriteOp_Sub_Alt(JitWriter *jit)
20.252 +static inline ConditionCode
20.253 +OpToCondition(OPCODE op)
20.254 {
20.255 - //neg eax
20.256 - //add eax, edx
20.257 - IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
20.258 - IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.259 -}
20.260 -
20.261 -inline void WriteOp_Proc(JitWriter *jit)
20.262 -{
20.263 -#if 0 /* :TODO: We no longer use this */
20.264 - /* Specialized code to align this taking in account the function magic number */
20.265 - jitoffs_t cur_offs = jit->get_outputpos();
20.266 - jitoffs_t offset = ((cur_offs & 0xFFFFFFF8) + 8) - cur_offs;
20.267 - if (!((offset + cur_offs) & 8))
20.268 - {
20.269 - offset += 8;
20.270 - }
20.271 - if (offset)
20.272 - {
20.273 - for (jit_uint32_t i=0; i<offset; i++)
20.274 - {
20.275 - jit->write_ubyte(IA32_INT3);
20.276 - }
20.277 - }
20.278 -
20.279 - /* Write the info struct about this function */
20.280 - jit->write_uint32(JIT_FUNCMAGIC);
20.281 - jit->write_uint32(co->func_idx);
20.282 -
20.283 - /* Now we have to backpatch our reloction offset! */
20.284 - {
20.285 - jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
20.286 - uint8_t *rebase = ((CompData *)jit->data)->rebase;
20.287 - *(jitoffs_t *)(rebase + offs) = jit->get_outputpos();
20.288 - }
20.289 -
20.290 - /* Lastly, if we're writing, keep track of the function count */
20.291 - if (jit->outbase)
20.292 - {
20.293 - co->func_idx++;
20.294 - }
20.295 -#endif
20.296 -
20.297 - //push old frame on stack:
20.298 - //mov ecx, [esi+frm]
20.299 - //mov [edi-4], ecx
20.300 - //sub edi, 8 ;extra un-used slot for non-existant CIP
20.301 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
20.302 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4);
20.303 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.304 -
20.305 - //save frame:
20.306 - //mov ecx, edi - get new frame
20.307 - //mov ebx, edi - store frame back
20.308 - //sub ecx, ebp - relocate local frame
20.309 - //mov [esi+frm], ecx
20.310 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
20.311 - IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
20.312 - IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
20.313 - IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG);
20.314 -}
20.315 -
20.316 -inline void WriteOp_Lidx_B(JitWriter *jit)
20.317 -{
20.318 - cell_t val = jit->read_cell();
20.319 - //shl eax, <val>
20.320 - //add eax, edx
20.321 - //mov eax, [ebp+eax]
20.322 - IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
20.323 - IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.324 - Write_Check_VerifyAddr(jit, AMX_REG_PRI);
20.325 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.326 -}
20.327 -
20.328 -inline void WriteOp_Idxaddr_B(JitWriter *jit)
20.329 -{
20.330 - //shl eax, <val>
20.331 - //add eax, edx
20.332 - cell_t val = jit->read_cell();
20.333 - IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
20.334 - IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.335 + switch (op) {
20.336 + case OP_EQ:
20.337 + case OP_JEQ:
20.338 + return equal;
20.339 + case OP_NEQ:
20.340 + case OP_JNEQ:
20.341 + return not_equal;
20.342 + case OP_SLESS:
20.343 + case OP_JSLESS:
20.344 + return less;
20.345 + case OP_SLEQ:
20.346 + case OP_JSLEQ:
20.347 + return less_equal;
20.348 + case OP_SGRTR:
20.349 + case OP_JSGRTR:
20.350 + return greater;
20.351 + case OP_SGEQ:
20.352 + case OP_JSGEQ:
20.353 + return greater_equal;
20.354 + default:
20.355 + assert(false);
20.356 + return negative;
20.357 + }
20.358 }
20.359
20.360 -inline void WriteOp_Shl(JitWriter *jit)
20.361 -{
20.362 - //mov ecx, edx
20.363 - //shl eax, cl
20.364 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
20.365 - IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
20.366 -}
20.367 -
20.368 -inline void WriteOp_Shr(JitWriter *jit)
20.369 +struct array_creation_t
20.370 {
20.371 - //mov ecx, edx
20.372 - //shr eax, cl
20.373 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
20.374 - IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
20.375 -}
20.376 + const cell_t *dim_list; /* Dimension sizes */
20.377 + cell_t dim_count; /* Number of dimensions */
20.378 + cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */
20.379 + cell_t *base; /* array base */
20.380 +};
20.381
20.382 -inline void WriteOp_Sshr(JitWriter *jit)
20.383 -{
20.384 - //mov ecx, edx
20.385 - //sar eax, cl
20.386 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
20.387 - IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
20.388 -}
20.389 -
20.390 -inline void WriteOp_Shl_C_Pri(JitWriter *jit)
20.391 +static cell_t
20.392 +GenerateInnerArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs)
20.393 {
20.394 - //shl eax, <val>
20.395 - jit_uint8_t val = (jit_uint8_t)jit->read_cell();
20.396 - if (val == 1)
20.397 - {
20.398 - IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG);
20.399 - } else {
20.400 - IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
20.401 - }
20.402 -}
20.403 + cell_t write_offs = cur_offs;
20.404 + cell_t *data_offs = ar->data_offs;
20.405
20.406 -inline void WriteOp_Shl_C_Alt(JitWriter *jit)
20.407 -{
20.408 - //shl edx, <val>
20.409 - jit_uint8_t val = (jit_uint8_t)jit->read_cell();
20.410 - if (val == 1)
20.411 - {
20.412 - IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG);
20.413 - } else {
20.414 - IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
20.415 - }
20.416 -}
20.417 + cur_offs += ar->dim_list[dim];
20.418
20.419 -inline void WriteOp_Shr_C_Pri(JitWriter *jit)
20.420 -{
20.421 - //shr eax, <val>
20.422 - jit_uint8_t val = (jit_uint8_t)jit->read_cell();
20.423 - if (val == 1)
20.424 - {
20.425 - IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG);
20.426 - } else {
20.427 - IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
20.428 - }
20.429 -}
20.430 + // Dimension n-x where x > 2 will have sub-vectors.
20.431 + // Otherwise, we just need to reference the data section.
20.432 + if (ar->dim_count > 2 && dim < ar->dim_count - 2) {
20.433 + // For each index at this dimension, write offstes to our sub-vectors.
20.434 + // After we write one sub-vector, we generate its sub-vectors recursively.
20.435 + // At the end, we're given the next offset we can use.
20.436 + for (int i = 0; i < ar->dim_list[dim]; i++) {
20.437 + ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t);
20.438 + write_offs++;
20.439 + cur_offs = GenerateInnerArrayIndirectionVectors(ar, dim + 1, cur_offs);
20.440 + }
20.441 + } else {
20.442 + // In this section, there are no sub-vectors, we need to write offsets
20.443 + // to the data. This is separate so the data stays in one big chunk.
20.444 + // The data offset will increment by the size of the last dimension,
20.445 + // because that is where the data is finally computed as.
20.446 + for (int i = 0; i < ar->dim_list[dim]; i++) {
20.447 + ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t);
20.448 + write_offs++;
20.449 + *data_offs = *data_offs + ar->dim_list[dim + 1];
20.450 + }
20.451 + }
20.452
20.453 -inline void WriteOp_Shr_C_Alt(JitWriter *jit)
20.454 -{
20.455 - //shr edx, <val>
20.456 - jit_uint8_t val = (jit_uint8_t)jit->read_cell();
20.457 - if (val == 1)
20.458 - {
20.459 - IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG);
20.460 - } else {
20.461 - IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
20.462 - }
20.463 + return cur_offs;
20.464 }
20.465
20.466 -inline void WriteOp_SMul(JitWriter *jit)
20.467 -{
20.468 - //mov ecx, edx
20.469 - //imul edx
20.470 - //mov edx, ecx
20.471 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
20.472 - IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG);
20.473 - IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
20.474 -}
20.475 -
20.476 -inline void WriteOp_Not(JitWriter *jit)
20.477 -{
20.478 - //test eax, eax
20.479 - //mov eax, 0
20.480 - //sete al
20.481 - IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
20.482 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.483 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
20.484 -}
20.485 -
20.486 -inline void WriteOp_Neg(JitWriter *jit)
20.487 -{
20.488 - //neg eax
20.489 - IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
20.490 -}
20.491 -
20.492 -inline void WriteOp_Xor(JitWriter *jit)
20.493 -{
20.494 - //xor eax, edx
20.495 - IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.496 -}
20.497 -
20.498 -inline void WriteOp_Or(JitWriter *jit)
20.499 +static cell_t
20.500 +calc_indirection(const array_creation_t *ar, cell_t dim)
20.501 {
20.502 - //or eax, edx
20.503 - IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.504 -}
20.505 -
20.506 -inline void WriteOp_And(JitWriter *jit)
20.507 -{
20.508 - //and eax, edx
20.509 - IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.510 -}
20.511 -
20.512 -inline void WriteOp_Invert(JitWriter *jit)
20.513 -{
20.514 - //not eax
20.515 - IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG);
20.516 -}
20.517 -
20.518 -inline void WriteOp_Add_C(JitWriter *jit)
20.519 -{
20.520 - //add eax, <val>
20.521 - cell_t val = jit->read_cell();
20.522 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.523 - IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
20.524 - else
20.525 - IA32_Add_Eax_Imm32(jit, val);
20.526 -}
20.527 -
20.528 -inline void WriteOp_SMul_C(JitWriter *jit)
20.529 -{
20.530 - //imul eax, <val>
20.531 - cell_t val = jit->read_cell();
20.532 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.533 - IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
20.534 - else
20.535 - IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val);
20.536 -}
20.537 -
20.538 -inline void WriteOp_Sign_Pri(JitWriter *jit)
20.539 -{
20.540 - //shl eax, 24
20.541 - //sar eax, 24
20.542 - IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
20.543 - IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
20.544 + cell_t size = ar->dim_list[dim];
20.545 + if (dim < ar->dim_count - 2)
20.546 + size += ar->dim_list[dim] * calc_indirection(ar, dim + 1);
20.547 + return size;
20.548 }
20.549
20.550 -inline void WriteOp_Sign_Alt(JitWriter *jit)
20.551 -{
20.552 - //shl edx, 24
20.553 - //sar edx, 24
20.554 - IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
20.555 - IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
20.556 -}
20.557 -
20.558 -inline void WriteOp_Eq(JitWriter *jit)
20.559 -{
20.560 - //cmp eax, edx ; PRI == ALT ?
20.561 - //mov eax, 0
20.562 - //sete al
20.563 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.564 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.565 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
20.566 -}
20.567 -
20.568 -inline void WriteOp_Neq(JitWriter *jit)
20.569 -{
20.570 - //cmp eax, edx ; PRI != ALT ?
20.571 - //mov eax, 0
20.572 - //setne al
20.573 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.574 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.575 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE);
20.576 -}
20.577 -
20.578 -inline void WriteOp_Sless(JitWriter *jit)
20.579 +static void
20.580 +GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero)
20.581 {
20.582 - //cmp eax, edx ; PRI < ALT ? (signed)
20.583 - //mov eax, 0
20.584 - //setl al
20.585 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.586 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.587 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L);
20.588 -}
20.589 -
20.590 -inline void WriteOp_Sleq(JitWriter *jit)
20.591 -{
20.592 - //cmp eax, edx ; PRI <= ALT ? (signed)
20.593 - //mov eax, 0
20.594 - //setle al
20.595 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.596 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.597 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE);
20.598 -}
20.599 + array_creation_t ar;
20.600 + cell_t data_offs;
20.601
20.602 -inline void WriteOp_Sgrtr(JitWriter *jit)
20.603 -{
20.604 - //cmp eax, edx ; PRI > ALT ? (signed)
20.605 - //mov eax, 0
20.606 - //setg al
20.607 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.608 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.609 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G);
20.610 -}
20.611 + /* Reverse the dimensions */
20.612 + cell_t dim_list[sDIMEN_MAX];
20.613 + int cur_dim = 0;
20.614 + for (int i = _dimcount - 1; i >= 0; i--)
20.615 + dim_list[cur_dim++] = dims[i];
20.616 +
20.617 + ar.base = arraybase;
20.618 + ar.dim_list = dim_list;
20.619 + ar.dim_count = _dimcount;
20.620 + ar.data_offs = &data_offs;
20.621
20.622 -inline void WriteOp_Sgeq(JitWriter *jit)
20.623 -{
20.624 - //cmp eax, edx ; PRI >= ALT ? (signed)
20.625 - //mov eax, 0
20.626 - //setge al
20.627 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.628 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.629 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE);
20.630 + data_offs = calc_indirection(&ar, 0);
20.631 +
20.632 + GenerateInnerArrayIndirectionVectors(&ar, 0, 0);
20.633 }
20.634
20.635 -inline void WriteOp_Eq_C_Pri(JitWriter *jit)
20.636 -{
20.637 - //cmp eax, <val> ; PRI == value ?
20.638 - //mov eax, 0
20.639 - //sete al
20.640 - cell_t val = jit->read_cell();
20.641 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.642 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
20.643 - else
20.644 - IA32_Cmp_Eax_Imm32(jit, val);
20.645 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
20.646 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
20.647 -}
20.648 -
20.649 -inline void WriteOp_Eq_C_Alt(JitWriter *jit)
20.650 +static int
20.651 +JIT_VerifyLowBoundTracker(sp_context_t *ctx)
20.652 {
20.653 - //xor eax, eax
20.654 - //cmp edx, <val> ; ALT == value ?
20.655 - //sete al
20.656 - cell_t val = jit->read_cell();
20.657 - IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
20.658 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.659 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val);
20.660 - else
20.661 - IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val);
20.662 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
20.663 -}
20.664 -
20.665 -inline void WriteOp_Inc_Pri(JitWriter *jit)
20.666 -{
20.667 - //add eax, 1
20.668 - IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
20.669 -}
20.670 -
20.671 -inline void WriteOp_Inc_Alt(JitWriter *jit)
20.672 -{
20.673 - //add edx, 1
20.674 - IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
20.675 + tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
20.676 + if (trk->pCur <= trk->pBase)
20.677 + return SP_ERROR_TRACKER_BOUNDS;
20.678 + return SP_ERROR_NONE;
20.679 }
20.680
20.681 -inline void WriteOp_Inc(JitWriter *jit)
20.682 -{
20.683 - //add [ebp+<val>], 1
20.684 - cell_t val = jit->read_cell();
20.685 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.686 - IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
20.687 - else
20.688 - IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
20.689 -}
20.690 -
20.691 -inline void WriteOp_Inc_S(JitWriter *jit)
20.692 -{
20.693 - //add [ebx+<val>], 1
20.694 - cell_t val = jit->read_cell();
20.695 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.696 - IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
20.697 - else
20.698 - IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
20.699 -}
20.700 -
20.701 -inline void WriteOp_Inc_I(JitWriter *jit)
20.702 +static int
20.703 +JIT_VerifyOrAllocateTracker(sp_context_t *ctx)
20.704 {
20.705 - //add [ebp+eax], 1
20.706 - IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
20.707 -}
20.708 + tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
20.709
20.710 -inline void WriteOp_Dec_Pri(JitWriter *jit)
20.711 -{
20.712 - //sub eax, 1
20.713 - IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
20.714 -}
20.715 + if ((size_t)(trk->pCur - trk->pBase) >= trk->size)
20.716 + return SP_ERROR_TRACKER_BOUNDS;
20.717
20.718 -inline void WriteOp_Dec_Alt(JitWriter *jit)
20.719 -{
20.720 - //sub edx, 1
20.721 - IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
20.722 -}
20.723 + if (trk->pCur+1 - (trk->pBase + trk->size) == 0) {
20.724 + size_t disp = trk->size - 1;
20.725 + trk->size *= 2;
20.726 + trk->pBase = (ucell_t *)realloc(trk->pBase, trk->size * sizeof(cell_t));
20.727
20.728 -inline void WriteOp_Dec(JitWriter *jit)
20.729 -{
20.730 - //sub [ebp+<val>], 1
20.731 - cell_t val = jit->read_cell();
20.732 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.733 - {
20.734 - IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
20.735 - } else {
20.736 - IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
20.737 - }
20.738 + if (!trk->pBase)
20.739 + return SP_ERROR_TRACKER_BOUNDS;
20.740 +
20.741 + trk->pCur = trk->pBase + disp;
20.742 + }
20.743 +
20.744 + return SP_ERROR_NONE;
20.745 }
20.746
20.747 -inline void WriteOp_Dec_S(JitWriter *jit)
20.748 -{
20.749 - //sub [ebx+<val>], 1
20.750 - cell_t val = jit->read_cell();
20.751 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.752 - {
20.753 - IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
20.754 - } else {
20.755 - IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
20.756 - }
20.757 -}
20.758 -
20.759 -inline void WriteOp_Dec_I(JitWriter *jit)
20.760 -{
20.761 - //sub [ebp+eax], 1
20.762 - IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
20.763 -}
20.764 -
20.765 -inline void WriteOp_Load_Pri(JitWriter *jit)
20.766 -{
20.767 - //mov eax, [ebp+<val>]
20.768 - cell_t val = jit->read_cell();
20.769 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.770 - {
20.771 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
20.772 - } else {
20.773 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
20.774 - }
20.775 -}
20.776 -
20.777 -inline void WriteOp_Load_Alt(JitWriter *jit)
20.778 -{
20.779 - //mov edx, [ebp+<val>]
20.780 - cell_t val = jit->read_cell();
20.781 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.782 - {
20.783 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
20.784 - } else {
20.785 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
20.786 - }
20.787 -}
20.788 -
20.789 -inline void WriteOp_Load_S_Pri(JitWriter *jit)
20.790 -{
20.791 - //mov eax, [ebx+<val>]
20.792 - cell_t val = jit->read_cell();
20.793 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.794 - {
20.795 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
20.796 - } else {
20.797 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
20.798 - }
20.799 -}
20.800 -
20.801 -inline void WriteOp_Load_S_Alt(JitWriter *jit)
20.802 -{
20.803 - //mov edx, [ebx+<val>]
20.804 - cell_t val = jit->read_cell();
20.805 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.806 - {
20.807 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
20.808 - } else {
20.809 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
20.810 - }
20.811 -}
20.812 -
20.813 -inline void WriteOp_Lref_Pri(JitWriter *jit)
20.814 +#if !defined NDEBUG
20.815 +static const char *
20.816 +GetFunctionName(const sp_plugin_t *plugin, uint32_t offs)
20.817 {
20.818 - //mov eax, [ebp+<val>]
20.819 - //mov eax, [ebp+eax]
20.820 - cell_t val = jit->read_cell();
20.821 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.822 - {
20.823 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
20.824 - } else {
20.825 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
20.826 - }
20.827 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.828 -}
20.829 + if (!plugin->debug.unpacked) {
20.830 + uint32_t max, iter;
20.831 + sp_fdbg_symbol_t *sym;
20.832 + sp_fdbg_arraydim_t *arr;
20.833 + uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
20.834
20.835 -inline void WriteOp_Lref_Alt(JitWriter *jit)
20.836 -{
20.837 - //mov edx, [ebp+<val>]
20.838 - //mov edx, [ebp+edx]
20.839 - cell_t val = jit->read_cell();
20.840 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.841 - {
20.842 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
20.843 - } else {
20.844 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
20.845 - }
20.846 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
20.847 -}
20.848 + max = plugin->debug.syms_num;
20.849 + for (iter = 0; iter < max; iter++) {
20.850 + sym = (sp_fdbg_symbol_t *)cursor;
20.851
20.852 -inline void WriteOp_Lref_S_Pri(JitWriter *jit)
20.853 -{
20.854 - //mov eax, [ebx+<val>]
20.855 - //mov eax, [ebp+eax]
20.856 - cell_t val = jit->read_cell();
20.857 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.858 - {
20.859 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
20.860 - } else {
20.861 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
20.862 - }
20.863 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.864 -}
20.865 + if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs)
20.866 + return plugin->debug.stringbase + sym->name;
20.867
20.868 -inline void WriteOp_Lref_S_Alt(JitWriter *jit)
20.869 -{
20.870 - //mov edx, [ebx+<val>]
20.871 - //mov edx, [ebp+edx]
20.872 - cell_t val = jit->read_cell();
20.873 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.874 - {
20.875 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
20.876 - } else {
20.877 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
20.878 - }
20.879 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
20.880 -}
20.881 -
20.882 -inline void WriteOp_Const_Pri(JitWriter *jit)
20.883 -{
20.884 - //mov eax, <val>
20.885 - cell_t val = jit->read_cell();
20.886 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val);
20.887 -}
20.888 + if (sym->dimcount > 0) {
20.889 + cursor += sizeof(sp_fdbg_symbol_t);
20.890 + arr = (sp_fdbg_arraydim_t *)cursor;
20.891 + cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
20.892 + continue;
20.893 + }
20.894
20.895 -inline void WriteOp_Const_Alt(JitWriter *jit)
20.896 -{
20.897 - //mov edx, <val>
20.898 - cell_t val = jit->read_cell();
20.899 - IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val);
20.900 -}
20.901 + cursor += sizeof(sp_fdbg_symbol_t);
20.902 + }
20.903 + } else {
20.904 + uint32_t max, iter;
20.905 + sp_u_fdbg_symbol_t *sym;
20.906 + sp_u_fdbg_arraydim_t *arr;
20.907 + uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
20.908
20.909 -inline void WriteOp_Addr_Pri(JitWriter *jit)
20.910 -{
20.911 - //mov eax, [esi+frm]
20.912 - //add eax, <val>
20.913 - cell_t val = jit->read_cell();
20.914 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
20.915 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.916 - {
20.917 - IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
20.918 - } else {
20.919 - IA32_Add_Eax_Imm32(jit, val);
20.920 - }
20.921 -}
20.922 + max = plugin->debug.syms_num;
20.923 + for (iter = 0; iter < max; iter++) {
20.924 + sym = (sp_u_fdbg_symbol_t *)cursor;
20.925 +
20.926 + if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs)
20.927 + return plugin->debug.stringbase + sym->name;
20.928
20.929 -inline void WriteOp_Addr_Alt(JitWriter *jit)
20.930 -{
20.931 - //mov edx, [esi+frm]
20.932 - //add edx, <val>
20.933 - cell_t val = jit->read_cell();
20.934 - IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG);
20.935 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.936 - {
20.937 - IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG);
20.938 - } else {
20.939 - IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG);
20.940 - }
20.941 -}
20.942 -
20.943 -inline void WriteOp_Stor_Pri(JitWriter *jit)
20.944 -{
20.945 - //mov [ebp+<val>], eax
20.946 - cell_t val = jit->read_cell();
20.947 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.948 - {
20.949 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val);
20.950 - } else {
20.951 - IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val);
20.952 - }
20.953 -}
20.954 + if (sym->dimcount > 0) {
20.955 + cursor += sizeof(sp_u_fdbg_symbol_t);
20.956 + arr = (sp_u_fdbg_arraydim_t *)cursor;
20.957 + cursor += sizeof(sp_u_fdbg_arraydim_t) * sym->dimcount;
20.958 + continue;
20.959 + }
20.960
20.961 -inline void WriteOp_Stor_Alt(JitWriter *jit)
20.962 -{
20.963 - //mov [ebp+<val>], edx
20.964 - cell_t val = jit->read_cell();
20.965 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.966 - {
20.967 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val);
20.968 - } else {
20.969 - IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val);
20.970 - }
20.971 -}
20.972 + cursor += sizeof(sp_u_fdbg_symbol_t);
20.973 + }
20.974 + }
20.975
20.976 -inline void WriteOp_Stor_S_Pri(JitWriter *jit)
20.977 -{
20.978 - //mov [ebx+<val>], eax
20.979 - cell_t val = jit->read_cell();
20.980 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.981 - {
20.982 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val);
20.983 - } else {
20.984 - IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val);
20.985 - }
20.986 + return NULL;
20.987 }
20.988 +#endif
20.989
20.990 -inline void WriteOp_Stor_S_Alt(JitWriter *jit)
20.991 -{
20.992 - //mov [ebx+<val>], edx
20.993 - cell_t val = jit->read_cell();
20.994 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.995 - {
20.996 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val);
20.997 - } else {
20.998 - IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val);
20.999 - }
20.1000 -}
20.1001 -
20.1002 -inline void WriteOp_Idxaddr(JitWriter *jit)
20.1003 -{
20.1004 - //lea eax, [edx+4*eax]
20.1005 - IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
20.1006 -}
20.1007 -
20.1008 -inline void WriteOp_Sref_Pri(JitWriter *jit)
20.1009 +static int
20.1010 +CompileFromThunk(BaseRuntime *runtime, cell_t pcode_offs, void **addrp, char *pc)
20.1011 {
20.1012 - //mov ecx, [ebp+<val>]
20.1013 - //mov [ebp+ecx], eax
20.1014 - cell_t val = jit->read_cell();
20.1015 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1016 - {
20.1017 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
20.1018 - } else {
20.1019 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
20.1020 - }
20.1021 - IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
20.1022 -}
20.1023 -
20.1024 -inline void WriteOp_Sref_Alt(JitWriter *jit)
20.1025 -{
20.1026 - //mov ecx, [ebp+<val>]
20.1027 - //mov [ebp+ecx], edx
20.1028 - cell_t val = jit->read_cell();
20.1029 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1030 - {
20.1031 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
20.1032 - } else {
20.1033 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
20.1034 - }
20.1035 - IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
20.1036 -}
20.1037 -
20.1038 -inline void WriteOp_Sref_S_Pri(JitWriter *jit)
20.1039 -{
20.1040 - //mov ecx, [ebx+<val>]
20.1041 - //mov [ebp+ecx], eax
20.1042 - cell_t val = jit->read_cell();
20.1043 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1044 - {
20.1045 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
20.1046 - } else {
20.1047 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
20.1048 - }
20.1049 - IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
20.1050 -}
20.1051 + JitFunction *fn = runtime->GetJittedFunctionByOffset(pcode_offs);
20.1052 + if (!fn) {
20.1053 + int err;
20.1054 + fn = g_Jit.CompileFunction(runtime, pcode_offs, &err);
20.1055 + if (!fn)
20.1056 + return err;
20.1057 + }
20.1058
20.1059 -inline void WriteOp_Sref_S_Alt(JitWriter *jit)
20.1060 -{
20.1061 - //mov ecx, [ebx+<val>]
20.1062 - //mov [ebp+ecx], edx
20.1063 - cell_t val = jit->read_cell();
20.1064 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1065 - {
20.1066 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
20.1067 - } else {
20.1068 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
20.1069 - }
20.1070 - IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
20.1071 -}
20.1072 +#if !defined NDEBUG
20.1073 + g_engine1.GetDebugHook()->OnDebugSpew(
20.1074 + "Patching thunk to %s::%s\n",
20.1075 + runtime->plugin()->name,
20.1076 + GetFunctionName(runtime->plugin(), pcode_offs));
20.1077 +#endif
20.1078
20.1079 -inline void WriteOp_Pop_Pri(JitWriter *jit)
20.1080 -{
20.1081 - //mov eax, [edi]
20.1082 - //add edi, 4
20.1083 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
20.1084 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.1085 -}
20.1086 + *addrp = fn->GetEntryAddress();
20.1087
20.1088 -inline void WriteOp_Pop_Alt(JitWriter *jit)
20.1089 -{
20.1090 - //mov edx, [edi]
20.1091 - //add edi, 4
20.1092 - IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
20.1093 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.1094 -}
20.1095 -
20.1096 -inline void WriteOp_Swap_Pri(JitWriter *jit)
20.1097 -{
20.1098 - //add [edi], eax
20.1099 - //sub eax, [edi]
20.1100 - //add [edi], eax
20.1101 - //neg eax
20.1102 - IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
20.1103 - IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
20.1104 - IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
20.1105 - IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
20.1106 + /* Right now, we always keep the code RWE */
20.1107 + *(intptr_t *)(pc - 4) = intptr_t(fn->GetEntryAddress()) - intptr_t(pc);
20.1108 + return SP_ERROR_NONE;
20.1109 }
20.1110
20.1111 -inline void WriteOp_Swap_Alt(JitWriter *jit)
20.1112 -{
20.1113 - //add [edi], edx
20.1114 - //sub edx, [edi]
20.1115 - //add [edi], edx
20.1116 - //neg edx
20.1117 - IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
20.1118 - IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
20.1119 - IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
20.1120 - IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG);
20.1121 -}
20.1122 -
20.1123 -inline void WriteOp_PushAddr(JitWriter *jit)
20.1124 +static cell_t
20.1125 +NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
20.1126 {
20.1127 - //mov ecx, [esi+frm] ;get address (offset from frame)
20.1128 - //sub edi, 4
20.1129 - //add ecx, <val>
20.1130 - //mov [edi], ecx
20.1131 - cell_t val = jit->read_cell();
20.1132 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
20.1133 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.1134 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1135 - {
20.1136 - IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG);
20.1137 - } else {
20.1138 - IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG);
20.1139 - }
20.1140 - IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
20.1141 + sp_native_t *native;
20.1142 + cell_t save_sp = ctx->sp;
20.1143 + cell_t save_hp = ctx->hp;
20.1144 + sp_plugin_t *pl = (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
20.1145 +
20.1146 + ctx->n_idx = native_idx;
20.1147 +
20.1148 + if (ctx->hp < (cell_t)pl->data_size) {
20.1149 + ctx->n_err = SP_ERROR_HEAPMIN;
20.1150 + return 0;
20.1151 + }
20.1152 +
20.1153 + if (ctx->hp + STACK_MARGIN > ctx->sp) {
20.1154 + ctx->n_err = SP_ERROR_STACKLOW;
20.1155 + return 0;
20.1156 + }
20.1157 +
20.1158 + if ((uint32_t)ctx->sp >= pl->mem_size) {
20.1159 + ctx->n_err = SP_ERROR_STACKMIN;
20.1160 + return 0;
20.1161 + }
20.1162 +
20.1163 + native = &pl->natives[native_idx];
20.1164 +
20.1165 + if (native->status == SP_NATIVE_UNBOUND) {
20.1166 + ctx->n_err = SP_ERROR_INVALID_NATIVE;
20.1167 + return 0;
20.1168 + }
20.1169 +
20.1170 + cell_t result = native->pfn(GET_CONTEXT(ctx), params);
20.1171 +
20.1172 + if (ctx->n_err != SP_ERROR_NONE)
20.1173 + return result;
20.1174 +
20.1175 + if (save_sp != ctx->sp) {
20.1176 + ctx->n_err = SP_ERROR_STACKLEAK;
20.1177 + return result;
20.1178 + }
20.1179 + if (save_hp != ctx->hp) {
20.1180 + ctx->n_err = SP_ERROR_HEAPLEAK;
20.1181 + return result;
20.1182 + }
20.1183 +
20.1184 + return result;
20.1185 }
20.1186
20.1187 -inline void WriteOp_Movs(JitWriter *jit)
20.1188 +Compiler::Compiler(BaseRuntime *rt, cell_t pcode_offs)
20.1189 + : rt_(rt),
20.1190 + plugin_(rt->plugin()),
20.1191 + error_(SP_ERROR_NONE),
20.1192 + pcode_start_(pcode_offs),
20.1193 + code_start_(reinterpret_cast<cell_t *>(plugin_->pcode + pcode_start_)),
20.1194 + cip_(code_start_),
20.1195 + code_end_(reinterpret_cast<cell_t *>(plugin_->pcode + plugin_->pcode_size))
20.1196 {
20.1197 - //cld
20.1198 - //push esi
20.1199 - //push edi
20.1200 - //lea esi, [ebp+eax]
20.1201 - //lea edi, [ebp+edx]
20.1202 - //if dword:
20.1203 - // mov ecx, dword
20.1204 - // rep movsd
20.1205 - //if byte:
20.1206 - // mov ecx, byte
20.1207 - // rep movsb
20.1208 - //pop edi
20.1209 - //pop esi
20.1210 - cell_t val = jit->read_cell();
20.1211 - unsigned int dwords = val >> 2;
20.1212 - unsigned int bytes = val & 0x3;
20.1213 -
20.1214 - IA32_Cld(jit);
20.1215 - IA32_Push_Reg(jit, REG_ESI);
20.1216 - IA32_Push_Reg(jit, REG_EDI);
20.1217 - IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.1218 - IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
20.1219 - if (dwords)
20.1220 - {
20.1221 - IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
20.1222 - IA32_Rep(jit);
20.1223 - IA32_Movsd(jit);
20.1224 - }
20.1225 - if (bytes)
20.1226 - {
20.1227 - IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
20.1228 - IA32_Rep(jit);
20.1229 - IA32_Movsb(jit);
20.1230 - }
20.1231 - IA32_Pop_Reg(jit, REG_EDI);
20.1232 - IA32_Pop_Reg(jit, REG_ESI);
20.1233 -}
20.1234 -
20.1235 -inline void WriteOp_Fill(JitWriter *jit)
20.1236 -{
20.1237 - //push edi
20.1238 - //lea edi, [ebp+edx]
20.1239 - //mov ecx, <val> >> 2
20.1240 - //cld
20.1241 - //rep stosd
20.1242 - //pop edi
20.1243 - unsigned int val = jit->read_cell() >> 2;
20.1244 -
20.1245 - IA32_Push_Reg(jit, REG_EDI);
20.1246 - IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
20.1247 - IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
20.1248 - IA32_Cld(jit);
20.1249 - IA32_Rep(jit);
20.1250 - IA32_Stosd(jit);
20.1251 - IA32_Pop_Reg(jit, REG_EDI);
20.1252 + size_t nmaxops = plugin_->pcode_size / sizeof(cell_t) + 1;
20.1253 + jump_map_ = new Label[nmaxops];
20.1254 }
20.1255
20.1256 -inline void WriteOp_GenArray(JitWriter *jit, bool autozero)
20.1257 +Compiler::~Compiler()
20.1258 {
20.1259 - cell_t val = jit->read_cell();
20.1260 - if (val == 1)
20.1261 - {
20.1262 - /* flat array. we can generate this without indirection tables. */
20.1263 - /* Note that we can overwrite ALT because technically STACK should be destroying ALT */
20.1264 - //mov edx, [esi+info.heap]
20.1265 - //mov ecx, [edi]
20.1266 - //mov [edi], edx ;store base of array into stack
20.1267 - //lea edx, [edx+ecx*4] ;get the final new heap pointer
20.1268 - //mov [esi+info.heap], edx ;store heap pointer back
20.1269 - //add edx, ebp ;relocate
20.1270 - //cmp edx, edi ;compare against stack pointer
20.1271 - //jae :error ;error out if not enough space
20.1272 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
20.1273 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
20.1274 - IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
20.1275 - IA32_Lea_Reg_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4);
20.1276 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP);
20.1277 - IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG);
20.1278 - IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG);
20.1279 - IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow);
20.1280 -
20.1281 - WriteOp_Tracker_Push_Reg(jit, REG_ECX);
20.1282 -
20.1283 - if (autozero)
20.1284 - {
20.1285 - /* Zero out the array - inline a quick fill */
20.1286 - //push eax ;save pri
20.1287 - //push edi ;save stk
20.1288 - //xor eax, eax ;zero source
20.1289 - //mov edi, [edi] ;get heap ptr out of the stack
20.1290 - //add edi, ebp ;relocate
20.1291 - //cld ;clear direction flag
20.1292 - //rep stosd ;copy (note: ECX is sane from above)
20.1293 - //pop edi ;pop stk
20.1294 - //pop eax ;pop pri
20.1295 - IA32_Push_Reg(jit, REG_EAX);
20.1296 - IA32_Push_Reg(jit, REG_EDI);
20.1297 - IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG);
20.1298 - IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG);
20.1299 - IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
20.1300 - IA32_Cld(jit);
20.1301 - IA32_Rep(jit);
20.1302 - IA32_Stosd(jit);
20.1303 - IA32_Pop_Reg(jit, REG_EDI);
20.1304 - IA32_Pop_Reg(jit, REG_EAX);
20.1305 - }
20.1306 - } else {
20.1307 - //mov ecx, num_dims
20.1308 - //mov edx, 0/1
20.1309 - //call [genarray]
20.1310 - IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val);
20.1311 - if (autozero)
20.1312 - {
20.1313 - IA32_Mov_Reg_Imm32(jit, REG_EDX, 1);
20.1314 - } else {
20.1315 - IA32_Mov_Reg_Imm32(jit, REG_EDX, 0);
20.1316 - }
20.1317 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
20.1318 - IA32_Write_Jump32_Abs(jit, call, g_Jit.GetGenArrayIntrinsic());
20.1319 - }
20.1320 -}
20.1321 -
20.1322 -inline void WriteOp_Load_Both(JitWriter *jit)
20.1323 -{
20.1324 - WriteOp_Load_Pri(jit);
20.1325 - WriteOp_Load_Alt(jit);
20.1326 -}
20.1327 -
20.1328 -inline void WriteOp_Load_S_Both(JitWriter *jit)
20.1329 -{
20.1330 - WriteOp_Load_S_Pri(jit);
20.1331 - WriteOp_Load_S_Alt(jit);
20.1332 -}
20.1333 -
20.1334 -inline void WriteOp_Const(JitWriter *jit)
20.1335 -{
20.1336 - //mov [ebp+<addr>], <val>
20.1337 - cell_t addr = jit->read_cell();
20.1338 - cell_t val = jit->read_cell();
20.1339 - if (addr <= SCHAR_MAX && addr >= SCHAR_MIN)
20.1340 - {
20.1341 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr);
20.1342 - } else {
20.1343 - IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr);
20.1344 - }
20.1345 -}
20.1346 -
20.1347 -inline void WriteOp_Const_S(JitWriter *jit)
20.1348 -{
20.1349 - //mov [ebx+<offs>], <val>
20.1350 - cell_t offs = jit->read_cell();
20.1351 - cell_t val = jit->read_cell();
20.1352 - if (offs <= SCHAR_MAX && offs >= SCHAR_MIN)
20.1353 - {
20.1354 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs);
20.1355 - } else {
20.1356 - IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs);
20.1357 - }
20.1358 + delete [] jump_map_;
20.1359 }
20.1360
20.1361 -inline void WriteOp_Load_I(JitWriter *jit)
20.1362 -{
20.1363 - //mov eax, [ebp+eax]
20.1364 - Write_Check_VerifyAddr(jit, AMX_REG_PRI);
20.1365 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.1366 -}
20.1367 -
20.1368 -inline void WriteOp_Lodb_I(JitWriter *jit)
20.1369 -{
20.1370 - Write_Check_VerifyAddr(jit, AMX_REG_PRI);
20.1371 -
20.1372 - //mov eax, [ebp+eax]
20.1373 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.1374 -
20.1375 - //and eax, <bitmask>
20.1376 - cell_t val = jit->read_cell();
20.1377 - switch(val)
20.1378 - {
20.1379 - case 1:
20.1380 - {
20.1381 - IA32_And_Eax_Imm32(jit, 0x000000FF);
20.1382 - break;
20.1383 - }
20.1384 - case 2:
20.1385 - {
20.1386 - IA32_And_Eax_Imm32(jit, 0x0000FFFF);
20.1387 - break;
20.1388 - }
20.1389 - }
20.1390 -}
20.1391 -
20.1392 -inline void WriteOp_Stor_I(JitWriter *jit)
20.1393 -{
20.1394 - //mov [ebp+edx], eax
20.1395 - Write_Check_VerifyAddr(jit, AMX_REG_ALT);
20.1396 - IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
20.1397 -}
20.1398 -
20.1399 -inline void WriteOp_Strb_I(JitWriter *jit)
20.1400 +JitFunction *
20.1401 +Compiler::emit(int *errp)
20.1402 {
20.1403 - Write_Check_VerifyAddr(jit, AMX_REG_ALT);
20.1404 - //mov [ebp+edx], eax
20.1405 - cell_t val = jit->read_cell();
20.1406 - switch (val)
20.1407 - {
20.1408 - case 1:
20.1409 - {
20.1410 - IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
20.1411 - break;
20.1412 - }
20.1413 - case 2:
20.1414 - {
20.1415 - IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
20.1416 - break;
20.1417 - }
20.1418 - case 4:
20.1419 - {
20.1420 - IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
20.1421 - break;
20.1422 - }
20.1423 - }
20.1424 -}
20.1425 + if (cip_ >= code_end_ || *cip_ != OP_PROC) {
20.1426 + *errp = SP_ERROR_INVALID_INSTRUCTION;
20.1427 + return NULL;
20.1428 + }
20.1429 +
20.1430 +#if !defined NDEBUG
20.1431 + g_engine1.GetDebugHook()->OnDebugSpew(
20.1432 + "Compiling function %s::%s\n",
20.1433 + plugin_->name,
20.1434 + GetFunctionName(plugin_, pcode_start_));
20.1435
20.1436 -inline void WriteOp_Lidx(JitWriter *jit)
20.1437 -{
20.1438 - //lea eax, [edx+4*eax]
20.1439 - //mov eax, [ebp+eax]
20.1440 - IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
20.1441 - Write_Check_VerifyAddr(jit, AMX_REG_PRI);
20.1442 - IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
20.1443 -}
20.1444 + SpewOpcode(plugin_, code_start_, cip_);
20.1445 +#endif
20.1446 +
20.1447 + cell_t *codeseg = reinterpret_cast<cell_t *>(plugin_->pcode);
20.1448 +
20.1449 + cip_++;
20.1450 + if (!emitOp(OP_PROC)) {
20.1451 + *errp = (error_ == SP_ERROR_NONE) ? SP_ERROR_OUT_OF_MEMORY : error_;
20.1452 + return NULL;
20.1453 + }
20.1454
20.1455 -inline void WriteOp_Stack(JitWriter *jit)
20.1456 -{
20.1457 - //add edi, <val>
20.1458 - cell_t val = jit->read_cell();
20.1459 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1460 - {
20.1461 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG);
20.1462 - } else {
20.1463 - IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG);
20.1464 - }
20.1465 + while (cip_ < code_end_) {
20.1466 + // If we reach the end of this function, or the beginning of a new
20.1467 + // procedure, then stop.
20.1468 + if (*cip_ == OP_PROC || *cip_ == OP_ENDPROC)
20.1469 + break;
20.1470
20.1471 - if (val > 0)
20.1472 - {
20.1473 - Write_CheckStack_Min(jit);
20.1474 - } else if (val < 0) {
20.1475 - Write_CheckStack_Low(jit);
20.1476 - }
20.1477 -}
20.1478 +#if !defined NDEBUG
20.1479 + SpewOpcode(plugin_, code_start_, cip_);
20.1480 +#endif
20.1481 +
20.1482 + // We assume every instruction is a jump target, so before emitting
20.1483 + // an opcode, we bind its corresponding label.
20.1484 + __ bind(&jump_map_[cip_ - codeseg]);
20.1485
20.1486 -inline void WriteOp_StackAdjust(JitWriter *jit)
20.1487 -{
20.1488 - cell_t val = jit->read_cell();
20.1489 -
20.1490 - assert(val <= 0);
20.1491 + OPCODE op = (OPCODE)readCell();
20.1492 + if (!emitOp(op) || error_ != SP_ERROR_NONE) {
20.1493 + *errp = (error_ == SP_ERROR_NONE) ? SP_ERROR_OUT_OF_MEMORY : error_;
20.1494 + return NULL;
20.1495 + }
20.1496 + }
20.1497
20.1498 - //lea edi, [ebx-val]
20.1499 -
20.1500 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1501 - {
20.1502 - IA32_Lea_DispRegImm8(jit, AMX_REG_STK, AMX_REG_FRM, val);
20.1503 - }
20.1504 - else
20.1505 - {
20.1506 - IA32_Lea_DispRegImm32(jit, AMX_REG_STK, AMX_REG_FRM, val);
20.1507 - }
20.1508 + emitCallThunks();
20.1509 + emitErrorPaths();
20.1510
20.1511 - /* We assume the compiler has generated good code --
20.1512 - * That is, we do not bother validating this amount!
20.1513 - */
20.1514 + void *code = LinkCode(masm);
20.1515 + if (!code) {
20.1516 + *errp = SP_ERROR_OUT_OF_MEMORY;
20.1517 + return NULL;
20.1518 + }
20.1519 +
20.1520 + return new JitFunction(code, pcode_start_);
20.1521 }
20.1522
20.1523 -inline void WriteOp_Heap(JitWriter *jit)
20.1524 -{
20.1525 - //mov edx, [esi+hea]
20.1526 - //add [esi+hea], <val>
20.1527 - cell_t val = jit->read_cell();
20.1528 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
20.1529 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1530 - {
20.1531 - IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP);
20.1532 - } else {
20.1533 - IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP);
20.1534 - }
20.1535 -
20.1536 - /* NOTE: Backwards from op.stack */
20.1537 - if (val > 0)
20.1538 - {
20.1539 - Write_CheckHeap_Low(jit);
20.1540 - } else if (val < 0) {
20.1541 - Write_CheckHeap_Min(jit);
20.1542 - }
20.1543 -}
20.1544 -
20.1545 -inline void WriteOp_SDiv(JitWriter *jit)
20.1546 -{
20.1547 - //mov ecx, edx
20.1548 - //mov edx, eax
20.1549 - //sar edx, 31
20.1550 - //idiv ecx
20.1551 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
20.1552 - IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
20.1553 - IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
20.1554 - Write_Check_DivZero(jit, AMX_REG_TMP);
20.1555 - IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
20.1556 -}
20.1557 -
20.1558 -inline void WriteOp_SDiv_Alt(JitWriter *jit)
20.1559 -{
20.1560 - //mov ecx, eax
20.1561 - //mov eax, edx
20.1562 - //sar edx, 31
20.1563 - //idiv ecx
20.1564 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
20.1565 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.1566 - IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
20.1567 - Write_Check_DivZero(jit, AMX_REG_TMP);
20.1568 - IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
20.1569 -}
20.1570 -
20.1571 -inline void WriteOp_Retn(JitWriter *jit)
20.1572 -{
20.1573 - //mov ebx, [edi+4] - get old frm
20.1574 - //add edi, 8 - pop stack
20.1575 - //mov [esi+frm], ebx - restore frame pointer
20.1576 - //add ebx, ebp - relocate
20.1577 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4);
20.1578 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.1579 - IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
20.1580 - IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
20.1581 -
20.1582 - /* pop params */
20.1583 - //mov ecx, [edi]
20.1584 - //lea edi, [edi+ecx*4+4]
20.1585 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
20.1586 - IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4);
20.1587 -
20.1588 - //ret - return (EIP on real stack!)
20.1589 - IA32_Return(jit);
20.1590 -}
20.1591 -
20.1592 -void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
20.1593 -{
20.1594 - ((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
20.1595 -}
20.1596 -
20.1597 -void ProfCallGate_End(sp_context_t *ctx)
20.1598 -{
20.1599 - ((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
20.1600 -}
20.1601 -
20.1602 -const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
20.1603 -{
20.1604 - if (!plugin->debug.unpacked)
20.1605 - {
20.1606 - uint32_t max, iter;
20.1607 - sp_fdbg_symbol_t *sym;
20.1608 - sp_fdbg_arraydim_t *arr;
20.1609 - uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
20.1610 -
20.1611 - max = plugin->debug.syms_num;
20.1612 - for (iter = 0; iter < max; iter++)
20.1613 - {
20.1614 - sym = (sp_fdbg_symbol_t *)cursor;
20.1615 -
20.1616 - if (sym->ident == SP_SYM_FUNCTION
20.1617 - && sym->codestart <= offs
20.1618 - && sym->codeend > offs)
20.1619 - {
20.1620 - return plugin->debug.stringbase + sym->name;
20.1621 - }
20.1622 -
20.1623 - if (sym->dimcount > 0)
20.1624 - {
20.1625 - cursor += sizeof(sp_fdbg_symbol_t);
20.1626 - arr = (sp_fdbg_arraydim_t *)cursor;
20.1627 - cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
20.1628 - continue;
20.1629 - }
20.1630 -
20.1631 - cursor += sizeof(sp_fdbg_symbol_t);
20.1632 - }
20.1633 - }
20.1634 - else
20.1635 - {
20.1636 - uint32_t max, iter;
20.1637 - sp_u_fdbg_symbol_t *sym;
20.1638 - sp_u_fdbg_arraydim_t *arr;
20.1639 - uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
20.1640 -
20.1641 - max = plugin->debug.syms_num;
20.1642 - for (iter = 0; iter < max; iter++)
20.1643 - {
20.1644 - sym = (sp_u_fdbg_symbol_t *)cursor;
20.1645 -
20.1646 - if (sym->ident == SP_SYM_FUNCTION
20.1647 - && sym->codestart <= offs
20.1648 - && sym->codeend > offs)
20.1649 - {
20.1650 - return plugin->debug.stringbase + sym->name;
20.1651 - }
20.1652 -
20.1653 - if (sym->dimcount > 0)
20.1654 - {
20.1655 - cursor += sizeof(sp_u_fdbg_symbol_t);
20.1656 - arr = (sp_u_fdbg_arraydim_t *)cursor;
20.1657 - cursor += sizeof(sp_u_fdbg_arraydim_t) * sym->dimcount;
20.1658 - continue;
20.1659 - }
20.1660 -
20.1661 - cursor += sizeof(sp_u_fdbg_symbol_t);
20.1662 - }
20.1663 - }
20.1664 -
20.1665 - return NULL;
20.1666 -}
20.1667 -
20.1668 -inline void WriteOp_Call(JitWriter *jit)
20.1669 -{
20.1670 - cell_t offs;
20.1671 - jitoffs_t jmp;
20.1672 - CompData *data;
20.1673 - uint32_t func_idx;
20.1674 -
20.1675 - data = (CompData *)jit->data;
20.1676 - offs = jit->read_cell();
20.1677 -
20.1678 - /* Get the context + rp */
20.1679 - //mov eax, [esi+ctx]
20.1680 - //mov ecx, [eax+rp]
20.1681 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
20.1682 - IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, rp));
20.1683 -
20.1684 - /* Check if the return stack is used up. */
20.1685 - //cmp ecx, <max stack>
20.1686 - //jae :stacklow
20.1687 - IA32_Cmp_Rm_Imm32(jit, MOD_REG, REG_ECX, SP_MAX_RETURN_STACK);
20.1688 - IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, data->jit_error_stacklow);
20.1689 -
20.1690 - /* Add us to the return stack */
20.1691 - //mov [eax+ecx*4+cips], cip
20.1692 - IA32_Mov_Rm_Imm32_SIB(jit,
20.1693 - REG_EAX,
20.1694 - (uint8_t *)(jit->inptr - 2) - data->plugin->pcode,
20.1695 - offsetof(sp_context_t, rstk_cips),
20.1696 - REG_ECX,
20.1697 - SCALE4);
20.1698 -
20.1699 - /* Increment the return stack pointer */
20.1700 - //inc [eax+rp]
20.1701 - if ((int)offsetof(sp_context_t, rp) >= SCHAR_MIN && (int)offsetof(sp_context_t, rp) <= SCHAR_MAX)
20.1702 - {
20.1703 - IA32_Inc_Rm_Disp8(jit, REG_EAX, offsetof(sp_context_t, rp));
20.1704 - }
20.1705 - else
20.1706 - {
20.1707 - IA32_Inc_Rm_Disp32(jit, REG_EAX, offsetof(sp_context_t, rp));
20.1708 - }
20.1709 -
20.1710 - /* Store the CIP of the function we're about to call. */
20.1711 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_INFO, offs, AMX_INFO_CIP);
20.1712 -
20.1713 - /* Call the function */
20.1714 - func_idx = FuncLookup(data, offs);
20.1715 -
20.1716 - /* We need to emit a delayed thunk instead. */
20.1717 - if (func_idx == 0)
20.1718 - {
20.1719 - if (jit->outbase == NULL)
20.1720 - {
20.1721 - data->num_thunks++;
20.1722 -
20.1723 - /* We still emit the call because we need consistent size counting */
20.1724 - IA32_Call_Imm32(jit, 0);
20.1725 - }
20.1726 - else
20.1727 - {
20.1728 - call_thunk_t *thunk;
20.1729 -
20.1730 - /* Find the thunk we're associated with */
20.1731 - thunk = &data->thunks[data->num_thunks];
20.1732 - data->num_thunks++;
20.1733 -
20.1734 - /* Emit the call, save its target position.
20.1735 - * Save thunk info, then patch the target to the thunk.
20.1736 - */
20.1737 - thunk->patch_addr = IA32_Call_Imm32(jit, 0);
20.1738 - thunk->pcode_offs = offs;
20.1739 - IA32_Write_Jump32(jit, thunk->patch_addr, thunk->thunk_addr);
20.1740 - }
20.1741 - }
20.1742 - /* The function is already jitted. We can emit a direct call. */
20.1743 - else
20.1744 - {
20.1745 - JitFunction *fn;
20.1746 -
20.1747 - fn = data->runtime->GetJittedFunction(func_idx);
20.1748 - jmp = IA32_Call_Imm32(jit, 0);
20.1749 - IA32_Write_Jump32_Abs(jit, jmp, fn->GetEntryAddress());
20.1750 - }
20.1751 -
20.1752 - /* Restore the last cip */
20.1753 - //mov [esi+cip], <cip>
20.1754 - IA32_Mov_Rm_Imm32_Disp8(jit,
20.1755 - AMX_REG_INFO,
20.1756 - (uint8_t *)(jit->inptr - 2) - data->plugin->pcode,
20.1757 - AMX_INFO_CIP);
20.1758 -
20.1759 - /* Mark us as leaving the last frame. */
20.1760 - //mov ecx, [esi+ctx]
20.1761 - //dec [ecx+rp]
20.1762 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
20.1763 - IA32_Dec_Rm_Disp8(jit, REG_ECX, offsetof(sp_context_t, rp));
20.1764 -}
20.1765 -
20.1766 -inline void WriteOp_Bounds(JitWriter *jit)
20.1767 -{
20.1768 - cell_t val = jit->read_cell();
20.1769 -
20.1770 - //cmp eax, <val>
20.1771 - //ja :error
20.1772 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
20.1773 - {
20.1774 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
20.1775 - } else {
20.1776 - IA32_Cmp_Eax_Imm32(jit, val);
20.1777 - }
20.1778 - IA32_Jump_Cond_Imm32_Rel(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds);
20.1779 -}
20.1780 -
20.1781 -inline void WriteOp_Halt(JitWriter *jit)
20.1782 -{
20.1783 - AlignMe(jit);
20.1784 -
20.1785 - //mov ecx, [esi+ret]
20.1786 - //mov [ecx], eax
20.1787 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL);
20.1788 - IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG);
20.1789 -
20.1790 - /* :TODO:
20.1791 - * We don't support sleeping or halting with weird values.
20.1792 - * So we're omitting the mov eax <val> that was here.
20.1793 - */
20.1794 - jit->read_cell();
20.1795 -
20.1796 - IA32_Jump_Imm32_Abs(jit, g_Jit.GetReturnPoint());
20.1797 -}
20.1798 -
20.1799 -inline void WriteOp_Break(JitWriter *jit)
20.1800 -{
20.1801 - CompData *data;
20.1802 -
20.1803 - data = (CompData *)jit->data;
20.1804 -
20.1805 - //mov [esi+cip], <cip>
20.1806 - IA32_Mov_Rm_Imm32_Disp8(jit,
20.1807 - AMX_REG_INFO,
20.1808 - (uint8_t *)(jit->inptr - 1) - data->plugin->pcode,
20.1809 - AMX_INFO_CIP);
20.1810 -}
20.1811 -
20.1812 -inline void WriteOp_Jump(JitWriter *jit)
20.1813 -{
20.1814 - //jmp <offs>
20.1815 - cell_t amx_offs = jit->read_cell();
20.1816 - IA32_Jump_Imm32_Rel(jit, RelocLookup(jit, amx_offs, false));
20.1817 -}
20.1818 -
20.1819 -inline void WriteOp_Jzer(JitWriter *jit)
20.1820 -{
20.1821 - //test eax, eax
20.1822 - //jz <target>
20.1823 - cell_t target = jit->read_cell();
20.1824 - IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
20.1825 - IA32_Jump_Cond_Imm32_Rel(jit, CC_Z, RelocLookup(jit, target, false));
20.1826 -}
20.1827 -
20.1828 -inline void WriteOp_Jnz(JitWriter *jit)
20.1829 +bool
20.1830 +Compiler::emitOp(OPCODE op)
20.1831 {
20.1832 - //test eax, eax
20.1833 - //jnz <target>
20.1834 - cell_t target = jit->read_cell();
20.1835 - IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
20.1836 - IA32_Jump_Cond_Imm32_Rel(jit, CC_NZ, RelocLookup(jit, target, false));
20.1837 -}
20.1838 + switch (op) {
20.1839 + case OP_MOVE_PRI:
20.1840 + __ movl(pri, alt);
20.1841 + break;
20.1842 +
20.1843 + case OP_MOVE_ALT:
20.1844 + __ movl(alt, pri);
20.1845 + break;
20.1846 +
20.1847 + case OP_XCHG:
20.1848 + __ xchgl(pri, alt);
20.1849 + break;
20.1850 +
20.1851 + case OP_ZERO:
20.1852 + {
20.1853 + cell_t offset = readCell();
20.1854 + __ movl(Operand(dat, offset), 0);
20.1855 + break;
20.1856 + }
20.1857 +
20.1858 + case OP_ZERO_S:
20.1859 + {
20.1860 + cell_t offset = readCell();
20.1861 + __ movl(Operand(frm, offset), 0);
20.1862 + break;
20.1863 + }
20.1864 +
20.1865 + case OP_PUSH_PRI:
20.1866 + case OP_PUSH_ALT:
20.1867 + {
20.1868 + Register reg = (op == OP_PUSH_PRI) ? pri : alt;
20.1869 + __ movl(Operand(stk, -4), reg);
20.1870 + __ subl(stk, 4);
20.1871 + break;
20.1872 + }
20.1873 +
20.1874 + case OP_PUSH_C:
20.1875 + case OP_PUSH2_C:
20.1876 + case OP_PUSH3_C:
20.1877 + case OP_PUSH4_C:
20.1878 + case OP_PUSH5_C:
20.1879 + {
20.1880 + int n = 1;
20.1881 + if (op >= OP_PUSH2_C)
20.1882 + n = ((op - OP_PUSH2_C) / 4) + 2;
20.1883
20.1884 -inline void WriteOp_Jeq(JitWriter *jit)
20.1885 -{
20.1886 - //cmp eax, edx
20.1887 - //je <target>
20.1888 - cell_t target = jit->read_cell();
20.1889 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.1890 - IA32_Jump_Cond_Imm32_Rel(jit, CC_E, RelocLookup(jit, target, false));
20.1891 -}
20.1892 + int i = 1;
20.1893 + do {
20.1894 + cell_t val = readCell();
20.1895 + __ movl(Operand(stk, -(4 * i)), val);
20.1896 + } while (i++ < n);
20.1897 + __ subl(stk, 4 * n);
20.1898 + break;
20.1899 + }
20.1900 +
20.1901 + case OP_PUSH_ADR:
20.1902 + case OP_PUSH2_ADR:
20.1903 + case OP_PUSH3_ADR:
20.1904 + case OP_PUSH4_ADR:
20.1905 + case OP_PUSH5_ADR:
20.1906 + {
20.1907 + int n = 1;
20.1908 + if (op >= OP_PUSH2_ADR)
20.1909 + n = ((op - OP_PUSH2_ADR) / 4) + 2;
20.1910 +
20.1911 + int i = 1;
20.1912
20.1913 -inline void WriteOp_Jneq(JitWriter *jit)
20.1914 -{
20.1915 - //cmp eax, edx
20.1916 - //jne <target>
20.1917 - cell_t target = jit->read_cell();
20.1918 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.1919 - IA32_Jump_Cond_Imm32_Rel(jit, CC_NE, RelocLookup(jit, target, false));
20.1920 -}
20.1921 + // We temporarily relocate FRM to be a local address instead of an
20.1922 + // absolute address.
20.1923 + __ subl(frm, dat);
20.1924 + do {
20.1925 + cell_t offset = readCell();
20.1926 + __ lea(tmp, Operand(frm, offset));
20.1927 + __ movl(Operand(stk, -(4 * i)), tmp);
20.1928 + } while (i++ < n);
20.1929 + __ subl(stk, 4 * n);
20.1930 + __ addl(frm, dat);
20.1931 + break;
20.1932 + }
20.1933 +
20.1934 + case OP_PUSH_S:
20.1935 + case OP_PUSH2_S:
20.1936 + case OP_PUSH3_S:
20.1937 + case OP_PUSH4_S:
20.1938 + case OP_PUSH5_S:
20.1939 + {
20.1940 + int n = 1;
20.1941 + if (op >= OP_PUSH2_S)
20.1942 + n = ((op - OP_PUSH2_S) / 4) + 2;
20.1943 +
20.1944 + int i = 1;
20.1945 + do {
20.1946 + cell_t offset = readCell();
20.1947 + __ movl(tmp, Operand(frm, offset));
20.1948 + __ movl(Operand(stk, -(4 * i)), tmp);
20.1949 + } while (i++ < n);
20.1950 + __ subl(stk, 4 * n);
20.1951 + break;
20.1952 + }
20.1953
20.1954 -inline void WriteOp_Jsless(JitWriter *jit)
20.1955 -{
20.1956 - //cmp eax, edx
20.1957 - //jl <target>
20.1958 - cell_t target = jit->read_cell();
20.1959 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.1960 - IA32_Jump_Cond_Imm32_Rel(jit, CC_L, RelocLookup(jit, target, false));
20.1961 -}
20.1962 + case OP_PUSH:
20.1963 + case OP_PUSH2:
20.1964 + case OP_PUSH3:
20.1965 + case OP_PUSH4:
20.1966 + case OP_PUSH5:
20.1967 + {
20.1968 + int n = 1;
20.1969 + if (op >= OP_PUSH2)
20.1970 + n = ((op - OP_PUSH2) / 4) + 2;
20.1971 +
20.1972 + int i = 1;
20.1973 + do {
20.1974 + cell_t offset = readCell();
20.1975 + __ movl(tmp, Operand(dat, offset));
20.1976 + __ movl(Operand(stk, -(4 * i)), tmp);
20.1977 + } while (i++ < n);
20.1978 + __ subl(stk, 4 * n);
20.1979 + break;
20.1980 + }
20.1981 +
20.1982 + case OP_ZERO_PRI:
20.1983 + __ xorl(pri, pri);
20.1984 + break;
20.1985
20.1986 -inline void WriteOp_Jsleq(JitWriter *jit)
20.1987 -{
20.1988 - //cmp eax, edx
20.1989 - //jle <target>
20.1990 - cell_t target = jit->read_cell();
20.1991 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.1992 - IA32_Jump_Cond_Imm32_Rel(jit, CC_LE, RelocLookup(jit, target, false));
20.1993 -}
20.1994 + case OP_ZERO_ALT:
20.1995 + __ xorl(alt, alt);
20.1996 + break;
20.1997 +
20.1998 + case OP_ADD:
20.1999 + __ addl(pri, alt);
20.2000 + break;
20.2001 +
20.2002 + case OP_SUB:
20.2003 + __ subl(pri, alt);
20.2004 + break;
20.2005 +
20.2006 + case OP_SUB_ALT:
20.2007 + __ movl(tmp, alt);
20.2008 + __ subl(tmp, pri);
20.2009 + __ movl(pri, tmp);
20.2010 + break;
20.2011 +
20.2012 + case OP_PROC:
20.2013 + // Push the old frame onto the stack.
20.2014 + __ movl(tmp, Operand(info, AMX_INFO_FRAME));
20.2015 + __ movl(Operand(stk, -4), tmp);
20.2016 + __ subl(stk, 8); // extra unused slot for non-existant CIP
20.2017 +
20.2018 + // Get and store the new frame.
20.2019 + __ movl(tmp, stk);
20.2020 + __ movl(frm, stk);
20.2021 + __ subl(tmp, dat);
20.2022 + __ movl(Operand(info, AMX_INFO_FRAME), tmp);
20.2023 + break;
20.2024
20.2025 -inline void WriteOp_JsGrtr(JitWriter *jit)
20.2026 -{
20.2027 - //cmp eax, edx
20.2028 - //jg <target>
20.2029 - cell_t target = jit->read_cell();
20.2030 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.2031 - IA32_Jump_Cond_Imm32_Rel(jit, CC_G, RelocLookup(jit, target, false));
20.2032 -}
20.2033 + case OP_IDXADDR_B:
20.2034 + {
20.2035 + cell_t val = readCell();
20.2036 + __ shll(pri, val);
20.2037 + __ addl(pri, alt);
20.2038 + break;
20.2039 + }
20.2040 +
20.2041 + case OP_SHL:
20.2042 + __ movl(ecx, alt);
20.2043 + __ shll_cl(pri);
20.2044 + break;
20.2045 +
20.2046 + case OP_SHR:
20.2047 + __ movl(ecx, alt);
20.2048 + __ shrl_cl(pri);
20.2049 + break;
20.2050 +
20.2051 + case OP_SSHR:
20.2052 + __ movl(ecx, alt);
20.2053 + __ sarl_cl(pri);
20.2054 + break;
20.2055
20.2056 -inline void WriteOp_JsGeq(JitWriter *jit)
20.2057 -{
20.2058 - //cmp eax, edx
20.2059 - //jge <target>
20.2060 - cell_t target = jit->read_cell();
20.2061 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
20.2062 - IA32_Jump_Cond_Imm32_Rel(jit, CC_GE, RelocLookup(jit, target, false));
20.2063 -}
20.2064 + case OP_SHL_C_PRI:
20.2065 + case OP_SHL_C_ALT:
20.2066 + {
20.2067 + Register reg = (op == OP_SHL_C_PRI) ? pri : alt;
20.2068 + cell_t val = readCell();
20.2069 + __ shll(reg, val);
20.2070 + break;
20.2071 + }
20.2072 +
20.2073 + case OP_SHR_C_PRI:
20.2074 + case OP_SHR_C_ALT:
20.2075 + {
20.2076 + Register reg = (op == OP_SHR_C_PRI) ? pri : alt;
20.2077 + cell_t val = readCell();
20.2078 + __ shrl(reg, val);
20.2079 + break;
20.2080 + }
20.2081 +
20.2082 + case OP_SMUL:
20.2083 + __ imull(pri, alt);
20.2084 + break;
20.2085 +
20.2086 + case OP_NOT:
20.2087 + __ testl(eax, eax);
20.2088 + __ movl(eax, 0);
20.2089 + __ set(zero, r8_al);
20.2090 + break;
20.2091 +
20.2092 + case OP_NEG:
20.2093 + __ negl(eax);
20.2094 + break;
20.2095 +
20.2096 + case OP_XOR:
20.2097 + __ xorl(pri, alt);
20.2098 + break;
20.2099
20.2100 -inline void WriteOp_Switch(JitWriter *jit)
20.2101 -{
20.2102 - CompData *data = (CompData *)jit->data;
20.2103 - cell_t offs = jit->read_cell();
20.2104 - cell_t *tbl = (cell_t *)((char *)data->plugin->pcode + offs + sizeof(cell_t));
20.2105 + case OP_OR:
20.2106 + __ orl(pri, alt);
20.2107 + break;
20.2108 +
20.2109 + case OP_AND:
20.2110 + __ andl(pri, alt);
20.2111 + break;
20.2112 +
20.2113 + case OP_INVERT:
20.2114 + __ notl(pri);
20.2115 + break;
20.2116 +
20.2117 + case OP_ADD_C:
20.2118 + {
20.2119 + cell_t val = readCell();
20.2120 + __ addl(pri, val);
20.2121 + break;
20.2122 + }
20.2123 +
20.2124 + case OP_SMUL_C:
20.2125 + {
20.2126 + cell_t val = readCell();
20.2127 + __ imull(pri, pri, val);
20.2128 + break;
20.2129 + }
20.2130 +
20.2131 + case OP_EQ:
20.2132 + case OP_NEQ:
20.2133 + case OP_SLESS:
20.2134 + case OP_SLEQ:
20.2135 + case OP_SGRTR:
20.2136 + case OP_SGEQ:
20.2137 + {
20.2138 + ConditionCode cc = OpToCondition(op);
20.2139 + __ cmpl(pri, alt);
20.2140 + __ movl(pri, 0);
20.2141 + __ set(cc, r8_al);
20.2142 + break;
20.2143 + }
20.2144 +
20.2145 + case OP_EQ_C_PRI:
20.2146 + case OP_EQ_C_ALT:
20.2147 + {
20.2148 + Register reg = (op == OP_EQ_C_PRI) ? pri : alt;
20.2149 + cell_t val = readCell();
20.2150 + __ cmpl(reg, val);
20.2151 + __ movl(pri, 0);
20.2152 + __ set(equal, r8_al);
20.2153 + break;
20.2154 + }
20.2155
20.2156 - struct casetbl
20.2157 - {
20.2158 - cell_t val;
20.2159 - cell_t offs;
20.2160 - };
20.2161 + case OP_INC_PRI:
20.2162 + case OP_INC_ALT:
20.2163 + {
20.2164 + Register reg = (OP_INC_PRI) ? pri : alt;
20.2165 + __ addl(reg, 1);
20.2166 + break;
20.2167 + }
20.2168 +
20.2169 + case OP_INC:
20.2170 + case OP_INC_S:
20.2171 + {
20.2172 + Register base = (op == OP_INC) ? dat : frm;
20.2173 + cell_t offset = readCell();
20.2174 + __ addl(Operand(base, offset), 1);
20.2175 + break;
20.2176 + }
20.2177 +
20.2178 + case OP_INC_I:
20.2179 + __ addl(Operand(dat, pri, NoScale), 1);
20.2180 + break;
20.2181 +
20.2182 + case OP_DEC_PRI:
20.2183 + case OP_DEC_ALT:
20.2184 + {
20.2185 + Register reg = (op == OP_DEC_PRI) ? pri : alt;
20.2186 + __ subl(reg, 1);
20.2187 + break;
20.2188 + }
20.2189 +
20.2190 + case OP_DEC:
20.2191 + case OP_DEC_S:
20.2192 + {
20.2193 + Register base = (op == OP_DEC) ? dat : frm;
20.2194 + cell_t offset = readCell();
20.2195 + __ subl(Operand(base, offset), 1);
20.2196 + break;
20.2197 + }
20.2198 +
20.2199 + case OP_DEC_I:
20.2200 + __ subl(Operand(dat, pri, NoScale), 1);
20.2201 + break;
20.2202 +
20.2203 + case OP_LOAD_PRI:
20.2204 + case OP_LOAD_ALT:
20.2205 + {
20.2206 + Register reg = (op == OP_LOAD_PRI) ? pri : alt;
20.2207 + cell_t offset = readCell();
20.2208 + __ movl(reg, Operand(dat, offset));
20.2209 + break;
20.2210 + }
20.2211
20.2212 - /* Read the number of cases, then advance by one */
20.2213 - cell_t num_cases = *tbl++;
20.2214 - if (!num_cases)
20.2215 - {
20.2216 - /* Special treatment for 0 cases */
20.2217 - //jmp <default>
20.2218 - IA32_Jump_Imm32_Rel(jit, RelocLookup(jit, *tbl, false));
20.2219 - } else {
20.2220 - /* Check if the case layout is fully sequential */
20.2221 - casetbl *iter = (casetbl *)(tbl + 1);
20.2222 - casetbl *cases = iter;
20.2223 - cell_t first = iter[0].val;
20.2224 - cell_t last = first;
20.2225 - bool sequential = true;
20.2226 - for (cell_t i=1; i<num_cases; i++)
20.2227 - {
20.2228 - if (iter[i].val != ++last)
20.2229 - {
20.2230 - sequential = false;
20.2231 - break;
20.2232 - }
20.2233 - }
20.2234 - /* Time to generate.
20.2235 - * First check whether the bounds are correct: if (a < LOW || a > HIGH)
20.2236 - * This check is valid for both sequential and non-sequential.
20.2237 - */
20.2238 - cell_t low_bound = cases[0].val;
20.2239 - if (low_bound != 0)
20.2240 - {
20.2241 - /* negate it so we'll get a lower bound of 0 */
20.2242 - //lea ecx, [eax-<LOWER_BOUND>]
20.2243 - low_bound = -low_bound;
20.2244 - if (low_bound >= SCHAR_MIN && low_bound <= SCHAR_MAX)
20.2245 - {
20.2246 - IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
20.2247 - } else {
20.2248 - IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
20.2249 - }
20.2250 - } else {
20.2251 - //mov ecx, eax
20.2252 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
20.2253 - }
20.2254 - cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val);
20.2255 - //cmp ecx, <UPPER BOUND BOUND>
20.2256 - if (high_bound >= SCHAR_MIN && high_bound <= SCHAR_MAX)
20.2257 - {
20.2258 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound);
20.2259 - } else {
20.2260 - IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound);
20.2261 - }
20.2262 - //ja <default case>
20.2263 - IA32_Jump_Cond_Imm32_Rel(jit, CC_A, RelocLookup(jit, *tbl, false));
20.2264 + case OP_LOAD_BOTH:
20.2265 + {
20.2266 + cell_t offs1 = readCell();
20.2267 + cell_t offs2 = readCell();
20.2268 + __ movl(pri, Operand(dat, offs1));
20.2269 + __ movl(alt, Operand(dat, offs2));
20.2270 + break;
20.2271 + }
20.2272 +
20.2273 + case OP_LOAD_S_PRI:
20.2274 + case OP_LOAD_S_ALT:
20.2275 + {
20.2276 + Register reg = (op == OP_LOAD_S_PRI) ? pri : alt;
20.2277 + cell_t offset = readCell();
20.2278 + __ movl(reg, Operand(frm, offset));
20.2279 + break;
20.2280 + }
20.2281 +
20.2282 + case OP_LOAD_S_BOTH:
20.2283 + {
20.2284 + cell_t offs1 = readCell();
20.2285 + cell_t offs2 = readCell();
20.2286 + __ movl(pri, Operand(frm, offs1));
20.2287 + __ movl(alt, Operand(frm, offs2));
20.2288 + break;
20.2289 + }
20.2290 +
20.2291 + case OP_LREF_S_PRI:
20.2292 + case OP_LREF_S_ALT:
20.2293 + {
20.2294 + Register reg = (op == OP_LREF_S_PRI) ? pri : alt;
20.2295 + cell_t offset = readCell();
20.2296 + __ movl(reg, Operand(frm, offset));
20.2297 + __ movl(reg, Operand(dat, reg, NoScale));
20.2298 + break;
20.2299 + }
20.2300 +
20.2301 + case OP_CONST_PRI:
20.2302 + case OP_CONST_ALT:
20.2303 + {
20.2304 + Register reg = (op == OP_CONST_PRI) ? pri : alt;
20.2305 + cell_t val = readCell();
20.2306 + __ movl(reg, val);
20.2307 + break;
20.2308 + }
20.2309 +
20.2310 + case OP_ADDR_PRI:
20.2311 + case OP_ADDR_ALT:
20.2312 + {
20.2313 + Register reg = (op == OP_ADDR_PRI) ? pri : alt;
20.2314 + cell_t offset = readCell();
20.2315 + __ movl(reg, Operand(info, AMX_INFO_FRAME));
20.2316 + __ addl(reg, offset);
20.2317 + break;
20.2318 + }
20.2319 +
20.2320 + case OP_STOR_PRI:
20.2321 + case OP_STOR_ALT:
20.2322 + {
20.2323 + Register reg = (op == OP_STOR_PRI) ? pri : alt;
20.2324 + cell_t offset = readCell();
20.2325 + __ movl(Operand(dat, offset), reg);
20.2326 + break;
20.2327 + }
20.2328 +
20.2329 + case OP_STOR_S_PRI:
20.2330 + case OP_STOR_S_ALT:
20.2331 + {
20.2332 + Register reg = (op == OP_STOR_S_PRI) ? pri : alt;
20.2333 + cell_t offset = readCell();
20.2334 + __ movl(Operand(frm, offset), reg);
20.2335 + break;
20.2336 + }
20.2337 +
20.2338 + case OP_IDXADDR:
20.2339 + __ lea(pri, Operand(alt, pri, ScaleFour));
20.2340 + break;
20.2341 +
20.2342 + case OP_SREF_S_PRI:
20.2343 + case OP_SREF_S_ALT:
20.2344 + {
20.2345 + Register reg = (op == OP_SREF_S_PRI) ? pri : alt;
20.2346 + cell_t offset = readCell();
20.2347 + __ movl(tmp, Operand(frm, offset));
20.2348 + __ movl(Operand(dat, tmp, NoScale), reg);
20.2349 + break;
20.2350 + }
20.2351 +
20.2352 + case OP_POP_PRI:
20.2353 + case OP_POP_ALT:
20.2354 + {
20.2355 + Register reg = (op == OP_POP_PRI) ? pri : alt;
20.2356 + __ movl(reg, Operand(stk, 0));
20.2357 + __ addl(stk, 4);
20.2358 + break;
20.2359 + }
20.2360 +
20.2361 + case OP_SWAP_PRI:
20.2362 + case OP_SWAP_ALT:
20.2363 + {
20.2364 + Register reg = (op == OP_SWAP_PRI) ? pri : alt;
20.2365 + __ movl(tmp, Operand(stk, 0));
20.2366 + __ movl(Operand(stk, 0), reg);
20.2367 + __ movl(reg, tmp);
20.2368 + break;
20.2369 + }
20.2370 +
20.2371 + case OP_LIDX:
20.2372 + __ lea(pri, Operand(alt, pri, ScaleFour));
20.2373 + __ movl(pri, Operand(dat, pri, NoScale));
20.2374 + break;
20.2375
20.2376 - /**
20.2377 - * Now we've taken the default case out of the way, it's time to do the
20.2378 - * full check, which is different for sequential vs. non-sequential.
20.2379 - */
20.2380 - if (sequential)
20.2381 - {
20.2382 - /* we're now theoretically guaranteed to be jumping to a correct offset.
20.2383 - * ECX still has the correctly bound offset in it, luckily!
20.2384 - * thus, we simply need to relocate ECX and store the cases.
20.2385 - */
20.2386 - //lea ecx, [ecx*4]
20.2387 - //add ecx, <case table start>
20.2388 - IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0);
20.2389 - jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG);
20.2390 - IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG);
20.2391 - /* The case table starts here. Go back and write the output pointer. */
20.2392 - jitoffs_t cur_pos = jit->get_outputpos();
20.2393 - jit->set_outputpos(tbl_offs);
20.2394 - jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos));
20.2395 - jit->set_outputpos(cur_pos);
20.2396 - //now we can write the case table, finally!
20.2397 - jit_uint32_t base = (jit_uint32_t)jit->outbase;
20.2398 - for (cell_t i=0; i<num_cases; i++)
20.2399 - {
20.2400 - jit->write_uint32(base + RelocLookup(jit, cases[i].offs, false));
20.2401 - }
20.2402 - } else {
20.2403 - /* The slow version. Go through each case and generate a check.
20.2404 - * In the future we should replace case tables of more than ~8 cases with a
20.2405 - * hash table lookup.
20.2406 - * :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case,
20.2407 - * but only if we're under N cases or so!
20.2408 - * :THOUGHT: Write out a static btree lookup :)
20.2409 - */
20.2410 - cell_t val;
20.2411 - for (cell_t i=0; i<num_cases; i++)
20.2412 - {
20.2413 - val = cases[i].val;
20.2414 - //cmp eax, <val>
20.2415 - IA32_Cmp_Eax_Imm32(jit, val);
20.2416 - IA32_Jump_Cond_Imm32_Rel(jit, CC_E, RelocLookup(jit, cases[i].offs, false));
20.2417 - }
20.2418 - /* After all this, jump to the default case! */
20.2419 - IA32_Jump_Imm32_Rel(jit, RelocLookup(jit, *tbl, false));
20.2420 - }
20.2421 - }
20.2422 -}
20.2423 + case OP_LIDX_B:
20.2424 + {
20.2425 + cell_t val = readCell();
20.2426 + if (val >= 0 && val <= 3) {
20.2427 + __ lea(pri, Operand(alt, pri, Scale(val)));
20.2428 + } else {
20.2429 + __ shll(pri, val);
20.2430 + __ addl(pri, alt);
20.2431 + }
20.2432 + emitCheckAddress(pri);
20.2433 + __ movl(pri, Operand(dat, pri, NoScale));
20.2434 + break;
20.2435 + }
20.2436 +
20.2437 + case OP_CONST:
20.2438 + case OP_CONST_S:
20.2439 + {
20.2440 + Register base = (op == OP_CONST) ? dat : frm;
20.2441 + cell_t offset = readCell();
20.2442 + cell_t val = readCell();
20.2443 + __ movl(Operand(base, offset), val);
20.2444 + break;
20.2445 + }
20.2446 +
20.2447 + case OP_LOAD_I:
20.2448 + emitCheckAddress(pri);
20.2449 + __ movl(pri, Operand(dat, pri, NoScale));
20.2450 + break;
20.2451 +
20.2452 + case OP_STOR_I:
20.2453 + emitCheckAddress(alt);
20.2454 + __ movl(Operand(dat, alt, NoScale), pri);
20.2455 + break;
20.2456 +
20.2457 + case OP_SDIV:
20.2458 + case OP_SDIV_ALT:
20.2459 + {
20.2460 + Register dividend = (op == OP_SDIV) ? pri : alt;
20.2461 + Register divisor = (op == OP_SDIV) ? alt : pri;
20.2462 +
20.2463 + // Guard against divide-by-zero.
20.2464 + __ testl(divisor, divisor);
20.2465 + __ j(zero, &error_divide_by_zero_);
20.2466 +
20.2467 + // A more subtle case; -INT_MIN / -1 yields an overflow exception.
20.2468 + Label ok;
20.2469 + __ cmpl(divisor, -1);
20.2470 + __ j(not_equal, &ok);
20.2471 + __ cmpl(dividend, 0x80000000);
20.2472 + __ j(equal, &error_integer_overflow_);
20.2473 + __ bind(&ok);
20.2474 +
20.2475 + // Now we can actually perform the divide.
20.2476 + __ movl(tmp, divisor);
20.2477 + if (op == OP_SDIV)
20.2478 + __ movl(edx, dividend);
20.2479 + else
20.2480 + __ movl(eax, dividend);
20.2481 + __ sarl(edx, 31);
20.2482 + __ idivl(tmp);
20.2483 + break;
20.2484 + }
20.2485 +
20.2486 + case OP_LODB_I:
20.2487 + {
20.2488 + cell_t val = readCell();
20.2489 + emitCheckAddress(pri);
20.2490 + __ movl(pri, Operand(dat, pri, NoScale));
20.2491 + if (val == 1)
20.2492 + __ andl(pri, 0xff);
20.2493 + else if (val == 2)
20.2494 + __ andl(pri, 0xffff);
20.2495 + break;
20.2496 + }
20.2497 +
20.2498 + case OP_STRB_I:
20.2499 + {
20.2500 + cell_t val = readCell();
20.2501 + emitCheckAddress(alt);
20.2502 + if (val == 1)
20.2503 + __ movb(Operand(dat, alt, NoScale), pri);
20.2504 + else if (val == 2)
20.2505 + __ movw(Operand(dat, alt, NoScale), pri);
20.2506 + else if (val == 4)
20.2507 + __ movl(Operand(dat, alt, NoScale), pri);
20.2508 + break;
20.2509 + }
20.2510 +
20.2511 + case OP_RETN:
20.2512 + {
20.2513 + // Restore the old frame pointer.
20.2514 + __ movl(frm, Operand(stk, 4)); // get the old frm
20.2515 + __ addl(stk, 8); // pop stack
20.2516 + __ movl(Operand(info, AMX_INFO_FRAME), frm); // store back old frm
20.2517 + __ addl(frm, dat); // relocate
20.2518 +
20.2519 + // Remove parameters.
20.2520 + __ movl(tmp, Operand(stk, 0));
20.2521 + __ lea(stk, Operand(stk, tmp, ScaleFour, 4));
20.2522 + __ ret();
20.2523 + break;
20.2524 + }
20.2525 +
20.2526 + case OP_MOVS:
20.2527 + {
20.2528 + cell_t val = readCell();
20.2529 + unsigned dwords = val / 4;
20.2530 + unsigned bytes = val % 4;
20.2531
20.2532 -inline void WriteOp_Casetbl(JitWriter *jit)
20.2533 -{
20.2534 - /* do nothing here, switch does all ze work */
20.2535 - cell_t num_cases = jit->read_cell();
20.2536 + __ cld();
20.2537 + __ push(esi);
20.2538 + __ push(edi);
20.2539 + __ lea(esi, Operand(dat, pri, NoScale));
20.2540 + __ lea(edi, Operand(dat, alt, NoScale));
20.2541 + if (dwords) {
20.2542 + __ movl(ecx, dwords);
20.2543 + __ rep_movsd();
20.2544 + }
20.2545 + if (bytes) {
20.2546 + __ movl(ecx, bytes);
20.2547 + __ rep_movsb();
20.2548 + }
20.2549 + __ pop(edi);
20.2550 + __ pop(esi);
20.2551 + break;
20.2552 + }
20.2553
20.2554 - /* Two cells per case, one extra case for the default jump */
20.2555 - num_cases = (num_cases * 2) + 1;
20.2556 - jit->inptr += num_cases;
20.2557 -}
20.2558 + case OP_FILL:
20.2559 + {
20.2560 + // eax/pri is used implicitly.
20.2561 + unsigned dwords = readCell() / 4;
20.2562 + __ push(edi);
20.2563 + __ lea(edi, Operand(dat, alt, NoScale));
20.2564 + __ movl(ecx, dwords);
20.2565 + __ cld();
20.2566 + __ rep_stosd();
20.2567 + __ pop(edi);
20.2568 + break;
20.2569 + }
20.2570 +
20.2571 + case OP_STRADJUST_PRI:
20.2572 + __ addl(pri, 4);
20.2573 + __ sarl(pri, 2);
20.2574 + break;
20.2575
20.2576 -inline void WriteOp_Sysreq_C(JitWriter *jit)
20.2577 -{
20.2578 - /* store the number of parameters on the stack,
20.2579 - * and store the native index as well.
20.2580 - */
20.2581 - cell_t native_index = jit->read_cell();
20.2582 + case OP_FABS:
20.2583 + __ movl(pri, Operand(stk, 0));
20.2584 + __ andl(pri, 0x7fffffff);
20.2585 + __ addl(stk, 4);
20.2586 + break;
20.2587 +
20.2588 + case OP_FLOAT:
20.2589 + __ fild32(Operand(edi, 0));
20.2590 + __ subl(esp, 4);
20.2591 + __ fstp32(Operand(esp, 0));
20.2592 + __ pop(pri);
20.2593 + __ addl(stk, 4);
20.2594 + break;
20.2595 +
20.2596 + case OP_FLOATADD:
20.2597 + case OP_FLOATSUB:
20.2598 + case OP_FLOATMUL:
20.2599 + case OP_FLOATDIV:
20.2600 + __ subl(esp, 4);
20.2601 + __ fld32(Operand(edi, 0));
20.2602
20.2603 - if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->num_natives)
20.2604 - {
20.2605 - ((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
20.2606 - return;
20.2607 - }
20.2608 + if (op == OP_FLOATADD)
20.2609 + __ fadd32(Operand(edi, 4));
20.2610 + else if (op == OP_FLOATSUB)
20.2611 + __ fsub32(Operand(edi, 4));
20.2612 + else if (op == OP_FLOATMUL)
20.2613 + __ fmul32(Operand(edi, 4));
20.2614 + else if (op == OP_FLOATDIV)
20.2615 + __ fdiv32(Operand(edi, 4));
20.2616 +
20.2617 + __ fstp32(Operand(esp, 0));
20.2618 + __ pop(pri);
20.2619 + __ addl(stk, 8);
20.2620 + break;
20.2621
20.2622 - //mov ecx, <native_index>
20.2623 - IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
20.2624 -
20.2625 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
20.2626 - IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c);
20.2627 -}
20.2628 + case OP_RND_TO_NEAREST:
20.2629 + {
20.2630 + static float kRoundToNearest = 0.5f;
20.2631 + // From http://wurstcaptures.untergrund.net/assembler_tricks.html#fastfloorf
20.2632 + __ fld32(Operand(edi, 0));
20.2633 + __ fadd32(st0, st0);
20.2634 + __ fadd32(Operand(ExternalAddress(&kRoundToNearest)));
20.2635 + __ subl(esp, 4);
20.2636 + __ fistp32(Operand(esp, 0));
20.2637 + __ pop(pri);
20.2638 + __ sarl(pri, 1);
20.2639 + __ addl(stk, 4);
20.2640 + break;
20.2641 + }
20.2642
20.2643 -inline void WriteOp_Sysreq_N(JitWriter *jit)
20.2644 -{
20.2645 - /* The big daddy of opcodes. */
20.2646 - cell_t native_index = jit->read_cell();
20.2647 - cell_t num_params = jit->read_cell();
20.2648 - CompData *data = (CompData *)jit->data;
20.2649 + case OP_RND_TO_CEIL:
20.2650 + {
20.2651 + static float kRoundToCeil = -0.5f;
20.2652 + // From http://wurstcaptures.untergrund.net/assembler_tricks.html#fastfloorf
20.2653 + __ fld32(Operand(edi, 0));
20.2654 + __ fadd32(st0, st0);
20.2655 + __ fsubr32(Operand(ExternalAddress(&kRoundToCeil)));
20.2656 + __ subl(esp, 4);
20.2657 + __ fistp32(Operand(esp, 0));
20.2658 + __ pop(pri);
20.2659 + __ sarl(pri, 1);
20.2660 + __ negl(pri);
20.2661 + __ addl(stk, 4);
20.2662 + break;
20.2663 + }
20.2664
20.2665 - if ((uint32_t)native_index >= data->plugin->num_natives)
20.2666 - {
20.2667 - data->error_set = SP_ERROR_INSTRUCTION_PARAM;
20.2668 - return;
20.2669 - }
20.2670 + case OP_RND_TO_ZERO:
20.2671 + __ fld32(Operand(edi, 0));
20.2672 + __ subl(esp, 8);
20.2673 + __ fstcw(Operand(esp, 4));
20.2674 + __ movl(Operand(esp, 0), 0xfff);
20.2675 + __ fldcw(Operand(esp, 0));
20.2676 + __ fistp32(Operand(esp, 0));
20.2677 + __ pop(pri);
20.2678 + __ fldcw(Operand(esp, 0));
20.2679 + __ addl(esp, 4);
20.2680 + __ addl(stk, 4);
20.2681 + break;
20.2682
20.2683 - /* store the number of parameters on the stack */
20.2684 - //mov [edi-4], num_params
20.2685 - //sub edi, 4
20.2686 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4);
20.2687 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.2688 + case OP_RND_TO_FLOOR:
20.2689 + __ fld32(Operand(stk, 0));
20.2690 + __ subl(esp, 8);
20.2691 + __ fstcw(Operand(esp, 4));
20.2692 + __ movl(Operand(esp, 0), 0x7ff);
20.2693 + __ fldcw(Operand(esp, 0));
20.2694 + __ fistp32(Operand(esp, 0));
20.2695 + __ pop(eax);
20.2696 + __ fldcw(Operand(esp, 0));
20.2697 + __ addl(esp, 4);
20.2698 + __ addl(stk, 4);
20.2699 + break;
20.2700
20.2701 - /* save registers we will need */
20.2702 - //push edx
20.2703 - IA32_Push_Reg(jit, AMX_REG_ALT);
20.2704 + case OP_FLOATCMP:
20.2705 + {
20.2706 + Label bl, ab, done;
20.2707 + __ fld32(Operand(edi, 0));
20.2708 + __ fld32(Operand(edi, 4));
20.2709 + __ fucomip(st1);
20.2710 + __ fstp(st0);
20.2711 + __ j(above, &ab);
20.2712 + __ j(below, &bl);
20.2713 + __ xorl(pri, pri);
20.2714 + __ jmp(&done);
20.2715 + __ bind(&ab);
20.2716 + __ movl(pri, -1);
20.2717 + __ jmp(&done);
20.2718 + __ bind(&bl);
20.2719 + __ movl(pri, 1);
20.2720 + __ bind(&done);
20.2721 + __ addl(stk, 8);
20.2722 + break;
20.2723 + }
20.2724 +
20.2725 + case OP_STACK:
20.2726 + {
20.2727 + cell_t amount = readCell();
20.2728 + __ addl(stk, amount);
20.2729 +
20.2730 + if (amount > 0) {
20.2731 + // Check if the stack went beyond the stack top - usually a compiler error.
20.2732 + __ cmpl(stk, Operand(info, AMX_INFO_STACKTOP));
20.2733 + __ j(not_below, &error_stack_min_);
20.2734 + } else {
20.2735 + // Check if the stack is going to collide with the heap.
20.2736 + __ movl(tmp, Operand(info, AMX_INFO_HEAP));
20.2737 + __ lea(tmp, Operand(dat, ecx, NoScale, STACK_MARGIN));
20.2738 + __ cmpl(stk, tmp);
20.2739 + __ j(below, &error_stack_low_);
20.2740 + }
20.2741 + break;
20.2742 + }
20.2743
20.2744 - /* Align the stack to 16 bytes */
20.2745 - //push ebx
20.2746 - //mov ebx, esp
20.2747 - //and esp, 0xFFFFFF0
20.2748 - //sub esp, 4
20.2749 - IA32_Push_Reg(jit, REG_EBX);
20.2750 - IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
20.2751 - IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
20.2752 - IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
20.2753 + case OP_HEAP:
20.2754 + {
20.2755 + cell_t amount = readCell();
20.2756 + __ movl(alt, Operand(info, AMX_INFO_HEAP));
20.2757 + __ addl(Operand(info, AMX_INFO_HEAP), amount);
20.2758 +
20.2759 + if (amount > 0) {
20.2760 + __ cmpl(Operand(info, AMX_INFO_HEAP), plugin_->data_size);
20.2761 + __ j(below, &error_heap_min_);
20.2762 + } else {
20.2763 + __ movl(tmp, Operand(info, AMX_INFO_HEAP));
20.2764 + __ lea(tmp, Operand(dat, ecx, NoScale, STACK_MARGIN));
20.2765 + __ cmpl(tmp, stk);
20.2766 + __ j(above, &error_heap_low_);
20.2767 + }
20.2768 + break;
20.2769 + }
20.2770 +
20.2771 + case OP_JUMP:
20.2772 + {
20.2773 + Label *target = labelAt(readCell());
20.2774 + if (!target)
20.2775 + return false;
20.2776 + __ jmp(target);
20.2777 + break;
20.2778 + }
20.2779
20.2780 - /* push some callback stuff */
20.2781 - //push edi ; stack
20.2782 - //push <native> ; native index
20.2783 - IA32_Push_Reg(jit, AMX_REG_STK);
20.2784 - if (native_index <= SCHAR_MAX && native_index >= SCHAR_MIN)
20.2785 - {
20.2786 - IA32_Push_Imm8(jit, (jit_int8_t)native_index);
20.2787 - } else {
20.2788 - IA32_Push_Imm32(jit, native_index);
20.2789 - }
20.2790 + case OP_JZER:
20.2791 + case OP_JNZ:
20.2792 + {
20.2793 + ConditionCode cc = (op == OP_JZER) ? zero : not_zero;
20.2794 + Label *target = labelAt(readCell());
20.2795 + if (!target)
20.2796 + return false;
20.2797 + __ testl(pri, pri);
20.2798 + __ j(cc, target);
20.2799 + break;
20.2800 + }
20.2801 +
20.2802 + case OP_JEQ:
20.2803 + case OP_JNEQ:
20.2804 + case OP_JSLESS:
20.2805 + case OP_JSLEQ:
20.2806 + case OP_JSGRTR:
20.2807 + case OP_JSGEQ:
20.2808 + {
20.2809 + Label *target = labelAt(readCell());
20.2810 + if (!target)
20.2811 + return false;
20.2812 + ConditionCode cc = OpToCondition(op);
20.2813 + __ cmpl(pri, alt);
20.2814 + __ j(cc, target);
20.2815 + break;
20.2816 + }
20.2817 +
20.2818 + case OP_TRACKER_PUSH_C:
20.2819 + {
20.2820 + cell_t amount = readCell();
20.2821
20.2822 - /* Relocate stack, heap, frm information, then store back */
20.2823 - //mov eax, [esi+context]
20.2824 - //mov ecx, [esi+hea]
20.2825 - //sub edi, ebp
20.2826 - //mov [eax+hp], ecx
20.2827 - //mov ecx, [esi]
20.2828 - //mov [eax+sp], edi
20.2829 - //mov [eax+frm], ecx
20.2830 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
20.2831 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
20.2832 - IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
20.2833 - IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
20.2834 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
20.2835 - IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
20.2836 - IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
20.2837 + // Save registers.
20.2838 + __ push(pri);
20.2839 + __ push(alt);
20.2840 +
20.2841 + // call JIT_VerifyorAllocateTracker
20.2842 + __ movl(eax, Operand(info, AMX_INFO_CONTEXT));
20.2843 + __ push(eax);
20.2844 + __ call(ExternalAddress((void *)JIT_VerifyOrAllocateTracker));
20.2845 + __ testl(eax, eax);
20.2846 + __ j(not_zero, &extern_error_);
20.2847 + __ pop(eax);
20.2848 +
20.2849 + // Push the value onto the stack and increment pCur.
20.2850 + __ movl(edx, Operand(eax, offsetof(sp_context_t, vm[JITVARS_TRACKER])));
20.2851 + __ movl(ecx, Operand(edx, offsetof(tracker_t, pCur)));
20.2852 + __ addl(Operand(edx, offsetof(tracker_t, pCur)), 4);
20.2853 + __ movl(Operand(ecx, 0), amount * 4);
20.2854 +
20.2855 + __ pop(alt);
20.2856 + __ pop(pri);
20.2857 + break;
20.2858 + }
20.2859 +
20.2860 + case OP_TRACKER_POP_SETHEAP:
20.2861 + {
20.2862 + // Save registers.
20.2863 + __ push(pri);
20.2864 + __ push(alt);
20.2865 +
20.2866 + // Get the context pointer and call the sanity checker.
20.2867 + __ movl(eax, Operand(info, AMX_INFO_CONTEXT));
20.2868 + __ push(eax);
20.2869 + __ call(ExternalAddress((void *)JIT_VerifyLowBoundTracker));
20.2870 + __ testl(eax, eax);
20.2871 + __ j(not_zero, &extern_error_);
20.2872 + __ pop(eax);
20.2873 +
20.2874 + // Pop the value from the tracker stack and decrease the heap by it.
20.2875 + __ movl(edx, Operand(eax, offsetof(sp_context_t, vm[JITVARS_TRACKER])));
20.2876 + __ movl(ecx, Operand(edx, offsetof(tracker_t, pCur)));
20.2877 + __ subl(ecx, 4);
20.2878 + __ movl(Operand(edx, offsetof(tracker_t, pCur)), eax);
20.2879 + __ movl(ecx, Operand(ecx, 0));
20.2880 + __ subl(Operand(info, AMX_INFO_HEAP), ecx);
20.2881 +
20.2882 + // Check that we didn't underflow the heap.
20.2883 + __ cmpl(Operand(info, AMX_INFO_HEAP), plugin_->data_size);
20.2884 + __ j(below, &error_heap_min_);
20.2885 +
20.2886 + __ pop(alt);
20.2887 + __ pop(pri);
20.2888 + break;
20.2889 + }
20.2890
20.2891 - /* finally, push the last parameter and make the call */
20.2892 - //push eax ; context
20.2893 - //call NativeCallback
20.2894 - IA32_Push_Reg(jit, REG_EAX);
20.2895 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
20.2896 - if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
20.2897 - {
20.2898 - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
20.2899 - }
20.2900 - else
20.2901 - {
20.2902 - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
20.2903 - }
20.2904 -
20.2905 - /* check for errors */
20.2906 - //mov ecx, [esi+context]
20.2907 - //cmp [ecx+err], 0
20.2908 - //jnz :error
20.2909 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
20.2910 - IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
20.2911 - IA32_Jump_Cond_Imm32_Rel(jit, CC_NZ, data->jit_extern_error);
20.2912 + case OP_BREAK:
20.2913 + {
20.2914 + cell_t cip = uintptr_t(cip_ - 1) - uintptr_t(plugin_->pcode);
20.2915 + __ movl(Operand(info, AMX_INFO_CIP), cip);
20.2916 + break;
20.2917 + }
20.2918 +
20.2919 + case OP_HALT:
20.2920 + __ align(16);
20.2921 + __ movl(tmp, Operand(info, AMX_INFO_RETVAL));
20.2922 + __ movl(Operand(ecx, 0), pri);
20.2923 + __ movl(pri, readCell());
20.2924 + __ jmp(&extern_error_);
20.2925 + break;
20.2926 +
20.2927 + case OP_BOUNDS:
20.2928 + {
20.2929 + cell_t value = readCell();
20.2930 + __ cmpl(eax, value);
20.2931 + __ j(above, &error_bounds_);
20.2932 + break;
20.2933 + }
20.2934 +
20.2935 + case OP_GENARRAY:
20.2936 + case OP_GENARRAY_Z:
20.2937 + emitGenArray(op == OP_GENARRAY_Z);
20.2938 + break;
20.2939
20.2940 - /* restore what we damaged */
20.2941 - //mov esp, ebx
20.2942 - //pop ebx
20.2943 - //add edi, ebp
20.2944 - //pop edx
20.2945 - IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
20.2946 - IA32_Pop_Reg(jit, REG_EBX);
20.2947 - IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
20.2948 - IA32_Pop_Reg(jit, AMX_REG_ALT);
20.2949 + case OP_CALL:
20.2950 + if (!emitCall())
20.2951 + return false;
20.2952 + break;
20.2953 +
20.2954 + case OP_SYSREQ_C:
20.2955 + case OP_SYSREQ_N:
20.2956 + if (!emitNativeCall(op))
20.2957 + return false;
20.2958 + break;
20.2959 +
20.2960 + case OP_SWITCH:
20.2961 + if (!emitSwitch())
20.2962 + return false;
20.2963 + break;
20.2964
20.2965 - /* pop the stack. do not check the margins.
20.2966 - * Note that this is not a true macro - we don't bother to
20.2967 - * set ALT here because nothing will be using it.
20.2968 - */
20.2969 - num_params++;
20.2970 - num_params *= 4;
20.2971 - //add edi, <val*4+4>
20.2972 - if (num_params <= SCHAR_MAX && num_params >= SCHAR_MIN)
20.2973 - {
20.2974 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG);
20.2975 - } else {
20.2976 - IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG);
20.2977 - }
20.2978 + case OP_CASETBL:
20.2979 + {
20.2980 + size_t ncases = readCell();
20.2981 +
20.2982 + // Two cells per case, and one extra cell for the default address.
20.2983 + cip_ += (ncases * 2) + 1;
20.2984 + break;
20.2985 + }
20.2986 +
20.2987 + case OP_NOP:
20.2988 + break;
20.2989 +
20.2990 + default:
20.2991 + error_ = SP_ERROR_INVALID_INSTRUCTION;
20.2992 + return false;
20.2993 + }
20.2994 +
20.2995 + return true;
20.2996 }
20.2997
20.2998 -inline void WriteOp_Tracker_Push_C(JitWriter *jit)
20.2999 +Label *
20.3000 +Compiler::labelAt(size_t offset)
20.3001 {
20.3002 - cell_t val = jit->read_cell();
20.3003 -
20.3004 - /* Save registers that may be damaged by the call */
20.3005 - //push eax
20.3006 - //push edx
20.3007 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3008 - IA32_Push_Reg(jit, AMX_REG_ALT);
20.3009 -
20.3010 - /* Get the context ptr, push it and call the check */
20.3011 - //mov eax, [esi+context]
20.3012 - //push eax
20.3013 - //call JIT_VerifyOrAllocateTracker
20.3014 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
20.3015 - IA32_Push_Reg(jit, REG_EAX);
20.3016 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
20.3017 - IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
20.3018 + if (offset % 4 != 0 ||
20.3019 + offset > plugin_->pcode_size ||
20.3020 + offset <= pcode_start_)
20.3021 + {
20.3022 + // If the jump target is misaligned, or out of pcode bounds, or is an
20.3023 + // address out of the function bounds, we abort. Unfortunately we can't
20.3024 + // test beyond the end of the function since we don't have a precursor
20.3025 + // pass (yet).
20.3026 + error_ = SP_ERROR_INSTRUCTION_PARAM;
20.3027 + return NULL;
20.3028 + }
20.3029
20.3030 - /* Check for errors */
20.3031 - //cmp eax, 0
20.3032 - //jnz :error
20.3033 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
20.3034 - IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, g_Jit.GetReturnPoint());
20.3035 -
20.3036 - /* Restore */
20.3037 - //pop eax
20.3038 - IA32_Pop_Reg(jit, REG_EAX);
20.3039 -
20.3040 - /* Push the value into the stack and increment pCur */
20.3041 - //mov edx, [eax+vm[]]
20.3042 - //mov ecx, [edx+pcur]
20.3043 - //add [edx+pcur], 4
20.3044 - //mov [ecx], <val>*4 ; we want the count in bytes not in cells
20.3045 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
20.3046 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
20.3047 - IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
20.3048 - IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG);
20.3049 -
20.3050 - /* Restore PRI & ALT */
20.3051 - //pop edx
20.3052 - //pop eax
20.3053 - IA32_Pop_Reg(jit, AMX_REG_ALT);
20.3054 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3055 + return &jump_map_[offset / sizeof(cell_t)];
20.3056 }
20.3057
20.3058 -inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit)
20.3059 +static void
20.3060 +EmitTrackerPushReg(AssemblerX86 &masm, Register reg, Label *error)
20.3061 {
20.3062 - /* Save registers that may be damaged by the call */
20.3063 - //push eax
20.3064 - //push edx
20.3065 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3066 - IA32_Push_Reg(jit, AMX_REG_ALT);
20.3067 + __ push(eax);
20.3068 + if (reg == ecx)
20.3069 + __ push(ecx);
20.3070 + __ push(edi);
20.3071 + __ movl(edi, reg);
20.3072 + __ shll(edi, 2); // Count in bytes, not cells.
20.3073
20.3074 - /* Get the context ptr, push it and call the check */
20.3075 - //mov eax, [esi+context]
20.3076 - //push eax
20.3077 - //call JIT_VerifyLowBoundTracker
20.3078 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
20.3079 - IA32_Push_Reg(jit, REG_EAX);
20.3080 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
20.3081 - IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker);
20.3082 -
20.3083 - /* Check for errors */
20.3084 - //cmp eax, 0
20.3085 - //jnz :error
20.3086 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
20.3087 - IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, g_Jit.GetReturnPoint());
20.3088 + // Get the context pointer, push it and call the check.
20.3089 + __ movl(eax, Operand(info, AMX_INFO_CONTEXT));
20.3090 + __ push(eax);
20.3091 + __ call(ExternalAddress((void *)JIT_VerifyOrAllocateTracker));
20.3092
20.3093 - /* Restore */
20.3094 - //pop eax
20.3095 - IA32_Pop_Reg(jit, REG_EAX);
20.3096 + // Check for errors.
20.3097 + __ testl(eax, eax);
20.3098 + __ j(not_zero, error);
20.3099 +
20.3100 + __ pop(eax);
20.3101
20.3102 - /* Pop the value from the stack and decrease the heap by it*/
20.3103 - //mov edx, [eax+vm[]]
20.3104 - //sub [edx+pcur], 4
20.3105 - //mov ecx, [edx+pcur]
20.3106 - //mov ecx, [ecx]
20.3107 - //sub [esi+hea], ecx
20.3108 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
20.3109 - IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
20.3110 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
20.3111 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG);
20.3112 - IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP);
20.3113 + // Push the register into the stack and increment pCur.
20.3114 + __ movl(edx, Operand(eax, offsetof(sp_context_t, vm[JITVARS_TRACKER])));
20.3115 + __ movl(eax, Operand(edx, offsetof(tracker_t, pCur)));
20.3116 + __ addl(Operand(edx, offsetof(tracker_t, pCur)), 4);
20.3117 + __ movl(Operand(eax, 0), edi);
20.3118
20.3119 - Write_CheckHeap_Min(jit);
20.3120 -
20.3121 - /* Restore PRI & ALT */
20.3122 - //pop edx
20.3123 - //pop eax
20.3124 - IA32_Pop_Reg(jit, AMX_REG_ALT);
20.3125 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3126 + // Restore pri, alt, stk.
20.3127 + __ pop(edi);
20.3128 + if (reg == ecx)
20.3129 + __ pop(ecx);
20.3130 + __ pop(eax);
20.3131 }
20.3132
20.3133 -inline void WriteOp_Stradjust_Pri(JitWriter *jit)
20.3134 -{
20.3135 - //add eax, 4
20.3136 - //sar eax, 2
20.3137 - IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG);
20.3138 - IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG);
20.3139 -}
20.3140 -
20.3141 -inline void WriteOp_FloatAbs(JitWriter *jit)
20.3142 -{
20.3143 - //mov eax, [edi]
20.3144 - //and eax, 0x7FFFFFFF
20.3145 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
20.3146 - IA32_And_Eax_Imm32(jit, 0x7FFFFFFF);
20.3147 -
20.3148 - /* Rectify the stack */
20.3149 - //add edi, 4
20.3150 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.3151 -}
20.3152 -
20.3153 -inline void WriteOp_Float(JitWriter *jit)
20.3154 +void
20.3155 +Compiler::emitCheckAddress(Register reg)
20.3156 {
20.3157 - //fild [edi]
20.3158 - //push eax
20.3159 - //fstp [esp]
20.3160 - //pop eax
20.3161 - IA32_Fild_Mem32(jit, AMX_REG_STK);
20.3162 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3163 - IA32_Fstp_Mem32_ESP(jit);
20.3164 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3165 -
20.3166 - /* Rectify the stack */
20.3167 - //add edi, 4
20.3168 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.3169 -}
20.3170 + // Check if we're in memory bounds.
20.3171 + __ cmpl(reg, plugin_->mem_size);
20.3172 + __ j(not_below, &error_memaccess_);
20.3173
20.3174 -inline void WriteOp_FloatAdd(JitWriter *jit)
20.3175 -{
20.3176 - //push eax
20.3177 - //fld [edi]
20.3178 - //fadd [edi+4]
20.3179 - //fstp [esp]
20.3180 - //pop eax
20.3181 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3182 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3183 - IA32_Fadd_Mem32_Disp8(jit, AMX_REG_STK, 4);
20.3184 - IA32_Fstp_Mem32_ESP(jit);
20.3185 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3186 -
20.3187 - /* Rectify the stack */
20.3188 - //add edi, 8
20.3189 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.3190 + // Check if we're in the invalid region between hp and sp.
20.3191 + Label done;
20.3192 + __ cmpl(reg, Operand(info, AMX_INFO_HEAP));
20.3193 + __ j(below, &done);
20.3194 + __ lea(tmp, Operand(dat, reg, NoScale));
20.3195 + __ cmpl(tmp, stk);
20.3196 + __ j(below, &error_memaccess_);
20.3197 + __ bind(&done);
20.3198 }
20.3199
20.3200 -inline void WriteOp_FloatSub(JitWriter *jit)
20.3201 -{
20.3202 - //push eax
20.3203 - //fld [edi]
20.3204 - //fsub [edi+4]
20.3205 - //fstp [esp]
20.3206 - //pop eax
20.3207 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3208 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3209 - IA32_Fsub_Mem32_Disp8(jit, AMX_REG_STK, 4);
20.3210 - IA32_Fstp_Mem32_ESP(jit);
20.3211 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3212 -
20.3213 - /* Rectify the stack */
20.3214 - //add edi, 8
20.3215 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.3216 -}
20.3217 -
20.3218 -inline void WriteOp_FloatMul(JitWriter *jit)
20.3219 +void
20.3220 +Compiler::emitGenArray(bool autozero)
20.3221 {
20.3222 - //push eax
20.3223 - //fld [edi]
20.3224 - //fmul [edi+4]
20.3225 - //fstp [esp]
20.3226 - //pop eax
20.3227 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3228 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3229 - IA32_Fmul_Mem32_Disp8(jit, AMX_REG_STK, 4);
20.3230 - IA32_Fstp_Mem32_ESP(jit);
20.3231 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3232 + cell_t val = readCell();
20.3233 + if (val == 1)
20.3234 + {
20.3235 + // flat array; we can generate this without indirection tables.
20.3236 + // Note that we can overwrite ALT because technically STACK should be destroying ALT
20.3237 + __ movl(alt, Operand(info, AMX_INFO_HEAP));
20.3238 + __ movl(tmp, Operand(stk, 0));
20.3239 + __ movl(Operand(stk, 0), alt); // store base of the array into the stack.
20.3240 + __ lea(alt, Operand(alt, tmp, ScaleFour));
20.3241 + __ movl(Operand(info, AMX_INFO_HEAP), alt);
20.3242 + __ addl(alt, dat);
20.3243 + __ cmpl(alt, stk);
20.3244 + __ j(not_below, &error_heap_low_);
20.3245
20.3246 - /* Rectify the stack */
20.3247 - //add edi, 8
20.3248 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.3249 -}
20.3250 + EmitTrackerPushReg(masm, ecx, &extern_error_);
20.3251
20.3252 -inline void WriteOp_FloatDiv(JitWriter *jit)
20.3253 -{
20.3254 - //push eax
20.3255 - //fld [edi]
20.3256 - //fdiv [edi+4]
20.3257 - //fstp [esp]
20.3258 - //pop eax
20.3259 - IA32_Push_Reg(jit, AMX_REG_PRI);
20.3260 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3261 - IA32_Fdiv_Mem32_Disp8(jit, AMX_REG_STK, 4);
20.3262 - IA32_Fstp_Mem32_ESP(jit);
20.3263 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3264 -
20.3265 - /* Rectify the stack */
20.3266 - //add edi, 8
20.3267 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.3268 + if (autozero) {
20.3269 + __ push(eax);
20.3270 + __ push(edi);
20.3271 + __ xorl(eax, eax);
20.3272 + __ movl(edi, Operand(stk, 0));
20.3273 + __ addl(edi, dat);
20.3274 + __ cld();
20.3275 + __ rep_stosd();
20.3276 + __ pop(edi);
20.3277 + __ pop(eax);
20.3278 + }
20.3279 + } else {
20.3280 + __ movl(tmp, val);
20.3281 + __ movl(edx, autozero ? 1 : 0);
20.3282 + __ call(g_Jit.GetGenArrayIntrinsic());
20.3283 + }
20.3284 }
20.3285
20.3286 -inline void WriteOp_RountToNearest(JitWriter *jit)
20.3287 +bool
20.3288 +Compiler::emitCall()
20.3289 {
20.3290 - //push eax
20.3291 - //fld [edi]
20.3292 + cell_t offset = readCell();
20.3293
20.3294 - //fstcw [esp]
20.3295 - //mov eax, [esp]
20.3296 - //push eax
20.3297 -
20.3298 - //mov [esp+4], 0x3FF
20.3299 - //fadd st(0), st(0)
20.3300 - //fldcw [esp+4]
20.3301 + // If this offset looks crappy, i.e. not aligned or out of bounds, we just
20.3302 + // abort.
20.3303 + if (offset % 4 != 0 || uint32_t(offset) >= plugin_->pcode_size) {
20.3304 + error_ = SP_ERROR_INSTRUCTION_PARAM;
20.3305 + return false;
20.3306 + }
20.3307
20.3308 - //push eax
20.3309 - //push 0x3F000000 ; 0.5f
20.3310 - //fadd [esp]
20.3311 - //fistp [esp+4]
20.3312 - //pop eax
20.3313 - //pop eax
20.3314 + // eax = context
20.3315 + // ecx = rp
20.3316 + __ movl(eax, Operand(info, AMX_INFO_CONTEXT));
20.3317 + __ movl(ecx, Operand(eax, offsetof(sp_context_t, rp)));
20.3318
20.3319 - //pop ecx
20.3320 - //sar eax, 1
20.3321 - //mov [esp], ecx
20.3322 - //fldcw [esp]
20.3323 - //add esp, 4
20.3324 + // Check if the return stack is used up.
20.3325 + __ cmpl(ecx, SP_MAX_RETURN_STACK);
20.3326 + __ j(not_below, &error_stack_low_);
20.3327 +
20.3328 + // Add to the return stack.
20.3329 + uintptr_t cip = uintptr_t(cip_ - 2) - uintptr_t(plugin_->pcode);
20.3330 + __ movl(Operand(eax, ecx, ScaleFour, offsetof(sp_context_t, rstk_cips)), cip);
20.3331
20.3332 - IA32_Push_Reg(jit, REG_EAX);
20.3333 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3334 + // Increment the return stack pointer.
20.3335 + __ addl(Operand(eax, offsetof(sp_context_t, rp)), 1);
20.3336
20.3337 - IA32_Fstcw_Mem16_ESP(jit);
20.3338 - IA32_Mov_Reg_RmESP(jit, REG_EAX);
20.3339 - IA32_Push_Reg(jit, REG_EAX);
20.3340 -
20.3341 - IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x3FF);
20.3342 - IA32_Fadd_FPUreg_ST0(jit, 0);
20.3343 - IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
20.3344 + // Store the CIP of the function we're about to call.
20.3345 + __ movl(Operand(info, AMX_INFO_CIP), offset);
20.3346
20.3347 - IA32_Push_Reg(jit, REG_EAX);
20.3348 - IA32_Push_Imm32(jit, 0x3F000000);
20.3349 - IA32_Fadd_Mem32_ESP(jit);
20.3350 - IA32_Fistp_Mem32_Disp8_Esp(jit, 4);
20.3351 - IA32_Pop_Reg(jit, REG_EAX);
20.3352 - IA32_Pop_Reg(jit, AMX_REG_PRI);
20.3353 + JitFunction *fun = rt_->GetJittedFunctionByOffset(offset);
20.3354 + if (!fun) {
20.3355 + // Need to emit a delayed thunk.
20.3356 + CallThunk *thunk = new CallThunk(offset);
20.3357 + __ call(&thunk->call);
20.3358 + if (!thunks_.append(thunk))
20.3359 + return false;
20.3360 + } else {
20.3361 + // Function is already emitted, we can do a direct call.
20.3362 + __ call(ExternalAddress(fun->GetEntryAddress()));
20.3363 + }
20.3364
20.3365 - IA32_Pop_Reg(jit, REG_ECX);
20.3366 - IA32_Sar_Rm_1(jit, REG_EAX, MOD_REG);
20.3367 - IA32_Mov_RmESP_Reg(jit, REG_ECX);
20.3368 - IA32_Fldcw_Mem16_ESP(jit);
20.3369 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
20.3370 + // Restore the last cip.
20.3371 + __ movl(Operand(info, AMX_INFO_CIP), cip);
20.3372
20.3373 - /* Rectify the stack */
20.3374 - //add edi, 4
20.3375 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.3376 + // Mark us as leaving the last frame.
20.3377 + __ movl(tmp, Operand(info, AMX_INFO_CONTEXT));
20.3378 + __ subl(Operand(tmp, offsetof(sp_context_t, rp)), 1);
20.3379 + return true;
20.3380 }
20.3381
20.3382 -inline void WriteOp_RoundToFloor(JitWriter *jit)
20.3383 +void
20.3384 +Compiler::emitCallThunks()
20.3385 {
20.3386 - //push eax
20.3387 - //fld [edi]
20.3388 -
20.3389 - //fstcw [esp]
20.3390 - //mov eax, [esp]
20.3391 - //push eax
20.3392 + for (size_t i = 0; i < thunks_.length(); i++) {
20.3393 + CallThunk *thunk = thunks_[i];
20.3394
20.3395 - //mov [esp+4], 0x7FF
20.3396 - //fldcw [esp+4]
20.3397 + Label error;
20.3398 + __ bind(&thunk->call);
20.3399 + // Huge hack - get the return address, since that is the call that we
20.3400 + // need to patch.
20.3401 + __ movl(eax, Operand(esp, 0));
20.3402
20.3403 - //push eax
20.3404 - //fistp [esp]
20.3405 - //pop eax
20.3406 -
20.3407 - //pop ecx
20.3408 - //mov [esp], ecx
20.3409 - //fldcw [esp]
20.3410 - //add esp, 4
20.3411 + // Align the stack. Unfortunately this is a pretty careful dance based
20.3412 + // on the number of words we push (4 args, 1 saved esp), and someday
20.3413 + // we should look into automating this.
20.3414 + __ movl(edx, esp);
20.3415 + __ andl(esp, 0xfffffff0);
20.3416 + __ subl(esp, 12);
20.3417 + __ push(edx);
20.3418
20.3419 - IA32_Push_Reg(jit, REG_EAX);
20.3420 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3421 -
20.3422 - IA32_Fstcw_Mem16_ESP(jit);
20.3423 - IA32_Mov_Reg_RmESP(jit, REG_EAX);
20.3424 - IA32_Push_Reg(jit, REG_EAX);
20.3425 -
20.3426 - IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x7FF);
20.3427 - IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
20.3428 + // Push arguments.
20.3429 + __ push(eax);
20.3430 + __ subl(esp, 4);
20.3431 + __ movl(Operand(esp, 0), esp);
20.3432 + __ push(thunk->pcode_offset);
20.3433 + __ push(intptr_t(rt_));
20.3434 + __ call(ExternalAddress((void *)CompileFromThunk));
20.3435 + __ movl(edx, Operand(esp, 8));
20.3436 + __ movl(esp, Operand(esp, 16));
20.3437 + __ testl(eax, eax);
20.3438 + __ j(not_zero, &error);
20.3439 + __ call(edx);
20.3440 + __ ret();
20.3441
20.3442 - IA32_Push_Reg(jit, REG_EAX);
20.3443 - IA32_Fistp_Mem32_ESP(jit);
20.3444 - IA32_Pop_Reg(jit, REG_EAX);
20.3445 + __ bind(&error);
20.3446 + __ movl(Operand(info, AMX_INFO_CIP), thunk->pcode_offset);
20.3447 + __ jmp(g_Jit.GetUniversalReturn());
20.3448 + }
20.3449 +}
20.3450
20.3451 - IA32_Pop_Reg(jit, REG_ECX);
20.3452 - IA32_Mov_RmESP_Reg(jit, REG_ECX);
20.3453 - IA32_Fldcw_Mem16_ESP(jit);
20.3454 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
20.3455 -
20.3456 - /* Rectify the stack */
20.3457 - //add edi, 4
20.3458 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.3459 +cell_t
20.3460 +Compiler::readCell()
20.3461 +{
20.3462 + if (cip_ >= code_end_) {
20.3463 + error_= SP_ERROR_INVALID_INSTRUCTION;
20.3464 + return 0;
20.3465 + }
20.3466 + return *cip_++;
20.3467 }
20.3468
20.3469 -inline void WriteOp_RoundToCeil(JitWriter *jit)
20.3470 +bool
20.3471 +Compiler::emitNativeCall(OPCODE op)
20.3472 {
20.3473 - //push eax
20.3474 - //fld [edi]
20.3475 -
20.3476 - //fstcw [esp]
20.3477 - //mov eax, [esp]
20.3478 - //push eax
20.3479 -
20.3480 - //mov [esp+4], 0xBFF
20.3481 - //fldcw [esp+4]
20.3482 -
20.3483 - //push eax
20.3484 - //fistp [esp]
20.3485 - //pop eax
20.3486 + uint32_t native_index = readCell();
20.3487
20.3488 - //pop ecx
20.3489 - //mov [esp], ecx
20.3490 - //fldcw [esp]
20.3491 - //add esp, 4
20.3492 -
20.3493 - IA32_Push_Reg(jit, REG_EAX);
20.3494 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3495 + if (native_index >= plugin_->num_natives) {
20.3496 + error_ = SP_ERROR_INSTRUCTION_PARAM;
20.3497 + return false;
20.3498 + }
20.3499
20.3500 - IA32_Fstcw_Mem16_ESP(jit);
20.3501 - IA32_Mov_Reg_RmESP(jit, REG_EAX);
20.3502 - IA32_Push_Reg(jit, REG_EAX);
20.3503 -
20.3504 - IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xBFF);
20.3505 - IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
20.3506 -
20.3507 - IA32_Push_Reg(jit, REG_EAX);
20.3508 - IA32_Fistp_Mem32_ESP(jit);
20.3509 - IA32_Pop_Reg(jit, REG_EAX);
20.3510 + uint32_t num_params;
20.3511 + if (op == OP_SYSREQ_N) {
20.3512 + num_params = readCell();
20.3513
20.3514 - IA32_Pop_Reg(jit, REG_ECX);
20.3515 - IA32_Mov_RmESP_Reg(jit, REG_ECX);
20.3516 - IA32_Fldcw_Mem16_ESP(jit);
20.3517 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
20.3518 -
20.3519 - /* Rectify the stack */
20.3520 - //add edi, 4
20.3521 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.3522 -}
20.3523 -
20.3524 -inline void WriteOp_RoundToZero(JitWriter *jit)
20.3525 -{
20.3526 - //push eax
20.3527 - //fld [edi]
20.3528 -
20.3529 - //fstcw [esp]
20.3530 - //mov eax, [esp]
20.3531 - //push eax
20.3532 + // See if we can get a replacement opcode. If we can, then recursively
20.3533 + // call emitOp() to generate it. Note: it's important that we do this
20.3534 + // before generating any code for the SYSREQ.N.
20.3535 + unsigned replacement = rt_->GetNativeReplacement(native_index);
20.3536 + if (replacement != OP_NOP)
20.3537 + return emitOp((OPCODE)replacement);
20.3538
20.3539 - //mov [esp+4], 0xFFF
20.3540 - //fldcw [esp+4]
20.3541 -
20.3542 - //push eax
20.3543 - //fistp [esp]
20.3544 - //pop eax
20.3545 + // Store the number of parameters.
20.3546 + __ movl(Operand(stk, -4), num_params);
20.3547 + __ subl(stk, 4);
20.3548 + }
20.3549
20.3550 - //pop ecx
20.3551 - //mov [esp], ecx
20.3552 - //fldcw [esp]
20.3553 - //add esp, 4
20.3554 + // Save registers.
20.3555 + __ push(edx);
20.3556
20.3557 - IA32_Push_Reg(jit, REG_EAX);
20.3558 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3559 -
20.3560 - IA32_Fstcw_Mem16_ESP(jit);
20.3561 - IA32_Mov_Reg_RmESP(jit, REG_EAX);
20.3562 - IA32_Push_Reg(jit, REG_EAX);
20.3563 -
20.3564 - IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xFFF);
20.3565 - IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
20.3566 + // Align the stack to 16 bytes.
20.3567 + __ push(ebx);
20.3568 + __ movl(ebx, esp);
20.3569 + __ andl(esp, 0xfffffff0);
20.3570 + __ subl(esp, 4);
20.3571
20.3572 - IA32_Push_Reg(jit, REG_EAX);
20.3573 - IA32_Fistp_Mem32_ESP(jit);
20.3574 - IA32_Pop_Reg(jit, REG_EAX);
20.3575 -
20.3576 - IA32_Pop_Reg(jit, REG_ECX);
20.3577 - IA32_Mov_RmESP_Reg(jit, REG_ECX);
20.3578 - IA32_Fldcw_Mem16_ESP(jit);
20.3579 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
20.3580 -
20.3581 - /* Rectify the stack */
20.3582 - //add edi, 4
20.3583 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
20.3584 -}
20.3585 + // Push the parameters for the C++ function.
20.3586 + __ push(stk);
20.3587 + __ push(native_index);
20.3588
20.3589 -inline void WriteOp_FloatCompare(JitWriter *jit)
20.3590 -{
20.3591 - //fld [edi]
20.3592 - //fld [edi+4]
20.3593 - //fucomip st(0), st(1)
20.3594 - //mov ecx, <round_table>
20.3595 - //cmovz eax, [ecx+4]
20.3596 - //cmovb eax, [ecx+8]
20.3597 - //cmova eax, [ecx]
20.3598 - //fstp st(0)
20.3599 + // Relocate all our absolute junk to be dat-relative, and store it all back
20.3600 + // into the context.
20.3601 + __ movl(eax, Operand(info, AMX_INFO_CONTEXT));
20.3602 + __ movl(ecx, Operand(info, AMX_INFO_HEAP));
20.3603 + __ movl(Operand(eax, offsetof(sp_context_t, hp)), ecx);
20.3604 + __ subl(stk, dat);
20.3605 + __ movl(Operand(eax, offsetof(sp_context_t, sp)), stk);
20.3606 + __ movl(ecx, Operand(info, AMX_INFO_FRAME));
20.3607 + __ movl(Operand(eax, offsetof(sp_context_t, frm)), ecx);
20.3608
20.3609 - IA32_Fld_Mem32(jit, AMX_REG_STK);
20.3610 - IA32_Fld_Mem32_Disp8(jit, AMX_REG_STK, 4);
20.3611 - IA32_Fucomip_ST0_FPUreg(jit, 1);
20.3612 - IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, (jit_int32_t)g_Jit.GetRoundingTable());
20.3613 - IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_Z, 4);
20.3614 - IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_B, 8);
20.3615 - IA32_CmovCC_Rm(jit, AMX_REG_TMP, CC_A);
20.3616 - IA32_Fstp_FPUreg(jit, 0);
20.3617 + // Push context and make the call.
20.3618 + __ push(eax);
20.3619 + __ call(ExternalAddress((void *)NativeCallback));
20.3620
20.3621 - /* Rectify the stack */
20.3622 - //add edi, 8
20.3623 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
20.3624 -}
20.3625 -
20.3626 -inline void WriteOp_EndProc(JitWriter *jit)
20.3627 -{
20.3628 -}
20.3629 -
20.3630 -void Write_CallThunk(JitWriter *jit, jitoffs_t jmploc, cell_t pcode_offs)
20.3631 -{
20.3632 - CompData *data;
20.3633 - jitoffs_t call;
20.3634 -
20.3635 - data = (CompData *)jit->data;
20.3636 + // Check for errors.
20.3637 + __ movl(ecx, Operand(info, AMX_INFO_CONTEXT));
20.3638 + __ movl(ecx, Operand(ecx, offsetof(sp_context_t, n_err)));
20.3639 + __ testl(ecx, ecx);
20.3640 + __ j(not_zero, &extern_error_);
20.3641 +
20.3642 + // Restore local state.
20.3643 + __ movl(esp, ebx);
20.3644 + __ pop(ebx);
20.3645 + __ addl(stk, dat);
20.3646 + __ pop(edx);
20.3647
20.3648 - //push <jmploc_addr>
20.3649 - //push <pcode_offs>
20.3650 - //push <runtime>
20.3651 - //call CompileFromThunk
20.3652 - //add esp, 4*3
20.3653 - //test eax, eax
20.3654 - //jz :error
20.3655 - //call eax
20.3656 - //ret
20.3657 - IA32_Push_Imm32(jit, (jit_int32_t)(jit->outbase + jmploc));
20.3658 - IA32_Push_Imm32(jit, pcode_offs);
20.3659 - IA32_Push_Imm32(jit, (jit_int32_t)(data->runtime));
20.3660 - call = IA32_Call_Imm32(jit, 0);
20.3661 - IA32_Write_Jump32_Abs(jit, call, (void *)CompileThunk);
20.3662 - IA32_Add_Rm_Imm32(jit, REG_ESP, 4*3, MOD_REG);
20.3663 - IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
20.3664 - call = IA32_Jump_Cond_Imm8(jit, CC_Z, 0);
20.3665 - IA32_Call_Reg(jit, REG_EAX);
20.3666 - IA32_Return(jit);
20.3667 -
20.3668 - /* We decrement the frame and store the target cip. */
20.3669 - //:error
20.3670 - //mov [esi+cip], pcode_offs
20.3671 - //goto error
20.3672 - IA32_Send_Jump8_Here(jit, call);
20.3673 - Write_SetError(jit, SP_ERROR_INVALID_INSTRUCTION);
20.3674 + if (op == OP_SYSREQ_N) {
20.3675 + // Pop the stack. Do not check the margins.
20.3676 + __ addl(stk, (num_params + 1) * sizeof(cell_t));
20.3677 + }
20.3678 + return true;
20.3679 }
20.3680
20.3681 -/*************************************************
20.3682 - *************************************************
20.3683 - * JIT PROPER ************************************
20.3684 - * The rest from now on is the JIT engine *
20.3685 - *************************************************
20.3686 - *************************************************/
20.3687 -
20.3688 -void *CompileThunk(BaseRuntime *runtime, cell_t pcode_offs, void *jmploc_addr)
20.3689 +bool
20.3690 +Compiler::emitSwitch()
20.3691 {
20.3692 - int err;
20.3693 - JitFunction *fn;
20.3694 - uint32_t func_idx;
20.3695 - void *target_addr;
20.3696 -
20.3697 - if ((func_idx = FuncLookup((CompData *)runtime->m_pCo, pcode_offs)) == 0)
20.3698 - {
20.3699 - fn = g_Jit.CompileFunction(runtime, pcode_offs, &err);
20.3700 - }
20.3701 - else
20.3702 - {
20.3703 - fn = runtime->GetJittedFunction(func_idx);
20.3704 + cell_t offset = readCell();
20.3705 + if (!labelAt(offset))
20.3706 + return false;
20.3707 +
20.3708 + cell_t *tbl = (cell_t *)((char *)plugin_->pcode + offset + sizeof(cell_t));
20.3709 +
20.3710 + struct Entry {
20.3711 + cell_t val;
20.3712 + cell_t offset;
20.3713 + };
20.3714 +
20.3715 + size_t ncases = *tbl++;
20.3716 +
20.3717 + Label *defaultCase = labelAt(*tbl);
20.3718 + if (!defaultCase)
20.3719 + return false;
20.3720 +
20.3721 + // Degenerate - 0 cases.
20.3722 + if (!ncases) {
20.3723 + __ jmp(defaultCase);
20.3724 + return true;
20.3725 + }
20.3726 +
20.3727 + Entry *cases = (Entry *)(tbl + 1);
20.3728 +
20.3729 + // Degenerate - 1 case.
20.3730 + if (ncases == 1) {
20.3731 + Label *maybe = labelAt(cases[0].offset);
20.3732 + if (!maybe)
20.3733 + return false;
20.3734 + __ cmpl(pri, cases[0].val);
20.3735 + __ j(equal, maybe);
20.3736 + __ jmp(defaultCase);
20.3737 + return true;
20.3738 + }
20.3739 +
20.3740 + // We have two or more cases, so let's generate a full switch. Decide
20.3741 + // whether we'll make an if chain, or a jump table, based on whether
20.3742 + // the numbers are strictly sequential.
20.3743 + bool sequential = true;
20.3744 + {
20.3745 + cell_t first = cases[0].val;
20.3746 + cell_t last = first;
20.3747 + for (size_t i = 1; i < ncases; i++) {
20.3748 + if (cases[i].val != ++last) {
20.3749 + sequential = false;
20.3750 + break;
20.3751 + }
20.3752 + }
20.3753 + }
20.3754 +
20.3755 + // First check whether the bounds are correct: if (a < LOW || a > HIGH);
20.3756 + // this check is valid whether or not we emit a sequential-optimized switch.
20.3757 + cell_t low = cases[0].val;
20.3758 + if (low != 0) {
20.3759 + // negate it so we'll get a lower bound of 0.
20.3760 + low = -low;
20.3761 + __ lea(tmp, Operand(pri, low));
20.3762 + } else {
20.3763 + __ movl(tmp, pri);
20.3764 + }
20.3765
20.3766 -#if defined _DEBUG
20.3767 - g_engine1.GetDebugHook()->OnDebugSpew("Patching thunk to %s::%s", runtime->m_pPlugin->name, find_func_name(runtime->m_pPlugin, pcode_offs));
20.3768 -#endif
20.3769 + cell_t high = abs(cases[0].val - cases[ncases - 1].val);
20.3770 + __ cmpl(tmp, high);
20.3771 + __ j(above, defaultCase);
20.3772
20.3773 - }
20.3774 + if (sequential) {
20.3775 + // Optimized table version. The tomfoolery below is because we only have
20.3776 + // one free register... it seems unlikely pri or alt will be used given
20.3777 + // that we're at the end of a control-flow point, but we'll play it safe.
20.3778 + DataLabel table;
20.3779 + __ push(eax);
20.3780 + __ movl(eax, &table);
20.3781 + __ movl(ecx, Operand(eax, ecx, ScaleFour));
20.3782 + __ pop(eax);
20.3783 + __ jmp(ecx);
20.3784
20.3785 - if (fn == NULL)
20.3786 - {
20.3787 - return NULL;
20.3788 - }
20.3789 + __ bind(&table);
20.3790 + for (size_t i = 0; i < ncases; i++) {
20.3791 + Label *label = labelAt(cases[i].offset);
20.3792 + if (!label)
20.3793 + return false;
20.3794 + __ emit_absolute_address(label);
20.3795 + }
20.3796 + } else {
20.3797 + // Slower version. Go through each case and generate a check.
20.3798 + for (size_t i = 0; i < ncases; i++) {
20.3799 + Label *label = labelAt(cases[i].offset);
20.3800 + if (!label)
20.3801 + return false;
20.3802 + __ cmpl(pri, cases[i].val);
20.3803 + __ j(equal, label);
20.3804 + }
20.3805 + __ jmp(defaultCase);
20.3806 + }
20.3807 + return true;
20.3808 +}
20.3809
20.3810 - target_addr = fn->GetEntryAddress();
20.3811 +void
20.3812 +Compiler::emitErrorPath(Label *dest, int code)
20.3813 +{
20.3814 + if (dest->used()) {
20.3815 + __ bind(dest);
20.3816 + __ movl(eax, code);
20.3817 + __ jmp(g_Jit.GetUniversalReturn());
20.3818 + }
20.3819 +}
20.3820
20.3821 - /* Right now, we always keep the code RWE */
20.3822 - *(intptr_t *)((char *)jmploc_addr) =
20.3823 - intptr_t(target_addr) - (intptr_t(jmploc_addr) + 4);
20.3824 +void
20.3825 +Compiler::emitErrorPaths()
20.3826 +{
20.3827 + emitErrorPath(&error_divide_by_zero_, SP_ERROR_DIVIDE_BY_ZERO);
20.3828 + emitErrorPath(&error_stack_low_, SP_ERROR_STACKLOW);
20.3829 + emitErrorPath(&error_stack_min_, SP_ERROR_STACKMIN);
20.3830 + emitErrorPath(&error_bounds_, SP_ERROR_ARRAY_BOUNDS);
20.3831 + emitErrorPath(&error_memaccess_, SP_ERROR_MEMACCESS);
20.3832 + emitErrorPath(&error_heap_low_, SP_ERROR_HEAPLOW);
20.3833 + emitErrorPath(&error_heap_min_, SP_ERROR_HEAPMIN);
20.3834 + emitErrorPath(&error_integer_overflow_, SP_ERROR_INTEGER_OVERFLOW);
20.3835
20.3836 - return target_addr;
20.3837 + if (extern_error_.used()) {
20.3838 + __ bind(&extern_error_);
20.3839 + __ movl(eax, Operand(info, AMX_INFO_CONTEXT));
20.3840 + __ movl(eax, Operand(eax, offsetof(sp_context_t, n_err)));
20.3841 + __ jmp(g_Jit.GetUniversalReturn());
20.3842 + }
20.3843 }
20.3844
20.3845 -cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
20.3846 +// Input dimension count is in ecx.
20.3847 +static void *
20.3848 +GenerateGenArrayIntrinsic(void *ret)
20.3849 {
20.3850 - sp_native_t *native;
20.3851 - cell_t save_sp = ctx->sp;
20.3852 - cell_t save_hp = ctx->hp;
20.3853 - sp_plugin_t *pl = GETPLUGIN(ctx);
20.3854 + AssemblerX86 masm;
20.3855
20.3856 - ctx->n_idx = native_idx;
20.3857 + __ push(ebx);
20.3858 + __ push(eax);
20.3859 + __ push(edx);
20.3860 + __ push(ecx); // We reference this in the body of this routine.
20.3861 +
20.3862 + Label toobig;
20.3863
20.3864 - if (ctx->hp < (cell_t)pl->data_size)
20.3865 - {
20.3866 - ctx->n_err = SP_ERROR_HEAPMIN;
20.3867 - return 0;
20.3868 - }
20.3869 + // Calculate how many cells will be needed.
20.3870 + __ movl(edx, Operand(stk, 0)); // Dimension's last count.
20.3871 + __ cmpl(edx, 0);
20.3872 + __ j(less, &toobig);
20.3873 + __ movl(eax, 1); // Position at second to last dimension.
20.3874
20.3875 - if (ctx->hp + STACK_MARGIN > ctx->sp)
20.3876 - {
20.3877 - ctx->n_err = SP_ERROR_STACKLOW;
20.3878 - return 0;
20.3879 - }
20.3880 -
20.3881 - if ((uint32_t)ctx->sp >= pl->mem_size)
20.3882 - {
20.3883 - ctx->n_err = SP_ERROR_STACKMIN;
20.3884 - return 0;
20.3885 - }
20.3886 -
20.3887 - native = &pl->natives[native_idx];
20.3888 + Label loop, done;
20.3889 + __ bind(&loop);
20.3890 + __ cmpl(eax, Operand(esp, 0)); // Compare to # of dimensions.
20.3891 + __ j(not_below, &done); // End loop if done.
20.3892 + __ movl(ecx, Operand(stk, eax, ScaleFour)); // Get dimension size.
20.3893 + __ cmpl(ecx, 0);
20.3894 + __ j(less, &toobig);
20.3895 + __ imull(edx, ecx); // Multiply by size.
20.3896 + __ j(overflow, &toobig);
20.3897 + __ addl(eax, 1); // Increment dimension cursor.
20.3898 + __ addl(edx, ecx); // Add indirection vector size.
20.3899 + __ j(overflow, &toobig);
20.3900 + __ jmp(&loop);
20.3901 + __ bind(&done);
20.3902
20.3903 - if (native->status == SP_NATIVE_UNBOUND)
20.3904 - {
20.3905 - ctx->n_err = SP_ERROR_INVALID_NATIVE;
20.3906 - return 0;
20.3907 - }
20.3908 + // Test if we have space for the size in edx.
20.3909 + __ movl(eax, Operand(info, AMX_INFO_HEAP));
20.3910 + __ imull(edx, edx, 4);
20.3911 + __ j(overflow, &toobig);
20.3912 + __ addl(eax, edx);
20.3913 + __ j(overflow, &toobig);
20.3914 + __ cmpl(eax, Operand(info, AMX_INFO_DATASIZE));
20.3915 + __ j(not_above, &toobig);
20.3916 + __ addl(eax, dat);
20.3917 + __ cmpl(eax, stk);
20.3918 + __ j(not_below, &toobig);
20.3919 + __ shrl(edx, 2); // Undo the imull.
20.3920
20.3921 - cell_t result = native->pfn(GET_CONTEXT(ctx), params);
20.3922 + // Allocate on the plugin heap.
20.3923 + __ movl(eax, Operand(info, AMX_INFO_HEAP)); // Get heap pointer.
20.3924 + __ lea(ebx, Operand(eax, edx, ScaleFour)); // New heap pointer.
20.3925 + __ movl(Operand(info, AMX_INFO_HEAP), ebx); // Store back.
20.3926 + __ push(eax); // Save on the stack.
20.3927
20.3928 - if (ctx->n_err != SP_ERROR_NONE)
20.3929 - {
20.3930 - return result;
20.3931 - }
20.3932 + Label extern_error;
20.3933 + EmitTrackerPushReg(masm, edx, &extern_error);
20.3934
20.3935 - if (save_sp != ctx->sp)
20.3936 - {
20.3937 - ctx->n_err = SP_ERROR_STACKLEAK;
20.3938 - return result;
20.3939 - }
20.3940 - else if (save_hp != ctx->hp)
20.3941 - {
20.3942 - ctx->n_err = SP_ERROR_HEAPLEAK;
20.3943 - return result;
20.3944 - }
20.3945 + // Call to C++ to generate indirection vectors.
20.3946 + __ lea(ebx, Operand(dat, eax, NoScale)); // relocate eax
20.3947 + __ push(Operand(esp, 8)); // push autozero
20.3948 + __ push(Operand(esp, 8)); // push dimension count
20.3949 + __ push(stk); // push dimension array
20.3950 + __ push(ebx);
20.3951 + __ call(ExternalAddress((void *)GenerateArrayIndirectionVectors));
20.3952 + __ addl(esp, 4 * sizeof(void *));
20.3953
20.3954 - return result;
20.3955 -}
20.3956 + __ pop(eax); // Restore array pointer.
20.3957 + __ pop(ecx); // Restore dimension count.
20.3958 + __ lea(stk, Operand(stk, ecx, ScaleFour, -4)); // Pop params off the stack.
20.3959 + __ movl(Operand(stk, 0), eax); // Store back array pointer.
20.3960 + __ pop(edx);
20.3961 + __ pop(eax);
20.3962 + __ pop(ebx);
20.3963 + __ ret();
20.3964
20.3965 -cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
20.3966 -{
20.3967 - /* :TODO: */
20.3968 - return NativeCallback(ctx, native_idx, params);
20.3969 + __ bind(&toobig);
20.3970 + __ movl(eax, SP_ERROR_ARRAY_TOO_BIG);
20.3971 + __ jmp(ExternalAddress(ret));
20.3972 +
20.3973 + __ bind(&extern_error);
20.3974 + __ jmp(ExternalAddress(ret));
20.3975 +
20.3976 + return LinkCode(masm);
20.3977 }
20.3978
20.3979 -uint32_t FuncLookup(CompData *data, cell_t pcode_offs)
20.3980 -{
20.3981 - /* Offset must always be 1)positive and 2)less than or equal to the codesize */
20.3982 - assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->plugin->pcode_size);
20.3983 -
20.3984 - /* Do the lookup in the native dictionary. */
20.3985 - return *(jitoffs_t *)(data->rebase + pcode_offs);
20.3986 -}
20.3987 -
20.3988 -jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
20.3989 +static void *
20.3990 +GenerateEntry(void **retp)
20.3991 {
20.3992 - if (jit->outptr)
20.3993 - {
20.3994 - CompData *data = (CompData *)jit->data;
20.3995 - if (relative)
20.3996 - {
20.3997 - /* The actual offset is EIP relative. We need to relocate it.
20.3998 - * Note that this assumes that we're pointing to the next op.
20.3999 - */
20.4000 - pcode_offs += jit->get_inputpos();
20.4001 - }
20.4002 - /* Offset must always be 1)positive and 2)less than or equal to the codesize */
20.4003 - assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->plugin->pcode_size);
20.4004 - /* Do the lookup in the native dictionary. */
20.4005 -#if defined _DEBUG
20.4006 - if (jit->outbase != NULL)
20.4007 - {
20.4008 - assert(*(jitoffs_t *)(data->rebase + pcode_offs) != 0);
20.4009 - }
20.4010 -#endif
20.4011 - return *(jitoffs_t *)(data->rebase + pcode_offs);
20.4012 - }
20.4013 - else
20.4014 - {
20.4015 - return 0;
20.4016 - }
20.4017 -}
20.4018 + AssemblerX86 masm;
20.4019 +
20.4020 + // Variables we're passed in:
20.4021 + // void *vars[], void *entry
20.4022 +
20.4023 + __ push(ebp);
20.4024 + __ movl(ebp, esp);
20.4025 +
20.4026 + __ push(esi);
20.4027 + __ push(edi);
20.4028 + __ push(ebx);
20.4029 +
20.4030 + __ movl(esi, Operand(ebp, 8 + 4 * 0));
20.4031 + __ movl(ecx, Operand(ebp, 8 + 4 * 1));
20.4032 + __ movl(eax, Operand(esi, AMX_INFO_MEMORY));
20.4033 + __ movl(edx, Operand(esi, AMX_INFO_CONTEXT));
20.4034 +
20.4035 + // Set up run-time registers.
20.4036 + __ movl(edi, Operand(edx, offsetof(sp_context_t, sp)));
20.4037 + __ addl(edi, eax);
20.4038 + __ movl(ebp, eax);
20.4039 + __ movl(ebx, edi);
20.4040 + __ movl(Operand(esi, AMX_INFO_NSTACK), esp);
20.4041
20.4042 -void WriteErrorRoutines(CompData *data, JitWriter *jit)
20.4043 -{
20.4044 - AlignMe(jit);
20.4045 + // Call into plugin.
20.4046 + __ call(ecx);
20.4047
20.4048 - data->jit_error_divzero = jit->get_outputpos();
20.4049 - Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO);
20.4050 -
20.4051 - data->jit_error_stacklow = jit->get_outputpos();
20.4052 - Write_SetError(jit, SP_ERROR_STACKLOW);
20.4053 -
20.4054 - data->jit_error_stackmin = jit->get_outputpos();
20.4055 - Write_SetError(jit, SP_ERROR_STACKMIN);
20.4056 + __ movl(ecx, Operand(info, AMX_INFO_RETVAL));
20.4057 + __ movl(Operand(ecx, 0), pri);
20.4058 + __ movl(eax, SP_ERROR_NONE);
20.4059
20.4060 - data->jit_error_bounds = jit->get_outputpos();
20.4061 - Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS);
20.4062 -
20.4063 - data->jit_error_memaccess = jit->get_outputpos();
20.4064 - Write_SetError(jit, SP_ERROR_MEMACCESS);
20.4065 + // If stuff goes wrong, it'll jump directly to here.
20.4066 + Label error;
20.4067 + __ bind(&error);
20.4068 + __ movl(esp, Operand(info, AMX_INFO_NSTACK));
20.4069 + __ movl(ecx, Operand(info, AMX_INFO_CONTEXT));
20.4070 + __ subl(stk, dat);
20.4071 + __ movl(Operand(ecx, offsetof(sp_context_t, sp)), stk);
20.4072
20.4073 - data->jit_error_heaplow = jit->get_outputpos();
20.4074 - Write_SetError(jit, SP_ERROR_HEAPLOW);
20.4075 + __ pop(ebx);
20.4076 + __ pop(edi);
20.4077 + __ pop(esi);
20.4078 + __ pop(ebp);
20.4079 + __ ret();
20.4080
20.4081 - data->jit_error_heapmin = jit->get_outputpos();
20.4082 - Write_SetError(jit, SP_ERROR_HEAPMIN);
20.4083 + void *code = LinkCode(masm);
20.4084 + if (!code)
20.4085 + return NULL;
20.4086
20.4087 - data->jit_extern_error = jit->get_outputpos();
20.4088 - Write_GetError(jit);
20.4089 + *retp = reinterpret_cast<uint8_t *>(code) + error.offset();
20.4090 + return code;
20.4091 }
20.4092
20.4093 ICompilation *JITX86::ApplyOptions(ICompilation *_IN, ICompilation *_OUT)
20.4094 {
20.4095 - if (_IN == NULL)
20.4096 - {
20.4097 - return _OUT;
20.4098 - }
20.4099 + if (_IN == NULL)
20.4100 + return _OUT;
20.4101 +
20.4102 + CompData *_in = (CompData * )_IN;
20.4103 + CompData *_out = (CompData * )_OUT;
20.4104
20.4105 - CompData *_in = (CompData * )_IN;
20.4106 - CompData *_out = (CompData * )_OUT;
20.4107 + _in->inline_level = _out->inline_level;
20.4108 + _in->profile = _out->profile;
20.4109
20.4110 - _in->inline_level = _out->inline_level;
20.4111 - _in->profile = _out->profile;
20.4112 -
20.4113 - _out->Abort();
20.4114 -
20.4115 - return _in;
20.4116 + _out->Abort();
20.4117 + return _in;
20.4118 }
20.4119
20.4120 JITX86::JITX86()
20.4121 {
20.4122 - m_pJitEntry = NULL;
20.4123 - m_pJitReturn = NULL;
20.4124 - m_RoundTable[0] = -1;
20.4125 - m_RoundTable[1] = 0;
20.4126 - m_RoundTable[2] = 1;
20.4127 - m_pJitGenArray = NULL;
20.4128 + m_pJitEntry = NULL;
20.4129 + m_pJitGenArray = NULL;
20.4130 }
20.4131
20.4132 bool JITX86::InitializeJIT()
20.4133 {
20.4134 - jitoffs_t offs;
20.4135 - JitWriter writer, *jit;
20.4136 + g_pCodeCache = KE_CreateCodeCache();
20.4137
20.4138 - g_pCodeCache = KE_CreateCodeCache();
20.4139 + m_pJitEntry = GenerateEntry(&m_pJitReturn);
20.4140 + if (!m_pJitEntry)
20.4141 + return false;
20.4142
20.4143 - jit = &writer;
20.4144 -
20.4145 - /* Build the entry point */
20.4146 - jit->outbase = NULL;
20.4147 - jit->outptr = NULL;
20.4148 - Write_Execute_Function(jit);
20.4149 - m_pJitEntry = Knight::KE_AllocCode(g_pCodeCache, jit->get_outputpos());
20.4150 - jit->outbase = (jitcode_t)m_pJitEntry;
20.4151 - jit->outptr = jit->outbase;
20.4152 - offs = Write_Execute_Function(jit);
20.4153 - m_pJitReturn = (uint8_t *)m_pJitEntry + offs;
20.4154 + m_pJitGenArray = GenerateGenArrayIntrinsic(m_pJitReturn);
20.4155 + if (!m_pJitGenArray)
20.4156 + return false;
20.4157
20.4158 - /* Build the genarray intrinsic */
20.4159 - writer = JitWriter();
20.4160 - jit->outbase = NULL;
20.4161 - jit->outptr = NULL;
20.4162 - WriteIntrinsic_GenArray(jit);
20.4163 - m_pJitGenArray = Knight::KE_AllocCode(g_pCodeCache, jit->get_outputpos());
20.4164 - jit->outbase = (jitcode_t)m_pJitGenArray;
20.4165 - jit->outptr = jit->outbase;
20.4166 - WriteIntrinsic_GenArray(jit);
20.4167 -
20.4168 - return true;
20.4169 + return true;
20.4170 }
20.4171
20.4172 -void JITX86::ShutdownJIT()
20.4173 +void
20.4174 +JITX86::ShutdownJIT()
20.4175 {
20.4176 - KE_DestroyCodeCache(g_pCodeCache);
20.4177 + KE_DestroyCodeCache(g_pCodeCache);
20.4178 +}
20.4179 +
20.4180 +JitFunction *
20.4181 +JITX86::CompileFunction(BaseRuntime *prt, cell_t pcode_offs, int *err)
20.4182 +{
20.4183 + Compiler cc(prt, pcode_offs);
20.4184 + JitFunction *fun = cc.emit(err);
20.4185 + if (!fun)
20.4186 + return NULL;
20.4187 + prt->AddJittedFunction(fun);
20.4188 + return fun;
20.4189 }
20.4190
20.4191 -JitFunction *JITX86::CompileFunction(BaseRuntime *prt, cell_t pcode_offs, int *err)
20.4192 +void
20.4193 +JITX86::SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx)
20.4194 {
20.4195 - CompData *data = (CompData *)prt->m_pCo;
20.4196 - sp_plugin_t *plugin = data->plugin;
20.4197 -
20.4198 - uint8_t *code = plugin->pcode + pcode_offs;
20.4199 - uint8_t *end_code = plugin->pcode + plugin->pcode_size;
20.4200 -
20.4201 - assert(FuncLookup(data, pcode_offs) == 0);
20.4202 -
20.4203 - if (code >= end_code || *(cell_t *)code != OP_PROC)
20.4204 - {
20.4205 - *err = SP_ERROR_INVALID_INSTRUCTION;
20.4206 - return NULL;
20.4207 - }
20.4208 -
20.4209 -#if defined _DEBUG
20.4210 - g_engine1.GetDebugHook()->OnDebugSpew("Compiling function %s::%s", prt->m_pPlugin->name, find_func_name(prt->m_pPlugin, pcode_offs));
20.4211 -#endif
20.4212 -
20.4213 - code += sizeof(cell_t);
20.4214 -
20.4215 - OPCODE op;
20.4216 - uint32_t code_size;
20.4217 - cell_t *cip, *end_cip;
20.4218 - JitWriter writer, *jit;
20.4219 -
20.4220 - jit = &writer;
20.4221 - cip = (cell_t *)code;
20.4222 - end_cip = (cell_t *)end_code;
20.4223 - writer.data = data;
20.4224 - writer.inbase = cip;
20.4225 - writer.outptr = NULL;
20.4226 - writer.outbase = NULL;
20.4227 - data->cur_func = pcode_offs;
20.4228 -
20.4229 -jit_rewind:
20.4230 - data->num_thunks = 0;
20.4231 - writer.inptr = writer.inbase;
20.4232 -
20.4233 - WriteOp_Proc(jit);
20.4234 -
20.4235 - /* Actual code generation! */
20.4236 - if (writer.outbase == NULL)
20.4237 - {
20.4238 - /* First Pass - find codesize and resolve relocation */
20.4239 - jitoffs_t jpcode_offs;
20.4240 - jitoffs_t native_offs;
20.4241 -
20.4242 - for (; writer.inptr < end_cip;)
20.4243 - {
20.4244 - op = (OPCODE)writer.peek_cell();
20.4245 -
20.4246 - /* If we hit another function, we must stop. */
20.4247 - if (op == OP_PROC || op == OP_ENDPROC)
20.4248 - {
20.4249 - break;
20.4250 - }
20.4251 -
20.4252 - /* Store the native offset into the rebase memory.
20.4253 - * This large chunk of memory lets us do an instant lookup
20.4254 - * based on an original pcode offset.
20.4255 - */
20.4256 - jpcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - plugin->pcode);
20.4257 - native_offs = jit->get_outputpos();
20.4258 - *((jitoffs_t *)(data->rebase + jpcode_offs)) = native_offs;
20.4259 -
20.4260 - /* Read past the opcode. */
20.4261 - writer.read_cell();
20.4262 + tracker_t *trk = new tracker_t;
20.4263
20.4264 - /* Patch the floating point natives with our opcodes */
20.4265 - if (op == OP_SYSREQ_N)
20.4266 - {
20.4267 - cell_t idx = writer.read_cell();
20.4268 - if (data->jit_float_table[idx].found)
20.4269 - {
20.4270 - writer.inptr -= 2;
20.4271 - *(writer.inptr++) = data->jit_float_table[idx].index;
20.4272 - *(writer.inptr++) = OP_NOP;
20.4273 - *(writer.inptr++) = OP_NOP;
20.4274 - op = (OPCODE)data->jit_float_table[idx].index;
20.4275 - }
20.4276 - else
20.4277 - {
20.4278 - writer.inptr--;
20.4279 - }
20.4280 - }
20.4281 - switch (op)
20.4282 - {
20.4283 - #include "opcode_switch.inc"
20.4284 - }
20.4285 - /* Check for errors. This should only happen in the first pass. */
20.4286 - if (data->error_set != SP_ERROR_NONE)
20.4287 - {
20.4288 - *err = data->error_set;
20.4289 - return NULL;
20.4290 - }
20.4291 - }
20.4292 -
20.4293 - /* Write these last because error jumps should be predicted forwardly (not taken) */
20.4294 - WriteErrorRoutines(data, jit);
20.4295 -
20.4296 - AlignMe(jit);
20.4297 - data->jit_sysreq_c = jit->get_outputpos();
20.4298 - WriteOp_Sysreq_C_Function(jit);
20.4299 -
20.4300 - /* Build thunk tables */
20.4301 - if (data->num_thunks > data->max_thunks)
20.4302 - {
20.4303 - data->max_thunks = data->num_thunks;
20.4304 - data->thunks = (call_thunk_t *)realloc(
20.4305 - data->thunks,
20.4306 - data->max_thunks * sizeof(call_thunk_t));
20.4307 - }
20.4308 -
20.4309 - /* Write the thunk offsets.
20.4310 - * :TODO: we can emit all but one call to Write_CallThunk().
20.4311 - */
20.4312 - for (unsigned int i = 0; i < data->num_thunks; i++)
20.4313 - {
20.4314 - data->thunks[i].thunk_addr = jit->get_outputpos();
20.4315 - Write_CallThunk(jit, 0, 0);
20.4316 - }
20.4317 + ctx->vm[JITVARS_TRACKER] = trk;
20.4318 + ctx->vm[JITVARS_BASECTX] = pCtx; /* GetDefaultContext() is not constructed yet */
20.4319 + ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
20.4320 + ctx->vm[JITVARS_PLUGIN] = const_cast<sp_plugin_t *>(runtime->plugin());
20.4321
20.4322 - /**
20.4323 - * I don't understand the purpose of this code.
20.4324 - * Why do we want to know about the last opcode?
20.4325 - * It should already have gotten written.
20.4326 - */
20.4327 - #if 0
20.4328 - /* Write the final CIP to the last position in the reloc array */
20.4329 - pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
20.4330 - native_offs = jit->get_outputpos();
20.4331 - *((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
20.4332 - #endif
20.4333 -
20.4334 - /* the total codesize is now known! */
20.4335 - code_size = writer.get_outputpos();
20.4336 - writer.outbase = (jitcode_t)Knight::KE_AllocCode(g_pCodeCache, code_size);
20.4337 - writer.outptr = writer.outbase;
20.4338 -
20.4339 - /* go back for second pass */
20.4340 - goto jit_rewind;
20.4341 - }
20.4342 - else
20.4343 - {
20.4344 - /*******
20.4345 - * SECOND PASS - write opcode info
20.4346 - *******/
20.4347 - for (; writer.inptr < end_cip;)
20.4348 - {
20.4349 - op = (OPCODE)writer.read_cell();
20.4350 -
20.4351 - /* If we hit another function, we must stop. */
20.4352 - if (op == OP_PROC || op == OP_ENDPROC)
20.4353 - {
20.4354 - break;
20.4355 - }
20.4356 -
20.4357 - switch (op)
20.4358 - {
20.4359 - #include "opcode_switch.inc"
20.4360 - }
20.4361 - }
20.4362 -
20.4363 - /* Write these last because error jumps should be predicted as not taken (forward) */
20.4364 - WriteErrorRoutines(data, jit);
20.4365 -
20.4366 - AlignMe(jit);
20.4367 - data->jit_sysreq_c = jit->get_outputpos();
20.4368 - WriteOp_Sysreq_C_Function(jit);
20.4369 -
20.4370 - /* Write the thunk offsets. */
20.4371 - for (unsigned int i = 0; i < data->num_thunks; i++)
20.4372 - {
20.4373 - Write_CallThunk(jit, data->thunks[i].patch_addr, data->thunks[i].pcode_offs);
20.4374 - }
20.4375 - }
20.4376 -
20.4377 - *err = SP_ERROR_NONE;
20.4378 -
20.4379 - JitFunction *fn;
20.4380 - uint32_t func_idx;
20.4381 -
20.4382 - fn = new JitFunction(writer.outbase, pcode_offs);
20.4383 - func_idx = prt->AddJittedFunction(fn);
20.4384 - *(cell_t *)(data->rebase + pcode_offs) = func_idx;
20.4385 -
20.4386 - return fn;
20.4387 + trk->pBase = (ucell_t *)malloc(1024);
20.4388 + trk->pCur = trk->pBase;
20.4389 + trk->size = 1024 / sizeof(cell_t);
20.4390 }
20.4391
20.4392 -void JITX86::SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx)
20.4393 +SPVM_NATIVE_FUNC
20.4394 +JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
20.4395 {
20.4396 - tracker_t *trk = new tracker_t;
20.4397 -
20.4398 - ctx->vm[JITVARS_TRACKER] = trk;
20.4399 - ctx->vm[JITVARS_BASECTX] = pCtx; /* GetDefaultContext() is not constructed yet */
20.4400 - ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
20.4401 - ctx->vm[JITVARS_PLUGIN] = runtime->m_pPlugin;
20.4402 -
20.4403 - trk->pBase = (ucell_t *)malloc(1024);
20.4404 - trk->pCur = trk->pBase;
20.4405 - trk->size = 1024 / sizeof(cell_t);
20.4406 -}
20.4407 -
20.4408 -SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
20.4409 -{
20.4410 - JitWriter jw;
20.4411 - JitWriter *jit = &jw;
20.4412 -
20.4413 - jw.outbase = NULL;
20.4414 - jw.outptr = NULL;
20.4415 - jw.data = NULL;
20.4416 + AssemblerX86 masm;
20.4417
20.4418 - /* First pass, calculate size */
20.4419 -rewind:
20.4420 - /* Align the stack to 16 bytes */
20.4421 - //push ebx
20.4422 - //push edi
20.4423 - //push esi
20.4424 - //mov edi, [esp+16] ;store ctx
20.4425 - //mov esi, [esp+20] ;store params
20.4426 - //mov ebx, esp
20.4427 - //and esp, 0xFFFFFF0
20.4428 - //sub esp, 4
20.4429 - IA32_Push_Reg(jit, REG_EBX);
20.4430 - IA32_Push_Reg(jit, REG_EDI);
20.4431 - IA32_Push_Reg(jit, REG_ESI);
20.4432 - IA32_Mov_Reg_Esp_Disp8(jit, REG_EDI, 16);
20.4433 - IA32_Mov_Reg_Esp_Disp8(jit, REG_ESI, 20);
20.4434 - IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
20.4435 - IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
20.4436 - IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
20.4437 + __ push(ebx);
20.4438 + __ push(edi);
20.4439 + __ push(esi);
20.4440 + __ movl(edi, Operand(esp, 16)); // store ctx
20.4441 + __ movl(esi, Operand(esp, 20)); // store params
20.4442 + __ movl(ebx, esp);
20.4443 + __ andl(esp, 0xfffffff0);
20.4444 + __ subl(esp, 4);
20.4445
20.4446 - //push pData ;push pData
20.4447 - //push esi ;push params
20.4448 - //push edi ;push ctx
20.4449 - //call [callback] ;invoke the meta-callback
20.4450 - //mov esp, ebx ;restore the stack
20.4451 - //pop esi ;restore esi
20.4452 - //pop edi ;restore edi
20.4453 - //pop ebx ;restore ebx
20.4454 - //ret ;return
20.4455 - IA32_Push_Imm32(jit, (jit_int32_t)pData);
20.4456 - IA32_Push_Reg(jit, REG_ESI);
20.4457 - IA32_Push_Reg(jit, REG_EDI);
20.4458 - uint32_t call = IA32_Call_Imm32(jit, 0);
20.4459 - IA32_Write_Jump32_Abs(jit, call, (void *)callback);
20.4460 - IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
20.4461 - IA32_Pop_Reg(jit, REG_ESI);
20.4462 - IA32_Pop_Reg(jit, REG_EDI);
20.4463 - IA32_Pop_Reg(jit, REG_EBX);
20.4464 - IA32_Return(jit);
20.4465 + __ push(intptr_t(pData));
20.4466 + __ push(esi);
20.4467 + __ push(edi);
20.4468 + __ call(ExternalAddress((void *)callback));
20.4469 + __ movl(esp, ebx);
20.4470 + __ pop(esi);
20.4471 + __ pop(edi);
20.4472 + __ pop(ebx);
20.4473 + __ ret();
20.4474
20.4475 - if (jw.outbase == NULL)
20.4476 - {
20.4477 - /* Second pass: Actually write */
20.4478 - jw.outbase = (jitcode_t)KE_AllocCode(g_pCodeCache, jw.get_outputpos());
20.4479 - if (!jw.outbase)
20.4480 - {
20.4481 - return NULL;
20.4482 - }
20.4483 - jw.outptr = jw.outbase;
20.4484 -
20.4485 - goto rewind;
20.4486 - }
20.4487 -
20.4488 - return (SPVM_NATIVE_FUNC)jw.outbase;
20.4489 + return (SPVM_NATIVE_FUNC)LinkCode(masm);
20.4490 }
20.4491
20.4492 void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
20.4493 {
20.4494 - KE_FreeCode(g_pCodeCache, (void *)func);
20.4495 + KE_FreeCode(g_pCodeCache, (void *)func);
20.4496 }
20.4497
20.4498 ICompilation *JITX86::StartCompilation()
20.4499 {
20.4500 - CompData *data = new CompData;
20.4501 -
20.4502 - data->jit_float_table = NULL;
20.4503 -
20.4504 - return data;
20.4505 -}
20.4506 -
20.4507 -void CompData::SetRuntime(BaseRuntime *runtime)
20.4508 -{
20.4509 - plugin = runtime->m_pPlugin;
20.4510 -
20.4511 - uint32_t max_natives = plugin->num_natives;
20.4512 -
20.4513 - this->runtime = runtime;
20.4514 - this->plugin = runtime->m_pPlugin;
20.4515 -
20.4516 - inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
20.4517 - error_set = SP_ERROR_NONE;
20.4518 -
20.4519 - jit_float_table = new floattbl_t[max_natives];
20.4520 - for (uint32_t i=0; i<max_natives; i++)
20.4521 - {
20.4522 - const char *name = plugin->natives[i].name;
20.4523 - if (!strcmp(name, "FloatAbs"))
20.4524 - {
20.4525 - jit_float_table[i].found = true;
20.4526 - jit_float_table[i].index = OP_FABS;
20.4527 - }
20.4528 - else if (!strcmp(name, "FloatAdd"))
20.4529 - {
20.4530 - jit_float_table[i].found = true;
20.4531 - jit_float_table[i].index = OP_FLOATADD;
20.4532 - }
20.4533 - else if (!strcmp(name, "FloatSub"))
20.4534 - {
20.4535 - jit_float_table[i].found = true;
20.4536 - jit_float_table[i].index = OP_FLOATSUB;
20.4537 - }
20.4538 - else if (!strcmp(name, "FloatMul"))
20.4539 - {
20.4540 - jit_float_table[i].found = true;
20.4541 - jit_float_table[i].index = OP_FLOATMUL;
20.4542 - }
20.4543 - else if (!strcmp(name, "FloatDiv"))
20.4544 - {
20.4545 - jit_float_table[i].found = true;
20.4546 - jit_float_table[i].index = OP_FLOATDIV;
20.4547 - }
20.4548 - else if (!strcmp(name, "float"))
20.4549 - {
20.4550 - jit_float_table[i].found = true;
20.4551 - jit_float_table[i].index = OP_FLOAT;
20.4552 - }
20.4553 - else if (!strcmp(name, "FloatCompare"))
20.4554 - {
20.4555 - jit_float_table[i].found = true;
20.4556 - jit_float_table[i].index = OP_FLOATCMP;
20.4557 - }
20.4558 - else if (!strcmp(name, "RoundToZero"))
20.4559 - {
20.4560 - jit_float_table[i].found = true;
20.4561 - jit_float_table[i].index = OP_RND_TO_ZERO;
20.4562 - }
20.4563 - else if (!strcmp(name, "RoundToCeil"))
20.4564 - {
20.4565 - jit_float_table[i].found = true;
20.4566 - jit_float_table[i].index = OP_RND_TO_CEIL;
20.4567 - }
20.4568 - else if (!strcmp(name, "RoundToFloor"))
20.4569 - {
20.4570 - jit_float_table[i].found = true;
20.4571 - jit_float_table[i].index = OP_RND_TO_FLOOR;
20.4572 - }
20.4573 - else if (!strcmp(name, "RoundToNearest"))
20.4574 - {
20.4575 - jit_float_table[i].found = true;
20.4576 - jit_float_table[i].index = OP_RND_TO_NEAREST;
20.4577 - }
20.4578 - }
20.4579 -
20.4580 - /* We need a relocation table. This is the relocation table we'll use for jumps
20.4581 - * and calls alike. One extra cell for final CIP.
20.4582 - */
20.4583 - this->rebase = (uint8_t *)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t));
20.4584 - memset(this->rebase, 0, plugin->pcode_size + sizeof(cell_t));
20.4585 + return new CompData;
20.4586 }
20.4587
20.4588 ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
20.4589 {
20.4590 - CompData *data = new CompData;
20.4591 -
20.4592 - data->SetRuntime(runtime);
20.4593 -
20.4594 - return data;
20.4595 + return new CompData;
20.4596 }
20.4597
20.4598 void CompData::Abort()
20.4599 {
20.4600 - if (rebase)
20.4601 - {
20.4602 - engine->BaseFree(rebase);
20.4603 - }
20.4604 - free(thunks);
20.4605 - delete [] jit_float_table;
20.4606 - delete this;
20.4607 + delete this;
20.4608 }
20.4609
20.4610 void JITX86::FreeContextVars(sp_context_t *ctx)
20.4611 {
20.4612 - free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
20.4613 - delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
20.4614 + free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
20.4615 + delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
20.4616 }
20.4617
20.4618 bool CompData::SetOption(const char *key, const char *val)
20.4619 {
20.4620 - if (strcmp(key, SP_JITCONF_DEBUG) == 0)
20.4621 - {
20.4622 - return true;
20.4623 - }
20.4624 - else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
20.4625 - {
20.4626 - profile = atoi(val);
20.4627 -
20.4628 - /** Callbacks must be profiled to profile functions! */
20.4629 - if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
20.4630 - {
20.4631 - profile |= SP_PROF_CALLBACKS;
20.4632 - }
20.4633 -
20.4634 - return true;
20.4635 - }
20.4636 + if (strcmp(key, SP_JITCONF_DEBUG) == 0)
20.4637 + return true;
20.4638 + if (strcmp(key, SP_JITCONF_PROFILE) == 0) {
20.4639 + profile = atoi(val);
20.4640
20.4641 - return false;
20.4642 -}
20.4643 -
20.4644 -void *JITX86::GetGenArrayIntrinsic()
20.4645 -{
20.4646 - return m_pJitGenArray;
20.4647 -}
20.4648 + /** Callbacks must be profiled to profile functions! */
20.4649 + if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
20.4650 + profile |= SP_PROF_CALLBACKS;
20.4651
20.4652 -void *JITX86::GetReturnPoint()
20.4653 -{
20.4654 - return m_pJitReturn;
20.4655 -}
20.4656 + return true;
20.4657 + }
20.4658
20.4659 -void *JITX86::GetRoundingTable()
20.4660 -{
20.4661 - return m_RoundTable;
20.4662 + return false;
20.4663 }
20.4664
20.4665 typedef int (*JIT_EXECUTE)(cell_t *vars, void *addr);
20.4666 int JITX86::InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result)
20.4667 {
20.4668 - int err;
20.4669 - JIT_EXECUTE pfn;
20.4670 - sp_context_t *ctx;
20.4671 - cell_t vars[AMX_NUM_INFO_VARS];
20.4672 + int err;
20.4673 + JIT_EXECUTE pfn;
20.4674 + sp_context_t *ctx;
20.4675 + cell_t vars[AMX_NUM_INFO_VARS];
20.4676
20.4677 - ctx = runtime->GetBaseContext()->GetCtx();
20.4678 + ctx = runtime->GetBaseContext()->GetCtx();
20.4679
20.4680 - vars[0] = ctx->sp;
20.4681 - vars[1] = ctx->hp;
20.4682 - vars[2] = (cell_t)result;
20.4683 - vars[3] = (cell_t)ctx;
20.4684 - vars[4] = (cell_t)(runtime->m_pPlugin->memory + runtime->m_pPlugin->mem_size);
20.4685 - vars[5] = fn->GetPCodeAddress();
20.4686 - vars[6] = runtime->m_pPlugin->data_size;
20.4687 - vars[7] = (cell_t)(runtime->m_pPlugin->memory);
20.4688 - /* vars[8] will be set to ESP */
20.4689 + vars[0] = ctx->sp;
20.4690 + vars[1] = ctx->hp;
20.4691 + vars[2] = (cell_t)result;
20.4692 + vars[3] = (cell_t)ctx;
20.4693 + vars[4] = (cell_t)(runtime->plugin()->memory + runtime->plugin()->mem_size);
20.4694 + vars[5] = fn->GetPCodeAddress();
20.4695 + vars[6] = runtime->plugin()->data_size;
20.4696 + vars[7] = (cell_t)(runtime->plugin()->memory);
20.4697 + /* vars[8] will be set to ESP */
20.4698
20.4699 - pfn = (JIT_EXECUTE)m_pJitEntry;
20.4700 - err = pfn(vars, fn->GetEntryAddress());
20.4701 + pfn = (JIT_EXECUTE)m_pJitEntry;
20.4702 + err = pfn(vars, fn->GetEntryAddress());
20.4703
20.4704 - ctx->hp = vars[1];
20.4705 - ctx->err_cip = vars[5];
20.4706 + ctx->hp = vars[1];
20.4707 + ctx->err_cip = vars[5];
20.4708
20.4709 - return err;
20.4710 + return err;
20.4711 }
20.4712
20.4713 void *JITX86::AllocCode(size_t size)
20.4714 {
20.4715 - return Knight::KE_AllocCode(g_pCodeCache, size);
20.4716 + return Knight::KE_AllocCode(g_pCodeCache, size);
20.4717 }
20.4718
20.4719 void JITX86::FreeCode(void *code)
20.4720 {
20.4721 - KE_FreeCode(g_pCodeCache, code);
20.4722 + KE_FreeCode(g_pCodeCache, code);
20.4723 }
21.1 --- a/sourcepawn/jit/x86/jit_x86.h Thu Aug 08 09:40:23 2013 -0700
21.2 +++ b/sourcepawn/jit/x86/jit_x86.h Thu Aug 08 09:41:24 2013 -0700
21.3 @@ -1,5 +1,5 @@
21.4 /**
21.5 - * vim: set ts=4 :
21.6 + * vim: set ts=4 sw=4 tw=99 et:
21.7 * =============================================================================
21.8 * SourceMod
21.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
21.10 @@ -35,164 +35,180 @@
21.11 #include <sp_vm_types.h>
21.12 #include <sp_vm_api.h>
21.13 #include <KeCodeAllocator.h>
21.14 -#include "jit_helpers.h"
21.15 +#include <assembler-x86.h>
21.16 +#include <ke_vector.h>
21.17 #include "jit_shared.h"
21.18 #include "BaseRuntime.h"
21.19 #include "jit_function.h"
21.20 +#include "opcodes.h"
21.21
21.22 using namespace SourcePawn;
21.23
21.24 -#define JIT_INLINE_ERRORCHECKS (1<<0)
21.25 -#define JIT_INLINE_NATIVES (1<<1)
21.26 -#define STACK_MARGIN 64 //8 parameters of safety, I guess
21.27 -#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
21.28 +#define JIT_INLINE_ERRORCHECKS (1<<0)
21.29 +#define JIT_INLINE_NATIVES (1<<1)
21.30 +#define STACK_MARGIN 64 //8 parameters of safety, I guess
21.31 +#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
21.32
21.33 -#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
21.34 -#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
21.35 -#define JITVARS_PROFILER 2 //profiler
21.36 -#define JITVARS_PLUGIN 3 //sp_plugin_t
21.37 +#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
21.38 +#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
21.39 +#define JITVARS_PROFILER 2 //profiler
21.40 +#define JITVARS_PLUGIN 3 //sp_plugin_t
21.41
21.42 -#define sDIMEN_MAX 5 //this must mirror what the compiler has.
21.43 +#define sDIMEN_MAX 5 //this must mirror what the compiler has.
21.44
21.45 #define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX])
21.46
21.47 typedef struct tracker_s
21.48 {
21.49 - size_t size;
21.50 - ucell_t *pBase;
21.51 - ucell_t *pCur;
21.52 + size_t size;
21.53 + ucell_t *pBase;
21.54 + ucell_t *pCur;
21.55 } tracker_t;
21.56
21.57 typedef struct funcinfo_s
21.58 {
21.59 - unsigned int magic;
21.60 - unsigned int index;
21.61 + unsigned int magic;
21.62 + unsigned int index;
21.63 } funcinfo_t;
21.64
21.65 typedef struct functracker_s
21.66 {
21.67 - unsigned int num_functions;
21.68 - unsigned int code_size;
21.69 + unsigned int num_functions;
21.70 + unsigned int code_size;
21.71 } functracker_t;
21.72
21.73 -struct floattbl_t
21.74 +struct CallThunk
21.75 {
21.76 - floattbl_t()
21.77 - {
21.78 - found = false;
21.79 - index = 0;
21.80 - }
21.81 - bool found;
21.82 - unsigned int index;
21.83 -};
21.84 + Label call;
21.85 + cell_t pcode_offset;
21.86
21.87 -struct call_thunk_t
21.88 -{
21.89 - jitoffs_t patch_addr;
21.90 - cell_t pcode_offs;
21.91 - jitoffs_t thunk_addr;
21.92 + CallThunk(cell_t pcode_offset)
21.93 + : pcode_offset(pcode_offset)
21.94 + {
21.95 + }
21.96 };
21.97
21.98 class CompData : public ICompilation
21.99 {
21.100 public:
21.101 - CompData()
21.102 - : runtime(NULL),
21.103 - plugin(NULL),
21.104 - rebase(NULL),
21.105 - jit_float_table(NULL),
21.106 - profile(0),
21.107 - inline_level(0),
21.108 - error_set(SP_ERROR_NONE),
21.109 - num_thunks(0),
21.110 - max_thunks(0),
21.111 - thunks(NULL)
21.112 - {
21.113 - };
21.114 - bool SetOption(const char *key, const char *val);
21.115 - void SetRuntime(BaseRuntime *runtime);
21.116 - void Abort();
21.117 + CompData()
21.118 + : profile(0),
21.119 + inline_level(0)
21.120 + {
21.121 + };
21.122 + bool SetOption(const char *key, const char *val);
21.123 + void Abort();
21.124 public:
21.125 - BaseRuntime *runtime; /* runtime handle */
21.126 - sp_plugin_t *plugin; /* plugin handle */
21.127 - uint8_t *rebase; /* relocation map */
21.128 - floattbl_t *jit_float_table;
21.129 - cell_t cur_func; /* current func pcode offset */
21.130 - /* Options */
21.131 - int profile; /* profiling flags */
21.132 - int inline_level; /* inline optimization level */
21.133 - /* Per-compilation properties */
21.134 - int error_set; /* error code to halt process */
21.135 - unsigned int func_idx; /* current function index */
21.136 - jitoffs_t jit_error_bounds;
21.137 - jitoffs_t jit_error_divzero;
21.138 - jitoffs_t jit_error_stacklow;
21.139 - jitoffs_t jit_error_stackmin;
21.140 - jitoffs_t jit_error_memaccess;
21.141 - jitoffs_t jit_error_heaplow;
21.142 - jitoffs_t jit_error_heapmin;
21.143 - jitoffs_t jit_extern_error; /* returning generic error */
21.144 - jitoffs_t jit_sysreq_c; /* old version! */
21.145 - uint32_t num_thunks; /* number of thunks needed */
21.146 - uint32_t max_thunks; /* maximum number of thunks */
21.147 - call_thunk_t *thunks; /* thunk array */
21.148 + cell_t cur_func; /* current func pcode offset */
21.149 + /* Options */
21.150 + int profile; /* profiling flags */
21.151 + int inline_level; /* inline optimization level */
21.152 + /* Per-compilation properties */
21.153 + unsigned int func_idx; /* current function index */
21.154 +};
21.155 +
21.156 +class Compiler
21.157 +{
21.158 + public:
21.159 + Compiler(BaseRuntime *rt, cell_t pcode_offs);
21.160 + ~Compiler();
21.161 +
21.162 + JitFunction *emit(int *errp);
21.163 +
21.164 + private:
21.165 + bool setup(cell_t pcode_offs);
21.166 + bool emitOp(OPCODE op);
21.167 + cell_t readCell();
21.168 +
21.169 + private:
21.170 + Label *labelAt(size_t offset);
21.171 + bool emitCall();
21.172 + bool emitNativeCall(OPCODE op);
21.173 + bool emitSwitch();
21.174 + void emitGenArray(bool autozero);
21.175 + void emitCallThunks();
21.176 + void emitCheckAddress(Register reg);
21.177 + void emitErrorPath(Label *dest, int code);
21.178 + void emitErrorPaths();
21.179 +
21.180 + private:
21.181 + AssemblerX86 masm;
21.182 + BaseRuntime *rt_;
21.183 + const sp_plugin_t *plugin_;
21.184 + int error_;
21.185 + uint32_t pcode_start_;
21.186 + cell_t *code_start_;
21.187 + cell_t *cip_;
21.188 + cell_t *code_end_;
21.189 + Label *jump_map_;
21.190 +
21.191 + // Errors
21.192 + Label error_bounds_;
21.193 + Label error_heap_low_;
21.194 + Label error_heap_min_;
21.195 + Label error_stack_low_;
21.196 + Label error_stack_min_;
21.197 + Label error_divide_by_zero_;
21.198 + Label error_memaccess_;
21.199 + Label error_integer_overflow_;
21.200 + Label extern_error_;
21.201 +
21.202 + ke::Vector<CallThunk *> thunks_; //:TODO: free
21.203 };
21.204
21.205 class JITX86
21.206 {
21.207 -public:
21.208 - JITX86();
21.209 -public:
21.210 - bool InitializeJIT();
21.211 - void ShutdownJIT();
21.212 - ICompilation *StartCompilation(BaseRuntime *runtime);
21.213 - ICompilation *StartCompilation();
21.214 - void SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx);
21.215 - void FreeContextVars(sp_context_t *ctx);
21.216 - SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
21.217 - void DestroyFakeNative(SPVM_NATIVE_FUNC func);
21.218 - JitFunction *CompileFunction(BaseRuntime *runtime, cell_t pcode_offs, int *err);
21.219 - ICompilation *ApplyOptions(ICompilation *_IN, ICompilation *_OUT);
21.220 - int InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result);
21.221 -public:
21.222 - void *GetGenArrayIntrinsic();
21.223 - void *GetReturnPoint();
21.224 - void *GetRoundingTable();
21.225 - void *AllocCode(size_t size);
21.226 - void FreeCode(void *code);
21.227 -private:
21.228 - void *m_pJitEntry; /* Entry function */
21.229 - void *m_pJitReturn; /* Return point for errors */
21.230 - int m_RoundTable[3]; /* [-1, 0, 1] rounding table */
21.231 - void *m_pJitGenArray; /* Generates an array */
21.232 + public:
21.233 + JITX86();
21.234 +
21.235 + public:
21.236 + bool InitializeJIT();
21.237 + void ShutdownJIT();
21.238 + ICompilation *StartCompilation(BaseRuntime *runtime);
21.239 + ICompilation *StartCompilation();
21.240 + void SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx);
21.241 + void FreeContextVars(sp_context_t *ctx);
21.242 + SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
21.243 + void DestroyFakeNative(SPVM_NATIVE_FUNC func);
21.244 + JitFunction *CompileFunction(BaseRuntime *runtime, cell_t pcode_offs, int *err);
21.245 + ICompilation *ApplyOptions(ICompilation *_IN, ICompilation *_OUT);
21.246 + int InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result);
21.247 +
21.248 + public:
21.249 + ExternalAddress GetGenArrayIntrinsic() {
21.250 + return ExternalAddress(m_pJitGenArray);
21.251 + }
21.252 + ExternalAddress GetUniversalReturn() {
21.253 + return ExternalAddress(m_pJitReturn);
21.254 + }
21.255 + void *AllocCode(size_t size);
21.256 + void FreeCode(void *code);
21.257 +
21.258 + private:
21.259 + void *m_pJitEntry; /* Entry function */
21.260 + void *m_pJitReturn; /* Universal return address */
21.261 + void *m_pJitGenArray; /* Generates an array */
21.262 };
21.263
21.264 -cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
21.265 -cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
21.266 -uint32_t FuncLookup(CompData *data, cell_t pcode_offs);
21.267 -jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
21.268 -void *CompileThunk(BaseRuntime *runtime, cell_t pcode_ffs, void *jmploc_addr);
21.269 +const Register pri = eax;
21.270 +const Register alt = edx;
21.271 +const Register stk = edi;
21.272 +const Register dat = ebp;
21.273 +const Register tmp = ecx;
21.274 +const Register info = esi;
21.275 +const Register frm = ebx;
21.276 +
21.277 +#define AMX_NUM_INFO_VARS 9
21.278
21.279 -#define AMX_REG_PRI REG_EAX
21.280 -#define AMX_REG_ALT REG_EDX
21.281 -#define AMX_REG_STK REG_EDI
21.282 -#define AMX_REG_DAT REG_EBP
21.283 -#define AMX_REG_TMP REG_ECX
21.284 -#define AMX_REG_INFO REG_ESI
21.285 -#define AMX_REG_FRM REG_EBX
21.286 -
21.287 -#define AMX_NUM_INFO_VARS 9
21.288 -
21.289 -#define AMX_INFO_FRM AMX_REG_INFO //not relocated
21.290 -#define AMX_INFO_FRAME 0 //(same thing as above)
21.291 -#define AMX_INFO_HEAP 4 //not relocated
21.292 -#define AMX_INFO_RETVAL 8 //physical
21.293 -#define AMX_INFO_CONTEXT 12 //physical
21.294 -#define AMX_INFO_STACKTOP 16 //relocated
21.295 -#define AMX_INFO_CIP 20 //pcode CIP
21.296 -#define AMX_INFO_DATASIZE 24 //plugin->data_size
21.297 -#define AMX_INFO_MEMORY 28 //plugin->memory
21.298 -#define AMX_INFO_NSTACK 32 //native stack
21.299 +#define AMX_INFO_FRAME 0 //(same thing as above)
21.300 +#define AMX_INFO_HEAP 4 //not relocated
21.301 +#define AMX_INFO_RETVAL 8 //physical
21.302 +#define AMX_INFO_CONTEXT 12 //physical
21.303 +#define AMX_INFO_STACKTOP 16 //relocated
21.304 +#define AMX_INFO_CIP 20 //pcode CIP
21.305 +#define AMX_INFO_DATASIZE 24 //plugin->data_size
21.306 +#define AMX_INFO_MEMORY 28 //plugin->memory
21.307 +#define AMX_INFO_NSTACK 32 //native stack
21.308
21.309 extern Knight::KeCodeCache *g_pCodeCache;
21.310 extern JITX86 g_Jit;
22.1 --- a/sourcepawn/jit/x86/opcode_helpers.cpp Thu Aug 08 09:40:23 2013 -0700
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,706 +0,0 @@
22.4 -/**
22.5 - * vim: set ts=4 :
22.6 - * =============================================================================
22.7 - * SourceMod
22.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
22.9 - * =============================================================================
22.10 - *
22.11 - * This program is free software; you can redistribute it and/or modify it under
22.12 - * the terms of the GNU General Public License, version 3.0, as published by the
22.13 - * Free Software Foundation.
22.14 - *
22.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
22.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
22.18 - * details.
22.19 - *
22.20 - * You should have received a copy of the GNU General Public License along with
22.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
22.22 - *
22.23 - * As a special exception, AlliedModders LLC gives you permission to link the
22.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
22.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
22.26 - * by the Valve Corporation. You must obey the GNU General Public License in
22.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
22.28 - * this exception to all derivative works. AlliedModders LLC defines further
22.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
22.30 - * or <http://www.sourcemod.net/license.php>.
22.31 - *
22.32 - * Version: $Id$
22.33 - */
22.34 -
22.35 -#include <limits.h>
22.36 -#include <string.h>
22.37 -#include <stdlib.h>
22.38 -#include "jit_x86.h"
22.39 -#include "opcode_helpers.h"
22.40 -#include "x86_macros.h"
22.41 -
22.42 -jitoffs_t Write_Execute_Function(JitWriter *jit)
22.43 -{
22.44 - /**
22.45 - * The variables we're passed in:
22.46 - * void *vars[], void *entry_func
22.47 - */
22.48 -
22.49 - /**
22.50 - * !NOTE!
22.51 - * Currently, we do not accept ctx->frm as the new frame pointer.
22.52 - * Instead, we copy the frame from the stack pointer.
22.53 - * This is because we do not support resuming or sleeping!
22.54 - */
22.55 -
22.56 - //push ebp
22.57 - //mov ebp, esp
22.58 - IA32_Push_Reg(jit, REG_EBP);
22.59 - IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
22.60 -
22.61 - //push esi
22.62 - //push edi
22.63 - //push ebx
22.64 - IA32_Push_Reg(jit, REG_ESI);
22.65 - IA32_Push_Reg(jit, REG_EDI);
22.66 - IA32_Push_Reg(jit, REG_EBX);
22.67 -
22.68 - /* Prep us for doing the real work */
22.69 - //mov esi, [ebp+param0] ;get vars
22.70 - //mov ecx, [ebp+param1] ;get entry addr
22.71 - //mov eax, [esi+MEMORY] ;get memory base
22.72 - //mov edx, [esi+CONTEXT] ;get context
22.73 - IA32_Mov_Reg_Rm_Disp8(jit, REG_ESI, REG_EBP, 8 + 4*0);
22.74 - IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EBP, 8 + 4*1);
22.75 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_ESI, AMX_INFO_MEMORY);
22.76 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_ESI, AMX_INFO_CONTEXT);
22.77 -
22.78 - /* Set up run-time registers */
22.79 - //mov edi, [edx+SP] ;non-reloc SP
22.80 - //add edi, eax ;reloc SP
22.81 - //mov ebp, eax ;DAT
22.82 - //mov ebx, edi ;reloc FRM
22.83 - //mov [esi+NSTACK], esp ;save ESP
22.84 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EDI, REG_EDX, offsetof(sp_context_t, sp));
22.85 - IA32_Add_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_REG);
22.86 - IA32_Mov_Reg_Rm(jit, REG_EBP, REG_EAX, MOD_REG);
22.87 - IA32_Mov_Reg_Rm(jit, REG_EBX, REG_EDI, MOD_REG);
22.88 - IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_ESP, AMX_INFO_NSTACK);
22.89 -
22.90 - /* by now, everything is set up, so we can call into the plugin */
22.91 - //call ecx
22.92 - IA32_Call_Reg(jit, REG_ECX);
22.93 -
22.94 - /* if the code flow gets to here, there was a normal return */
22.95 - //mov ecx, [esi+RETVAL] ;get retval pointer
22.96 - //mov [ecx], eax ;store retval from PRI
22.97 - //mov eax, SP_ERROR_NONE ;set no error
22.98 - IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, AMX_REG_INFO, AMX_INFO_RETVAL);
22.99 - IA32_Mov_Rm_Reg(jit, REG_ECX, AMX_REG_PRI, MOD_MEM_REG);
22.100 - IA32_Mov_Reg_Imm32(jit, REG_EAX, SP_ERROR_NONE);
22.101 -
22.102 - /* save where error checking/halting functions should go to */
22.103 - jitoffs_t offs_return = jit->get_outputpos();
22.104 - //mov esp, [esi+NSTACK] ;restore stack pointer
22.105 - IA32_Mov_Reg_Rm_Disp8(jit, REG_ESP, REG_ESI, AMX_INFO_NSTACK);
22.106 -
22.107 - /* Restore SP */
22.108 - //mov ecx, [esi+CONTEXT]
22.109 - //sub edi, ebp
22.110 - //mov [ecx+SP], edi
22.111 - IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_ESI, AMX_INFO_CONTEXT);
22.112 - IA32_Sub_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
22.113 - IA32_Mov_Rm_Reg_Disp8(jit, REG_ECX, REG_EDI, offsetof(sp_context_t, sp));
22.114 -
22.115 - //pop ebx
22.116 - //pop edi
22.117 - //pop esi
22.118 - //pop ebp
22.119 - //ret
22.120 - IA32_Pop_Reg(jit, REG_EBX);
22.121 - IA32_Pop_Reg(jit, REG_EDI);
22.122 - IA32_Pop_Reg(jit, REG_ESI);
22.123 - IA32_Pop_Reg(jit, REG_EBP);
22.124 - IA32_Return(jit);
22.125 -
22.126 - return offs_return;
22.127 -}
22.128 -
22.129 -void Write_GetError(JitWriter *jit)
22.130 -{
22.131 - //mov eax, [esi+info.context]
22.132 - //mov eax, [eax+ctx.error]
22.133 - //jmp [jit_return]
22.134 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
22.135 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EAX, offsetof(sp_context_t, n_err));
22.136 - IA32_Jump_Imm32_Abs(jit, g_Jit.GetReturnPoint());
22.137 -}
22.138 -
22.139 -void Write_SetError(JitWriter *jit, int error)
22.140 -{
22.141 - //mov eax, <error>
22.142 - //jmp [jit_return]
22.143 - IA32_Mov_Reg_Imm32(jit, REG_EAX, error);
22.144 - IA32_Jump_Imm32_Abs(jit, g_Jit.GetReturnPoint());
22.145 -}
22.146 -
22.147 -void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg)
22.148 -{
22.149 - //test reg, reg
22.150 - //jz :error
22.151 - IA32_Test_Rm_Reg(jit, reg, reg, MOD_REG);
22.152 - IA32_Jump_Cond_Imm32_Rel(jit, CC_Z, ((CompData *)jit->data)->jit_error_divzero);
22.153 -}
22.154 -
22.155 -void Write_CheckHeap_Min(JitWriter *jit)
22.156 -{
22.157 - /* Check if the stack went beyond the heap low.
22.158 - * This usually means there was a compiler error.
22.159 - * NOTE: Special optimization here.
22.160 - * The heap low is always known ahead of time! :)
22.161 - */
22.162 - CompData *data = (CompData *)jit->data;
22.163 - //cmp [esi+info.heap], <heaplow>
22.164 - //jb :error
22.165 - IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, data->plugin->data_size);
22.166 - IA32_Jump_Cond_Imm32_Rel(jit, CC_B, data->jit_error_heapmin);
22.167 -}
22.168 -
22.169 -void Write_CheckHeap_Low(JitWriter *jit)
22.170 -{
22.171 - /* Check if the heap is trying to grow beyond the stack.
22.172 - */
22.173 - //mov ecx, [esi+info.heap]
22.174 - //lea ecx, [ebp+ecx+STACK_MARGIN]
22.175 - //cmp ecx, edi
22.176 - //ja :error ; I think this is right
22.177 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
22.178 - IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN);
22.179 - IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
22.180 - IA32_Jump_Cond_Imm32_Rel(jit, CC_A, ((CompData *)jit->data)->jit_error_heaplow);
22.181 -}
22.182 -
22.183 -void Write_CheckStack_Min(JitWriter *jit)
22.184 -{
22.185 - /* Check if the stack went beyond the stack top
22.186 - * This usually means there was a compiler error.
22.187 - */
22.188 - //cmp edi, [esi+info.stacktop]
22.189 - //jae :error
22.190 - IA32_Cmp_Reg_Rm_Disp8(jit, AMX_REG_STK, AMX_REG_INFO, AMX_INFO_STACKTOP);
22.191 - IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, ((CompData *)jit->data)->jit_error_stackmin);
22.192 -}
22.193 -
22.194 -void Write_CheckStack_Low(JitWriter *jit)
22.195 -{
22.196 - /* Check if the stack went beyond the heap boundary.
22.197 - * Unfortunately this one isn't as quick as the other check.
22.198 - * The stack margin check is important for sysreq.n having space.
22.199 - */
22.200 - //mov ecx, [esi+info.heap]
22.201 - //lea ecx, [ebp+ecx+STACK_MARGIN]
22.202 - //cmp edi, ecx
22.203 - //jb :error ; I think this is right
22.204 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
22.205 - IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN);
22.206 - IA32_Cmp_Reg_Rm(jit, AMX_REG_STK, AMX_REG_TMP, MOD_REG);
22.207 - IA32_Jump_Cond_Imm32_Rel(jit, CC_B, ((CompData *)jit->data)->jit_error_stacklow);
22.208 -}
22.209 -
22.210 -void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
22.211 -{
22.212 - /* :TODO: Should this be checking for below heaplow?
22.213 - * The old JIT did not.
22.214 - */
22.215 -
22.216 - /**
22.217 - * :TODO: If we can't find a nicer way of doing this,
22.218 - * then scrap it on high optimizations. The second portion is not needed at all!
22.219 - */
22.220 -
22.221 - /* Part 1: Check if we're in the memory bounds */
22.222 - //cmp <reg>, <stpu>
22.223 - //jae :error
22.224 - IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->mem_size);
22.225 - IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
22.226 -
22.227 - /* Part 2: Check if we're in the invalid region between HP and SP */
22.228 - jitoffs_t jmp;
22.229 - //cmp <reg>, [esi+info.heap]
22.230 - //jb :continue
22.231 - //lea ecx, [ebp+<reg>]
22.232 - //cmp edi, ecx
22.233 - //jb :error
22.234 - //:continue
22.235 - IA32_Cmp_Reg_Rm_Disp8(jit, reg, AMX_REG_INFO, AMX_INFO_HEAP);
22.236 - jmp = IA32_Jump_Cond_Imm8(jit, CC_B, 0);
22.237 - IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, reg, NOSCALE, 0);
22.238 - IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
22.239 - IA32_Jump_Cond_Imm32_Rel(jit, CC_B, ((CompData *)jit->data)->jit_error_memaccess);
22.240 - IA32_Send_Jump8_Here(jit, jmp);
22.241 -}
22.242 -
22.243 -void Macro_PushN_Addr(JitWriter *jit, int i)
22.244 -{
22.245 - //push eax
22.246 - //mov eax, [esi+frm]
22.247 - //loop i times:
22.248 - // lea ecx, [eax+<val>]
22.249 - // mov [edi-4*i], ecx
22.250 - //sub edi, 4*N
22.251 - //pop eax
22.252 -
22.253 - cell_t val;
22.254 - int n = 1;
22.255 - IA32_Push_Reg(jit, AMX_REG_PRI);
22.256 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
22.257 - do
22.258 - {
22.259 - val = jit->read_cell();
22.260 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
22.261 - IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, (jit_int8_t)val);
22.262 - else
22.263 - IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, val);
22.264 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
22.265 - } while (n++ < i);
22.266 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
22.267 - IA32_Pop_Reg(jit, AMX_REG_PRI);
22.268 -}
22.269 -
22.270 -void Macro_PushN_S(JitWriter *jit, int i)
22.271 -{
22.272 - //loop i times:
22.273 - // mov ecx, [ebx+<val>]
22.274 - // mov [edi-4*i], ecx
22.275 - //sub edi, 4*N
22.276 -
22.277 - cell_t val;
22.278 - int n = 1;
22.279 - do
22.280 - {
22.281 - val = jit->read_cell();
22.282 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
22.283 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
22.284 - else
22.285 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
22.286 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
22.287 - } while (n++ < i);
22.288 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
22.289 -}
22.290 -
22.291 -void Macro_PushN_C(JitWriter *jit, int i)
22.292 -{
22.293 - //loop i times:
22.294 - // mov [edi-4*i], <val>
22.295 - //sub edi, 4*N
22.296 -
22.297 - int n = 1;
22.298 - do
22.299 - {
22.300 - IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, jit->read_cell(), -4*n);
22.301 - } while (n++ < i);
22.302 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
22.303 -}
22.304 -
22.305 -void Macro_PushN(JitWriter *jit, int i)
22.306 -{
22.307 - //loop i times:
22.308 - // mov ecx, [ebp+<val>]
22.309 - // mov [edi-4*i], ecx
22.310 - //sub edi, 4*N
22.311 -
22.312 - cell_t val;
22.313 - int n = 1;
22.314 - do
22.315 - {
22.316 - val = jit->read_cell();
22.317 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
22.318 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
22.319 - else
22.320 - IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
22.321 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
22.322 - } while (n++ < i);
22.323 - IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
22.324 -}
22.325 -
22.326 -void WriteOp_Sysreq_C_Function(JitWriter *jit)
22.327 -{
22.328 - /* The small daddy of the big daddy of opcodes.
22.329 - * ecx - native index
22.330 - */
22.331 - CompData *data = (CompData *)jit->data;
22.332 -
22.333 - /* save registers we will need */
22.334 - //push edx
22.335 - IA32_Push_Reg(jit, AMX_REG_ALT);
22.336 -
22.337 - /* Align the stack to 16 bytes */
22.338 - //push ebx
22.339 - //mov ebx, esp
22.340 - //and esp, 0xFFFFFF0
22.341 - //sub esp, 4
22.342 - IA32_Push_Reg(jit, REG_EBX);
22.343 - IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
22.344 - IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
22.345 - IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
22.346 -
22.347 - /* push some callback stuff */
22.348 - //push edi ; stack
22.349 - //push ecx ; native index
22.350 - IA32_Push_Reg(jit, AMX_REG_STK);
22.351 - IA32_Push_Reg(jit, REG_ECX);
22.352 -
22.353 - /* Relocate stack, heap, frm information, then store back */
22.354 - //mov eax, [esi+context]
22.355 - //mov ecx, [esi+hea]
22.356 - //sub edi, ebp
22.357 - //mov [eax+hp], ecx
22.358 - //mov ecx, [esi]
22.359 - //mov [eax+sp], edi
22.360 - //mov [eax+frm], ecx
22.361 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
22.362 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
22.363 - IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
22.364 - IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
22.365 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
22.366 - IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
22.367 - IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
22.368 -
22.369 - /* finally, push the last parameter and make the call */
22.370 - //push eax ; context
22.371 - //call NativeCallback
22.372 - IA32_Push_Reg(jit, REG_EAX);
22.373 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
22.374 - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
22.375 -
22.376 - /* Test for error */
22.377 - //mov ecx, [esi+context]
22.378 - //cmp [ecx+err], 0
22.379 - //jnz :error
22.380 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
22.381 - IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
22.382 - IA32_Jump_Cond_Imm32_Rel(jit, CC_NZ, data->jit_extern_error);
22.383 -
22.384 - /* restore what we damaged */
22.385 - //mov esp, ebx
22.386 - //pop ebx
22.387 - //add edi, ebp
22.388 - //pop edx
22.389 - IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
22.390 - IA32_Pop_Reg(jit, REG_EBX);
22.391 - IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
22.392 - IA32_Pop_Reg(jit, AMX_REG_ALT);
22.393 -
22.394 - //ret
22.395 - IA32_Return(jit);
22.396 -}
22.397 -
22.398 -typedef struct array_creation_s
22.399 -{
22.400 - const cell_t *dim_list; /* Dimension sizes */
22.401 - cell_t dim_count; /* Number of dimensions */
22.402 - cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */
22.403 - cell_t *base; /* array base */
22.404 -} array_creation_t;
22.405 -
22.406 -cell_t _GenerateArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs)
22.407 -{
22.408 - cell_t write_offs = cur_offs;
22.409 - cell_t *data_offs = ar->data_offs;
22.410 -
22.411 - cur_offs += ar->dim_list[dim];
22.412 -
22.413 - /**
22.414 - * Dimension n-x where x > 2 will have sub-vectors.
22.415 - * Otherwise, we just need to reference the data section.
22.416 - */
22.417 - if (ar->dim_count > 2 && dim < ar->dim_count - 2)
22.418 - {
22.419 - /**
22.420 - * For each index at this dimension, write offstes to our sub-vectors.
22.421 - * After we write one sub-vector, we generate its sub-vectors recursively.
22.422 - * At the end, we're given the next offset we can use.
22.423 - */
22.424 - for (int i = 0; i < ar->dim_list[dim]; i++)
22.425 - {
22.426 - ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t);
22.427 - write_offs++;
22.428 - cur_offs = _GenerateArrayIndirectionVectors(ar, dim + 1, cur_offs);
22.429 - }
22.430 - } else {
22.431 - /**
22.432 - * In this section, there are no sub-vectors, we need to write offsets
22.433 - * to the data. This is separate so the data stays in one big chunk.
22.434 - * The data offset will increment by the size of the last dimension,
22.435 - * because that is where the data is finally computed as.
22.436 - */
22.437 - for (int i = 0; i < ar->dim_list[dim]; i++)
22.438 - {
22.439 - ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t);
22.440 - write_offs++;
22.441 - *data_offs = *data_offs + ar->dim_list[dim + 1];
22.442 - }
22.443 - }
22.444 -
22.445 - return cur_offs;
22.446 -}
22.447 -
22.448 -static cell_t calc_indirection(const array_creation_t *ar, cell_t dim)
22.449 -{
22.450 - cell_t size = ar->dim_list[dim];
22.451 -
22.452 - if (dim < ar->dim_count - 2)
22.453 - {
22.454 - size += ar->dim_list[dim] * calc_indirection(ar, dim + 1);
22.455 - }
22.456 -
22.457 - return size;
22.458 -}
22.459 -
22.460 -void GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero)
22.461 -{
22.462 - array_creation_t ar;
22.463 - cell_t data_offs;
22.464 -
22.465 - /* Reverse the dimensions */
22.466 - cell_t dim_list[sDIMEN_MAX];
22.467 - int cur_dim = 0;
22.468 - for (int i = _dimcount - 1; i >= 0; i--)
22.469 - {
22.470 - dim_list[cur_dim++] = dims[i];
22.471 - }
22.472 -
22.473 - ar.base = arraybase;
22.474 - ar.dim_list = dim_list;
22.475 - ar.dim_count = _dimcount;
22.476 - ar.data_offs = &data_offs;
22.477 -
22.478 - data_offs = calc_indirection(&ar, 0);
22.479 -
22.480 - _GenerateArrayIndirectionVectors(&ar, 0, 0);
22.481 -}
22.482 -
22.483 -/**
22.484 - * A few notes about this function.
22.485 - * I was more concerned about efficient use of registers here, rather than
22.486 - * fine-tuned optimization. The reason is that the code is already complicated,
22.487 - * and it is very easy to mess up.
22.488 - */
22.489 -void WriteIntrinsic_GenArray(JitWriter *jit)
22.490 -{
22.491 - jitoffs_t err1, err2;
22.492 -
22.493 - /**
22.494 - * save important values
22.495 - */
22.496 - //push ebx
22.497 - //push eax
22.498 - //push edx
22.499 - //push ecx ;value is referenced on stack
22.500 - IA32_Push_Reg(jit, REG_EBX);
22.501 - IA32_Push_Reg(jit, REG_EAX);
22.502 - IA32_Push_Reg(jit, REG_EDX);
22.503 - IA32_Push_Reg(jit, REG_ECX);
22.504 -
22.505 - /**
22.506 - * Calculate how many cells will be needed.
22.507 - */
22.508 - //mov edx, [edi] ;get last dimension's count
22.509 - //mov eax, 1 ;position at second to last dimension
22.510 - //:loop
22.511 - //cmp eax, [esp] ;compare to # of params
22.512 - //jae :done ;end loop if done
22.513 - //mov ecx, [edi+eax*4] ;get dimension size
22.514 - //imul edx, ecx ;multiply by size
22.515 - //add eax, 1 ;increment
22.516 - //add edx, ecx ;add size (indirection vector)
22.517 - //jmp :loop ;jump back
22.518 - //:done
22.519 - IA32_Mov_Reg_Rm(jit, REG_EDX, AMX_REG_STK, MOD_MEM_REG);
22.520 - IA32_Mov_Reg_Imm32(jit, REG_EAX, 1);
22.521 - jitoffs_t loop1 = jit->get_outputpos();
22.522 - IA32_Cmp_Reg_Rm_ESP(jit, REG_EAX);
22.523 - jitoffs_t done1 = IA32_Jump_Cond_Imm8(jit, CC_AE, 0);
22.524 - IA32_Mov_Reg_Rm_Disp_Reg(jit, REG_ECX, AMX_REG_STK, REG_EAX, SCALE4);
22.525 - IA32_IMul_Reg_Rm(jit, REG_EDX, REG_ECX, MOD_REG);
22.526 - IA32_Add_Rm_Imm8(jit, REG_EAX, 1, MOD_REG);
22.527 - IA32_Add_Reg_Rm(jit, REG_EDX, REG_ECX, MOD_REG);
22.528 - IA32_Write_Jump8(jit, IA32_Jump_Imm8(jit, loop1), loop1);
22.529 - IA32_Send_Jump8_Here(jit, done1);
22.530 -
22.531 - /* Test if we have heap space for this */
22.532 - //mov eax, [esi+info.heap] ;get heap pointer
22.533 - //lea eax, [eax+edx*4] ;new heap pointer
22.534 - //cmp eax, [esi+info.datasz] ;compare to heap low
22.535 - //jbe :error ;die if we hit this (it should always be >)
22.536 - //add eax, ebp ;relocate to stack
22.537 - //cmp eax, edi ;die if above the stack pointer
22.538 - //jae :error
22.539 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP);
22.540 - IA32_Lea_Reg_DispRegMult(jit, REG_EAX, REG_EAX, REG_EDX, SCALE4);
22.541 - IA32_Cmp_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_DATASIZE);
22.542 - err1 = IA32_Jump_Cond_Imm32(jit, CC_BE, 0);
22.543 - IA32_Add_Reg_Rm(jit, REG_EAX, AMX_REG_DAT, MOD_REG);
22.544 - IA32_Cmp_Reg_Rm(jit, REG_EAX, AMX_REG_STK, MOD_REG);
22.545 - err2 = IA32_Jump_Cond_Imm32(jit, CC_AE, 0);
22.546 -
22.547 - /* Prepare for indirection iteration */
22.548 - //mov eax, [esi+info.heap] ;get heap pointer
22.549 - //lea ebx, [eax+edx*4] ;new heap pointer
22.550 - //mov [esi+info.heap], ebx ;store back
22.551 - //push eax ;save heap pointer - we need it
22.552 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP);
22.553 - IA32_Lea_Reg_DispRegMult(jit, REG_EBX, REG_EAX, REG_EDX, SCALE4);
22.554 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EBX, AMX_INFO_HEAP);
22.555 - IA32_Push_Reg(jit, REG_EAX);
22.556 -
22.557 - WriteOp_Tracker_Push_Reg(jit, REG_EDX);
22.558 -
22.559 - /* This part is too messy to do in straight assembly.
22.560 - * I'm letting the compiler handle it and thus it's in C.
22.561 - */
22.562 - //lea ebx, [ebp+eax] ;get base pointer
22.563 - //push dword [esp-8] ;push autozero
22.564 - //push dword [esp-8] ;push dimension count
22.565 - //push edi ;push dim array
22.566 - //push ebx
22.567 - //call GenerateArrayIndirectionVectors
22.568 - //add esp, 4*4
22.569 - IA32_Lea_Reg_DispRegMult(jit, REG_EBX, REG_EAX, REG_EBP, NOSCALE);
22.570 - IA32_Push_Rm_Disp8_ESP(jit, 8);
22.571 - IA32_Push_Rm_Disp8_ESP(jit, 8);
22.572 - IA32_Push_Reg(jit, REG_EDI);
22.573 - IA32_Push_Reg(jit, REG_EBX);
22.574 - IA32_Write_Jump32_Abs(jit, IA32_Call_Imm32(jit, 0), (void *)&GenerateArrayIndirectionVectors);
22.575 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4*4, MOD_REG);
22.576 -
22.577 - /* Store the heap pointer back into the stack */
22.578 - //pop eax ;restore heap pointer
22.579 - //pop ecx ;restore param count
22.580 - //lea edi, [edi+ecx*4-4] ;pop params-4 off the stack
22.581 - //mov [edi], eax ;store back the heap pointer
22.582 - IA32_Pop_Reg(jit, REG_EAX);
22.583 - IA32_Pop_Reg(jit, REG_ECX);
22.584 - IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, REG_ECX, SCALE4, -4);
22.585 - IA32_Mov_Rm_Reg(jit, AMX_REG_STK, REG_EAX, MOD_MEM_REG);
22.586 -
22.587 - /* Return to caller */
22.588 - //pop edx
22.589 - //pop eax
22.590 - //pop ebx
22.591 - //ret
22.592 - IA32_Pop_Reg(jit, REG_ECX);
22.593 - IA32_Pop_Reg(jit, REG_EAX);
22.594 - IA32_Pop_Reg(jit, REG_EBX);
22.595 - IA32_Return(jit);
22.596 -
22.597 - //:error
22.598 - IA32_Send_Jump32_Here(jit, err1);
22.599 - IA32_Send_Jump32_Here(jit, err2);
22.600 - Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG);
22.601 -}
22.602 -
22.603 -void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg)
22.604 -{
22.605 - /* Save registers that may be damaged by the call */
22.606 - //push eax
22.607 - //push ecx
22.608 - //push edi
22.609 - //lea edi, [<reg>*4] ; we want the count in bytes not in cells
22.610 - IA32_Push_Reg(jit, AMX_REG_PRI);
22.611 - if (reg == REG_ECX)
22.612 - {
22.613 - IA32_Push_Reg(jit, AMX_REG_TMP);
22.614 - }
22.615 - IA32_Push_Reg(jit, AMX_REG_STK);
22.616 - IA32_Lea_Reg_RegMultImm32(jit, REG_EDI, reg, SCALE4, 0);
22.617 -
22.618 - /* Get the context ptr, push it and call the check */
22.619 - //mov eax, [esi+context]
22.620 - //push eax
22.621 - //call JIT_VerifyOrAllocateTracker
22.622 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
22.623 - IA32_Push_Reg(jit, REG_EAX);
22.624 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
22.625 - IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
22.626 -
22.627 - /* Check for errors */
22.628 - //cmp eax, 0
22.629 - //jnz :error
22.630 - IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
22.631 - IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, g_Jit.GetReturnPoint());
22.632 -
22.633 - /* Restore */
22.634 - //pop eax
22.635 - IA32_Pop_Reg(jit, REG_EAX);
22.636 -
22.637 - /* Push the register into the stack and increment pCur */
22.638 - //mov edx, [eax+vm[]]
22.639 - //mov eax, [edx+pcur]
22.640 - //add [edx+pcur], 4
22.641 - //mov [eax], edi
22.642 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
22.643 - IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EDX, offsetof(tracker_t, pCur));
22.644 - IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
22.645 - IA32_Mov_Rm_Reg(jit, REG_EAX, REG_EDI, MOD_MEM_REG);
22.646 -
22.647 - /* Restore PRI, ALT and STK */
22.648 - //pop edi
22.649 - //pop ecx
22.650 - //pop eax
22.651 - IA32_Pop_Reg(jit, AMX_REG_STK);
22.652 - if (reg == REG_ECX)
22.653 - {
22.654 - IA32_Pop_Reg(jit, AMX_REG_TMP);
22.655 - }
22.656 - IA32_Pop_Reg(jit, AMX_REG_PRI);
22.657 -}
22.658 -
22.659 -int JIT_VerifyOrAllocateTracker(sp_context_t *ctx)
22.660 -{
22.661 - tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
22.662 -
22.663 - if ((size_t)(trk->pCur - trk->pBase) >= trk->size)
22.664 - {
22.665 - return SP_ERROR_TRACKER_BOUNDS;
22.666 - }
22.667 -
22.668 - if (trk->pCur+1 - (trk->pBase + trk->size) == 0)
22.669 - {
22.670 - size_t disp = trk->size - 1;
22.671 - trk->size *= 2;
22.672 - trk->pBase = (ucell_t *)realloc(trk->pBase, trk->size * sizeof(cell_t));
22.673 -
22.674 - if (!trk->pBase)
22.675 - {
22.676 - return SP_ERROR_TRACKER_BOUNDS;
22.677 - }
22.678 -
22.679 - trk->pCur = trk->pBase + disp;
22.680 - }
22.681 -
22.682 - return SP_ERROR_NONE;
22.683 -}
22.684 -
22.685 -int JIT_VerifyLowBoundTracker(sp_context_t *ctx)
22.686 -{
22.687 - tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
22.688 -
22.689 - if (trk->pCur <= trk->pBase)
22.690 - {
22.691 - return SP_ERROR_TRACKER_BOUNDS;
22.692 - }
22.693 -
22.694 - return SP_ERROR_NONE;
22.695 -}
22.696 -
22.697 -void AlignMe(JitWriter *jit)
22.698 -{
22.699 - jitoffs_t cur_offs = jit->get_outputpos();
22.700 - jitoffs_t offset = ((cur_offs & 0xFFFFFFF0) + 16) - cur_offs;
22.701 -
22.702 - if (offset)
22.703 - {
22.704 - for (jit_uint32_t i=0; i<offset; i++)
22.705 - {
22.706 - jit->write_ubyte(IA32_INT3);
22.707 - }
22.708 - }
22.709 -}
23.1 --- a/sourcepawn/jit/x86/opcode_helpers.h Thu Aug 08 09:40:23 2013 -0700
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,317 +0,0 @@
23.4 -/**
23.5 - * vim: set ts=4 :
23.6 - * =============================================================================
23.7 - * SourceMod
23.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
23.9 - * =============================================================================
23.10 - *
23.11 - * This program is free software; you can redistribute it and/or modify it under
23.12 - * the terms of the GNU General Public License, version 3.0, as published by the
23.13 - * Free Software Foundation.
23.14 - *
23.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
23.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
23.18 - * details.
23.19 - *
23.20 - * You should have received a copy of the GNU General Public License along with
23.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
23.22 - *
23.23 - * As a special exception, AlliedModders LLC gives you permission to link the
23.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
23.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23.26 - * by the Valve Corporation. You must obey the GNU General Public License in
23.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
23.28 - * this exception to all derivative works. AlliedModders LLC defines further
23.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
23.30 - * or <http://www.sourcemod.net/license.php>.
23.31 - *
23.32 - * Version: $Id$
23.33 - */
23.34 -
23.35 -#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
23.36 -#define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
23.37 -
23.38 -#include "../jit_helpers.h"
23.39 -
23.40 -/**
23.41 - * This outputs the execution function for a plugin.
23.42 - * It also returns the 'return' offset, which is used for
23.43 - * breaking out of the JIT during runtime.
23.44 - */
23.45 -jitoffs_t Write_Execute_Function(JitWriter *jit);
23.46 -
23.47 -/**
23.48 - * Writes the Sysreq.* opcodes as a function call.
23.49 - */
23.50 -void WriteOp_Sysreq_C_Function(JitWriter *jit);
23.51 -
23.52 -/**
23.53 - * Write the GENARRAY intrinsic function.
23.54 - */
23.55 -void WriteIntrinsic_GenArray(JitWriter *jit);
23.56 -
23.57 -void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg);
23.58 -
23.59 -/**
23.60 - * Generates code to set an error state in the VM and return.
23.61 - * This is used for generating the error set points in the VM.
23.62 - * GetError writes the error from the context. SetError hardcodes.
23.63 - */
23.64 -void Write_GetError(JitWriter *jit);
23.65 -void Write_SetError(JitWriter *jit, int error);
23.66 -
23.67 -/**
23.68 - * Checks the stacks for min and low errors.
23.69 - * :TODO: Should a variation of this go in the pushN opcodes?
23.70 - */
23.71 -void Write_CheckStack_Min(JitWriter *jit);
23.72 -void Write_CheckStack_Low(JitWriter *jit);
23.73 -
23.74 -/**
23.75 - * Checks the heap for min and low errors.
23.76 - */
23.77 -void Write_CheckHeap_Min(JitWriter *jit);
23.78 -void Write_CheckHeap_Low(JitWriter *jit);
23.79 -
23.80 -/**
23.81 - * Checks for division by zero.
23.82 - */
23.83 -void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg);
23.84 -
23.85 -/**
23.86 - * Writes the break debug function.
23.87 - */
23.88 -void Write_BreakDebug(JitWriter *jit);
23.89 -
23.90 -/**
23.91 - * These are for writing the PushN opcodes.
23.92 - */
23.93 -void Macro_PushN_Addr(JitWriter *jit, int i);
23.94 -void Macro_PushN_S(JitWriter *jit, int i);
23.95 -void Macro_PushN_C(JitWriter *jit, int i);
23.96 -void Macro_PushN(JitWriter *jit, int i);
23.97 -
23.98 -/**
23.99 -* Bound checking for the tracker stack,
23.100 -*/
23.101 -int JIT_VerifyLowBoundTracker(sp_context_t *ctx);
23.102 -int JIT_VerifyOrAllocateTracker(sp_context_t *ctx);
23.103 -
23.104 -/**
23.105 -* Writes the push into tracker function.
23.106 -*/
23.107 -void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg);
23.108 -
23.109 -/**
23.110 -* Writes the rounding table for the float compare opcode.
23.111 -*/
23.112 -void Write_RoundingTable(JitWriter *jit);
23.113 -
23.114 -/**
23.115 -* Aligns the current code position to 16 bytes.
23.116 -*/
23.117 -void AlignMe(JitWriter *jit);
23.118 -
23.119 -/**
23.120 - * Legend for Statuses:
23.121 - * ****** *** ********
23.122 - * DONE -> code generation is done
23.123 - * !GEN -> code generation is deliberate skipped because:
23.124 - * (default): compiler does not generate
23.125 - * DEPRECATED: this feature no longer exists/supported
23.126 - * UNSUPPORTED: this opcode is not supported
23.127 - * TODO: done in case needed
23.128 - * VERIFIED -> code generation is checked as run-time working. prefixes:
23.129 - * ! errors are not checked yet.
23.130 - * - non-inline errors are not checked yet.
23.131 - * ~ assumed checked because of related variation, but not actually checked
23.132 - */
23.133 -
23.134 -typedef enum
23.135 -{
23.136 - OP_NONE, /* invalid opcode */
23.137 - OP_LOAD_PRI, //!VERIFIED
23.138 - OP_LOAD_ALT, //~!VERIFIED (load.pri)
23.139 - OP_LOAD_S_PRI, //VERIFIED
23.140 - OP_LOAD_S_ALT, //VERIFIED
23.141 - OP_LREF_PRI, //VERIFIED
23.142 - OP_LREF_ALT, //~VERIFIED
23.143 - OP_LREF_S_PRI, //VERIFIED
23.144 - OP_LREF_S_ALT, //~VERIFIED (lref.s.pri)
23.145 - OP_LOAD_I, //VERIFIED
23.146 - OP_LODB_I, //VERIFIED
23.147 - OP_CONST_PRI, //VERIFIED
23.148 - OP_CONST_ALT, //~VERIFIED (const.pri)
23.149 - OP_ADDR_PRI, //VERIFIED
23.150 - OP_ADDR_ALT, //VERIFIED
23.151 - OP_STOR_PRI, //VERIFIED
23.152 - OP_STOR_ALT, //~VERIFIED (stor.pri)
23.153 - OP_STOR_S_PRI, //VERIFIED
23.154 - OP_STOR_S_ALT, //~VERIFIED (stor.s.pri)
23.155 - OP_SREF_PRI, //VERIFIED
23.156 - OP_SREF_ALT, //~VERIFIED
23.157 - OP_SREF_S_PRI, //VERIFIED
23.158 - OP_SREF_S_ALT, //~VERIFIED (stor.s.alt)
23.159 - OP_STOR_I, //VERIFIED
23.160 - OP_STRB_I, //VERIFIED
23.161 - OP_LIDX, //VERIFIED
23.162 - OP_LIDX_B, //DONE
23.163 - OP_IDXADDR, //VERIFIED
23.164 - OP_IDXADDR_B, //DONE
23.165 - OP_ALIGN_PRI, // !GEN :TODO: - only used for pack access, drop support in compiler first
23.166 - OP_ALIGN_ALT, // !GEN :TODO: - only used for pack access, drop support in compiler first
23.167 - OP_LCTRL, // !GEN
23.168 - OP_SCTRL, // !GEN
23.169 - OP_MOVE_PRI, //~VERIFIED (move.alt)
23.170 - OP_MOVE_ALT, //VERIFIED
23.171 - OP_XCHG, //DONE
23.172 - OP_PUSH_PRI, //DONE
23.173 - OP_PUSH_ALT, //DONE
23.174 - OP_PUSH_R, // !GEN DEPRECATED
23.175 - OP_PUSH_C, //VERIFIED
23.176 - OP_PUSH, //DONE
23.177 - OP_PUSH_S, //VERIFIED
23.178 - OP_POP_PRI, //VERIFIED
23.179 - OP_POP_ALT, //VERIFIED
23.180 - OP_STACK, //VERIFIED
23.181 - OP_HEAP, //VERIFIED
23.182 - OP_PROC, //VERIFIED
23.183 - OP_RET, // !GEN
23.184 - OP_RETN, //VERIFIED
23.185 - OP_CALL, //VERIFIED
23.186 - OP_CALL_PRI, // !GEN
23.187 - OP_JUMP, //VERIFIED
23.188 - OP_JREL, // !GEN
23.189 - OP_JZER, //VERIFIED
23.190 - OP_JNZ, //DONE
23.191 - OP_JEQ, //VERIFIED
23.192 - OP_JNEQ, //VERIFIED
23.193 - OP_JLESS, // !GEN
23.194 - OP_JLEQ, // !GEN
23.195 - OP_JGRTR, // !GEN
23.196 - OP_JGEQ, // !GEN
23.197 - OP_JSLESS, //VERIFIED
23.198 - OP_JSLEQ, //VERIFIED
23.199 - OP_JSGRTR, //VERIFIED
23.200 - OP_JSGEQ, //VERIFIED
23.201 - OP_SHL, //VERIFIED
23.202 - OP_SHR, //VERIFIED (Note: operator >>>)
23.203 - OP_SSHR, //VERIFIED (Note: operator >>)
23.204 - OP_SHL_C_PRI, //DONE
23.205 - OP_SHL_C_ALT, //DONE
23.206 - OP_SHR_C_PRI, //DONE
23.207 - OP_SHR_C_ALT, //DONE
23.208 - OP_SMUL, //VERIFIED
23.209 - OP_SDIV, //DONE
23.210 - OP_SDIV_ALT, //VERIFIED
23.211 - OP_UMUL, // !GEN
23.212 - OP_UDIV, // !GEN
23.213 - OP_UDIV_ALT, // !GEN
23.214 - OP_ADD, //VERIFIED
23.215 - OP_SUB, //DONE
23.216 - OP_SUB_ALT, //VERIFIED
23.217 - OP_AND, //VERIFIED
23.218 - OP_OR, //VERIFIED
23.219 - OP_XOR, //VERIFIED
23.220 - OP_NOT, //VERIFIED
23.221 - OP_NEG, //VERIFIED
23.222 - OP_INVERT, //VERIFIED
23.223 - OP_ADD_C, //VERIFIED
23.224 - OP_SMUL_C, //VERIFIED
23.225 - OP_ZERO_PRI, //VERIFIED
23.226 - OP_ZERO_ALT, //~VERIFIED
23.227 - OP_ZERO, //VERIFIED
23.228 - OP_ZERO_S, //VERIFIED
23.229 - OP_SIGN_PRI, //DONE
23.230 - OP_SIGN_ALT, //DONE
23.231 - OP_EQ, //VERIFIED
23.232 - OP_NEQ, //VERIFIED
23.233 - OP_LESS, // !GEN
23.234 - OP_LEQ, // !GEN
23.235 - OP_GRTR, // !GEN
23.236 - OP_GEQ, // !GEN
23.237 - OP_SLESS, //VERIFIED
23.238 - OP_SLEQ, //VERIFIED
23.239 - OP_SGRTR, //VERIFIED
23.240 - OP_SGEQ, //VERIFIED
23.241 - OP_EQ_C_PRI, //DONE
23.242 - OP_EQ_C_ALT, //DONE
23.243 - OP_INC_PRI, //VERIFIED
23.244 - OP_INC_ALT, //~VERIFIED (inc.pri)
23.245 - OP_INC, //VERIFIED
23.246 - OP_INC_S, //VERIFIED
23.247 - OP_INC_I, //VERIFIED
23.248 - OP_DEC_PRI, //VERIFIED
23.249 - OP_DEC_ALT, //~VERIFIED (dec.pri)
23.250 - OP_DEC, //VERIFIED
23.251 - OP_DEC_S, //VERIFIED
23.252 - OP_DEC_I, //VERIFIED
23.253 - OP_MOVS, //VERIFIED
23.254 - OP_CMPS, // !GEN
23.255 - OP_FILL, //VERIFIED
23.256 - OP_HALT, //DONE
23.257 - OP_BOUNDS, //VERIFIED
23.258 - OP_SYSREQ_PRI, // !GEN
23.259 - OP_SYSREQ_C, //VERIFIED
23.260 - OP_FILE, // !GEN DEPRECATED
23.261 - OP_LINE, // !GEN DEPRECATED
23.262 - OP_SYMBOL, // !GEN DEPRECATED
23.263 - OP_SRANGE, // !GEN DEPRECATED
23.264 - OP_JUMP_PRI, // !GEN
23.265 - OP_SWITCH, //VERIFIED
23.266 - OP_CASETBL, //VERIFIED
23.267 - OP_SWAP_PRI, //VERIFIED
23.268 - OP_SWAP_ALT, //~VERIFIED (swap.alt)
23.269 - OP_PUSH_ADR, //VERIFIED
23.270 - OP_NOP, //VERIFIED (lol)
23.271 - OP_SYSREQ_N, //VERIFIED
23.272 - OP_SYMTAG, // !GEN DEPRECATED
23.273 - OP_BREAK, //DONE
23.274 - OP_PUSH2_C, //~VERIFIED (push3.c)
23.275 - OP_PUSH2, //VERIFIED
23.276 - OP_PUSH2_S, //VERIFIED
23.277 - OP_PUSH2_ADR, //VERIFIED
23.278 - OP_PUSH3_C, //VERIFIED
23.279 - OP_PUSH3, //~VERIFIED (push2)
23.280 - OP_PUSH3_S, //~VERIFIED (push2.s)
23.281 - OP_PUSH3_ADR, //~VERIFIED (push2.adr)
23.282 - OP_PUSH4_C, //~VERIFIED (push3.c)
23.283 - OP_PUSH4, //~VERIFIED (push2)
23.284 - OP_PUSH4_S, //~VERIFIED (push2.s)
23.285 - OP_PUSH4_ADR, //~VERIFIED (push2.adr)
23.286 - OP_PUSH5_C, //~VERIFIED (push3.c)
23.287 - OP_PUSH5, //~VERIFIED (push2)
23.288 - OP_PUSH5_S, //~VERIFIED (push2.s)
23.289 - OP_PUSH5_ADR, //~VERIFIED (push2.adr)
23.290 - OP_LOAD_BOTH, //VERIFIED
23.291 - OP_LOAD_S_BOTH, //VERIFIED
23.292 - OP_CONST, //VERIFIED
23.293 - OP_CONST_S, //DONE
23.294 - /* ----- */
23.295 - OP_SYSREQ_D, // !GEN UNSUPPORT
23.296 - OP_SYSREQ_ND, // !GEN UNSUPPORT
23.297 - /* ----- */
23.298 - OP_TRACKER_PUSH_C, //DONE
23.299 - OP_TRACKER_POP_SETHEAP, //VERIFIED
23.300 - OP_GENARRAY, //VERIFIED
23.301 - OP_GENARRAY_Z, //-VERIFIED (not tested for 1D arrays)
23.302 - OP_STRADJUST_PRI, //VERIFIED
23.303 - OP_STACKADJUST, //:TODO: VERIFY
23.304 - OP_ENDPROC, //VERIFIED
23.305 - OP_FABS, //VERIFIED
23.306 - OP_FLOAT, //VERIFIED
23.307 - OP_FLOATADD, //VERIFIED
23.308 - OP_FLOATSUB, //VERIFIED
23.309 - OP_FLOATMUL, //VERIFIED
23.310 - OP_FLOATDIV, //VERIFIED
23.311 - OP_RND_TO_NEAREST, //VERIFIED
23.312 - OP_RND_TO_FLOOR, //VERIFIED
23.313 - OP_RND_TO_CEIL, //VERIFIED
23.314 - OP_RND_TO_ZERO, //VERIFIED
23.315 - OP_FLOATCMP, //VERIFIED
23.316 - /* ----- */
23.317 - OP_NUM_OPCODES
23.318 -} OPCODE;
23.319 -
23.320 -#endif //_INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
24.1 --- a/sourcepawn/jit/x86/opcode_switch.inc Thu Aug 08 09:40:23 2013 -0700
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,779 +0,0 @@
24.4 -/**
24.5 - * vim: set ts=4 :
24.6 - * =============================================================================
24.7 - * SourceMod
24.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
24.9 - * =============================================================================
24.10 - *
24.11 - * This program is free software; you can redistribute it and/or modify it under
24.12 - * the terms of the GNU General Public License, version 3.0, as published by the
24.13 - * Free Software Foundation.
24.14 - *
24.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
24.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
24.18 - * details.
24.19 - *
24.20 - * You should have received a copy of the GNU General Public License along with
24.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
24.22 - *
24.23 - * As a special exception, AlliedModders LLC gives you permission to link the
24.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
24.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
24.26 - * by the Valve Corporation. You must obey the GNU General Public License in
24.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
24.28 - * this exception to all derivative works. AlliedModders LLC defines further
24.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
24.30 - * or <http://www.sourcemod.net/license.php>.
24.31 - *
24.32 - * Version: $Id$
24.33 - */
24.34 -
24.35 - case OP_MOVE_PRI:
24.36 - {
24.37 - WriteOp_Move_Pri(jit);
24.38 - break;
24.39 - }
24.40 - case OP_MOVE_ALT:
24.41 - {
24.42 - WriteOp_Move_Alt(jit);
24.43 - break;
24.44 - }
24.45 - case OP_XCHG:
24.46 - {
24.47 - WriteOp_Xchg(jit);
24.48 - break;
24.49 - }
24.50 - case OP_PUSH:
24.51 - {
24.52 - WriteOp_Push(jit);
24.53 - break;
24.54 - }
24.55 - case OP_PUSH_S:
24.56 - {
24.57 - WriteOp_Push_S(jit);
24.58 - break;
24.59 - }
24.60 - case OP_PUSH2_C:
24.61 - {
24.62 - WriteOp_Push2_C(jit);
24.63 - break;
24.64 - }
24.65 - case OP_PUSH3_C:
24.66 - {
24.67 - WriteOp_Push3_C(jit);
24.68 - break;
24.69 - }
24.70 - case OP_PUSH4_C:
24.71 - {
24.72 - WriteOp_Push4_C(jit);
24.73 - break;
24.74 - }
24.75 - case OP_PUSH5_C:
24.76 - {
24.77 - WriteOp_Push5_C(jit);
24.78 - break;
24.79 - }
24.80 - case OP_PUSH2_ADR:
24.81 - {
24.82 - WriteOp_Push2_Adr(jit);
24.83 - break;
24.84 - }
24.85 - case OP_PUSH3_ADR:
24.86 - {
24.87 - WriteOp_Push3_Adr(jit);
24.88 - break;
24.89 - }
24.90 - case OP_PUSH4_ADR:
24.91 - {
24.92 - WriteOp_Push4_Adr(jit);
24.93 - break;
24.94 - }
24.95 - case OP_PUSH5_ADR:
24.96 - {
24.97 - WriteOp_Push5_Adr(jit);
24.98 - break;
24.99 - }
24.100 - case OP_PUSH2_S:
24.101 - {
24.102 - WriteOp_Push2_S(jit);
24.103 - break;
24.104 - }
24.105 - case OP_PUSH3_S:
24.106 - {
24.107 - WriteOp_Push3_S(jit);
24.108 - break;
24.109 - }
24.110 - case OP_PUSH4_S:
24.111 - {
24.112 - WriteOp_Push4_S(jit);
24.113 - break;
24.114 - }
24.115 - case OP_PUSH5_S:
24.116 - {
24.117 - WriteOp_Push5_S(jit);
24.118 - break;
24.119 - }
24.120 - case OP_PUSH5:
24.121 - {
24.122 - WriteOp_Push5(jit);
24.123 - break;
24.124 - }
24.125 - case OP_PUSH4:
24.126 - {
24.127 - WriteOp_Push4(jit);
24.128 - break;
24.129 - }
24.130 - case OP_PUSH3:
24.131 - {
24.132 - WriteOp_Push3(jit);
24.133 - break;
24.134 - }
24.135 - case OP_PUSH2:
24.136 - {
24.137 - WriteOp_Push2(jit);
24.138 - break;
24.139 - }
24.140 - case OP_ZERO_PRI:
24.141 - {
24.142 - WriteOp_Zero_Pri(jit);
24.143 - break;
24.144 - }
24.145 - case OP_ZERO_ALT:
24.146 - {
24.147 - WriteOp_Zero_Alt(jit);
24.148 - break;
24.149 - }
24.150 - case OP_PROC:
24.151 - {
24.152 - WriteOp_Proc(jit);
24.153 - break;
24.154 - }
24.155 - case OP_SHL:
24.156 - {
24.157 - WriteOp_Shl(jit);
24.158 - break;
24.159 - }
24.160 - case OP_SHR:
24.161 - {
24.162 - WriteOp_Shr(jit);
24.163 - break;
24.164 - }
24.165 - case OP_SSHR:
24.166 - {
24.167 - WriteOp_Sshr(jit);
24.168 - break;
24.169 - }
24.170 - case OP_SHL_C_PRI:
24.171 - {
24.172 - WriteOp_Shl_C_Pri(jit);
24.173 - break;
24.174 - }
24.175 - case OP_SHL_C_ALT:
24.176 - {
24.177 - WriteOp_Shl_C_Alt(jit);
24.178 - break;
24.179 - }
24.180 - case OP_SHR_C_PRI:
24.181 - {
24.182 - WriteOp_Shr_C_Pri(jit);
24.183 - break;
24.184 - }
24.185 - case OP_SHR_C_ALT:
24.186 - {
24.187 - WriteOp_Shr_C_Alt(jit);
24.188 - break;
24.189 - }
24.190 - case OP_SMUL:
24.191 - {
24.192 - WriteOp_SMul(jit);
24.193 - break;
24.194 - }
24.195 - case OP_ADD:
24.196 - {
24.197 - WriteOp_Add(jit);
24.198 - break;
24.199 - }
24.200 - case OP_SUB:
24.201 - {
24.202 - WriteOp_Sub(jit);
24.203 - break;
24.204 - }
24.205 - case OP_SUB_ALT:
24.206 - {
24.207 - WriteOp_Sub_Alt(jit);
24.208 - break;
24.209 - }
24.210 - case OP_NOP:
24.211 - {
24.212 - /* do nothing */
24.213 - break;
24.214 - }
24.215 - case OP_NOT:
24.216 - {
24.217 - WriteOp_Not(jit);
24.218 - break;
24.219 - }
24.220 - case OP_NEG:
24.221 - {
24.222 - WriteOp_Neg(jit);
24.223 - break;
24.224 - }
24.225 - case OP_XOR:
24.226 - {
24.227 - WriteOp_Xor(jit);
24.228 - break;
24.229 - }
24.230 - case OP_OR:
24.231 - {
24.232 - WriteOp_Or(jit);
24.233 - break;
24.234 - }
24.235 - case OP_AND:
24.236 - {
24.237 - WriteOp_And(jit);
24.238 - break;
24.239 - }
24.240 - case OP_INVERT:
24.241 - {
24.242 - WriteOp_Invert(jit);
24.243 - break;
24.244 - }
24.245 - case OP_ADD_C:
24.246 - {
24.247 - WriteOp_Add_C(jit);
24.248 - break;
24.249 - }
24.250 - case OP_SMUL_C:
24.251 - {
24.252 - WriteOp_SMul_C(jit);
24.253 - break;
24.254 - }
24.255 - case OP_SIGN_PRI:
24.256 - {
24.257 - WriteOp_Sign_Pri(jit);
24.258 - break;
24.259 - }
24.260 - case OP_SIGN_ALT:
24.261 - {
24.262 - WriteOp_Sign_Alt(jit);
24.263 - break;
24.264 - }
24.265 - case OP_EQ:
24.266 - {
24.267 - WriteOp_Eq(jit);
24.268 - break;
24.269 - }
24.270 - case OP_NEQ:
24.271 - {
24.272 - WriteOp_Neq(jit);
24.273 - break;
24.274 - }
24.275 - case OP_SLESS:
24.276 - {
24.277 - WriteOp_Sless(jit);
24.278 - break;
24.279 - }
24.280 - case OP_SLEQ:
24.281 - {
24.282 - WriteOp_Sleq(jit);
24.283 - break;
24.284 - }
24.285 - case OP_SGRTR:
24.286 - {
24.287 - WriteOp_Sgrtr(jit);
24.288 - break;
24.289 - }
24.290 - case OP_SGEQ:
24.291 - {
24.292 - WriteOp_Sgeq(jit);
24.293 - break;
24.294 - }
24.295 - case OP_EQ_C_PRI:
24.296 - {
24.297 - WriteOp_Eq_C_Pri(jit);
24.298 - break;
24.299 - }
24.300 - case OP_EQ_C_ALT:
24.301 - {
24.302 - WriteOp_Eq_C_Alt(jit);
24.303 - break;
24.304 - }
24.305 - case OP_INC_PRI:
24.306 - {
24.307 - WriteOp_Inc_Pri(jit);
24.308 - break;
24.309 - }
24.310 - case OP_INC_ALT:
24.311 - {
24.312 - WriteOp_Inc_Alt(jit);
24.313 - break;
24.314 - }
24.315 - case OP_INC:
24.316 - {
24.317 - WriteOp_Inc(jit);
24.318 - break;
24.319 - }
24.320 - case OP_INC_S:
24.321 - {
24.322 - WriteOp_Inc_S(jit);
24.323 - break;
24.324 - }
24.325 - case OP_INC_I:
24.326 - {
24.327 - WriteOp_Inc_I(jit);
24.328 - break;
24.329 - }
24.330 - case OP_DEC_PRI:
24.331 - {
24.332 - WriteOp_Dec_Pri(jit);
24.333 - break;
24.334 - }
24.335 - case OP_DEC_ALT:
24.336 - {
24.337 - WriteOp_Dec_Alt(jit);
24.338 - break;
24.339 - }
24.340 - case OP_DEC:
24.341 - {
24.342 - WriteOp_Dec(jit);
24.343 - break;
24.344 - }
24.345 - case OP_DEC_S:
24.346 - {
24.347 - WriteOp_Dec_S(jit);
24.348 - break;
24.349 - }
24.350 - case OP_DEC_I:
24.351 - {
24.352 - WriteOp_Dec_I(jit);
24.353 - break;
24.354 - }
24.355 - case OP_LOAD_PRI:
24.356 - {
24.357 - WriteOp_Load_Pri(jit);
24.358 - break;
24.359 - }
24.360 - case OP_LOAD_ALT:
24.361 - {
24.362 - WriteOp_Load_Alt(jit);
24.363 - break;
24.364 - }
24.365 - case OP_LOAD_S_PRI:
24.366 - {
24.367 - WriteOp_Load_S_Pri(jit);
24.368 - break;
24.369 - }
24.370 - case OP_LOAD_S_ALT:
24.371 - {
24.372 - WriteOp_Load_S_Alt(jit);
24.373 - break;
24.374 - }
24.375 - case OP_LREF_PRI:
24.376 - {
24.377 - WriteOp_Lref_Pri(jit);
24.378 - break;
24.379 - }
24.380 - case OP_LREF_ALT:
24.381 - {
24.382 - WriteOp_Lref_Alt(jit);
24.383 - break;
24.384 - }
24.385 - case OP_LREF_S_PRI:
24.386 - {
24.387 - WriteOp_Lref_S_Pri(jit);
24.388 - break;
24.389 - }
24.390 - case OP_LREF_S_ALT:
24.391 - {
24.392 - WriteOp_Lref_S_Alt(jit);
24.393 - break;
24.394 - }
24.395 - case OP_CONST_PRI:
24.396 - {
24.397 - WriteOp_Const_Pri(jit);
24.398 - break;
24.399 - }
24.400 - case OP_CONST_ALT:
24.401 - {
24.402 - WriteOp_Const_Alt(jit);
24.403 - break;
24.404 - }
24.405 - case OP_ADDR_PRI:
24.406 - {
24.407 - WriteOp_Addr_Pri(jit);
24.408 - break;
24.409 - }
24.410 - case OP_ADDR_ALT:
24.411 - {
24.412 - WriteOp_Addr_Alt(jit);
24.413 - break;
24.414 - }
24.415 - case OP_STOR_PRI:
24.416 - {
24.417 - WriteOp_Stor_Pri(jit);
24.418 - break;
24.419 - }
24.420 - case OP_STOR_ALT:
24.421 - {
24.422 - WriteOp_Stor_Alt(jit);
24.423 - break;
24.424 - }
24.425 - case OP_STOR_S_PRI:
24.426 - {
24.427 - WriteOp_Stor_S_Pri(jit);
24.428 - break;
24.429 - }
24.430 - case OP_STOR_S_ALT:
24.431 - {
24.432 - WriteOp_Stor_S_Alt(jit);
24.433 - break;
24.434 - }
24.435 - case OP_IDXADDR:
24.436 - {
24.437 - WriteOp_Idxaddr(jit);
24.438 - break;
24.439 - }
24.440 - case OP_SREF_PRI:
24.441 - {
24.442 - WriteOp_Sref_Pri(jit);
24.443 - break;
24.444 - }
24.445 - case OP_SREF_ALT:
24.446 - {
24.447 - WriteOp_Sref_Alt(jit);
24.448 - break;
24.449 - }
24.450 - case OP_SREF_S_PRI:
24.451 - {
24.452 - WriteOp_Sref_S_Pri(jit);
24.453 - break;
24.454 - }
24.455 - case OP_SREF_S_ALT:
24.456 - {
24.457 - WriteOp_Sref_S_Alt(jit);
24.458 - break;
24.459 - }
24.460 - case OP_POP_PRI:
24.461 - {
24.462 - WriteOp_Pop_Pri(jit);
24.463 - break;
24.464 - }
24.465 - case OP_POP_ALT:
24.466 - {
24.467 - WriteOp_Pop_Alt(jit);
24.468 - break;
24.469 - }
24.470 - case OP_SWAP_PRI:
24.471 - {
24.472 - WriteOp_Swap_Pri(jit);
24.473 - break;
24.474 - }
24.475 - case OP_SWAP_ALT:
24.476 - {
24.477 - WriteOp_Swap_Alt(jit);
24.478 - break;
24.479 - }
24.480 - case OP_PUSH_ADR:
24.481 - {
24.482 - WriteOp_PushAddr(jit);
24.483 - break;
24.484 - }
24.485 - case OP_MOVS:
24.486 - {
24.487 - WriteOp_Movs(jit);
24.488 - break;
24.489 - }
24.490 - case OP_FILL:
24.491 - {
24.492 - WriteOp_Fill(jit);
24.493 - break;
24.494 - }
24.495 - case OP_PUSH_C:
24.496 - {
24.497 - WriteOp_Push_C(jit);
24.498 - break;
24.499 - }
24.500 - case OP_ZERO:
24.501 - {
24.502 - WriteOp_Zero(jit);
24.503 - break;
24.504 - }
24.505 - case OP_ZERO_S:
24.506 - {
24.507 - WriteOp_Zero_S(jit);
24.508 - break;
24.509 - }
24.510 - case OP_PUSH_PRI:
24.511 - {
24.512 - WriteOp_Push_Pri(jit);
24.513 - break;
24.514 - }
24.515 - case OP_PUSH_ALT:
24.516 - {
24.517 - WriteOp_Push_Alt(jit);
24.518 - break;
24.519 - }
24.520 - case OP_LOAD_BOTH:
24.521 - {
24.522 - WriteOp_Load_Both(jit);
24.523 - break;
24.524 - }
24.525 - case OP_LOAD_S_BOTH:
24.526 - {
24.527 - WriteOp_Load_S_Both(jit);
24.528 - break;
24.529 - }
24.530 - case OP_CONST:
24.531 - {
24.532 - WriteOp_Const(jit);
24.533 - break;
24.534 - }
24.535 - case OP_CONST_S:
24.536 - {
24.537 - WriteOp_Const_S(jit);
24.538 - break;
24.539 - }
24.540 - case OP_LOAD_I:
24.541 - {
24.542 - WriteOp_Load_I(jit);
24.543 - break;
24.544 - }
24.545 - case OP_LODB_I:
24.546 - {
24.547 - WriteOp_Lodb_I(jit);
24.548 - break;
24.549 - }
24.550 - case OP_STOR_I:
24.551 - {
24.552 - WriteOp_Stor_I(jit);
24.553 - break;
24.554 - }
24.555 - case OP_STRB_I:
24.556 - {
24.557 - WriteOp_Strb_I(jit);
24.558 - break;
24.559 - }
24.560 - case OP_LIDX:
24.561 - {
24.562 - WriteOp_Lidx(jit);
24.563 - break;
24.564 - }
24.565 - case OP_LIDX_B:
24.566 - {
24.567 - WriteOp_Lidx_B(jit);
24.568 - break;
24.569 - }
24.570 - case OP_IDXADDR_B:
24.571 - {
24.572 - WriteOp_Idxaddr_B(jit);
24.573 - break;
24.574 - }
24.575 - case OP_STACK:
24.576 - {
24.577 - WriteOp_Stack(jit);
24.578 - break;
24.579 - }
24.580 - case OP_HEAP:
24.581 - {
24.582 - WriteOp_Heap(jit);
24.583 - break;
24.584 - }
24.585 - case OP_SDIV:
24.586 - {
24.587 - WriteOp_SDiv(jit);
24.588 - break;
24.589 - }
24.590 - case OP_SDIV_ALT:
24.591 - {
24.592 - WriteOp_SDiv_Alt(jit);
24.593 - break;
24.594 - }
24.595 - case OP_RETN:
24.596 - {
24.597 - WriteOp_Retn(jit);
24.598 - break;
24.599 - }
24.600 - case OP_BOUNDS:
24.601 - {
24.602 - WriteOp_Bounds(jit);
24.603 - break;
24.604 - }
24.605 - case OP_HALT:
24.606 - {
24.607 - WriteOp_Halt(jit);
24.608 - break;
24.609 - }
24.610 - case OP_BREAK:
24.611 - {
24.612 - WriteOp_Break(jit);
24.613 - break;
24.614 - }
24.615 - case OP_JUMP:
24.616 - {
24.617 - WriteOp_Jump(jit);
24.618 - break;
24.619 - }
24.620 - case OP_JZER:
24.621 - {
24.622 - WriteOp_Jzer(jit);
24.623 - break;
24.624 - }
24.625 - case OP_JNZ:
24.626 - {
24.627 - WriteOp_Jnz(jit);
24.628 - break;
24.629 - }
24.630 - case OP_JEQ:
24.631 - {
24.632 - WriteOp_Jeq(jit);
24.633 - break;
24.634 - }
24.635 - case OP_JNEQ:
24.636 - {
24.637 - WriteOp_Jneq(jit);
24.638 - break;
24.639 - }
24.640 - case OP_JSLESS:
24.641 - {
24.642 - WriteOp_Jsless(jit);
24.643 - break;
24.644 - }
24.645 - case OP_JSGRTR:
24.646 - {
24.647 - WriteOp_JsGrtr(jit);
24.648 - break;
24.649 - }
24.650 - case OP_JSGEQ:
24.651 - {
24.652 - WriteOp_JsGeq(jit);
24.653 - break;
24.654 - }
24.655 - case OP_JSLEQ:
24.656 - {
24.657 - WriteOp_Jsleq(jit);
24.658 - break;
24.659 - }
24.660 - case OP_SWITCH:
24.661 - {
24.662 - WriteOp_Switch(jit);
24.663 - break;
24.664 - }
24.665 - case OP_CASETBL:
24.666 - {
24.667 - WriteOp_Casetbl(jit);
24.668 - break;
24.669 - }
24.670 - case OP_CALL:
24.671 - {
24.672 - WriteOp_Call(jit);
24.673 - break;
24.674 - }
24.675 - case OP_SYSREQ_C:
24.676 - {
24.677 - WriteOp_Sysreq_C(jit);
24.678 - break;
24.679 - }
24.680 - case OP_SYSREQ_N:
24.681 - {
24.682 - WriteOp_Sysreq_N(jit);
24.683 - break;
24.684 - }
24.685 - case OP_TRACKER_PUSH_C:
24.686 - {
24.687 - WriteOp_Tracker_Push_C(jit);
24.688 - break;
24.689 - }
24.690 - case OP_TRACKER_POP_SETHEAP:
24.691 - {
24.692 - WriteOp_Tracker_Pop_SetHeap(jit);
24.693 - break;
24.694 - }
24.695 - case OP_GENARRAY:
24.696 - {
24.697 - WriteOp_GenArray(jit, false);
24.698 - break;
24.699 - }
24.700 - case OP_GENARRAY_Z:
24.701 - {
24.702 - WriteOp_GenArray(jit, true);
24.703 - break;
24.704 - }
24.705 - case OP_STRADJUST_PRI:
24.706 - {
24.707 - WriteOp_Stradjust_Pri(jit);
24.708 - break;
24.709 - }
24.710 - case OP_FABS:
24.711 - {
24.712 - WriteOp_FloatAbs(jit);
24.713 - break;
24.714 - }
24.715 - case OP_FLOAT:
24.716 - {
24.717 - WriteOp_Float(jit);
24.718 - break;
24.719 - }
24.720 - case OP_FLOATADD:
24.721 - {
24.722 - WriteOp_FloatAdd(jit);
24.723 - break;
24.724 - }
24.725 - case OP_FLOATSUB:
24.726 - {
24.727 - WriteOp_FloatSub(jit);
24.728 - break;
24.729 - }
24.730 - case OP_FLOATMUL:
24.731 - {
24.732 - WriteOp_FloatMul(jit);
24.733 - break;
24.734 - }
24.735 - case OP_FLOATDIV:
24.736 - {
24.737 - WriteOp_FloatDiv(jit);
24.738 - break;
24.739 - }
24.740 - case OP_RND_TO_NEAREST:
24.741 - {
24.742 - WriteOp_RountToNearest(jit);
24.743 - break;
24.744 - }
24.745 - case OP_RND_TO_FLOOR:
24.746 - {
24.747 - WriteOp_RoundToFloor(jit);
24.748 - break;
24.749 - }
24.750 - case OP_RND_TO_ZERO:
24.751 - {
24.752 - WriteOp_RoundToZero(jit);
24.753 - break;
24.754 - }
24.755 - case OP_RND_TO_CEIL:
24.756 - {
24.757 - WriteOp_RoundToCeil(jit);
24.758 - break;
24.759 - }
24.760 - case OP_FLOATCMP:
24.761 - {
24.762 - WriteOp_FloatCompare(jit);
24.763 - break;
24.764 - }
24.765 - case OP_STACKADJUST:
24.766 - {
24.767 - WriteOp_StackAdjust(jit);
24.768 - break;
24.769 - }
24.770 - case OP_ENDPROC:
24.771 - {
24.772 - WriteOp_EndProc(jit);
24.773 - break;
24.774 - }
24.775 -#if defined USE_UNGEN_OPCODES
24.776 - #include "ungen_opcode_switch.inc"
24.777 -#endif
24.778 - default:
24.779 - {
24.780 - data->error_set = SP_ERROR_INVALID_INSTRUCTION;
24.781 - break;
24.782 - }
25.1 --- a/sourcepawn/jit/x86/ungen_opcode_switch.inc Thu Aug 08 09:40:23 2013 -0700
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,121 +0,0 @@
25.4 -/**
25.5 - * vim: set ts=4 :
25.6 - * =============================================================================
25.7 - * SourceMod
25.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
25.9 - * =============================================================================
25.10 - *
25.11 - * This program is free software; you can redistribute it and/or modify it under
25.12 - * the terms of the GNU General Public License, version 3.0, as published by the
25.13 - * Free Software Foundation.
25.14 - *
25.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
25.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
25.18 - * details.
25.19 - *
25.20 - * You should have received a copy of the GNU General Public License along with
25.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
25.22 - *
25.23 - * As a special exception, AlliedModders LLC gives you permission to link the
25.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
25.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
25.26 - * by the Valve Corporation. You must obey the GNU General Public License in
25.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
25.28 - * this exception to all derivative works. AlliedModders LLC defines further
25.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
25.30 - * or <http://www.sourcemod.net/license.php>.
25.31 - *
25.32 - * Version: $Id$
25.33 - */
25.34 -
25.35 - case OP_UMUL:
25.36 - {
25.37 - WriteOp_UMul(jit);
25.38 - break;
25.39 - }
25.40 - case OP_LESS:
25.41 - {
25.42 - WriteOp_Less(jit);
25.43 - break;
25.44 - }
25.45 - case OP_LEQ:
25.46 - {
25.47 - WriteOp_Leq(jit);
25.48 - break;
25.49 - }
25.50 - case OP_GRTR:
25.51 - {
25.52 - WriteOp_Grtr(jit);
25.53 - break;
25.54 - }
25.55 - case OP_GEQ:
25.56 - {
25.57 - WriteOp_Geq(jit);
25.58 - break;
25.59 - }
25.60 - case OP_ALIGN_PRI:
25.61 - {
25.62 - WriteOp_Align_Pri(jit);
25.63 - break;
25.64 - }
25.65 - case OP_ALIGN_ALT:
25.66 - {
25.67 - WriteOp_Align_Alt(jit);
25.68 - break;
25.69 - }
25.70 - case OP_LCTRL:
25.71 - {
25.72 - WriteOp_Lctrl(jit);
25.73 - break;
25.74 - }
25.75 - case OP_SCTRL:
25.76 - {
25.77 - WriteOp_Sctrl(jit);
25.78 - break;
25.79 - }
25.80 - case OP_UDIV:
25.81 - {
25.82 - WriteOp_UDiv(jit);
25.83 - break;
25.84 - }
25.85 - case OP_UDIV_ALT:
25.86 - {
25.87 - WriteOp_UDiv_Alt(jit);
25.88 - break;
25.89 - }
25.90 - case OP_RET:
25.91 - {
25.92 - WriteOp_Ret(jit);
25.93 - break;
25.94 - }
25.95 - case OP_CMPS:
25.96 - {
25.97 - WriteOp_Cmps(jit);
25.98 - break;
25.99 - }
25.100 - case OP_JREL:
25.101 - {
25.102 - WriteOp_JRel(jit);
25.103 - break;
25.104 - }
25.105 - case OP_JLESS:
25.106 - {
25.107 - WriteOp_Jless(jit);
25.108 - break;
25.109 - }
25.110 - case OP_JLEQ:
25.111 - {
25.112 - WriteOp_Jeq(jit);
25.113 - break;
25.114 - }
25.115 - case OP_JGRTR:
25.116 - {
25.117 - WriteOp_Jgrtr(jit);
25.118 - break;
25.119 - }
25.120 - case OP_JGEQ:
25.121 - {
25.122 - WriteOp_Jgeq(jit);
25.123 - break;
25.124 - }
25.125 \ No newline at end of file
26.1 --- a/sourcepawn/jit/x86/ungen_opcodes.h Thu Aug 08 09:40:23 2013 -0700
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,325 +0,0 @@
26.4 -/**
26.5 - * vim: set ts=4 :
26.6 - * =============================================================================
26.7 - * SourceMod
26.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
26.9 - * =============================================================================
26.10 - *
26.11 - * This program is free software; you can redistribute it and/or modify it under
26.12 - * the terms of the GNU General Public License, version 3.0, as published by the
26.13 - * Free Software Foundation.
26.14 - *
26.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
26.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
26.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
26.18 - * details.
26.19 - *
26.20 - * You should have received a copy of the GNU General Public License along with
26.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
26.22 - *
26.23 - * As a special exception, AlliedModders LLC gives you permission to link the
26.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
26.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
26.26 - * by the Valve Corporation. You must obey the GNU General Public License in
26.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
26.28 - * this exception to all derivative works. AlliedModders LLC defines further
26.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
26.30 - * or <http://www.sourcemod.net/license.php>.
26.31 - *
26.32 - * Version: $Id$
26.33 - */
26.34 -
26.35 -#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
26.36 -#define _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
26.37 -
26.38 -inline void WriteOp_UMul(JitWriter *jit)
26.39 -{
26.40 - //mov ecx, edx
26.41 - //mul edx
26.42 - //mov edx, ecx
26.43 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
26.44 - IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG);
26.45 - IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
26.46 -}
26.47 -
26.48 -inline void WriteOp_Less(JitWriter *jit)
26.49 -{
26.50 - //cmp eax, edx ; PRI < ALT ? (unsigned)
26.51 - //mov eax, 0
26.52 - //setb al
26.53 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.54 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
26.55 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B);
26.56 -}
26.57 -
26.58 -inline void WriteOp_Leq(JitWriter *jit)
26.59 -{
26.60 - //cmp eax, edx ; PRI <= ALT ? (unsigned)
26.61 - //mov eax, 0
26.62 - //setbe al
26.63 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.64 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
26.65 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE);
26.66 -}
26.67 -
26.68 -inline void WriteOp_Grtr(JitWriter *jit)
26.69 -{
26.70 - //cmp eax, edx ; PRI > ALT ? (unsigned)
26.71 - //mov eax, 0
26.72 - //seta al
26.73 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.74 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
26.75 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A);
26.76 -}
26.77 -
26.78 -inline void WriteOp_Geq(JitWriter *jit)
26.79 -{
26.80 - //cmp eax, edx ; PRI >= ALT ? (unsigned)
26.81 - //mov eax, 0
26.82 - //setae al
26.83 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.84 - IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
26.85 - IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE);
26.86 -}
26.87 -
26.88 -inline void WriteOp_Align_Pri(JitWriter *jit)
26.89 -{
26.90 - //xor eax, <cellsize - val>
26.91 - cell_t val = sizeof(cell_t) - jit->read_cell();
26.92 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
26.93 - {
26.94 - IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
26.95 - } else {
26.96 - IA32_Xor_Eax_Imm32(jit, val);
26.97 - }
26.98 -}
26.99 -
26.100 -inline void WriteOp_Align_Alt(JitWriter *jit)
26.101 -{
26.102 - //xor edx, <cellsize - val>
26.103 - cell_t val = sizeof(cell_t) - jit->read_cell();
26.104 - if (val <= SCHAR_MAX && val >= SCHAR_MIN)
26.105 - {
26.106 - IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val);
26.107 - } else {
26.108 - IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val);
26.109 - }
26.110 -}
26.111 -
26.112 -inline void WriteOp_Cmps(JitWriter *jit)
26.113 -{
26.114 - //push edi
26.115 - //push esi
26.116 - //lea esi, [ebp+edx]
26.117 - //lea edi, [ebp+eax]
26.118 - //mov ecx, <val>
26.119 - unsigned int val = jit->read_cell();
26.120 -
26.121 - IA32_Push_Reg(jit, REG_EDI);
26.122 - IA32_Push_Reg(jit, REG_ESI);
26.123 - IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
26.124 - IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
26.125 - IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
26.126 -
26.127 - //xor eax, eax
26.128 - //repe cmpsb
26.129 - //je :cmps1
26.130 - IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
26.131 - IA32_Rep(jit);
26.132 - IA32_Cmpsb(jit);
26.133 - jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0);
26.134 -
26.135 - //sbb eax, eax
26.136 - //sbb eax, -1
26.137 - IA32_Sbb_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
26.138 - IA32_Sbb_Rm_Imm8(jit, AMX_REG_PRI, -1, MOD_REG);
26.139 -
26.140 - //:cmps1
26.141 - //pop esi
26.142 - //pop edi
26.143 - IA32_Send_Jump8_Here(jit, jmp);
26.144 - IA32_Pop_Reg(jit, REG_ESI);
26.145 - IA32_Pop_Reg(jit, REG_EDI);
26.146 -}
26.147 -
26.148 -inline void WriteOp_Lctrl(JitWriter *jit)
26.149 -{
26.150 - cell_t val = jit->read_cell();
26.151 - switch (val)
26.152 - {
26.153 - case 0:
26.154 - {
26.155 - //mov ecx, [esi+ctx]
26.156 - //mov eax, [ecx+ctx.codebase]
26.157 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
26.158 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, codebase));
26.159 - break;
26.160 - }
26.161 - case 1:
26.162 - {
26.163 - //mov eax, ebp
26.164 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
26.165 - break;
26.166 - }
26.167 - case 2:
26.168 - {
26.169 - //mov eax, [esi+hea]
26.170 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP);
26.171 - break;
26.172 - }
26.173 - case 3:
26.174 - {
26.175 - //mov ecx, [esi+ctx]
26.176 - //mov eax, [ecx+ctx.memory]
26.177 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
26.178 - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory));
26.179 - break;
26.180 - }
26.181 - case 4:
26.182 - {
26.183 - //mov eax, edi
26.184 - //sub eax, ebp - unrelocate
26.185 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG);
26.186 - IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
26.187 - break;
26.188 - }
26.189 - case 5:
26.190 - {
26.191 - //mov eax, [esi+frm]
26.192 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
26.193 - break;
26.194 - }
26.195 - case 6:
26.196 - {
26.197 - //mov eax, [cip]
26.198 - jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
26.199 - jitoffs_t save = jit->get_outputpos();
26.200 - jit->set_outputpos(imm32);
26.201 - jit->write_int32((uint32_t)(jit->outbase + save));
26.202 - jit->set_outputpos(save);
26.203 - break;
26.204 - }
26.205 - }
26.206 -}
26.207 -
26.208 -inline void WriteOp_Sctrl(JitWriter *jit)
26.209 -{
26.210 - cell_t val = jit->read_cell();
26.211 - switch (val)
26.212 - {
26.213 - case 2:
26.214 - {
26.215 - //mov [esi+hea], eax
26.216 - IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_PRI, AMX_INFO_HEAP);
26.217 - break;
26.218 - }
26.219 - case 4:
26.220 - {
26.221 - //lea edi, [ebp+eax]
26.222 - IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
26.223 - break;
26.224 - }
26.225 - case 5:
26.226 - {
26.227 - //lea ebx, [ebp+eax] - overwrite frm
26.228 - //mov [esi+frm], eax - overwrite stacked frame
26.229 - IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_FRM, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
26.230 - IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_PRI, MOD_MEM_REG);
26.231 - break;
26.232 - }
26.233 - case 6:
26.234 - {
26.235 - IA32_Jump_Reg(jit, AMX_REG_PRI);
26.236 - break;
26.237 - }
26.238 - }
26.239 -}
26.240 -
26.241 -inline void WriteOp_UDiv(JitWriter *jit)
26.242 -{
26.243 - //mov ecx, edx
26.244 - //xor edx, edx
26.245 - //div ecx
26.246 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
26.247 - IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
26.248 - Write_Check_DivZero(jit, AMX_REG_TMP);
26.249 - IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
26.250 -}
26.251 -
26.252 -inline void WriteOp_UDiv_Alt(JitWriter *jit)
26.253 -{
26.254 - //mov ecx, eax
26.255 - //mov eax, edx
26.256 - //xor edx, edx
26.257 - //div ecx
26.258 - IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
26.259 - IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.260 - IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
26.261 - Write_Check_DivZero(jit, AMX_REG_TMP);
26.262 - IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
26.263 -}
26.264 -
26.265 -inline void WriteOp_Ret(JitWriter *jit)
26.266 -{
26.267 - //mov ebx, [edi] - get old FRM
26.268 - //add edi, 4 - pop stack
26.269 - //mov [esi+frm], ebx - restore
26.270 - //add ebx, ebp - relocate
26.271 - //ret
26.272 - IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
26.273 - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
26.274 - IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
26.275 - IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
26.276 - IA32_Return(jit);
26.277 -}
26.278 -
26.279 -inline void WriteOp_JRel(JitWriter *jit)
26.280 -{
26.281 - //jmp <offs> ;relative jump
26.282 - cell_t cip_offs = jit->read_cell();
26.283 -
26.284 - /* Note that since code size calculation has to be done in the same
26.285 - * phase as building relocation information, we cannot know the jump size
26.286 - * beforehand. Thus, we always write full 32bit jumps for safety.
26.287 - */
26.288 - jitoffs_t jmp = IA32_Jump_Imm32(jit, 0);
26.289 - IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs));
26.290 -}
26.291 -
26.292 -inline void WriteOp_Jless(JitWriter *jit)
26.293 -{
26.294 - //cmp eax, edx
26.295 - //jb <target>
26.296 - cell_t target = jit->read_cell();
26.297 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.298 - IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false));
26.299 -}
26.300 -
26.301 -inline void WriteOp_Jleq(JitWriter *jit)
26.302 -{
26.303 - //cmp eax, edx
26.304 - //jbe <target>
26.305 - cell_t target = jit->read_cell();
26.306 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.307 - IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false));
26.308 -}
26.309 -
26.310 -inline void WriteOp_Jgrtr(JitWriter *jit)
26.311 -{
26.312 - //cmp eax, edx
26.313 - //ja <target>
26.314 - cell_t target = jit->read_cell();
26.315 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.316 - IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false));
26.317 -}
26.318 -
26.319 -inline void WriteOp_Jgeq(JitWriter *jit)
26.320 -{
26.321 - //cmp eax, edx
26.322 - //jae <target>
26.323 - cell_t target = jit->read_cell();
26.324 - IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
26.325 - IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false));
26.326 -}
26.327 -
26.328 -#endif //_INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_