1
0
Fork 1
forked from suyu/suyu

dyncom: Various cleanups to match coding style, no functional changes.

This commit is contained in:
bunnei 2014-12-29 01:39:12 -05:00
parent 2d2aa2c0be
commit aa49019afb
5 changed files with 5705 additions and 6830 deletions

View file

@ -1,27 +1,6 @@
/* Copyright (C)
* 2012 - Michael.Kang blackfin.kang@gmail.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.
*
*/
/**
* @file arm_dyncom_dec.cpp
* @brief Some common utility for arm decoder
* @author Michael.Kang blackfin.kang@gmail.com
* @version 7849
* @date 2012-03-15
*/
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/armdefs.h"
@ -404,27 +383,25 @@ const ISEITEM arm_exclusion_code[] = {
{ "ldc", 0, 0, 0 },
{ "swi", 0, 0, 0 },
{ "bbl", 0, 0, 0 },
{"bl_1_thumb", 0, INVALID, 0},/* should be table[-4] */
{"bl_2_thumb", 0, INVALID, 0}, /* should be located at the end of the table[-3] */
{"blx_1_thumb", 0, INVALID, 0}, /* should be located at table[-2] */
{ "bl_1_thumb", 0, INVALID, 0 }, // Should be table[-4]
{ "bl_2_thumb", 0, INVALID, 0 }, // Should be located at the end of the table[-3]
{ "blx_1_thumb", 0, INVALID, 0 }, // Should be located at table[-2]
{ "invalid", 0, INVALID, 0 }
};
int decode_arm_instr(uint32_t instr, int32_t *idx)
{
int decode_arm_instr(uint32_t instr, int32_t *idx) {
int n = 0;
int base = 0;
int ret = DECODE_FAILURE;
int i = 0;
int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM);
for (i = 0; i < instr_slots; i++)
{
// ret = DECODE_SUCCESS;
for (i = 0; i < instr_slots; i++) {
n = arm_instruction[i].attribute_value;
base = 0;
while (n) {
if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
/* clrex */
// clrex
if (instr != arm_instruction[i].content[base + 2]) {
break;
}
@ -434,6 +411,7 @@ int decode_arm_instr(uint32_t instr, int32_t *idx)
base += 3;
n--;
}
// All conditions is satisfied.
if (n == 0)
ret = DECODE_SUCCESS;
@ -444,10 +422,12 @@ int decode_arm_instr(uint32_t instr, int32_t *idx)
base = 0;
while (n) {
if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {
break; }
break;
}
base += 3;
n--;
}
// All conditions is satisfied.
if (n == 0)
ret = DECODE_FAILURE;
@ -461,4 +441,3 @@ int decode_arm_instr(uint32_t instr, int32_t *idx)
}
return ret;
}

File diff suppressed because it is too large Load diff

View file

@ -1,41 +1,15 @@
/* Copyright (C)
* 2011 - Michael.Kang blackfin.kang@gmail.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.
*
*/
/**
* @file arm_dyncom_run.cpp
* @brief The dyncom run implementation for arm
* @author Michael.Kang blackfin.kang@gmail.com
* @version 78.77
* @date 2011-11-20
*/
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <assert.h>
#include "core/arm/skyeye_common/armdefs.h"
void switch_mode(arm_core_t *core, uint32_t mode)
{
if (core->Mode == mode) {
//Mode not changed.
//printf("mode not changed\n");
void switch_mode(arm_core_t *core, uint32_t mode) {
if (core->Mode == mode)
return;
}
//printf("%d --->>> %d\n", core->Mode, mode);
//printf("In %s, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
if (mode != USERBANK) {
switch (core->Mode) {
case USER32MODE:
@ -109,11 +83,8 @@ void switch_mode(arm_core_t *core, uint32_t mode)
}
core->Mode = mode;
//printf("In %si end, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
//printf("\n--------------------------------------\n");
}
else {
printf("user mode\n");
} else {
LOG_CRITICAL(Core_ARM11, "user mode");
exit(-2);
}
}

View file

@ -1,35 +1,13 @@
/* Copyright (C)
* 2011 - Michael.Kang blackfin.kang@gmail.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.
*
*/
/**
* @file arm_dyncom_thumb.c
* @brief The thumb dynamic interpreter
* @author Michael.Kang blackfin.kang@gmail.com
* @version 78.77
* @date 2011-11-07
*/
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
/* We can provide simple Thumb simulation by decoding the Thumb
instruction into its corresponding ARM instruction, and using the
existing ARM simulator. */
// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
// ARM instruction, and using the existing ARM simulator.
#include "core/arm/skyeye_common/skyeye_defs.h"
#ifndef MODET /* required for the Thumb instruction support */
#ifndef MODET // Required for the Thumb instruction support
#if 1
#error "MODET needs to be defined for the Thumb world to work"
#else
@ -40,482 +18,359 @@ existing ARM simulator. */
#include "core/arm/skyeye_common/armos.h"
#include "core/arm/dyncom/arm_dyncom_thumb.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. */
// 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 thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size)
{
tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size) {
tdstate valid = t_uninitialized;
ARMword next_instr;
ARMword tinstr;
tinstr = instr;
/* The endian should be judge here */
#if 0
if (state->bigendSig) {
next_instr = tinstr & 0xFFFF;
tinstr >>= 16;
}
else {
next_instr = tinstr >> 16;
tinstr &= 0xFFFF;
}
#endif
// The endian should be judge here
if((addr & 0x3) != 0)
tinstr = instr >> 16;
else
tinstr &= 0xFFFF;
//printf("In %s, instr=0x%x, tinstr=0x%x, r15=0x%x\n", __FUNCTION__, instr, tinstr, cpu->translate_pc);
#if 1 /* debugging to catch non updates */
*ainstr = 0xDEADC0DE;
#endif
*ainstr = 0xDEADC0DE; // Debugging to catch non updates
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 */
case 0: // LSL
case 1: // LSR
case 2: // ASR
*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) {
typedef enum
{ t_norm, t_shift, t_neg, t_mul }otype_t;
/* Format 4 */
struct
case 3: // ADD/SUB
{
ARMword opcode;
otype_t 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 */
ARMword subset[4] = {
0xE0900000, // ADDS Rd,Rs,Rn
0xE0500000, // SUBS Rd,Rs,Rn
0xE2900000, // ADDS Rd,Rs,#imm3
0xE2500000 // SUBS Rd,Rs,#imm3
};
*ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; /* base */
switch (subset[(tinstr & 0x03C0) >> 6].otype) {
// 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
{
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) {
enum otype {
t_norm,
t_shift,
t_neg,
t_mul
};
struct {
ARMword opcode;
otype type;
} 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].type) {
case t_norm:
*ainstr |= ((tinstr & 0x0007) << 16) /* Rn */
|((tinstr & 0x0007) << 12) /* Rd */
|((tinstr & 0x0038) >> 3); /* Rs */
*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 */
*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 */
*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 */
*ainstr |= ((tinstr & 0x0007) << 16) // Rd
|((tinstr & 0x0007) << 8) // Rs
|((tinstr & 0x0038) >> 3); // Rm
break;
}
}
else {
/* Format 5 */
} else {
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 */
valid = t_undefined;
break;
case 0xE: /* BLX */
case 0xF: /* BLX */
//if (state->is_v5) {
if(1){
//valid = t_branch;
#if 1
*ainstr = 0xE1200030 /* base */
|(Rs << 0); /* Rm */
#endif
} else {
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
valid = t_undefined;
}
break;
case 0xE: // BLX
case 0xF: // BLX
*ainstr = 0xE1200030 // base
| (Rs << 0); // Rm
break;
}
}
break;
case 9: /* LDR Rd,[PC,#imm8] */
/* Format 6 */
*ainstr = 0xE59F0000 /* base */
| ((tinstr & 0x0700) << (12 - 8)) /* Rd */
|((tinstr & 0x00FF) << (2 - 0)); /* off8 */
case 9: // LDR Rd,[PC,#imm8]
*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: */
// 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] = {
0xE7800000, /* STR Rd,[Rb,Ro] */
0xE7C00000, /* STRB Rd,[Rb,Ro] */
0xE7900000, /* LDR Rd,[Rb,Ro] */
0xE7D00000 /* LDRB Rd,[Rb,Ro] */
0xE7800000, // STR Rd,[Rb,Ro]
0xE7C00000, // STRB Rd,[Rb,Ro]
0xE7900000, // LDR Rd,[Rb,Ro]
0xE7D00000 // LDRB Rd,[Rb,Ro]
};
*ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x01C0) >> 6); /* Ro */
}
else {
/* Format 8 */
*ainstr = subset[(tinstr & 0x0C00) >> 10] // base
|((tinstr & 0x0007) << (12 - 0)) // Rd
|((tinstr & 0x0038) << (16 - 3)) // Rb
|((tinstr & 0x01C0) >> 6); // Ro
} else {
ARMword subset[4] = {
0xE18000B0, /* STRH Rd,[Rb,Ro] */
0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
0xE19000B0, /* LDRH Rd,[Rb,Ro] */
0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
0xE18000B0, // STRH Rd,[Rb,Ro]
0xE19000D0, // LDRSB Rd,[Rb,Ro]
0xE19000B0, // LDRH Rd,[Rb,Ro]
0xE19000F0 // LDRSH Rd,[Rb,Ro]
};
*ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x01C0) >> 6); /* Ro */
*ainstr = subset[(tinstr & 0x0C00) >> 10] // base
|((tinstr & 0x0007) << (12 - 0)) // Rd
|((tinstr & 0x0038) << (16 - 3)) // Rb
|((tinstr & 0x01C0) >> 6); // Ro
}
break;
case 12: /* STR Rd,[Rb,#imm5] */
case 13: /* LDR Rd,[Rb,#imm5] */
case 14: /* STRB Rd,[Rb,#imm5] */
case 15: /* LDRB Rd,[Rb,#imm5] */
/* Format 9 */
case 12: // STR Rd,[Rb,#imm5]
case 13: // LDR Rd,[Rb,#imm5]
case 14: // STRB Rd,[Rb,#imm5]
case 15: // LDRB Rd,[Rb,#imm5]
{
ARMword subset[4] = {
0xE5800000, /* STR Rd,[Rb,#imm5] */
0xE5900000, /* LDR Rd,[Rb,#imm5] */
0xE5C00000, /* STRB Rd,[Rb,#imm5] */
0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
0xE5800000, // STR Rd,[Rb,#imm5]
0xE5900000, // LDR Rd,[Rb,#imm5]
0xE5C00000, // STRB Rd,[Rb,#imm5]
0xE5D00000 // LDRB Rd,[Rb,#imm5]
};
/* The offset range defends on whether we are transferring a
byte or word value: */
*ainstr = subset[(tinstr & 0x1800) >> 11] /* base */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */
// The offset range defends on whether we are transferring a byte or word value:
*ainstr = subset[(tinstr & 0x1800) >> 11] // base
|((tinstr & 0x0007) << (12 - 0)) // Rd
|((tinstr & 0x0038) << (16 - 3)) // Rb
|((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5
}
break;
case 16: /* STRH Rd,[Rb,#imm5] */
case 17: /* LDRH Rd,[Rb,#imm5] */
/* Format 10 */
*ainstr = ((tinstr & (1 << 11)) /* base */
? 0xE1D000B0 /* LDRH */
: 0xE1C000B0) /* STRH */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */
|((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */
case 16: // STRH Rd,[Rb,#imm5]
case 17: // LDRH Rd,[Rb,#imm5]
*ainstr = ((tinstr & (1 << 11)) // base
? 0xE1D000B0 // LDRH
: 0xE1C000B0) // STRH
|((tinstr & 0x0007) << (12 - 0)) // Rd
|((tinstr & 0x0038) << (16 - 3)) // Rb
|((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble
|((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
break;
case 18: /* STR Rd,[SP,#imm8] */
case 19: /* LDR Rd,[SP,#imm8] */
/* Format 11 */
*ainstr = ((tinstr & (1 << 11)) /* base */
? 0xE59D0000 /* LDR */
: 0xE58D0000) /* STR */
|((tinstr & 0x0700) << (12 - 8)) /* Rd */
|((tinstr & 0x00FF) << 2); /* off8 */
case 18: // STR Rd,[SP,#imm8]
case 19: // LDR Rd,[SP,#imm8]
*ainstr = ((tinstr & (1 << 11)) // base
? 0xE59D0000 // LDR
: 0xE58D0000) // STR
|((tinstr & 0x0700) << (12 - 8)) // Rd
|((tinstr & 0x00FF) << 2); // off8
break;
case 20: /* ADD Rd,PC,#imm8 */
case 21: /* ADD Rd,SP,#imm8 */
/* Format 12 */
case 20: // ADD Rd,PC,#imm8
case 21: // ADD Rd,SP,#imm8
if ((tinstr & (1 << 11)) == 0) {
/* NOTE: The PC value used here should by word aligned */
/* We encode shift-left-by-2 in the rotate immediate field,
so no shift of off8 is needed. */
*ainstr = 0xE28F0F00 /* base */
| ((tinstr & 0x0700) << (12 - 8)) /* Rd */
|(tinstr & 0x00FF); /* off8 */
}
else {
/* We encode shift-left-by-2 in the rotate immediate field,
so no shift of off8 is needed. */
*ainstr = 0xE28D0F00 /* base */
| ((tinstr & 0x0700) << (12 - 8)) /* Rd */
|(tinstr & 0x00FF); /* off8 */
// NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the
// rotate immediate field, so no shift of off8 is needed.
*ainstr = 0xE28F0F00 // base
| ((tinstr & 0x0700) << (12 - 8)) // Rd
|(tinstr & 0x00FF); // off8
} else {
// We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is needed.
*ainstr = 0xE28D0F00 // base
| ((tinstr & 0x0700) << (12 - 8)) // Rd
|(tinstr & 0x00FF); // off8
}
break;
case 22:
case 23:
if ((tinstr & 0x0F00) == 0x0000) {
/* Format 13 */
/* NOTE: The instruction contains a shift left of 2
equivalent (implemented as ROR #30): */
*ainstr = ((tinstr & (1 << 7)) /* base */
? 0xE24DDF00 /* SUB */
: 0xE28DDF00) /* ADD */
|(tinstr & 0x007F); /* off7 */
}
else if ((tinstr & 0x0F00) == 0x0e00)
// NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30):
*ainstr = ((tinstr & (1 << 7)) // base
? 0xE24DDF00 // SUB
: 0xE28DDF00) // ADD
|(tinstr & 0x007F); // off7
} else if ((tinstr & 0x0F00) == 0x0e00)
*ainstr = 0xEF000000 | SWI_Breakpoint;
else {
/* Format 14 */
ARMword subset[4] = {
0xE92D0000, /* STMDB sp!,{rlist} */
0xE92D4000, /* STMDB sp!,{rlist,lr} */
0xE8BD0000, /* LDMIA sp!,{rlist} */
0xE8BD8000 /* LDMIA sp!,{rlist,pc} */
0xE92D0000, // STMDB sp!,{rlist}
0xE92D4000, // STMDB sp!,{rlist,lr}
0xE8BD0000, // LDMIA sp!,{rlist}
0xE8BD8000 // LDMIA sp!,{rlist,pc}
};
*ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] /* base */
|(tinstr & 0x00FF); /* mask8 */
*ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
|(tinstr & 0x00FF); // mask8
}
break;
case 24: /* STMIA */
case 25: /* LDMIA */
/* Format 15 */
*ainstr = ((tinstr & (1 << 11)) /* base */
? 0xE8B00000 /* LDMIA */
: 0xE8A00000) /* STMIA */
|((tinstr & 0x0700) << (16 - 8)) /* Rb */
|(tinstr & 0x00FF); /* mask8 */
case 24: // STMIA
case 25: // LDMIA
*ainstr = ((tinstr & (1 << 11)) // base
? 0xE8B00000 // LDMIA
: 0xE8A00000) // STMIA
|((tinstr & 0x0700) << (16 - 8)) // Rb
|(tinstr & 0x00FF); // mask8
break;
case 26: /* Bcc */
case 27: /* Bcc/SWI */
case 26: // Bcc
case 27: // Bcc/SWI
if ((tinstr & 0x0F00) == 0x0F00) {
#if 0
if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
state->AbortAddr == pc) {
*ainstr = ARMul_ABORTWORD;
break;
}
#endif
/* Format 17 : SWI */
// Format 17 : SWI
*ainstr = 0xEF000000;
/* Breakpoint must be handled specially. */
// Breakpoint must be handled specially.
if ((tinstr & 0x00FF) == 0x18)
*ainstr |= ((tinstr & 0x00FF) << 16);
/* New breakpoint value. See gdb/arm-tdep.c */
// New breakpoint value. See gdb/arm-tdep.c
else if ((tinstr & 0x00FF) == 0xFE)
*ainstr |= SWI_Breakpoint;
else
*ainstr |= (tinstr & 0x00FF);
}
else if ((tinstr & 0x0F00) != 0x0E00) {
/* Format 16 */
#if 0
int doit = FALSE;
/* TODO: Since we are doing a switch here, we could just add
the SWI and undefined instruction checks into this
switch to same on a couple of conditionals: */
switch ((tinstr & 0x0F00) >> 8) {
case EQ:
doit = ZFLAG;
break;
case NE:
doit = !ZFLAG;
break;
case VS:
doit = VFLAG;
break;
case VC:
doit = !VFLAG;
break;
case MI:
doit = NFLAG;
break;
case PL:
doit = !NFLAG;
break;
case CS:
doit = CFLAG;
break;
case CC:
doit = !CFLAG;
break;
case HI:
doit = (CFLAG && !ZFLAG);
break;
case LS:
doit = (!CFLAG || ZFLAG);
break;
case GE:
doit = ((!NFLAG && !VFLAG)
|| (NFLAG && VFLAG));
break;
case LT:
doit = ((NFLAG && !VFLAG)
|| (!NFLAG && VFLAG));
break;
case GT:
doit = ((!NFLAG && !VFLAG && !ZFLAG)
|| (NFLAG && VFLAG && !ZFLAG));
break;
case LE:
doit = ((NFLAG && !VFLAG)
|| (!NFLAG && VFLAG)) || ZFLAG;
break;
}
if (doit) {
state->Reg[15] = (pc + 4
+ (((tinstr & 0x7F) << 1)
| ((tinstr & (1 << 7)) ?
0xFFFFFF00 : 0)));
FLUSHPIPE;
}
#endif
} else if ((tinstr & 0x0F00) != 0x0E00)
valid = t_branch;
}
else /* UNDEFINED : cc=1110(AL) uses different format */
else // UNDEFINED : cc=1110(AL) uses different format
valid = t_undefined;
break;
case 28: /* B */
/* Format 18 */
#if 0
state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
| ((tinstr & (1 << 10)) ?
0xFFFFF800 : 0)));
#endif
//FLUSHPIPE;
case 28: // B
valid = t_branch;
break;
case 29:
if(tinstr & 0x1)
valid = t_undefined;
else{
/* BLX 1 for armv5t and above */
//printf("In %s, After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
valid = t_branch;
}
break;
case 30: /* BL instruction 1 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this Thumb
instruction. To keep the simulation simple (from the user
perspective) we check if the following instruction is the
second half of this BL, and if it is we simulate it
immediately. */
else
valid = t_branch;
break;
case 31: /* BL instruction 2 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this
instruction. Also, it should only ever be matched with the
fmt19 "BL instruction 1" instruction. However, we do allow
the simulation of it on its own, with undefined results if
r14 is not suitably initialised. */
{
#if 0
ARMword tmp = (pc + 2);
state->Reg[15] =
(state->Reg[14] + ((tinstr & 0x07FF) << 1));
state->Reg[14] = (tmp | 1);
#endif
case 30: // BL instruction 1
// There is no single ARM instruction equivalent for this Thumb instruction. To keep the
// simulation simple (from the user perspective) we check if the following instruction is
// the second half of this BL, and if it is we simulate it immediately
valid = t_branch;
break;
case 31: // BL instruction 2
// There is no single ARM instruction equivalent for this instruction. Also, it should only
// ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
// simulation of it on its own, with undefined results if r14 is not suitably initialised.
valid = t_branch;
}
break;
}
*inst_size = 2;
return valid;
}

View file

@ -56,7 +56,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMLA_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -180,7 +179,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMLS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -304,7 +302,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VNMLA_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -430,7 +427,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VNMLS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -554,7 +550,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VNMUL_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -669,7 +664,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMUL_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -797,7 +791,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VADD_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -919,7 +912,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VSUB_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1039,7 +1031,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VDIV_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1167,7 +1158,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVI_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1256,7 +1246,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVR_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1338,7 +1327,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VABS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1447,7 +1435,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VNEG_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1555,7 +1542,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VSQRT_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1651,7 +1637,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VCMP_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1774,7 +1759,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VCMP2_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1897,7 +1881,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VCVTBDS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -1994,7 +1977,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VCVTBFF_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2070,7 +2052,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VCVTBFI_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2243,7 +2224,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBRS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2323,7 +2303,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMSR_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
/* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
and in privilegied mode */
@ -2426,7 +2405,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBRC_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2493,7 +2471,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMRS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
/* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
and in privilegied mode */
@ -2657,7 +2634,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBCR_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2733,7 +2709,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBRRSS_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2803,7 +2778,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBRRD_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -2895,7 +2869,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VSTR_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -3037,7 +3010,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VPUSH_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -3204,7 +3176,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VSTM_INST: /* encoding 1 */
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -3392,7 +3363,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VPOP_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -3573,7 +3543,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VLDR_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
@ -3737,7 +3706,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VLDM_INST:
{
INC_ICOUNTER;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;