⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thumbemu.c

📁 skyeye-1.0.0.rar surce code
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  thumbemu.c -- Thumb instruction emulation.
    Copyright (C) 1996, Cygnus Software Technologies Ltd.

    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. */

/* We can provide simple Thumb simulation by decoding the Thumb
instruction into its corresponding ARM instruction, and using the
existing ARM simulator.  */

#ifndef MODET			/* required for the Thumb instruction support */
#if 1
#error "MODET needs to be defined for the Thumb world to work"
#else
#define MODET (1)
#endif
#endif

#include "armdefs.h"
#include "armemu.h"
#include "armos.h"

/* Decode a 16bit Thumb instruction.  The instruction is in the low
   16-bits of the tinstr field, with the following Thumb instruction
   held in the high 16-bits.  Passing in two Thumb instructions allows
   easier simulation of the special dual BL instruction.  */

tdstate
ARMul_ThumbDecode (state, pc, tinstr, ainstr)
     ARMul_State *state;
ARMword pc;
ARMword tinstr;
     ARMword *ainstr;
{
  tdstate valid = t_decoded;	/* default assumes a valid instruction */
  ARMword next_instr;

  if (state->bigendSig)
    {
      next_instr = tinstr & 0xFFFF;
      tinstr >>= 16;
    }
  else
    {
      next_instr = tinstr >> 16;
      tinstr &= 0xFFFF;
    }

#if 1				/* debugging to catch non updates */
  *ainstr = 0xDEADC0DE;
#endif

  switch ((tinstr & 0xF800) >> 11)
    {
    case 0:			/* LSL */
    case 1:			/* LSR */
    case 2:			/* ASR */
      /* Format 1 */
      *ainstr = 0xE1B00000	/* base opcode */
	| ((tinstr & 0x1800) >> (11 - 5))	/* shift type */
	| ((tinstr & 0x07C0) << (7 - 6))	/* imm5 */
	| ((tinstr & 0x0038) >> 3)	/* Rs */
	| ((tinstr & 0x0007) << 12);	/* Rd */
      break;
    case 3:			/* ADD/SUB */
      /* Format 2 */
      {
	ARMword subset[4] = {
	  0xE0900000,		/* ADDS Rd,Rs,Rn    */
	  0xE0500000,		/* SUBS Rd,Rs,Rn    */
	  0xE2900000,		/* ADDS Rd,Rs,#imm3 */
	  0xE2500000		/* SUBS Rd,Rs,#imm3 */
	};
	/* It is quicker indexing into a table, than performing switch
	   or conditionals: */
	*ainstr = subset[(tinstr & 0x0600) >> 9]	/* base opcode */
	  | ((tinstr & 0x01C0) >> 6)	/* Rn or imm3 */
	  | ((tinstr & 0x0038) << (16 - 3))	/* Rs */
	  | ((tinstr & 0x0007) << (12 - 0));	/* Rd */
      }
      break;
    case 4:			/* MOV */
    case 5:			/* CMP */
    case 6:			/* ADD */
    case 7:			/* SUB */
      /* Format 3 */
      {
	ARMword subset[4] = {
	  0xE3B00000,		/* MOVS Rd,#imm8    */
	  0xE3500000,		/* CMP  Rd,#imm8    */
	  0xE2900000,		/* ADDS Rd,Rd,#imm8 */
	  0xE2500000,		/* SUBS Rd,Rd,#imm8 */
	};
	*ainstr = subset[(tinstr & 0x1800) >> 11]	/* base opcode */
	  | ((tinstr & 0x00FF) >> 0)	/* imm8 */
	  | ((tinstr & 0x0700) << (16 - 8))	/* Rn */
	  | ((tinstr & 0x0700) << (12 - 8));	/* Rd */
      }
      break;
    case 8:			/* Arithmetic and high register transfers */
      /* TODO: Since the subsets for both Format 4 and Format 5
         instructions are made up of different ARM encodings, we could
         save the following conditional, and just have one large
         subset. */
      if ((tinstr & (1 << 10)) == 0)
	{
	  /* Format 4 */
	  struct
	  {
	    ARMword opcode;
	    enum
	    { t_norm, t_shift, t_neg, t_mul }
	    otype;
	  }
	  subset[16] =
	  {
	    {
	    0xE0100000, t_norm},	/* ANDS Rd,Rd,Rs     */
	    {
	    0xE0300000, t_norm},	/* EORS Rd,Rd,Rs     */
	    {
	    0xE1B00010, t_shift},	/* MOVS Rd,Rd,LSL Rs */
	    {
	    0xE1B00030, t_shift},	/* MOVS Rd,Rd,LSR Rs */
	    {
	    0xE1B00050, t_shift},	/* MOVS Rd,Rd,ASR Rs */
	    {
	    0xE0B00000, t_norm},	/* ADCS Rd,Rd,Rs     */
	    {
	    0xE0D00000, t_norm},	/* SBCS Rd,Rd,Rs     */
	    {
	    0xE1B00070, t_shift},	/* MOVS Rd,Rd,ROR Rs */
	    {
	    0xE1100000, t_norm},	/* TST  Rd,Rs        */
	    {
	    0xE2700000, t_neg},	/* RSBS Rd,Rs,#0     */
	    {
	    0xE1500000, t_norm},	/* CMP  Rd,Rs        */
	    {
	    0xE1700000, t_norm},	/* CMN  Rd,Rs        */
	    {
	    0xE1900000, t_norm},	/* ORRS Rd,Rd,Rs     */
	    {
	    0xE0100090, t_mul},	/* MULS Rd,Rd,Rs     */
	    {
	    0xE1D00000, t_norm},	/* BICS Rd,Rd,Rs     */
	    {
	    0xE1F00000, t_norm}	/* MVNS Rd,Rs        */
	  };
	  *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode;	/* base */
	  switch (subset[(tinstr & 0x03C0) >> 6].otype)
	    {
	    case t_norm:
	      *ainstr |= ((tinstr & 0x0007) << 16)	/* Rn */
		| ((tinstr & 0x0007) << 12)	/* Rd */
		| ((tinstr & 0x0038) >> 3);	/* Rs */
	      break;
	    case t_shift:
	      *ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
		| ((tinstr & 0x0007) >> 0)	/* Rm */
		| ((tinstr & 0x0038) << (8 - 3));	/* Rs */
	      break;
	    case t_neg:
	      *ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
		| ((tinstr & 0x0038) << (16 - 3));	/* Rn */
	      break;
	    case t_mul:
	      *ainstr |= ((tinstr & 0x0007) << 16)	/* Rd */
		| ((tinstr & 0x0007) << 8)	/* Rs */
		| ((tinstr & 0x0038) >> 3);	/* Rm */
	      break;
	    }
	}
      else
	{
	  /* Format 5 */
	  ARMword Rd = ((tinstr & 0x0007) >> 0);
	  ARMword Rs = ((tinstr & 0x0038) >> 3);
	  if (tinstr & (1 << 7))
	    Rd += 8;
	  if (tinstr & (1 << 6))
	    Rs += 8;
	  switch ((tinstr & 0x03C0) >> 6)
	    {
	    case 0x1:		/* ADD Rd,Rd,Hs */
	    case 0x2:		/* ADD Hd,Hd,Rs */
	    case 0x3:		/* ADD Hd,Hd,Hs */
	      *ainstr = 0xE0800000	/* base */
		| (Rd << 16)	/* Rn */
		| (Rd << 12)	/* Rd */
		| (Rs << 0);	/* Rm */
	      break;
	    case 0x5:		/* CMP Rd,Hs */
	    case 0x6:		/* CMP Hd,Rs */
	    case 0x7:		/* CMP Hd,Hs */
	      *ainstr = 0xE1500000	/* base */
		| (Rd << 16)	/* Rn */
		| (Rd << 12)	/* Rd */
		| (Rs << 0);	/* Rm */
	      break;
	    case 0x9:		/* MOV Rd,Hs */
	    case 0xA:		/* MOV Hd,Rs */
	    case 0xB:		/* MOV Hd,Hs */
	      *ainstr = 0xE1A00000	/* base */
		| (Rd << 16)	/* Rn */
		| (Rd << 12)	/* Rd */
		| (Rs << 0);	/* Rm */
	      break;
	    case 0xC:		/* BX Rs */
	    case 0xD:		/* BX Hs */
	      *ainstr = 0xE12FFF10	/* base */
		| ((tinstr & 0x0078) >> 3);	/* Rd */
	      break;
	    case 0x0:		/* UNDEFINED */
	    case 0x4:		/* UNDEFINED */
	    case 0x8:		/* UNDEFINED */
	    case 0xE:		/* UNDEFINED */
	    case 0xF:		/* UNDEFINED */
	      valid = t_undefined;
	      break;
	    }
	}
      break;
    case 9:			/* LDR Rd,[PC,#imm8] */
      /* Format 6 */
      *ainstr = 0xE59F0000	/* base */
	| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
	| ((tinstr & 0x00FF) << (2 - 0));	/* off8 */
      break;
    case 10:
    case 11:
      /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
         the following could be merged into a single subset, saving on
         the following boolean: */
      if ((tinstr & (1 << 9)) == 0)
	{
	  /* Format 7 */
	  ARMword subset[4] = {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -