📄 iwmmxt.c
字号:
/* iwmmxt.c -- Intel(r) Wireless MMX(tm) technology co-processor interface. Copyright (C) 2002 Free Software Foundation, Inc. Contributed by matthew green (mrg@redhat.com). 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. */#include "armdefs.h"#include "armos.h"#include "armemu.h"#include "ansidecl.h"#include "iwmmxt.h"/* #define DEBUG 1 *//* Intel(r) Wireless MMX(tm) technology co-processor. It uses co-processor numbers (0 and 1). There are 16 vector registers wRx and 16 control registers wCx. Co-processors 0 and 1 are used in MCR/MRC to access wRx and wCx respectively. */static ARMdword wR[16];static ARMword wC[16] = { 0x69051010 };#define SUBSTR(w,t,m,n) ((t)(w << ((sizeof (t) * 8 - 1) - (n))) \ >> (((sizeof (t) * 8 - 1) - (n)) + (m)))#define wCBITS(w,x,y) SUBSTR (wC[w], ARMword, x, y)#define wRBITS(w,x,y) SUBSTR (wR[w], ARMdword, x, y)#define wCID 0#define wCon 1#define wCSSF 2#define wCASF 3#define wCGR0 8#define wCGR1 9#define wCGR2 10#define wCGR3 11/* Bits in the wCon register. */#define WCON_CUP (1 << 0)#define WCON_MUP (1 << 1)/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations. */#define SIMD8_SET(x, v, n, b) (x) |= ((v != 0) << ((((b) + 1) * 4) + (n)))#define SIMD16_SET(x, v, n, h) (x) |= ((v != 0) << ((((h) + 1) * 8) + (n)))#define SIMD32_SET(x, v, n, w) (x) |= ((v != 0) << ((((w) + 1) * 16) + (n)))#define SIMD64_SET(x, v, n) (x) |= ((v != 0) << (32 + (n)))/* Flags to pass as "n" above. */#define SIMD_NBIT -1#define SIMD_ZBIT -2#define SIMD_CBIT -3#define SIMD_VBIT -4/* Various status bit macros. */#define NBIT8(x) ((x) & 0x80)#define NBIT16(x) ((x) & 0x8000)#define NBIT32(x) ((x) & 0x80000000)#define NBIT64(x) ((x) & 0x8000000000000000ULL)#define ZBIT8(x) (((x) & 0xff) == 0)#define ZBIT16(x) (((x) & 0xffff) == 0)#define ZBIT32(x) (((x) & 0xffffffff) == 0)#define ZBIT64(x) (x == 0)/* Access byte/half/word "n" of register "x". */#define wRBYTE(x,n) wRBITS ((x), (n) * 8, (n) * 8 + 7)#define wRHALF(x,n) wRBITS ((x), (n) * 16, (n) * 16 + 15)#define wRWORD(x,n) wRBITS ((x), (n) * 32, (n) * 32 + 31)/* Macro to handle how the G bit selects wCGR registers. */#define DECODE_G_BIT(state, instr, shift) \{ \ unsigned int reg; \ \ reg = BITS (0, 3); \ \ if (BIT (8)) /* G */ \ { \ if (reg < wCGR0 || reg > wCGR3) \ { \ ARMul_UndefInstr (state, instr); \ return ARMul_DONE; \ } \ shift = wC [reg]; \ } \ else \ shift = wR [reg]; \ \ shift &= 0xff; \}/* Index calculations for the satrv[] array. */#define BITIDX8(x) (x)#define BITIDX16(x) (((x) + 1) * 2 - 1)#define BITIDX32(x) (((x) + 1) * 4 - 1)/* Sign extension macros. */#define EXTEND8(a) ((a) & 0x80 ? ((a) | 0xffffff00) : (a))#define EXTEND16(a) ((a) & 0x8000 ? ((a) | 0xffff0000) : (a))#define EXTEND32(a) ((a) & 0x80000000ULL ? ((a) | 0xffffffff00000000ULL) : (a))/* Set the wCSSF from 8 values. */#define SET_wCSSF(a,b,c,d,e,f,g,h) \ wC[wCSSF] = (((h) != 0) << 7) | (((g) != 0) << 6) \ | (((f) != 0) << 5) | (((e) != 0) << 4) \ | (((d) != 0) << 3) | (((c) != 0) << 2) \ | (((b) != 0) << 1) | (((a) != 0) << 0);/* Set the wCSSR from an array with 8 values. */#define SET_wCSSFvec(v) \ SET_wCSSF((v)[0],(v)[1],(v)[2],(v)[3],(v)[4],(v)[5],(v)[6],(v)[7])/* Size qualifiers for vector operations. */#define Bqual 0#define Hqual 1#define Wqual 2#define Dqual 3/* Saturation qualifiers for vector operations. */#define NoSaturation 0#define UnsignedSaturation 1#define SignedSaturation 3/* Prototypes. */static ARMword Add32 (ARMword, ARMword, int *, int *, ARMword);static ARMdword AddS32 (ARMdword, ARMdword, int *, int *);static ARMdword AddU32 (ARMdword, ARMdword, int *, int *);static ARMword AddS16 (ARMword, ARMword, int *, int *);static ARMword AddU16 (ARMword, ARMword, int *, int *);static ARMword AddS8 (ARMword, ARMword, int *, int *);static ARMword AddU8 (ARMword, ARMword, int *, int *);static ARMword Sub32 (ARMword, ARMword, int *, int *, ARMword);static ARMdword SubS32 (ARMdword, ARMdword, int *, int *);static ARMdword SubU32 (ARMdword, ARMdword, int *, int *);static ARMword SubS16 (ARMword, ARMword, int *, int *);static ARMword SubS8 (ARMword, ARMword, int *, int *);static ARMword SubU16 (ARMword, ARMword, int *, int *);static ARMword SubU8 (ARMword, ARMword, int *, int *);static unsigned char IwmmxtSaturateU8 (signed short, int *);static signed char IwmmxtSaturateS8 (signed short, int *);static unsigned short IwmmxtSaturateU16 (signed int, int *);static signed short IwmmxtSaturateS16 (signed int, int *);static unsigned long IwmmxtSaturateU32 (signed long long, int *);static signed long IwmmxtSaturateS32 (signed long long, int *);static ARMword Compute_Iwmmxt_Address (ARMul_State *, ARMword, int *);static ARMdword Iwmmxt_Load_Double_Word (ARMul_State *, ARMword);static ARMword Iwmmxt_Load_Word (ARMul_State *, ARMword);static ARMword Iwmmxt_Load_Half_Word (ARMul_State *, ARMword);static ARMword Iwmmxt_Load_Byte (ARMul_State *, ARMword);static void Iwmmxt_Store_Double_Word (ARMul_State *, ARMword, ARMdword);static void Iwmmxt_Store_Word (ARMul_State *, ARMword, ARMword);static void Iwmmxt_Store_Half_Word (ARMul_State *, ARMword, ARMword);static void Iwmmxt_Store_Byte (ARMul_State *, ARMword, ARMword);static int Process_Instruction (ARMul_State *, ARMword);static int TANDC (ARMul_State *, ARMword);static int TBCST (ARMul_State *, ARMword);static int TEXTRC (ARMul_State *, ARMword);static int TEXTRM (ARMul_State *, ARMword);static int TINSR (ARMul_State *, ARMword);static int TMCR (ARMul_State *, ARMword);static int TMCRR (ARMul_State *, ARMword);static int TMIA (ARMul_State *, ARMword);static int TMIAPH (ARMul_State *, ARMword);static int TMIAxy (ARMul_State *, ARMword);static int TMOVMSK (ARMul_State *, ARMword);static int TMRC (ARMul_State *, ARMword);static int TMRRC (ARMul_State *, ARMword);static int TORC (ARMul_State *, ARMword);static int WACC (ARMul_State *, ARMword);static int WADD (ARMul_State *, ARMword);static int WALIGNI (ARMword);static int WALIGNR (ARMul_State *, ARMword);static int WAND (ARMword);static int WANDN (ARMword);static int WAVG2 (ARMword);static int WCMPEQ (ARMul_State *, ARMword);static int WCMPGT (ARMul_State *, ARMword);static int WLDR (ARMul_State *, ARMword);static int WMAC (ARMword);static int WMADD (ARMword);static int WMAX (ARMul_State *, ARMword);static int WMIN (ARMul_State *, ARMword);static int WMUL (ARMword);static int WOR (ARMword);static int WPACK (ARMul_State *, ARMword);static int WROR (ARMul_State *, ARMword);static int WSAD (ARMword);static int WSHUFH (ARMword);static int WSLL (ARMul_State *, ARMword);static int WSRA (ARMul_State *, ARMword);static int WSRL (ARMul_State *, ARMword);static int WSTR (ARMul_State *, ARMword);static int WSUB (ARMul_State *, ARMword);static int WUNPCKEH (ARMul_State *, ARMword);static int WUNPCKEL (ARMul_State *, ARMword);static int WUNPCKIH (ARMul_State *, ARMword);static int WUNPCKIL (ARMul_State *, ARMword);static int WXOR (ARMword);/* This function does the work of adding two 32bit values together, and calculating if a carry has occurred. */static ARMwordAdd32 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr, ARMword sign_mask){ ARMword result = (a1 + a2); unsigned int uresult = (unsigned int) result; unsigned int ua1 = (unsigned int) a1; /* If (result == a1) and (a2 == 0), or (result > a2) then we have no carry. */ * carry_ptr = ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)); /* Overflow occurs when both arguments are the same sign, but the result is a different sign. */ * overflow_ptr = ( ( (result & sign_mask) && !(a1 & sign_mask) && !(a2 & sign_mask)) || (!(result & sign_mask) && (a1 & sign_mask) && (a2 & sign_mask))); return result;}static ARMdwordAddS32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr){ ARMdword result; unsigned int uresult; unsigned int ua1; a1 = EXTEND32 (a1); a2 = EXTEND32 (a2); result = a1 + a2; uresult = (unsigned int) result; ua1 = (unsigned int) a1; * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1)); * overflow_ptr = ( ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL)) || (!(result & 0x80000000ULL) && (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL))); return result;}static ARMdwordAddU32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr){ ARMdword result; unsigned int uresult; unsigned int ua1; a1 &= 0xffffffff; a2 &= 0xffffffff; result = a1 + a2; uresult = (unsigned int) result; ua1 = (unsigned int) a1; * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1)); * overflow_ptr = ( ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL)) || (!(result & 0x80000000ULL) && (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL))); return result;}static ARMwordAddS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 = EXTEND16 (a1); a2 = EXTEND16 (a2); return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);}static ARMwordAddU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 &= 0xffff; a2 &= 0xffff; return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);}static ARMwordAddS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 = EXTEND8 (a1); a2 = EXTEND8 (a2); return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);}static ARMwordAddU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 &= 0xff; a2 &= 0xff; return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);}static ARMwordSub32 (ARMword a1, ARMword a2, int * borrow_ptr, int * overflow_ptr, ARMword sign_mask){ ARMword result = (a1 - a2); unsigned int ua1 = (unsigned int) a1; unsigned int ua2 = (unsigned int) a2; /* A borrow occurs if a2 is (unsigned) larger than a1. However the carry flag is *cleared* if a borrow occurs. */ * borrow_ptr = ! (ua2 > ua1); /* Overflow occurs when a negative number is subtracted from a positive number and the result is negative or a positive number is subtracted from a negative number and the result is positive. */ * overflow_ptr = ( (! (a1 & sign_mask) && (a2 & sign_mask) && (result & sign_mask)) || ((a1 & sign_mask) && ! (a2 & sign_mask) && ! (result & sign_mask))); return result;}static ARMdwordSubS32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr){ ARMdword result; unsigned int ua1; unsigned int ua2; a1 = EXTEND32 (a1); a2 = EXTEND32 (a2); result = a1 - a2; ua1 = (unsigned int) a1; ua2 = (unsigned int) a2; * borrow_ptr = ! (ua2 > ua1); * overflow_ptr = ( (! (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL) && (result & 0x80000000ULL)) || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL))); return result;}static ARMwordSubS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 = EXTEND16 (a1); a2 = EXTEND16 (a2); return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);}static ARMwordSubS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 = EXTEND8 (a1); a2 = EXTEND8 (a2); return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);}static ARMwordSubU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 &= 0xffff; a2 &= 0xffff; return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);}static ARMwordSubU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr){ a1 &= 0xff; a2 &= 0xff; return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);}static ARMdwordSubU32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr){ ARMdword result; unsigned int ua1; unsigned int ua2; a1 &= 0xffffffff; a2 &= 0xffffffff; result = a1 - a2; ua1 = (unsigned int) a1; ua2 = (unsigned int) a2; * borrow_ptr = ! (ua2 > ua1); * overflow_ptr = ( (! (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL) && (result & 0x80000000ULL)) || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL))); return result;}/* For the saturation. */static unsigned charIwmmxtSaturateU8 (signed short val, int * sat){ unsigned char rv; if (val < 0) { rv = 0; *sat = 1; } else if (val > 0xff) { rv = 0xff; *sat = 1; } else { rv = val & 0xff; *sat = 0; } return rv;}static signed charIwmmxtSaturateS8 (signed short val, int * sat){ signed char rv; if (val < -0x80) { rv = -0x80; *sat = 1; } else if (val > 0x7f) { rv = 0x7f; *sat = 1; } else { rv = val & 0xff; *sat = 0; } return rv;}static unsigned shortIwmmxtSaturateU16 (signed int val, int * sat){ unsigned short rv; if (val < 0) { rv = 0; *sat = 1; } else if (val > 0xffff) { rv = 0xffff; *sat = 1; } else { rv = val & 0xffff; *sat = 0; } return rv;}static signed shortIwmmxtSaturateS16 (signed int val, int * sat){ signed short rv; if (val < -0x8000) { rv = - 0x8000; *sat = 1; } else if (val > 0x7fff) { rv = 0x7fff; *sat = 1; } else { rv = val & 0xffff; *sat = 0; } return rv;}static unsigned longIwmmxtSaturateU32 (signed long long val, int * sat){ unsigned long rv; if (val < 0) { rv = 0; *sat = 1; } else if (val > 0xffffffff) { rv = 0xffffffff; *sat = 1; } else { rv = val & 0xffffffff; *sat = 0; } return rv;}static signed longIwmmxtSaturateS32 (signed long long val, int * sat){ signed long rv; if (val < -0x80000000LL) { rv = -0x80000000; *sat = 1; } else if (val > 0x7fffffff) { rv = 0x7fffffff; *sat = 1; } else { rv = val & 0xffffffff; *sat = 0; } return rv;}/* Intel(r) Wireless MMX(tm) technology Acessor functions. */unsignedIwmmxtLDC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword data){ return ARMul_CANT;}unsignedIwmmxtSTC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * data){ return ARMul_CANT;}unsignedIwmmxtMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value){ return ARMul_CANT;}unsignedIwmmxtMCR (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value){ return ARMul_CANT;}unsignedIwmmxtCDP (ARMul_State * state, unsigned type, ARMword instr){ return ARMul_CANT;}/* Intel(r) Wireless MMX(tm) technology instruction implementations. */static intTANDC (ARMul_State * state, ARMword instr){ ARMword cpsr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -