www.pudn.com > coremp4-1.0.zip > DynamicArmCode.h


/***************************************************************************** 
 * 
 * This program is free software ; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
 * 
 * $Id: dyncode_arm.h 131 2004-12-04 20:36:04Z picard $ 
 * 
 * The Core Pocket Media Player 
 * Copyright (c) 2004-2005 Gabor Kovacs 
 * 
 ****************************************************************************/ 
 
#ifndef _DYNAMICARMCODE_H 
#define _DYNAMICARMCODE_H 
 
#include "Rules.h" 
 
class C_dyn_code{ 
public: 
   enum{ 
      STACKFRAME = 9,         //number of dwords saved on stack inside of function 
      NONE = 0xff, 
   }; 
   enum E_CONDITION{ 
      EQ,   //equal 
      NE,   //not equal 
      CS,   //carry set 
      CC,   //carry clear 
      MI,   //minus 
      PL,   //plus 
      VS,   //overflow set 
      VC,   //overflow clear 
      HI,   //higher 
      LS,   //lower or same 
      GE,   //greater or equal 
      LT,   //less than 
      GT,   //greater than 
      LE,   //less or equal 
      AL,   //always 
      NV,   //newer 
   }; 
 
   enum E_REGISTER{ 
      r0, 
      r1, 
      r2, 
      r3, 
      r4, 
      r5, 
      r6, 
      r7, 
      r8, 
      r9, 
      r10, 
      r11, 
      r12, 
      sp, 
      r14, 
      lr = r14, 
      pc 
   }; 
   enum E_WMMX_REGISTER{ 
                              //wmmx registers 
      wr0 = 16, 
      wr1, 
      wr2, 
      wr3, 
      wr4, 
      wr5, 
      wr6, 
      wr7, 
      wr8, 
      wr9, 
      wr10, 
      wr11, 
      wr12, 
      wr13, 
      wr14, 
      wr15 
   }; 
   enum E_WMMX_SPECIAL_REGISTER{ 
                              //wmmx special registers 
      wcid = 32, 
      wcssf = 2+32, 
      wcasf 
   }; 
   enum E_WMMX_GENERAL_REGISTER{ 
      wcgr0 = 8+32, 
      wcgr1, 
      wcgr2, 
      wcgr3 
   }; 
 
   enum E_SHIFT_TYPE{ 
      LSL, 
      ASL = LSL, 
      LSR, 
      ASR, 
      ROR, 
   }; 
 
   enum E_OPCODE{ 
      AND, 
      EOR, 
      SUB, 
      RSB, 
      ADD, 
      ADC, 
      SBC, 
      RSC, 
      TST, 
      TEQ, 
      CMP, 
      CMN, 
      ORR, 
      MOV, 
      BIC, 
      MVN, 
      MUL, 
      MLA, 
      QADD, 
      QSUB, 
      QDADD, 
      QDSUB, 
      LDR, 
      STR, 
      LDR_POST, 
      STR_POST, 
      LDR_PRE, 
      STR_PRE, 
      LDR_POSTSUB, 
      STR_POSTSUB, 
      LDR_PRESUB, 
      STR_PRESUB, 
      B, 
      BL, 
      PLD, 
      PLD_POST, 
      PLD_PRE, 
      PLD_POSTSUB, 
      PLD_PRESUB, 
   }; 
 
   enum E_WMMX_OPCODE{ 
      TBCSTB = 0x1E400010, 
      TBCSTH = 0x1E400050, 
      TBCSTW = 0x1E400090, 
      TINSRB = 0x2E600010, 
      TINSRH = 0x2E600050, 
      TINSRW = 0x2E600090, 
      TMCR = 0x1E000110, 
      TMCRR = 0x4C400000, 
      TMRC = 0x6E100110, 
      TMRRC = 0x7C500000, 
      WACCB = 0x6E0001C0, 
      WACCH = 0x6E4001C0, 
      WACCW = 0x6E8001C0, 
      WADDB = 0x7E000180, 
      WADDH = 0x7E400180, 
      WADDW = 0x7E800180, 
      WADDBUS = 0x7E100180, 
      WADDHUS = 0x7E500180, 
      WADDWUS = 0x7E900180, 
      WADDBSS = 0x7E300180, 
      WADDHSS = 0x7E700180, 
      WADDWSS = 0x7EB00180, 
      WALIGNI = 0x8E000020, 
      WALIGNR0 = 0x7E800020, 
      WALIGNR1 = 0x7E900020, 
      WALIGNR2 = 0x7EA00020, 
      WALIGNR3 = 0x7EB00020, 
      WAND = 0x7E200000, 
      WANDN = 0x7E300000, 
      WAVG2B = 0x7E800000, 
      WAVG2H = 0x7EC00000, 
      WAVG2BR = 0x7E900000, 
      WAVG2HR = 0x7ED00000, 
      WCMPEQB = 0x7E000060, 
      WCMPEQH = 0x7E400060, 
      WCMPEQW = 0x7E800060, 
      WCMPGTUB = 0x7E100060, 
      WCMPGTUH = 0x7E500060, 
      WCMPGTUW = 0x7E900060, 
      WCMPGTSB = 0x7E300060, 
      WCMPGTSH = 0x7E700060, 
      WCMPGTSW = 0x7EB00060, 
      WLDRB = 0xFD900000, 
      WLDRH = 0xFDD00000, 
      WLDRW = 0xFD900100, 
      WLDRD = 0xFDD00100, 
      WSTRB = 0xFD800000, 
      WSTRH = 0xFDC00000, 
      WSTRW = 0xFD800100, 
      WSTRD = 0xFDC00100, 
      WLDRB_PRE = 0xFDB00000, 
      WLDRH_PRE = 0xFDF00000, 
      WLDRW_PRE = 0xFDB00100, 
      WLDRD_PRE = 0xFDF00100, 
      WSTRB_PRE = 0xFDA00000, 
      WSTRH_PRE = 0xFDE00000, 
      WSTRW_PRE = 0xFDA00100, 
      WSTRD_PRE = 0xFDE00100, 
      WLDRB_PRESUB = 0xFD300000, 
      WLDRH_PRESUB = 0xFD700000, 
      WLDRW_PRESUB = 0xFD300100, 
      WLDRD_PRESUB = 0xFD700100, 
      WSTRB_PRESUB = 0xFD200000, 
      WSTRH_PRESUB = 0xFD600000, 
      WSTRW_PRESUB = 0xFD200100, 
      WSTRD_PRESUB = 0xFD600100, 
      WLDRB_POST = 0xFCB00000, 
      WLDRH_POST = 0xFCF00000, 
      WLDRW_POST = 0xFCB00100, 
      WLDRD_POST = 0xFCF00100, 
      WSTRB_POST = 0xFCA00000, 
      WSTRH_POST = 0xFCE00000, 
      WSTRW_POST = 0xFCA00100, 
      WSTRD_POST = 0xFCE00100, 
      WLDRB_POSTSUB = 0xFC300000, 
      WLDRH_POSTSUB = 0xFC700000, 
      WLDRW_POSTSUB = 0xFC300100, 
      WLDRD_POSTSUB = 0xFC700100, 
      WSTRB_POSTSUB = 0xFC200000, 
      WSTRH_POSTSUB = 0xFC600000, 
      WSTRW_POSTSUB = 0xFC200100, 
      WSTRD_POSTSUB = 0xFC600100, 
      WMACU = 0x7E400100, 
      WMACS = 0x7E600100, 
      WMACUZ = 0x7E500100, 
      WMACSZ = 0x7E700100, 
      WMADDU = 0x7E800100, 
      WMADDS = 0x7EA00100, 
      WMAXUB = 0x7E000160, 
      WMAXUH = 0x7E400160, 
      WMAXUW = 0x7E800160, 
      WMAXSB = 0x7E200160, 
      WMAXSH = 0x7E600160, 
      WMAXSW = 0x7EA00160, 
      WMINUB = 0x7E100160, 
      WMINUH = 0x7E500160, 
      WMINUW = 0x7E900160, 
      WMINSB = 0x7E300160, 
      WMINSH = 0x7E700160, 
      WMINSW = 0x7EB00160, 
      WMULUL = 0x7E000100, 
      WMULUM = 0x7E100100, 
      WMULSL = 0x7E200100, 
      WMULSM = 0x7E300100, 
      WOR = 0x7E000000, 
      WPACKHUS = 0x7E500080, 
      WPACKWUS = 0x7E900080, 
      WPACKDUS = 0x7ED00080, 
      WPACKHSS = 0x7E700080, 
      WPACKWSS = 0x7EB00080, 
      WPACKDSS = 0x7EF00080, 
      WRORH = 0x7E700040, 
      WRORW = 0x7EB00040, 
      WRORD = 0x7EF00040, 
      WRORHG = 0x7E700140, 
      WRORWG = 0x7EB00140, 
      WRORDG = 0x7EF00140, 
      WSADB = 0x7E000120, 
      WSADBZ = 0x7E100120, 
      WSADH = 0x7E400120, 
      WSADHZ = 0x7E500120, 
      WSHUFH = 0x9E0001E0, 
      WSLLH = 0x7E500040, 
      WSLLW = 0x7E900040, 
      WSLLD = 0x7ED00040, 
      WSLLHG = 0x7E500140, 
      WSLLWG = 0x7E900140, 
      WSLLDG = 0x7ED00140, 
      WSRAH = 0x7E400040, 
      WSRAW = 0x7E800040, 
      WSRAD = 0x7EC00040, 
      WSRAHG = 0x7E400140, 
      WSRAWG = 0x7E800140, 
      WSRADG = 0x7EC00140, 
      WSRLH = 0x7E600040, 
      WSRLW = 0x7EA00040, 
      WSRLD = 0x7EE00040, 
      WSRLHG = 0x7E600140, 
      WSRLWG = 0x7EA00140, 
      WSRLDG = 0x7EE00140, 
      WSUBB = 0x7E0001A0, 
      WSUBH = 0x7E4001A0, 
      WSUBW = 0x7E8001A0, 
      WSUBBUS = 0x7E1001A0, 
      WSUBHUS = 0x7E5001A0, 
      WSUBWUS = 0x7E9001A0, 
      WSUBBSS = 0x7E3001A0, 
      WSUBHSS = 0x7E7001A0, 
      WSUBWSS = 0x7EB001A0, 
      WUNPCKEHUB = 0x6E0000C0, 
      WUNPCKEHUH = 0x6E4000C0, 
      WUNPCKEHUW = 0x6E8000C0, 
      WUNPCKEHSB = 0x6E2000C0, 
      WUNPCKEHSH = 0x6E6000C0, 
      WUNPCKEHSW = 0x6EA000C0, 
      WUNPCKIHB = 0x7E1000C0, 
      WUNPCKIHH = 0x7E5000C0, 
      WUNPCKIHW = 0x7E9000C0, 
      WUNPCKELUB = 0x6E0000E0, 
      WUNPCKELUH = 0x6E4000E0, 
      WUNPCKELUW = 0x6E8000E0, 
      WUNPCKELSB = 0x6E2000E0, 
      WUNPCKELSH = 0x6E6000E0, 
      WUNPCKELSW = 0x6EA000E0, 
      WUNPCKILB = 0x7E1000E0, 
      WUNPCKILH = 0x7E5000E0, 
      WUNPCKILW = 0x7E9000E0, 
      WXOR = 0x7E100000, 
   }; 
 
//---------------------------- 
   virtual ~C_dyn_code(){} 
 
//---------------------------- 
// Beginning of function - save all regs. 
   virtual void FunctionBegin(dword local_vars_size = 0) = 0; 
 
//---------------------------- 
// End of function - restore regs and return to caller. 
   virtual void FunctionEnd() = 0; 
 
//---------------------------- 
// Align code to specified byt boundary. 
   virtual void Align(dword bytes) = 0; 
 
//---------------------------- 
// Insert instructions. 
   virtual void I3C(int code, byte Dest, byte op_1, byte Op2, int constant) = 0; 
   virtual void I3(int code, byte Dest, byte op_1, byte Op2) = 0; 
   virtual void I3S(int code, byte Dest, byte op_1, byte Op2, E_SHIFT_TYPE ShiftType, int Shift) = 0; 
   virtual void I4(int code, byte Dest, byte op_1, byte Op2, byte Op3) = 0; 
   virtual void IConst(byte Dest, int constant) = 0; 
   virtual void I2(int code, byte Dest, byte op_1) = 0; 
   virtual void I2C(int code, byte Dest, byte op_1, int constant) = 0; 
   virtual void I1P(int code, byte Dest, void *label, int Ofs) = 0; 
   virtual void I0P(int code, int Cond, void *label) = 0; 
 
//---------------------------- 
// ARM instructions: 
   inline void Mov(E_REGISTER dst, E_REGISTER src, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(MOV, dst, NONE, src, shift_type, shift_count); } 
   inline void Mov(E_REGISTER dst, dword v){ I2C(MOV, dst, NONE, v); } 
   inline void Mvn(E_REGISTER dst, E_REGISTER src, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(MVN, dst, NONE, src, shift_type, shift_count); } 
   inline void Mvn(E_REGISTER dst, dword v){ I2C(MVN, dst, NONE, v); } 
   inline void MovLabel(E_REGISTER dst, void *label){ I1P(MOV, dst, label, 0); } 
   inline void Add(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(ADD, dst, src1, src2, shift_type, shift_count); } 
   inline void Add(E_REGISTER dst, E_REGISTER src, dword v){ I2C(ADD, dst, src, v); } 
   inline void And(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(AND, dst, src1, src2, shift_type, shift_count); } 
   inline void And(E_REGISTER dst, E_REGISTER src, dword v){ I2C(AND, dst, src, v); } 
   inline void Orr(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(ORR, dst, src1, src2, shift_type, shift_count); } 
   inline void Orr(E_REGISTER dst, E_REGISTER src, dword v){ I2C(ORR, dst, src, v); } 
   inline void Eor(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(EOR, dst, src1, src2, shift_type, shift_count); } 
   inline void Eor(E_REGISTER dst, E_REGISTER src, dword v){ I2C(EOR, dst, src, v); } 
   inline void Bic(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(BIC, dst, src1, src2, shift_type, shift_count); } 
   inline void Bic(E_REGISTER dst, E_REGISTER src, dword v){ I2C(BIC, dst, src, v); } 
   inline void Sub(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(SUB, dst, src1, src2, shift_type, shift_count); } 
   inline void Sub(E_REGISTER dst, E_REGISTER src, dword v){ I2C(SUB, dst, src, v); } 
   inline void Rsb(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(RSB, dst, src1, src2, shift_type, shift_count); } 
   inline void Rsb(E_REGISTER dst, E_REGISTER src, dword v){ I2C(RSB, dst, src, v); } 
   inline void Ldr(E_REGISTER dst, E_REGISTER src_ptr, int offs){ I2C(LDR, dst, src_ptr, offs); } 
   inline void Ldr(E_REGISTER dst, E_REGISTER src_ptr, E_REGISTER offs, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(LDR, dst, src_ptr, offs, shift_type, shift_count); } 
   inline void LdrAdvance(E_REGISTER dst, E_REGISTER src_ptr, E_REGISTER offs, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(LDR_POST, dst, src_ptr, offs, shift_type, shift_count); } 
   inline void LdrAdvance(E_REGISTER dst, E_REGISTER src_ptr, int offs){ I2C(LDR_POST, dst, src_ptr, offs); } 
   inline void Ldr(E_REGISTER dst, void *label, int offs = 0){ I1P(LDR, dst, label, offs); } 
   inline void Str(E_REGISTER src, E_REGISTER dst_ptr, int offs){ I2C(STR, src, dst_ptr, offs); } 
   inline void Str(E_REGISTER src, E_REGISTER dst_ptr, E_REGISTER offs, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(STR, src, dst_ptr, offs, shift_type, shift_count); } 
   inline void Cmp(E_REGISTER r1, E_REGISTER r2){ I3(CMP, NONE, r1, r2); } 
   inline void Cmp(E_REGISTER r1, dword v){ I2C(CMP, NONE, r1, v); } 
   inline void Tst(E_REGISTER r1, E_REGISTER r2){ I3(TST, NONE, r1, r2); } 
   inline void Tst(E_REGISTER r1, dword v){ I2C(TST, NONE, r1, v); } 
   inline void Mul(E_REGISTER dst, E_REGISTER src1, E_REGISTER src2, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(MUL, dst, src1, src2, shift_type, shift_count); } 
   virtual void MulC(E_REGISTER dst, E_REGISTER src, int constant) = 0; 
   inline void Mla(E_REGISTER dst, E_REGISTER mul1, E_REGISTER mul2, E_REGISTER add){ I4(MLA, dst, mul1, mul2, add); } 
   inline void StrAdvance(E_REGISTER src, E_REGISTER dst_ptr, E_REGISTER offs, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(STR_POST, src, dst_ptr, offs, shift_type, shift_count); } 
   inline void StrAdvance(E_REGISTER src, E_REGISTER dst_ptr, int offs){ I2C(STR_POST, src, dst_ptr, offs); } 
   inline void Pld(E_REGISTER dst, int offs){ I2C(PLD, NONE, dst, offs); } 
   inline void Pld(E_REGISTER dst, E_REGISTER offs, E_SHIFT_TYPE shift_type = LSL, int shift_count = 0){ I3S(PLD, NONE, dst, offs, shift_type, shift_count); } 
 
   inline void Branch(E_CONDITION cond, void *label){ I0P(B, cond, label); } 
   inline void Branch(void *label){ I0P(B, AL, label); } 
   inline void BranchLink(void *label){ I0P(BL, AL, label); } 
   /* 
      ADC, SBC, RSC, TEQ, CMN,  
      QADD, QSUB, QDADD, QDSUB, 
      LDR_PRE, STR_PRE, 
      LDR_POSTSUB, STR_POSTSUB, LDR_PRESUB, STR_PRESUB, 
   */ 
 
//---------------------------- 
// Transfer the contents of the src ARM registers to a 32-bit dst WMMX control register. 
   inline void Tmcr(E_WMMX_GENERAL_REGISTER dst, E_REGISTER src){ I2(TMCR, dst, src); } 
   inline void Tmcrr(E_WMMX_GENERAL_REGISTER dst, E_REGISTER src1, E_REGISTER src2){ I3(TMCRR, dst, src1, src2); } 
//---------------------------- 
// Transfer the contents of the 32-bit WMMX control register to the dst ARM register. 
   inline void Tmrc(E_REGISTER dst, E_WMMX_GENERAL_REGISTER src){ I2(TMRC, dst, src); } 
   inline void Tmrrc(E_REGISTER dst1, E_REGISTER dst2, E_WMMX_GENERAL_REGISTER src){ I3(TMRRC, dst1, dst2, src); } 
//---------------------------- 
// Transfer and insert 8-/16-/32-bit data from ARM* src register to the position in WMMX dst register, specified by the 3-bit Immediate. 
   inline void Tinsrb(E_WMMX_REGISTER dst, E_REGISTER src, byte c){ I2C(TINSRB, dst, src, c); } 
   inline void Tinsrh(E_WMMX_REGISTER dst, E_REGISTER src, byte c){ I2C(TINSRH, dst, src, c); } 
   inline void Tinsrw(E_WMMX_REGISTER dst, E_REGISTER src, byte c){ I2C(TINSRW, dst, src, c); } 
//---------------------------- 
// Broadcast a value from the ARM* src to every SIMD position in the WMMX dst register, can operate on 8-, 16-, and 32-bit data values. 
   inline void Tbcstb(E_WMMX_REGISTER dst, E_REGISTER src){ I2(TBCSTB, dst, src); } 
   inline void Tbcsth(E_WMMX_REGISTER dst, E_REGISTER src){ I2(TBCSTH, dst, src); } 
   inline void Tbcstw(E_WMMX_REGISTER dst, E_REGISTER src){ I2(TBCSTW, dst, src); } 
//---------------------------- 
   inline void Wldrb(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRB, dst, src, offs); } 
   inline void Wldrh(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRH, dst, src, offs); } 
   inline void Wldrw(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRW, dst, src, offs); } 
   inline void Wldrd(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRD, dst, src, offs); } 
   inline void Wldrd(E_WMMX_REGISTER dst, void *label, int offs){ I1P(WLDRD, dst, label, offs); } 
   inline void Wstrb(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRB, src, dst, offs); } 
   inline void Wstrh(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRH, src, dst, offs); } 
   inline void Wstrw(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRW, src, dst, offs); } 
   inline void Wstrd(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRD, src, dst, offs); } 
   inline void Wstrd(E_WMMX_REGISTER src, void *label, int offs){ I1P(WSTRD, src, label, offs); } 
 
   inline void WldrbAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WLDRB_POST, src, dst, offs); } 
   inline void WldrhAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WLDRH_POST, src, dst, offs); } 
   inline void WldrwAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WLDRW_POST, src, dst, offs); } 
   inline void WldrdAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WLDRD_POST, src, dst, offs); } 
   inline void WstrbAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRB_POST, src, dst, offs); } 
   inline void WstrhAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRH_POST, src, dst, offs); } 
   inline void WstrwAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRW_POST, src, dst, offs); } 
   inline void WstrdAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRD_POST, src, dst, offs); } 
 
   inline void WldrbPreAdvance(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRB_PRE, dst, src, offs); } 
   inline void WldrhPreAdvance(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRH_PRE, dst, src, offs); } 
   inline void WldrwPreAdvance(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRW_PRE, dst, src, offs); } 
   inline void WldrdPreAdvance(E_WMMX_REGISTER dst, E_REGISTER src, int offs){ I2C(WLDRD_PRE, dst, src, offs); } 
   inline void WstrbPreAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRB_PRE, src, dst, offs); } 
   inline void WstrhPreAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRH_PRE, src, dst, offs); } 
   inline void WstrwPreAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRW_PRE, src, dst, offs); } 
   inline void WstrdPreAdvance(E_WMMX_REGISTER src, E_REGISTER dst, int offs){ I2C(WSTRD_PRE, src, dst, offs); } 
 
   inline void Wand(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WAND, dst, src1, src2); } 
   inline void Wandn(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WANDN, dst, src1, src2); } 
   inline void Wor(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WOR, dst, src1, src2); } 
   inline void Wxor(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WXOR, dst, src1, src2); } 
//---------------------------- 
// Extract a 64-bit value from the two 64-bit Source registers, and place the result in 'dst'; instruction uses a 3-bit value stored in the specified general register to specify the byte offset of the value to extract. 
   inline void Walignr(int ri, E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(!ri ? WALIGNR0 : ri==1 ? WALIGNR1 : ri==2 ? WALIGNR2 : WALIGNR3, dst, src1, src2); } 
//---------------------------- 
   inline void Waddb(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDB, dst, src1, src2); } 
   inline void Waddh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDH, dst, src1, src2); } 
   inline void Waddw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDW, dst, src1, src2); } 
   inline void Waddbus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDBUS, dst, src1, src2); } 
   inline void Waddhus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDHUS, dst, src1, src2); } 
   inline void Waddwus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDWUS, dst, src1, src2); } 
   inline void Waddbss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDBSS, dst, src1, src2); } 
   inline void Waddhss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDHSS, dst, src1, src2); } 
   inline void Waddwss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WADDWSS, dst, src1, src2); } 
 
   inline void Wsubb(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBB, dst, src1, src2); } 
   inline void Wsubh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBH, dst, src1, src2); } 
   inline void Wsubw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBW, dst, src1, src2); } 
   inline void Wsubbus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBBUS, dst, src1, src2); } 
   inline void Wsubhus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBHUS, dst, src1, src2); } 
   inline void Wsubwus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBWUS, dst, src1, src2); } 
   inline void Wsubbss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBBSS, dst, src1, src2); } 
   inline void Wsubhss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBHSS, dst, src1, src2); } 
   inline void Wsubwss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WSUBWSS, dst, src1, src2); } 
//---------------------------- 
// Perform a 2-pixel average of wRn and wRm on unsigned vectors of 8- or 16-bit data with optional rounding of +1 and places the result in the 'dst'. 
   inline void Wavg2b(bool round, E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(round ? WAVG2BR : WAVG2B, dst, src1, src2); } 
   inline void Wavg2h(bool round, E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(round ? WAVG2HR : WAVG2H, dst, src1, src2); } 
//---------------------------- 
// Perform vector rotate-right / shift-arithmetic-right / logical-shift-left / logical-shift-right 
// of src by sh for vectors of 16-, 32-, or 64-bit data and places the result in 'dst'. 
// Version with G uses general-purpose register. 
   inline void Wrorh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WRORH, dst, src, sh); } 
   inline void Wrorw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WRORW, dst, src, sh); } 
   inline void Wrord(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WRORD, dst, src, sh); } 
   inline void Wrorhg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WRORHG, dst, src, sh); } 
   inline void Wrorwg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WRORWG, dst, src, sh); } 
   inline void Wrordg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WRORDG, dst, src, sh); } 
 
   inline void Wsrah(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSRAH, dst, src, sh); } 
   inline void Wsraw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSRAW, dst, src, sh); } 
   inline void Wsrad(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSRAD, dst, src, sh); } 
   inline void Wsrahg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSRAHG, dst, src, sh); } 
   inline void Wsrawg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSRAWG, dst, src, sh); } 
   inline void Wsradg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSRADG, dst, src, sh); } 
 
   inline void Wsllh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSLLH, dst, src, sh); } 
   inline void Wsllw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSLLW, dst, src, sh); } 
   inline void Wslld(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSLLD, dst, src, sh); } 
   inline void Wsllhg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSLLHG, dst, src, sh); } 
   inline void Wsllwg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSLLWG, dst, src, sh); } 
   inline void Wslldg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSLLDG, dst, src, sh); } 
 
   inline void Wsrlh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSRLH, dst, src, sh); } 
   inline void Wsrlw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSRLW, dst, src, sh); } 
   inline void Wsrld(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_REGISTER sh){ I3(WSRLD, dst, src, sh); } 
   inline void Wsrlhg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSRLHG, dst, src, sh); } 
   inline void Wsrlwg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSRLWG, dst, src, sh); } 
   inline void Wsrldg(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, E_WMMX_GENERAL_REGISTER sh){ I3(WSRLDG, dst, src, sh); } 
 
