Refactor the JIT to use a newer, simpler macro assembler. (bug 5827, r=ann)
authorDavid Anderson <danderson@mozilla.com>
Thu Aug 08 09:41:24 2013 -0700 (2013-08-08)
changeset 3977fca2b54741ca
parent 3976 bc77cfde7c5c
child 3978 5bdc0f106c05
Refactor the JIT to use a newer, simpler macro assembler. (bug 5827, r=ann)
public/jit/assembler.h
public/jit/x86/assembler-x86.h
public/jit/x86/x86_macros.h
public/sourcepawn/ke_allocator_policies.h
public/sourcepawn/ke_utility.h
public/sourcepawn/ke_vector.h
public/sourcepawn/sp_vm_types.h
sourcepawn/jit/AMBuilder
sourcepawn/jit/BaseRuntime.cpp
sourcepawn/jit/BaseRuntime.h
sourcepawn/jit/Makefile
sourcepawn/jit/Makefile.shell
sourcepawn/jit/dll_exports.cpp
sourcepawn/jit/engine2.cpp
sourcepawn/jit/opcodes.cpp
sourcepawn/jit/opcodes.h
sourcepawn/jit/sp_vm_basecontext.cpp
sourcepawn/jit/sp_vm_basecontext.h
sourcepawn/jit/sp_vm_engine.cpp
sourcepawn/jit/x86/jit_x86.cpp
sourcepawn/jit/x86/jit_x86.h
sourcepawn/jit/x86/opcode_helpers.cpp
sourcepawn/jit/x86/opcode_helpers.h
sourcepawn/jit/x86/opcode_switch.inc
sourcepawn/jit/x86/ungen_opcode_switch.inc
sourcepawn/jit/x86/ungen_opcodes.h
     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 &dividend) {
   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_