//---------------------------- 
// Select (shuffle) 16-bit data values in dst register from 16-bit fields in src register specified by the 8-bit immediate value. 
// The 8-bit constant specifies 2 bits per half-word, which specify index in source register (0-3) from where data are taken. 
   inline void Wshufh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src, byte c){ I2C(WSHUFH, dst, src, c); } 
//---------------------------- 
// Performs a vector multiplication of src1 and src2 on vectors of 16-bit data only. 
// M-qualifier indicates that the higher 16 bits of the result are to be stored in dst. 
// L-qualifier indicates that the lower 16 bits of the result are to be stored in dst. 
// Can be performed on signed or unsigned data. 
   inline void Wmulul(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WMULUL, dst, src1, src2); } 
   inline void Wmulum(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WMULUM, dst, src1, src2); } 
   inline void Wmulsl(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WMULSL, dst, src1, src2); } 
   inline void Wmulsm(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WMULSM, dst, src1, src2); } 
//---------------------------- 
// Unpacks 8-bit, 16-bit, or 32-bit data from the higher/lower half of src, and either zero or signed extend each field, and place the result into dst. 
   inline void Wunpckehub(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKEHUB, dst, src); } 
   inline void Wunpckehuh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKEHUH, dst, src); } 
   inline void Wunpckehuw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKEHUW, dst, src); } 
   inline void Wunpckehsb(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKEHSB, dst, src); } 
   inline void Wunpckehsh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKEHSH, dst, src); } 
   inline void Wunpckehsw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKEHSW, dst, src); } 
 
   inline void Wunpckelub(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKELUB, dst, src); } 
   inline void Wunpckeluh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKELUH, dst, src); } 
   inline void Wunpckeluw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKELUW, dst, src); } 
   inline void Wunpckelsb(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKELSB, dst, src); } 
   inline void Wunpckelsh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKELSH, dst, src); } 
   inline void Wunpckelsw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src){ I2(WUNPCKELSW, dst, src); } 
//---------------------------- 
// Interleave and merge eight bytes, four 16-bit halfwords, words, or two 32-bit words. 
// Unpacks either 8-bit, 16-bit, or 32 bit data from the higher/lower half of src1, interleaves with the higher/lower half of src2, and place the result into dst. 
   inline void Wunpckihb(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WUNPCKIHB, dst, src1, src2); } 
   inline void Wunpckihh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WUNPCKIHH, dst, src1, src2); } 
   inline void Wunpckihw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WUNPCKIHW, dst, src1, src2); } 
 
   inline void Wunpckilb(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WUNPCKILB, dst, src1, src2); } 
   inline void Wunpckilh(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WUNPCKILH, dst, src1, src2); } 
   inline void Wunpckilw(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WUNPCKILW, dst, src1, src2); } 
//---------------------------- 
// Pack data from src1 and src2 into dst, with src1 packed into the lower half, and src2 into the upper half, for vectors of 16-, 32-, or 64-bit data, 
// and saturate the results and place in the dst. 
// Packing can be performed with signed saturation or unsigned saturation. 
   inline void Wpackhus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WPACKHUS, dst, src1, src2); } 
   inline void Wpackwus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WPACKWUS, dst, src1, src2); } 
   inline void Wpackdus(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WPACKDUS, dst, src1, src2); } 
 
   inline void Wpackhss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WPACKHSS, dst, src1, src2); } 
   inline void Wpackwss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WPACKWSS, dst, src1, src2); } 
   inline void Wpackdss(E_WMMX_REGISTER dst, E_WMMX_REGISTER src1, E_WMMX_REGISTER src2){ I3(WPACKDSS, dst, src1, src2); } 
//---------------------------- 
   /* 
      WACCB 
      WACCH 
      WACCW 
      WALIGNI 
      WAVG2B 
      WAVG2H 
      WAVG2BR  
      WAVG2HR  
      WCMPEQB  
      WCMPEQH  
      WCMPEQW  
      WCMPGTUB 
      WCMPGTUH 
      WCMPGTUW 
      WCMPGTSB 
      WCMPGTSH 
      WCMPGTSW 
      WLDRB_PRESUB  
      WLDRH_PRESUB  
      WLDRW_PRESUB  
      WLDRD_PRESUB  
      WSTRB_PRESUB  
      WSTRH_PRESUB  
      WSTRW_PRESUB  
      WSTRD_PRESUB  
      WLDRB_POSTSUB 
      WLDRH_POSTSUB 
      WLDRW_POSTSUB 
      WLDRD_POSTSUB 
      WSTRB_POSTSUB 
      WSTRH_POSTSUB 
      WSTRW_POSTSUB 
      WSTRD_POSTSUB 
      WMACU  
      WMACS  
      WMACUZ 
      WMACSZ 
      WMADDU 
      WMADDS 
      WMAXUB 
      WMAXUH 
      WMAXUW 
      WMAXSB 
      WMAXSH 
      WMAXSW 
      WMINUB 
      WMINUH 
      WMINUW 
      WMINSB 
      WMINSH 
      WMINSW 
      WSADB  
      WSADBZ 
      WSADH  
      WSADHZ 
   */ 
 
//---------------------------- 
// Instruction modifications for next instruction: 
   virtual void Byte() = 0;            //instruction operates on byte 
   virtual void Half() = 0;            //    '' word 
   virtual void SByte() = 0;           //    '' signed char 
   virtual void SHalf() = 0;           //    '' signed short 
   virtual void Cond(E_CONDITION) = 0; //conditional instruction 
   virtual void Set() = 0;             //set flags from result 
   virtual void MoveBack() = 0;        //move next instruction back while register dependency allows it 
 
//---------------------------- 
// Create label and optionally put to code. 
// Labels not put to code during creation are forward-references, and must be put by using PutLabel. 
   virtual void *Label(bool put = true) = 0; 
 
//---------------------------- 
// Put label to code. 
   virtual void PutLabel(void *label) = 0; 
 
//---------------------------- 
// Declare constant data stored in code. Returned is label for referencing. Use PutLabel to actually instantiate data (at end of function). 
   virtual void *DeclareData(void *data, dword data_size) = 0; 
   inline void *DeclareData(dword data){ return DeclareData(&data, 4); } 
   virtual void StoreLabelAddress(void *label) = 0; 
 
//---------------------------- 
// Build code. 
   virtual void CodeBuild() = 0; 
 
//---------------------------- 
// Get pointer to function compiled code. 
   virtual void *Code(dword fnc_index = 0) const = 0; 
 
//---------------------------- 
   enum{ 
      CPU_WIRELESS_MMX = 1, 
      CPU_ARM5T = 2, 
   }; 
   static dword GetCpuCaps(); 
 
//---------------------------- 
// Create instance of this class. 
   static C_dyn_code *Create(); 
}; 
 
//---------------------------- 
 
#endif