Sources: Run clang-format on everything.

This commit is contained in:
Emmanuel Gil Peyrot 2016-09-18 09:38:01 +09:00
parent fe948af095
commit dc8479928c
386 changed files with 19560 additions and 18080 deletions

View file

@ -9,7 +9,7 @@
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
namespace Core {
struct ThreadContext;
struct ThreadContext;
}
/// Generic ARM11 CPU interface
@ -141,10 +141,10 @@ public:
return num_instructions;
}
s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop
s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event,
/// decreased by the cpu run loop
protected:
/**
* Executes the given number of instructions
* @param num_instructions Number of instructions to executes
@ -152,6 +152,5 @@ protected:
virtual void ExecuteInstructions(int num_instructions) = 0;
private:
u64 num_instructions = 0; ///< Number of instructions executed
};

File diff suppressed because it is too large Load diff

View file

@ -187,53 +187,53 @@ enum Opcode {
OP_THUMB_SWI,
OP_THUMB_TST,
OP_END // must be last
OP_END // must be last
};
class ARM_Disasm {
public:
static std::string Disassemble(u32 addr, u32 insn);
static Opcode Decode(u32 insn);
public:
static std::string Disassemble(u32 addr, u32 insn);
static Opcode Decode(u32 insn);
private:
static Opcode Decode00(u32 insn);
static Opcode Decode01(u32 insn);
static Opcode Decode10(u32 insn);
static Opcode Decode11(u32 insn);
static Opcode DecodeSyncPrimitive(u32 insn);
static Opcode DecodeParallelAddSub(u32 insn);
static Opcode DecodePackingSaturationReversal(u32 insn);
static Opcode DecodeMUL(u32 insn);
static Opcode DecodeMSRImmAndHints(u32 insn);
static Opcode DecodeMediaMulDiv(u32 insn);
static Opcode DecodeMedia(u32 insn);
static Opcode DecodeLDRH(u32 insn);
static Opcode DecodeALU(u32 insn);
private:
static Opcode Decode00(u32 insn);
static Opcode Decode01(u32 insn);
static Opcode Decode10(u32 insn);
static Opcode Decode11(u32 insn);
static Opcode DecodeSyncPrimitive(u32 insn);
static Opcode DecodeParallelAddSub(u32 insn);
static Opcode DecodePackingSaturationReversal(u32 insn);
static Opcode DecodeMUL(u32 insn);
static Opcode DecodeMSRImmAndHints(u32 insn);
static Opcode DecodeMediaMulDiv(u32 insn);
static Opcode DecodeMedia(u32 insn);
static Opcode DecodeLDRH(u32 insn);
static Opcode DecodeALU(u32 insn);
static std::string DisassembleALU(Opcode opcode, u32 insn);
static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn);
static std::string DisassembleBX(u32 insn);
static std::string DisassembleBKPT(u32 insn);
static std::string DisassembleCLZ(u32 insn);
static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn);
static std::string DisassembleMemblock(Opcode opcode, u32 insn);
static std::string DisassembleMem(u32 insn);
static std::string DisassembleMemHalf(u32 insn);
static std::string DisassembleMCR(Opcode opcode, u32 insn);
static std::string DisassembleMLA(Opcode opcode, u32 insn);
static std::string DisassembleUMLAL(Opcode opcode, u32 insn);
static std::string DisassembleMUL(Opcode opcode, u32 insn);
static std::string DisassembleMRS(u32 insn);
static std::string DisassembleMSR(u32 insn);
static std::string DisassembleNoOperands(Opcode opcode, u32 insn);
static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn);
static std::string DisassemblePKH(u32 insn);
static std::string DisassemblePLD(u32 insn);
static std::string DisassembleREV(Opcode opcode, u32 insn);
static std::string DisassembleREX(Opcode opcode, u32 insn);
static std::string DisassembleSAT(Opcode opcode, u32 insn);
static std::string DisassembleSEL(u32 insn);
static std::string DisassembleSWI(u32 insn);
static std::string DisassembleSWP(Opcode opcode, u32 insn);
static std::string DisassembleXT(Opcode opcode, u32 insn);
static std::string DisassembleALU(Opcode opcode, u32 insn);
static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn);
static std::string DisassembleBX(u32 insn);
static std::string DisassembleBKPT(u32 insn);
static std::string DisassembleCLZ(u32 insn);
static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn);
static std::string DisassembleMemblock(Opcode opcode, u32 insn);
static std::string DisassembleMem(u32 insn);
static std::string DisassembleMemHalf(u32 insn);
static std::string DisassembleMCR(Opcode opcode, u32 insn);
static std::string DisassembleMLA(Opcode opcode, u32 insn);
static std::string DisassembleUMLAL(Opcode opcode, u32 insn);
static std::string DisassembleMUL(Opcode opcode, u32 insn);
static std::string DisassembleMRS(u32 insn);
static std::string DisassembleMSR(u32 insn);
static std::string DisassembleNoOperands(Opcode opcode, u32 insn);
static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn);
static std::string DisassemblePKH(u32 insn);
static std::string DisassemblePLD(u32 insn);
static std::string DisassembleREV(Opcode opcode, u32 insn);
static std::string DisassembleREX(Opcode opcode, u32 insn);
static std::string DisassembleSAT(Opcode opcode, u32 insn);
static std::string DisassembleSEL(u32 insn);
static std::string DisassembleSWI(u32 insn);
static std::string DisassembleSWP(Opcode opcode, u32 insn);
static std::string DisassembleXT(Opcode opcode, u32 insn);
};

View file

@ -6,8 +6,8 @@
#include <string>
#include <vector>
#include "common/symbols.h"
#include "common/file_util.h"
#include "common/symbols.h"
#include "core/arm/disassembler/load_symbol_map.h"

View file

@ -430,12 +430,15 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
continue;
while (n) {
if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
if (arm_instruction[i].content[base + 1] == 31 &&
arm_instruction[i].content[base] == 0) {
// clrex
if (instr != arm_instruction[i].content[base + 2]) {
break;
}
} else if (BITS(instr, arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) {
} else if (BITS(instr, arm_instruction[i].content[base],
arm_instruction[i].content[base + 1]) !=
arm_instruction[i].content[base + 2]) {
break;
}
base += 3;
@ -451,7 +454,9 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
if (n != 0) {
base = 0;
while (n) {
if (BITS(instr, arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {
if (BITS(instr, arm_exclusion_code[i].content[base],
arm_exclusion_code[i].content[base + 1]) !=
arm_exclusion_code[i].content[base + 2]) {
break;
}
base += 3;

View file

@ -6,15 +6,12 @@
#include "common/common_types.h"
enum class ARMDecodeStatus {
SUCCESS,
FAILURE
};
enum class ARMDecodeStatus { SUCCESS, FAILURE };
ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx);
struct InstructionSetEncodingItem {
const char *name;
const char* name;
int attribute_value;
int version;
u32 content[21];

File diff suppressed because it is too large Load diff

View file

@ -21,50 +21,48 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
*ainstr = 0xDEADC0DE; // Debugging to catch non updates
switch ((tinstr & 0xF800) >> 11) {
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
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
{
static const u32 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;
{
static const u32 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
{
static const u32 subset[4] = {
0xE3B00000, // MOVS Rd,#imm8
0xE3500000, // CMP Rd,#imm8
0xE2900000, // ADDS Rd,Rd,#imm8
0xE2500000, // SUBS Rd,Rd,#imm8
};
{
static const u32 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;
*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
@ -73,56 +71,51 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
// large subset
if ((tinstr & (1 << 10)) == 0) {
enum otype {
t_norm,
t_shift,
t_neg,
t_mul
};
enum otype { t_norm, t_shift, t_neg, t_mul };
static const struct {
u32 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
{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 {
@ -133,109 +126,106 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
Rd += 8;
switch ((tinstr & 0x03C0) >> 6) {
case 0x0: // ADD Rd,Rd,Rs
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
case 0x0: // ADD Rd,Rd,Rs
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 0x4: // CMP Rd,Rs
case 0x5: // CMP Rd,Hs
case 0x6: // CMP Hd,Rs
case 0x7: // CMP Hd,Hs
*ainstr = 0xE1500000 // base
| (Rd << 16) // Rn
|(Rs << 0); // Rm
case 0x4: // CMP Rd,Rs
case 0x5: // CMP Rd,Hs
case 0x6: // CMP Hd,Rs
case 0x7: // CMP Hd,Hs
*ainstr = 0xE1500000 // base
| (Rd << 16) // Rn
| (Rs << 0); // Rm
break;
case 0x8: // MOV Rd,Rs
case 0x9: // MOV Rd,Hs
case 0xA: // MOV Hd,Rs
case 0xB: // MOV Hd,Hs
*ainstr = 0xE1A00000 // base
|(Rd << 12) // Rd
|(Rs << 0); // Rm
case 0x8: // MOV Rd,Rs
case 0x9: // MOV Rd,Hs
case 0xA: // MOV Hd,Rs
case 0xB: // MOV Hd,Hs
*ainstr = 0xE1A00000 // base
| (Rd << 12) // Rd
| (Rs << 0); // Rm
break;
case 0xC: // BX Rs
case 0xD: // BX Hs
*ainstr = 0xE12FFF10 // base
| ((tinstr & 0x0078) >> 3); // Rd
case 0xC: // BX Rs
case 0xD: // BX Hs
*ainstr = 0xE12FFF10 // base
| ((tinstr & 0x0078) >> 3); // Rd
break;
case 0xE: // BLX
case 0xF: // BLX
*ainstr = 0xE1200030 // base
| (Rs << 0); // Rm
case 0xE: // BLX
case 0xF: // BLX
*ainstr = 0xE1200030 // base
| (Rs << 0); // Rm
break;
}
}
break;
case 9: // LDR Rd,[PC,#imm8]
*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:
{
static const u32 subset[8] = {
0xE7800000, // STR Rd,[Rb,Ro]
0xE18000B0, // STRH Rd,[Rb,Ro]
0xE7C00000, // STRB Rd,[Rb,Ro]
0xE19000D0, // LDRSB Rd,[Rb,Ro]
0xE7900000, // LDR Rd,[Rb,Ro]
0xE19000B0, // LDRH Rd,[Rb,Ro]
0xE7D00000, // LDRB Rd,[Rb,Ro]
0xE19000F0 // LDRSH Rd,[Rb,Ro]
};
case 11: {
static const u32 subset[8] = {
0xE7800000, // STR Rd,[Rb,Ro]
0xE18000B0, // STRH Rd,[Rb,Ro]
0xE7C00000, // STRB Rd,[Rb,Ro]
0xE19000D0, // LDRSB Rd,[Rb,Ro]
0xE7900000, // LDR Rd,[Rb,Ro]
0xE19000B0, // LDRH Rd,[Rb,Ro]
0xE7D00000, // LDRB Rd,[Rb,Ro]
0xE19000F0 // LDRSH Rd,[Rb,Ro]
};
*ainstr = subset[(tinstr & 0xE00) >> 9] // base
|((tinstr & 0x0007) << (12 - 0)) // Rd
|((tinstr & 0x0038) << (16 - 3)) // Rb
|((tinstr & 0x01C0) >> 6); // Ro
}
break;
*ainstr = subset[(tinstr & 0xE00) >> 9] // 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]
{
static const u32 subset[4] = {
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
}
{
static const u32 subset[4] = {
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
} break;
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 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]
*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
@ -246,14 +236,15 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
// 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
*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
// 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;
@ -261,15 +252,15 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
case 23:
if ((tinstr & 0x0F00) == 0x0000) {
// 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
*ainstr = ((tinstr & (1 << 7)) // base
? 0xE24DDF00 // SUB
: 0xE28DDF00) // ADD
| (tinstr & 0x007F); // off7
} else if ((tinstr & 0x0F00) == 0x0e00) {
// BKPT
*ainstr = 0xEF000000 // base
| BITS(tinstr, 0, 3) // imm4 field;
| (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
*ainstr = 0xEF000000 // base
| BITS(tinstr, 0, 3) // imm4 field;
| (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
} else if ((tinstr & 0x0F00) == 0x0200) {
static const u32 subset[4] = {
0xE6BF0070, // SXTH
@ -278,21 +269,21 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
0xE6EF0070, // UXTB
};
*ainstr = subset[BITS(tinstr, 6, 7)] // base
| (BITS(tinstr, 0, 2) << 12) // Rd
| BITS(tinstr, 3, 5); // Rm
*ainstr = subset[BITS(tinstr, 6, 7)] // base
| (BITS(tinstr, 0, 2) << 12) // Rd
| BITS(tinstr, 3, 5); // Rm
} else if ((tinstr & 0x0F00) == 0x600) {
if (BIT(tinstr, 5) == 0) {
// SETEND
*ainstr = 0xF1010000 // base
| (BIT(tinstr, 3) << 9); // endian specifier
*ainstr = 0xF1010000 // base
| (BIT(tinstr, 3) << 9); // endian specifier
} else {
// CPS
*ainstr = 0xF1080000 // base
| (BIT(tinstr, 0) << 6) // fiq bit
| (BIT(tinstr, 1) << 7) // irq bit
| (BIT(tinstr, 2) << 8) // abort bit
| (BIT(tinstr, 4) << 18); // enable bit
*ainstr = 0xF1080000 // base
| (BIT(tinstr, 0) << 6) // fiq bit
| (BIT(tinstr, 1) << 7) // irq bit
| (BIT(tinstr, 2) << 8) // abort bit
| (BIT(tinstr, 4) << 18); // enable bit
}
} else if ((tinstr & 0x0F00) == 0x0a00) {
static const u32 subset[4] = {
@ -307,9 +298,9 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
if (subset_index == 2) {
valid = ThumbDecodeStatus::UNDEFINED;
} else {
*ainstr = subset[subset_index] // base
| (BITS(tinstr, 0, 2) << 12) // Rd
| BITS(tinstr, 3, 5); // Rm
*ainstr = subset[subset_index] // base
| (BITS(tinstr, 0, 2) << 12) // Rd
| BITS(tinstr, 3, 5); // Rm
}
} else {
static const u32 subset[4] = {
@ -319,14 +310,13 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
0xE8BD8000 // LDMIA sp!,{rlist,pc}
};
*ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
|(tinstr & 0x00FF); // mask8
| (tinstr & 0x00FF); // mask8
}
break;
case 24: // STMIA
case 25: // LDMIA
if (tinstr & (1 << 11))
{
if (tinstr & (1 << 11)) {
unsigned int base = 0xE8900000;
unsigned int rn = BITS(tinstr, 8, 10);
@ -334,15 +324,13 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
if ((tinstr & (1 << rn)) == 0)
base |= (1 << 21);
*ainstr = base // base (LDMIA)
| (rn << 16) // Rn
| (tinstr & 0x00FF); // Register list
}
else
{
*ainstr = 0xE8A00000 // base (STMIA)
| (BITS(tinstr, 8, 10) << 16) // Rn
| (tinstr & 0x00FF); // Register list
*ainstr = base // base (LDMIA)
| (rn << 16) // Rn
| (tinstr & 0x00FF); // Register list
} else {
*ainstr = 0xE8A00000 // base (STMIA)
| (BITS(tinstr, 8, 10) << 16) // Rn
| (tinstr & 0x00FF); // Register list
}
break;

View file

@ -29,9 +29,9 @@
#include "common/common_types.h"
enum class ThumbDecodeStatus {
UNDEFINED, // Undefined Thumb instruction
DECODED, // Instruction decoded to ARM equivalent
BRANCH, // Thumb branch (already processed)
UNDEFINED, // Undefined Thumb instruction
DECODED, // Instruction decoded to ARM equivalent
BRANCH, // Thumb branch (already processed)
UNINITIALIZED,
};

File diff suppressed because it is too large Load diff

View file

@ -2,15 +2,15 @@ struct ARMul_State;
typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
enum class TransExtData {
COND = (1 << 0),
NON_BRANCH = (1 << 1),
DIRECT_BRANCH = (1 << 2),
COND = (1 << 0),
NON_BRANCH = (1 << 1),
DIRECT_BRANCH = (1 << 2),
INDIRECT_BRANCH = (1 << 3),
CALL = (1 << 4),
RET = (1 << 5),
END_OF_PAGE = (1 << 6),
THUMB = (1 << 7),
SINGLE_STEP = (1 << 8)
CALL = (1 << 4),
RET = (1 << 5),
END_OF_PAGE = (1 << 6),
THUMB = (1 << 7),
SINGLE_STEP = (1 << 8)
};
struct arm_inst {
@ -106,8 +106,7 @@ struct cps_inst {
unsigned int mode;
};
struct clrex_inst {
};
struct clrex_inst {};
struct cpy_inst {
unsigned int Rm;
@ -163,11 +162,9 @@ struct bkpt_inst {
u32 imm;
};
struct stc_inst {
};
struct stc_inst {};
struct ldc_inst {
};
struct ldc_inst {};
struct swi_inst {
unsigned int num;
@ -369,8 +366,7 @@ struct msr_inst {
unsigned int inst;
};
struct pld_inst {
};
struct pld_inst {};
struct sxtb_inst {
unsigned int Rd;
@ -475,7 +471,7 @@ struct pkh_inst {
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_INTERPRETER_STRUCT
typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr);
typedef void (*get_addr_fp_t)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr);
struct ldst_inst {
unsigned int inst;

View file

@ -16,7 +16,7 @@ enum {
R12,
R13,
LR,
R15, //PC,
R15, // PC,
CPSR_REG,
SPSR_REG,

View file

@ -2,22 +2,20 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/swap.h"
#include "common/logging/log.h"
#include "core/memory.h"
#include "core/arm/skyeye_common/armstate.h"
#include <algorithm>
#include "common/logging/log.h"
#include "common/swap.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/gdbstub/gdbstub.h"
#include "core/memory.h"
ARMul_State::ARMul_State(PrivilegeMode initial_mode)
{
ARMul_State::ARMul_State(PrivilegeMode initial_mode) {
Reset();
ChangePrivilegeMode(initial_mode);
}
void ARMul_State::ChangePrivilegeMode(u32 new_mode)
{
void ARMul_State::ChangePrivilegeMode(u32 new_mode) {
if (Mode == new_mode)
return;
@ -103,8 +101,7 @@ void ARMul_State::ChangePrivilegeMode(u32 new_mode)
}
// Performs a reset
void ARMul_State::Reset()
{
void ARMul_State::Reset() {
VFPInit(this);
// Set stack pointer to the top of the stack
@ -128,8 +125,7 @@ void ARMul_State::Reset()
}
// Resets certain MPCore CP15 values to their ARM-defined reset values.
void ARMul_State::ResetMPCoreCP15Registers()
{
void ARMul_State::ResetMPCoreCP15Registers() {
// c0
CP15[CP15_MAIN_ID] = 0x410FB024;
CP15[CP15_TLB_TYPE] = 0x00000800;
@ -185,23 +181,20 @@ void ARMul_State::ResetMPCoreCP15Registers()
CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
}
static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type)
{
static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {
if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) {
LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address);
GDBStub::Break(true);
}
}
u8 ARMul_State::ReadMemory8(u32 address) const
{
u8 ARMul_State::ReadMemory8(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
return Memory::Read8(address);
}
u16 ARMul_State::ReadMemory16(u32 address) const
{
u16 ARMul_State::ReadMemory16(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
u16 data = Memory::Read16(address);
@ -212,8 +205,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const
return data;
}
u32 ARMul_State::ReadMemory32(u32 address) const
{
u32 ARMul_State::ReadMemory32(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
u32 data = Memory::Read32(address);
@ -224,8 +216,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const
return data;
}
u64 ARMul_State::ReadMemory64(u32 address) const
{
u64 ARMul_State::ReadMemory64(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
u64 data = Memory::Read64(address);
@ -236,15 +227,13 @@ u64 ARMul_State::ReadMemory64(u32 address) const
return data;
}
void ARMul_State::WriteMemory8(u32 address, u8 data)
{
void ARMul_State::WriteMemory8(u32 address, u8 data) {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
Memory::Write8(address, data);
}
void ARMul_State::WriteMemory16(u32 address, u16 data)
{
void ARMul_State::WriteMemory16(u32 address, u16 data) {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
if (InBigEndianMode())
@ -253,8 +242,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data)
Memory::Write16(address, data);
}
void ARMul_State::WriteMemory32(u32 address, u32 data)
{
void ARMul_State::WriteMemory32(u32 address, u32 data) {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
if (InBigEndianMode())
@ -263,8 +251,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data)
Memory::Write32(address, data);
}
void ARMul_State::WriteMemory64(u32 address, u64 data)
{
void ARMul_State::WriteMemory64(u32 address, u64 data) {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
if (InBigEndianMode())
@ -273,15 +260,12 @@ void ARMul_State::WriteMemory64(u32 address, u64 data)
Memory::Write64(address, data);
}
// Reads from the CP15 registers. Used with implementation of the MRC instruction.
// Note that since the 3DS does not have the hypervisor extensions, these registers
// are not implemented.
u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const
{
u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const {
// Unprivileged registers
if (crn == 13 && opcode_1 == 0 && crm == 0)
{
if (crn == 13 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 2)
return CP15[CP15_THREAD_UPRW];
@ -289,12 +273,9 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
return CP15[CP15_THREAD_URO];
}
if (InAPrivilegedMode())
{
if (crn == 0 && opcode_1 == 0)
{
if (crm == 0)
{
if (InAPrivilegedMode()) {
if (crn == 0 && opcode_1 == 0) {
if (crm == 0) {
if (opcode_2 == 0)
return CP15[CP15_MAIN_ID];
@ -306,9 +287,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
if (opcode_2 == 5)
return CP15[CP15_CPU_ID];
}
else if (crm == 1)
{
} else if (crm == 1) {
if (opcode_2 == 0)
return CP15[CP15_PROCESSOR_FEATURE_0];
@ -329,9 +308,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
if (opcode_2 == 7)
return CP15[CP15_MEMORY_MODEL_FEATURE_3];
}
else if (crm == 2)
{
} else if (crm == 2) {
if (opcode_2 == 0)
return CP15[CP15_ISA_FEATURE_0];
@ -349,8 +326,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
}
}
if (crn == 1 && opcode_1 == 0 && crm == 0)
{
if (crn == 1 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
return CP15[CP15_CONTROL];
@ -361,8 +337,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
return CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
}
if (crn == 2 && opcode_1 == 0 && crm == 0)
{
if (crn == 2 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
return CP15[CP15_TRANSLATION_BASE_TABLE_0];
@ -376,8 +351,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
return CP15[CP15_DOMAIN_ACCESS_CONTROL];
if (crn == 5 && opcode_1 == 0 && crm == 0)
{
if (crn == 5 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
return CP15[CP15_FAULT_STATUS];
@ -385,8 +359,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
return CP15[CP15_INSTR_FAULT_STATUS];
}
if (crn == 6 && opcode_1 == 0 && crm == 0)
{
if (crn == 6 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
return CP15[CP15_FAULT_ADDRESS];
@ -400,13 +373,11 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
return CP15[CP15_DATA_CACHE_LOCKDOWN];
if (crn == 10 && opcode_1 == 0)
{
if (crn == 10 && opcode_1 == 0) {
if (crm == 0 && opcode_2 == 0)
return CP15[CP15_TLB_LOCKDOWN];
if (crm == 2)
{
if (crm == 2) {
if (opcode_2 == 0)
return CP15[CP15_PRIMARY_REGION_REMAP];
@ -415,8 +386,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
}
}
if (crn == 13 && crm == 0)
{
if (crn == 13 && crm == 0) {
if (opcode_2 == 0)
return CP15[CP15_PID];
@ -427,10 +397,8 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
return CP15[CP15_THREAD_PRW];
}
if (crn == 15)
{
if (opcode_1 == 0 && crm == 12)
{
if (crn == 15) {
if (opcode_1 == 0 && crm == 12) {
if (opcode_2 == 0)
return CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
@ -444,8 +412,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
return CP15[CP15_COUNT_1];
}
if (opcode_1 == 5 && opcode_2 == 2)
{
if (opcode_1 == 5 && opcode_2 == 2) {
if (crm == 5)
return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
@ -461,66 +428,49 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
}
}
LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2);
LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.",
crn, crm, opcode_1, opcode_2);
return 0;
}
// Write to the CP15 registers. Used with implementation of the MCR instruction.
// Note that since the 3DS does not have the hypervisor extensions, these registers
// are not implemented.
void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
{
if (InAPrivilegedMode())
{
if (crn == 1 && opcode_1 == 0 && crm == 0)
{
void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) {
if (InAPrivilegedMode()) {
if (crn == 1 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
CP15[CP15_CONTROL] = value;
else if (opcode_2 == 1)
CP15[CP15_AUXILIARY_CONTROL] = value;
else if (opcode_2 == 2)
CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
}
else if (crn == 2 && opcode_1 == 0 && crm == 0)
{
} else if (crn == 2 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
else if (opcode_2 == 1)
CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
else if (opcode_2 == 2)
CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
}
else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
{
} else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
}
else if (crn == 5 && opcode_1 == 0 && crm == 0)
{
} else if (crn == 5 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
CP15[CP15_FAULT_STATUS] = value;
else if (opcode_2 == 1)
CP15[CP15_INSTR_FAULT_STATUS] = value;
}
else if (crn == 6 && opcode_1 == 0 && crm == 0)
{
} else if (crn == 6 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
CP15[CP15_FAULT_ADDRESS] = value;
else if (opcode_2 == 1)
CP15[CP15_WFAR] = value;
}
else if (crn == 7 && opcode_1 == 0)
{
if (crm == 0 && opcode_2 == 4)
{
} else if (crn == 7 && opcode_1 == 0) {
if (crm == 0 && opcode_2 == 4) {
CP15[CP15_WAIT_FOR_INTERRUPT] = value;
}
else if (crm == 4 && opcode_2 == 0)
{
} else if (crm == 4 && opcode_2 == 0) {
// NOTE: Not entirely accurate. This should do permission checks.
CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
}
else if (crm == 5)
{
} else if (crm == 5) {
if (opcode_2 == 0)
CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
else if (opcode_2 == 1)
@ -531,31 +481,23 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
else if (opcode_2 == 7)
CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
}
else if (crm == 6)
{
} else if (crm == 6) {
if (opcode_2 == 0)
CP15[CP15_INVALIDATE_DATA_CACHE] = value;
else if (opcode_2 == 1)
CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
else if (opcode_2 == 2)
CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
}
else if (crm == 7 && opcode_2 == 0)
{
} else if (crm == 7 && opcode_2 == 0) {
CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
}
else if (crm == 10)
{
} else if (crm == 10) {
if (opcode_2 == 0)
CP15[CP15_CLEAN_DATA_CACHE] = value;
else if (opcode_2 == 1)
CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
else if (opcode_2 == 2)
CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
}
else if (crm == 14)
{
} else if (crm == 14) {
if (opcode_2 == 0)
CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
else if (opcode_2 == 1)
@ -563,11 +505,8 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
else if (opcode_2 == 2)
CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
}
}
else if (crn == 8 && opcode_1 == 0)
{
if (crm == 5)
{
} else if (crn == 8 && opcode_1 == 0) {
if (crm == 5) {
if (opcode_2 == 0)
CP15[CP15_INVALIDATE_ITLB] = value;
else if (opcode_2 == 1)
@ -576,9 +515,7 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
else if (opcode_2 == 3)
CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
}
else if (crm == 6)
{
} else if (crm == 6) {
if (opcode_2 == 0)
CP15[CP15_INVALIDATE_DTLB] = value;
else if (opcode_2 == 1)
@ -587,9 +524,7 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
else if (opcode_2 == 3)
CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
}
else if (crm == 7)
{
} else if (crm == 7) {
if (opcode_2 == 0)
CP15[CP15_INVALIDATE_UTLB] = value;
else if (opcode_2 == 1)
@ -599,27 +534,18 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
else if (opcode_2 == 3)
CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
}
}
else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
{
} else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
}
else if (crn == 10 && opcode_1 == 0)
{
if (crm == 0 && opcode_2 == 0)
{
} else if (crn == 10 && opcode_1 == 0) {
if (crm == 0 && opcode_2 == 0) {
CP15[CP15_TLB_LOCKDOWN] = value;
}
else if (crm == 2)
{
} else if (crm == 2) {
if (opcode_2 == 0)
CP15[CP15_PRIMARY_REGION_REMAP] = value;
else if (opcode_2 == 1)
CP15[CP15_NORMAL_REGION_REMAP] = value;
}
}
else if (crn == 13 && opcode_1 == 0 && crm == 0)
{
} else if (crn == 13 && opcode_1 == 0 && crm == 0) {
if (opcode_2 == 0)
CP15[CP15_PID] = value;
else if (opcode_2 == 1)
@ -628,11 +554,8 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
CP15[CP15_THREAD_URO] = value;
else if (opcode_2 == 4)
CP15[CP15_THREAD_PRW] = value;
}
else if (crn == 15)
{
if (opcode_1 == 0 && crm == 12)
{
} else if (crn == 15) {
if (opcode_1 == 0 && crm == 12) {
if (opcode_2 == 0)
CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
else if (opcode_2 == 1)
@ -641,50 +564,34 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
CP15[CP15_COUNT_0] = value;
else if (opcode_2 == 3)
CP15[CP15_COUNT_1] = value;
}
else if (opcode_1 == 5)
{
if (crm == 4)
{
} else if (opcode_1 == 5) {
if (crm == 4) {
if (opcode_2 == 2)
CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
else if (opcode_2 == 4)
CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
}
else if (crm == 5 && opcode_2 == 2)
{
} else if (crm == 5 && opcode_2 == 2) {
CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
}
else if (crm == 6 && opcode_2 == 2)
{
} else if (crm == 6 && opcode_2 == 2) {
CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
}
else if (crm == 7 && opcode_2 == 2)
{
} else if (crm == 7 && opcode_2 == 2) {
CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
}
}
else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
{
} else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) {
CP15[CP15_TLB_DEBUG_CONTROL] = value;
}
}
}
// Unprivileged registers
if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4)
{
if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) {
CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
}
else if (crn == 7 && opcode_1 == 0 && crm == 10)
{
} else if (crn == 7 && opcode_1 == 0 && crm == 10) {
if (opcode_2 == 4)
CP15[CP15_DATA_SYNC_BARRIER] = value;
else if (opcode_2 == 5)
CP15[CP15_DATA_MEMORY_BARRIER] = value;
}
else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
{
} else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) {
CP15[CP15_THREAD_UPRW] = value;
}
}

View file

@ -24,75 +24,70 @@
#include "core/arm/skyeye_common/arm_regformat.h"
// Signal levels
enum {
LOW = 0,
HIGH = 1,
LOWHIGH = 1,
HIGHLOW = 2
};
enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 };
// Cache types
enum {
NONCACHE = 0,
NONCACHE = 0,
DATACACHE = 1,
INSTCACHE = 2,
};
// ARM privilege modes
enum PrivilegeMode {
USER32MODE = 16,
FIQ32MODE = 17,
IRQ32MODE = 18,
SVC32MODE = 19,
ABORT32MODE = 23,
UNDEF32MODE = 27,
USER32MODE = 16,
FIQ32MODE = 17,
IRQ32MODE = 18,
SVC32MODE = 19,
ABORT32MODE = 23,
UNDEF32MODE = 27,
SYSTEM32MODE = 31
};
// ARM privilege mode register banks
enum {
USERBANK = 0,
FIQBANK = 1,
IRQBANK = 2,
SVCBANK = 3,
ABORTBANK = 4,
UNDEFBANK = 5,
DUMMYBANK = 6,
USERBANK = 0,
FIQBANK = 1,
IRQBANK = 2,
SVCBANK = 3,
ABORTBANK = 4,
UNDEFBANK = 5,
DUMMYBANK = 6,
SYSTEMBANK = 7
};
// Hardware vector addresses
enum {
ARMResetV = 0,
ARMResetV = 0,
ARMUndefinedInstrV = 4,
ARMSWIV = 8,
ARMPrefetchAbortV = 12,
ARMDataAbortV = 16,
ARMAddrExceptnV = 20,
ARMIRQV = 24,
ARMFIQV = 28,
ARMErrorV = 32, // This is an offset, not an address!
ARMSWIV = 8,
ARMPrefetchAbortV = 12,
ARMDataAbortV = 16,
ARMAddrExceptnV = 20,
ARMIRQV = 24,
ARMFIQV = 28,
ARMErrorV = 32, // This is an offset, not an address!
ARMul_ResetV = ARMResetV,
ARMul_ResetV = ARMResetV,
ARMul_UndefinedInstrV = ARMUndefinedInstrV,
ARMul_SWIV = ARMSWIV,
ARMul_PrefetchAbortV = ARMPrefetchAbortV,
ARMul_DataAbortV = ARMDataAbortV,
ARMul_AddrExceptnV = ARMAddrExceptnV,
ARMul_IRQV = ARMIRQV,
ARMul_FIQV = ARMFIQV
ARMul_SWIV = ARMSWIV,
ARMul_PrefetchAbortV = ARMPrefetchAbortV,
ARMul_DataAbortV = ARMDataAbortV,
ARMul_AddrExceptnV = ARMAddrExceptnV,
ARMul_IRQV = ARMIRQV,
ARMul_FIQV = ARMFIQV
};
// Coprocessor status values
enum {
ARMul_FIRST = 0,
ARMul_TRANSFER = 1,
ARMul_BUSY = 2,
ARMul_DATA = 3,
ARMul_FIRST = 0,
ARMul_TRANSFER = 1,
ARMul_BUSY = 2,
ARMul_DATA = 3,
ARMul_INTERRUPT = 4,
ARMul_DONE = 0,
ARMul_CANT = 1,
ARMul_INC = 3
ARMul_DONE = 0,
ARMul_CANT = 1,
ARMul_INC = 3
};
// Instruction condition codes
@ -136,15 +131,13 @@ enum : u32 {
// Values for Emulate.
enum {
STOP = 0, // Stop
STOP = 0, // Stop
CHANGEMODE = 1, // Change mode
ONCE = 2, // Execute just one iteration
RUN = 3 // Continuous execution
ONCE = 2, // Execute just one iteration
RUN = 3 // Continuous execution
};
struct ARMul_State final
{
struct ARMul_State final {
public:
explicit ARMul_State(PrivilegeMode initial_mode);
@ -193,7 +186,7 @@ public:
return TFlag ? 2 : 4;
}
std::array<u32, 16> Reg{}; // The current register file
std::array<u32, 16> Reg{}; // The current register file
std::array<u32, 2> Reg_usr{};
std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC
std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT
@ -216,8 +209,8 @@ public:
u32 Spsr_copy;
u32 phys_pc;
u32 Mode; // The current mode
u32 Bank; // The current register bank
u32 Mode; // The current mode
u32 Bank; // The current register bank
u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
unsigned int shifter_carry_out;
@ -243,8 +236,10 @@ public:
private:
void ResetMPCoreCP15Registers();
// Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
// This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
// Defines a reservation granule of 2 words, which protects the first 2 words starting at the
// tag.
// This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough
// to
// support LDR/STREXD.
static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;

View file

@ -22,8 +22,7 @@
#include "core/arm/skyeye_common/armsupp.h"
// Unsigned sum of absolute difference
u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
{
u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) {
if (left > right)
return left - right;
@ -31,8 +30,8 @@ u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
}
// Add with carry, indicates if a carry-out or signed overflow occurred.
u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred)
{
u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred,
bool* overflow_occurred) {
u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
u64 result = (unsigned_sum & 0xFFFFFFFF);
@ -47,22 +46,17 @@ u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bo
}
// Compute whether an addition of A and B, giving RESULT, overflowed.
bool AddOverflow(u32 a, u32 b, u32 result)
{
return ((NEG(a) && NEG(b) && POS(result)) ||
(POS(a) && POS(b) && NEG(result)));
bool AddOverflow(u32 a, u32 b, u32 result) {
return ((NEG(a) && NEG(b) && POS(result)) || (POS(a) && POS(b) && NEG(result)));
}
// Compute whether a subtraction of A and B, giving RESULT, overflowed.
bool SubOverflow(u32 a, u32 b, u32 result)
{
return ((NEG(a) && POS(b) && POS(result)) ||
(POS(a) && NEG(b) && NEG(result)));
bool SubOverflow(u32 a, u32 b, u32 result) {
return ((NEG(a) && POS(b) && POS(result)) || (POS(a) && NEG(b) && NEG(result)));
}
// Returns true if the Q flag should be set as a result of overflow.
bool ARMul_AddOverflowQ(u32 a, u32 b)
{
bool ARMul_AddOverflowQ(u32 a, u32 b) {
u32 result = a + b;
if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
return true;
@ -71,8 +65,7 @@ bool ARMul_AddOverflowQ(u32 a, u32 b)
}
// 8-bit signed saturated addition
u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
{
u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) {
u8 result = left + right;
if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
@ -86,8 +79,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
}
// 8-bit signed saturated subtraction
u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
{
u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) {
u8 result = left - right;
if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
@ -101,8 +93,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
}
// 16-bit signed saturated addition
u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
{
u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) {
u16 result = left + right;
if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
@ -116,8 +107,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
}
// 16-bit signed saturated subtraction
u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
{
u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) {
u16 result = left - right;
if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
@ -131,8 +121,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
}
// 8-bit unsigned saturated addition
u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
{
u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) {
u8 result = left + right;
if (result < left)
@ -142,8 +131,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
}
// 16-bit unsigned saturated addition
u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
{
u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) {
u16 result = left + right;
if (result < left)
@ -153,8 +141,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
}
// 8-bit unsigned saturated subtraction
u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
{
u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) {
if (left <= right)
return 0;
@ -162,8 +149,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
}
// 16-bit unsigned saturated subtraction
u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
{
u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) {
if (left <= right)
return 0;
@ -171,16 +157,14 @@ u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
}
// Signed saturation.
u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
{
u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
const u32 max = (1 << shift) - 1;
const s32 top = (value >> shift);
if (top > 0) {
*saturation_occurred = true;
return max;
}
else if (top < -1) {
} else if (top < -1) {
*saturation_occurred = true;
return ~max;
}
@ -190,8 +174,7 @@ u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
}
// Unsigned saturation
u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
{
u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
const u32 max = (1 << shift) - 1;
if (value < 0) {

View file

@ -9,8 +9,8 @@
#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
#define BIT(s, n) ((s >> (n)) & 1)
#define POS(i) ( (~(i)) >> 31 )
#define NEG(i) ( (i) >> 31 )
#define POS(i) ((~(i)) >> 31)
#define NEG(i) ((i) >> 31)
bool AddOverflow(u32, u32, u32);
bool SubOverflow(u32, u32, u32);

View file

@ -10,74 +10,74 @@
// ARM11 MPCore FPSID Information
// Note that these are used as values and not as flags.
enum : u32 {
VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0
VFP_FPSID_SW = 0, // Software emulation bit value
VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number
VFP_FPSID_PARTNUM = 0x20, // Part number
VFP_FPSID_VARIANT = 0xB, // Variant number
VFP_FPSID_REVISION = 0x4 // Revision number
VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0
VFP_FPSID_SW = 0, // Software emulation bit value
VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number
VFP_FPSID_PARTNUM = 0x20, // Part number
VFP_FPSID_VARIANT = 0xB, // Variant number
VFP_FPSID_REVISION = 0x4 // Revision number
};
// FPEXC bits
enum : u32 {
FPEXC_EX = (1U << 31U),
FPEXC_EN = (1 << 30),
FPEXC_DEX = (1 << 29),
FPEXC_FP2V = (1 << 28),
FPEXC_VV = (1 << 27),
FPEXC_TFV = (1 << 26),
FPEXC_LENGTH_BIT = (8),
FPEXC_EX = (1U << 31U),
FPEXC_EN = (1 << 30),
FPEXC_DEX = (1 << 29),
FPEXC_FP2V = (1 << 28),
FPEXC_VV = (1 << 27),
FPEXC_TFV = (1 << 26),
FPEXC_LENGTH_BIT = (8),
FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT),
FPEXC_IDF = (1 << 7),
FPEXC_IXF = (1 << 4),
FPEXC_UFF = (1 << 3),
FPEXC_OFF = (1 << 2),
FPEXC_DZF = (1 << 1),
FPEXC_IOF = (1 << 0),
FPEXC_TRAP_MASK = (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF)
FPEXC_IDF = (1 << 7),
FPEXC_IXF = (1 << 4),
FPEXC_UFF = (1 << 3),
FPEXC_OFF = (1 << 2),
FPEXC_DZF = (1 << 1),
FPEXC_IOF = (1 << 0),
FPEXC_TRAP_MASK = (FPEXC_IDF | FPEXC_IXF | FPEXC_UFF | FPEXC_OFF | FPEXC_DZF | FPEXC_IOF)
};
// FPSCR Flags
enum : u32 {
FPSCR_NFLAG = (1U << 31U), // Negative condition flag
FPSCR_ZFLAG = (1 << 30), // Zero condition flag
FPSCR_CFLAG = (1 << 29), // Carry condition flag
FPSCR_VFLAG = (1 << 28), // Overflow condition flag
FPSCR_NFLAG = (1U << 31U), // Negative condition flag
FPSCR_ZFLAG = (1 << 30), // Zero condition flag
FPSCR_CFLAG = (1 << 29), // Carry condition flag
FPSCR_VFLAG = (1 << 28), // Overflow condition flag
FPSCR_QC = (1 << 27), // Cumulative saturation bit
FPSCR_AHP = (1 << 26), // Alternative half-precision control bit
FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit
FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit
FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask
FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask
FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask
FPSCR_QC = (1 << 27), // Cumulative saturation bit
FPSCR_AHP = (1 << 26), // Alternative half-precision control bit
FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit
FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit
FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask
FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask
FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask
FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable.
FPSCR_IXE = (1 << 12), // Inexact exception trap enable
FPSCR_UFE = (1 << 11), // Undeflow exception trap enable
FPSCR_OFE = (1 << 10), // Overflow exception trap enable
FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable
FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable
FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable.
FPSCR_IXE = (1 << 12), // Inexact exception trap enable
FPSCR_UFE = (1 << 11), // Undeflow exception trap enable
FPSCR_OFE = (1 << 10), // Overflow exception trap enable
FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable
FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable
FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit
FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit
FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit
FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit
FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit
FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit
FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit
FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit
FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit
FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit
FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit
FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit
};
// FPSCR bit offsets
enum : u32 {
FPSCR_RMODE_BIT = 22,
FPSCR_RMODE_BIT = 22,
FPSCR_STRIDE_BIT = 20,
FPSCR_LENGTH_BIT = 16,
};
// FPSCR rounding modes
enum : u32 {
FPSCR_ROUND_NEAREST = (0 << 22),
FPSCR_ROUND_PLUSINF = (1 << 22),
FPSCR_ROUND_NEAREST = (0 << 22),
FPSCR_ROUND_PLUSINF = (1 << 22),
FPSCR_ROUND_MINUSINF = (2 << 22),
FPSCR_ROUND_TOZERO = (3 << 22)
FPSCR_ROUND_TOZERO = (3 << 22)
};

View file

@ -28,15 +28,14 @@
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
void VFPInit(ARMul_State* state)
{
state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
void VFPInit(ARMul_State* state) {
state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN << 24 | VFP_FPSID_SW << 23 | VFP_FPSID_SUBARCH << 16 |
VFP_FPSID_PARTNUM << 8 | VFP_FPSID_VARIANT << 4 | VFP_FPSID_REVISION;
state->VFP[VFP_FPEXC] = 0;
state->VFP[VFP_FPSCR] = 0;
// ARM11 MPCore instruction register reset values.
state->VFP[VFP_FPINST] = 0xEE000A00;
state->VFP[VFP_FPINST] = 0xEE000A00;
state->VFP[VFP_FPINST2] = 0;
// ARM11 MPCore feature register values.
@ -44,104 +43,80 @@ void VFPInit(ARMul_State* state)
state->VFP[VFP_MVFR1] = 0;
}
void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value)
{
if (to_arm)
{
void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) {
if (to_arm) {
*value = state->ExtReg[n];
}
else
{
} else {
state->ExtReg[n] = *value;
}
}
void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2)
{
if (to_arm)
{
*value2 = state->ExtReg[n*2+1];
*value1 = state->ExtReg[n*2];
}
else
{
state->ExtReg[n*2+1] = *value2;
state->ExtReg[n*2] = *value1;
void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
if (to_arm) {
*value2 = state->ExtReg[n * 2 + 1];
*value1 = state->ExtReg[n * 2];
} else {
state->ExtReg[n * 2 + 1] = *value2;
state->ExtReg[n * 2] = *value1;
}
}
void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2)
{
if (to_arm)
{
*value1 = state->ExtReg[n+0];
*value2 = state->ExtReg[n+1];
}
else
{
state->ExtReg[n+0] = *value1;
state->ExtReg[n+1] = *value2;
void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
if (to_arm) {
*value1 = state->ExtReg[n + 0];
*value2 = state->ExtReg[n + 1];
} else {
state->ExtReg[n + 0] = *value1;
state->ExtReg[n + 1] = *value2;
}
}
void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm)
{
if (single)
{
void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) {
if (single) {
state->ExtReg[d] = imm;
}
else
{
} else {
/* Check endian please */
state->ExtReg[d*2+1] = imm;
state->ExtReg[d*2] = 0;
state->ExtReg[d * 2 + 1] = imm;
state->ExtReg[d * 2] = 0;
}
}
void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m)
{
if (single)
{
void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) {
if (single) {
state->ExtReg[d] = state->ExtReg[m];
}
else
{
} else {
/* Check endian please */
state->ExtReg[d*2+1] = state->ExtReg[m*2+1];
state->ExtReg[d*2] = state->ExtReg[m*2];
state->ExtReg[d * 2 + 1] = state->ExtReg[m * 2 + 1];
state->ExtReg[d * 2] = state->ExtReg[m * 2];
}
}
/* Miscellaneous functions */
s32 vfp_get_float(ARMul_State* state, unsigned int reg)
{
s32 vfp_get_float(ARMul_State* state, unsigned int reg) {
LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]);
return state->ExtReg[reg];
}
void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg)
{
void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) {
LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val);
state->ExtReg[reg] = val;
}
u64 vfp_get_double(ARMul_State* state, unsigned int reg)
{
u64 result = ((u64) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
u64 vfp_get_double(ARMul_State* state, unsigned int reg) {
u64 result = ((u64)state->ExtReg[reg * 2 + 1]) << 32 | state->ExtReg[reg * 2];
LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result);
return result;
}
void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg)
{
LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2, (u32)(val >> 32), (u32)(val & 0xffffffff));
state->ExtReg[reg*2] = (u32) (val & 0xffffffff);
state->ExtReg[reg*2+1] = (u32) (val>>32);
void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) {
LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2,
(u32)(val >> 32), (u32)(val & 0xffffffff));
state->ExtReg[reg * 2] = (u32)(val & 0xffffffff);
state->ExtReg[reg * 2 + 1] = (u32)(val >> 32);
}
/*
* Process bitmask of exception conditions. (from vfpmodule.c)
*/
void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr)
{
void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) {
LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions);
if (exceptions == VFP_EXCEPTION_ERROR) {
@ -154,8 +129,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
* Comparison instructions always return at least one of
* these flags set.
*/
if (exceptions & (FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG))
fpscr &= ~(FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG);
if (exceptions & (FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG))
fpscr &= ~(FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG);
fpscr |= exceptions;

View file

@ -37,56 +37,56 @@
#include "core/arm/skyeye_common/armstate.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#define do_div(n, base) {n/=base;}
#define do_div(n, base) \
{ n /= base; }
enum : u32 {
FOP_MASK = 0x00b00040,
FOP_FMAC = 0x00000000,
FOP_MASK = 0x00b00040,
FOP_FMAC = 0x00000000,
FOP_FNMAC = 0x00000040,
FOP_FMSC = 0x00100000,
FOP_FMSC = 0x00100000,
FOP_FNMSC = 0x00100040,
FOP_FMUL = 0x00200000,
FOP_FMUL = 0x00200000,
FOP_FNMUL = 0x00200040,
FOP_FADD = 0x00300000,
FOP_FSUB = 0x00300040,
FOP_FDIV = 0x00800000,
FOP_EXT = 0x00b00040
FOP_FADD = 0x00300000,
FOP_FSUB = 0x00300040,
FOP_FDIV = 0x00800000,
FOP_EXT = 0x00b00040
};
#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
enum : u32 {
FEXT_MASK = 0x000f0080,
FEXT_FCPY = 0x00000000,
FEXT_FABS = 0x00000080,
FEXT_FNEG = 0x00010000,
FEXT_FSQRT = 0x00010080,
FEXT_FCMP = 0x00040000,
FEXT_FCMPE = 0x00040080,
FEXT_FCMPZ = 0x00050000,
FEXT_MASK = 0x000f0080,
FEXT_FCPY = 0x00000000,
FEXT_FABS = 0x00000080,
FEXT_FNEG = 0x00010000,
FEXT_FSQRT = 0x00010080,
FEXT_FCMP = 0x00040000,
FEXT_FCMPE = 0x00040080,
FEXT_FCMPZ = 0x00050000,
FEXT_FCMPEZ = 0x00050080,
FEXT_FCVT = 0x00070080,
FEXT_FUITO = 0x00080000,
FEXT_FSITO = 0x00080080,
FEXT_FTOUI = 0x000c0000,
FEXT_FCVT = 0x00070080,
FEXT_FUITO = 0x00080000,
FEXT_FSITO = 0x00080080,
FEXT_FTOUI = 0x000c0000,
FEXT_FTOUIZ = 0x000c0080,
FEXT_FTOSI = 0x000d0000,
FEXT_FTOSI = 0x000d0000,
FEXT_FTOSIZ = 0x000d0080
};
#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
#define vfp_single(inst) (((inst)&0x0000f00) == 0xa00)
inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
{
inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) {
if (shift) {
if (shift < 32)
val = val >> shift | ((val << (32 - shift)) != 0);
@ -96,8 +96,7 @@ inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
return val;
}
inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
{
inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) {
if (shift) {
if (shift < 64)
val = val >> shift | ((val << (64 - shift)) != 0);
@ -107,8 +106,7 @@ inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
return val;
}
inline u32 vfp_hi64to32jamming(u64 val)
{
inline u32 vfp_hi64to32jamming(u64 val) {
u32 v;
u32 highval = val >> 32;
u32 lowval = val & 0xffffffff;
@ -121,24 +119,21 @@ inline u32 vfp_hi64to32jamming(u64 val)
return v;
}
inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
{
inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) {
*resl = nl + ml;
*resh = nh + mh;
if (*resl < nl)
*resh += 1;
}
inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
{
inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) {
*resl = nl - ml;
*resh = nh - mh;
if (*resl > nl)
*resh -= 1;
}
inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
{
inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) {
u32 nh, nl, mh, ml;
u64 rh, rma, rmb, rl;
@ -164,21 +159,18 @@ inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
*resh = rh;
}
inline void shift64left(u64* resh, u64* resl, u64 n)
{
inline void shift64left(u64* resh, u64* resl, u64 n) {
*resh = n >> 63;
*resl = n << 1;
}
inline u64 vfp_hi64multiply64(u64 n, u64 m)
{
inline u64 vfp_hi64multiply64(u64 n, u64 m) {
u64 rh, rl;
mul64to128(&rh, &rl, n, m);
return rh | (rl != 0);
}
inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
{
inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) {
u64 mh, ml, remh, reml, termh, terml, z;
if (nh >= m)
@ -213,9 +205,9 @@ inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
// Single-precision
struct vfp_single {
s16 exponent;
u16 sign;
u32 significand;
s16 exponent;
u16 sign;
u32 significand;
};
// VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
@ -224,33 +216,33 @@ struct vfp_single {
// which are not propagated to the float upon packing.
#define VFP_SINGLE_MANTISSA_BITS (23)
#define VFP_SINGLE_EXPONENT_BITS (8)
#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1)
// The bit in an unpacked float which indicates that it is a quiet NaN
#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
// Operations on packed single-precision numbers
#define vfp_single_packed_sign(v) ((v) & 0x80000000)
#define vfp_single_packed_negate(v) ((v) ^ 0x80000000)
#define vfp_single_packed_abs(v) ((v) & ~0x80000000)
#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
#define vfp_single_packed_sign(v) ((v)&0x80000000)
#define vfp_single_packed_negate(v) ((v) ^ 0x80000000)
#define vfp_single_packed_abs(v) ((v) & ~0x80000000)
#define vfp_single_packed_exponent(v) \
(((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
enum : u32 {
VFP_NUMBER = (1 << 0),
VFP_ZERO = (1 << 1),
VFP_DENORMAL = (1 << 2),
VFP_INFINITY = (1 << 3),
VFP_NAN = (1 << 4),
VFP_NUMBER = (1 << 0),
VFP_ZERO = (1 << 1),
VFP_DENORMAL = (1 << 2),
VFP_INFINITY = (1 << 3),
VFP_NAN = (1 << 4),
VFP_NAN_SIGNAL = (1 << 5),
VFP_QNAN = (VFP_NAN),
VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL)
VFP_QNAN = (VFP_NAN),
VFP_SNAN = (VFP_NAN | VFP_NAN_SIGNAL)
};
inline int vfp_single_type(const vfp_single* s)
{
inline int vfp_single_type(const vfp_single* s) {
int type = VFP_NUMBER;
if (s->exponent == 255) {
if (s->significand == 0)
@ -271,11 +263,9 @@ inline int vfp_single_type(const vfp_single* s)
// Unpack a single-precision float. Note that this returns the magnitude
// of the single-precision float mantissa with the 1. if necessary,
// aligned to bit 30.
inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr)
{
inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) {
u32 exceptions = 0;
s->sign = vfp_single_packed_sign(val) >> 16,
s->exponent = vfp_single_packed_exponent(val);
s->sign = vfp_single_packed_sign(val) >> 16, s->exponent = vfp_single_packed_exponent(val);
u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
if (s->exponent && s->exponent != 255)
@ -295,22 +285,20 @@ inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr)
// Re-pack a single-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
inline s32 vfp_single_pack(const vfp_single* s)
{
u32 val = (s->sign << 16) +
(s->exponent << VFP_SINGLE_MANTISSA_BITS) +
inline s32 vfp_single_pack(const vfp_single* s) {
u32 val = (s->sign << 16) + (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
(s->significand >> VFP_SINGLE_LOW_BITS);
return (s32)val;
}
u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, const char* func);
u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr,
const char* func);
// Double-precision
struct vfp_double {
s16 exponent;
u16 sign;
u64 significand;
s16 exponent;
u16 sign;
u64 significand;
};
// VFP_REG_ZERO is a special register number for vfp_get_double
@ -324,21 +312,21 @@ struct vfp_double {
#define VFP_DOUBLE_MANTISSA_BITS (52)
#define VFP_DOUBLE_EXPONENT_BITS (11)
#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1)
// The bit in an unpacked double which indicates that it is a quiet NaN
#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
// Operations on packed single-precision numbers
#define vfp_double_packed_sign(v) ((v) & (1ULL << 63))
#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63))
#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63))
#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
#define vfp_double_packed_sign(v) ((v) & (1ULL << 63))
#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63))
#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63))
#define vfp_double_packed_exponent(v) \
(((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
inline int vfp_double_type(const vfp_double* s)
{
inline int vfp_double_type(const vfp_double* s) {
int type = VFP_NUMBER;
if (s->exponent == 2047) {
if (s->significand == 0)
@ -359,8 +347,7 @@ inline int vfp_double_type(const vfp_double* s)
// Unpack a double-precision float. Note that this returns the magnitude
// of the double-precision float mantissa with the 1. if necessary,
// aligned to bit 62.
inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr)
{
inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) {
u32 exceptions = 0;
s->sign = vfp_double_packed_sign(val) >> 48;
s->exponent = vfp_double_packed_exponent(val);
@ -383,10 +370,8 @@ inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr)
// Re-pack a double-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
inline s64 vfp_double_pack(const vfp_double* s)
{
u64 val = ((u64)s->sign << 48) +
((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
inline s64 vfp_double_pack(const vfp_double* s) {
u64 val = ((u64)s->sign << 48) + ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
(s->significand >> VFP_DOUBLE_LOW_BITS);
return (s64)val;
}
@ -407,20 +392,14 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
// OP_SD - The instruction exceptionally writes to a single precision result.
// OP_DD - The instruction exceptionally writes to a double precision result.
// OP_SM - The instruction exceptionally reads from a single precision operand.
enum : u32 {
OP_SCALAR = (1 << 0),
OP_SD = (1 << 1),
OP_DD = (1 << 1),
OP_SM = (1 << 2)
};
enum : u32 { OP_SCALAR = (1 << 0), OP_SD = (1 << 1), OP_DD = (1 << 1), OP_SM = (1 << 2) };
struct op {
u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
u32 (*const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
u32 flags;
};
inline u32 fls(u32 x)
{
inline u32 fls(u32 x) {
int r = 32;
if (!x)
@ -446,9 +425,9 @@ inline u32 fls(u32 x)
r -= 1;
}
return r;
}
u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double *vdm, u32 fpscr);
u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, const char* func);
u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr,
const char* func);

View file

@ -51,26 +51,22 @@
* ===========================================================================
*/
#include "core/arm/skyeye_common/vfp/vfp.h"
#include <algorithm>
#include "common/logging/log.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
static struct vfp_double vfp_double_default_qnan = {
2047,
0,
VFP_DOUBLE_SIGNIFICAND_QNAN,
2047, 0, VFP_DOUBLE_SIGNIFICAND_QNAN,
};
static void vfp_double_dump(const char *str, struct vfp_double *d)
{
LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx",
str, d->sign != 0, d->exponent, d->significand);
static void vfp_double_dump(const char* str, struct vfp_double* d) {
LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx", str, d->sign != 0,
d->exponent, d->significand);
}
static void vfp_double_normalise_denormal(struct vfp_double *vd)
{
static void vfp_double_normalise_denormal(struct vfp_double* vd) {
int bits = 31 - fls((u32)(vd->significand >> 32));
if (bits == 31)
bits = 63 - fls((u32)vd->significand);
@ -85,8 +81,8 @@ static void vfp_double_normalise_denormal(struct vfp_double *vd)
vfp_double_dump("normalise_denormal: out", vd);
}
u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, const char *func)
{
u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double* vd, u32 fpscr,
const char* func) {
u64 significand, incr;
int exponent, shift, underflow;
u32 rmode;
@ -193,7 +189,7 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd,
vd->exponent = 2045;
vd->significand = 0x7fffffffffffffffULL;
} else {
vd->exponent = 2047; /* infinity */
vd->exponent = 2047; /* infinity */
vd->significand = 0;
}
} else {
@ -211,8 +207,7 @@ pack:
vfp_double_dump("pack: final", vd);
{
s64 d = vfp_double_pack(vd);
LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func,
dd, d, exceptions);
LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func, dd, d, exceptions);
vfp_put_double(state, d, dd);
}
return exceptions;
@ -222,11 +217,9 @@ pack:
* Propagate the NaN, setting exceptions if it is signalling.
* 'n' is always a NaN. 'm' may be a number, NaN or infinity.
*/
static u32
vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
struct vfp_double *vdm, u32 fpscr)
{
struct vfp_double *nan;
static u32 vfp_propagate_nan(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm,
u32 fpscr) {
struct vfp_double* nan;
int tn, tm = 0;
tn = vfp_double_type(vdn);
@ -266,29 +259,25 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
/*
* Extended operations
*/
static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd);
return 0;
}
static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
vfp_put_double(state, vfp_get_double(state, dm), dd);
return 0;
}
static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd);
return 0;
}
static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
vfp_double vdm, vdd, *vdp;
int ret, tm;
@ -297,17 +286,17 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32
exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr);
tm = vfp_double_type(&vdm);
if (tm & (VFP_NAN|VFP_INFINITY)) {
if (tm & (VFP_NAN | VFP_INFINITY)) {
vdp = &vdd;
if (tm & VFP_NAN)
ret = vfp_propagate_nan(vdp, &vdm, nullptr, fpscr);
else if (vdm.sign == 0) {
sqrt_copy:
sqrt_copy:
vdp = &vdm;
ret = 0;
} else {
sqrt_invalid:
sqrt_invalid:
vdp = &vfp_double_default_qnan;
ret = FPSCR_IOC;
}
@ -381,8 +370,7 @@ sqrt_invalid:
* Greater than := C
* Unordered := CV
*/
static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr)
{
static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr) {
s64 d, m;
u32 ret = 0;
@ -390,7 +378,8 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
m = vfp_get_double(state, dm);
if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
ret |= FPSCR_CFLAG | FPSCR_VFLAG;
if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
if (signal_on_qnan ||
!(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
/*
* Signalling NaN, or signalling on quiet NaN
*/
@ -400,7 +389,8 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
d = vfp_get_double(state, dd);
if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
ret |= FPSCR_CFLAG | FPSCR_VFLAG;
if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
if (signal_on_qnan ||
!(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
/*
* Signalling NaN, or signalling on quiet NaN
*/
@ -408,13 +398,13 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
}
if (ret == 0) {
//printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
// printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
if (d == m || vfp_double_packed_abs(d | m) == 0) {
/*
* equal
*/
ret |= FPSCR_ZFLAG | FPSCR_CFLAG;
//printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
// printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
} else if (vfp_double_packed_sign(d ^ m)) {
/*
* different signs
@ -446,32 +436,27 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
return ret;
}
static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_compare(state, dd, 0, dm, fpscr);
}
static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_compare(state, dd, 1, dm, fpscr);
}
static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr);
}
static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
}
static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
struct vfp_double vdm;
struct vfp_single vsd;
int tm;
@ -497,7 +482,7 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32
/*
* If we have an infinity or a NaN, the exponent must be 255
*/
if (tm & (VFP_INFINITY|VFP_NAN)) {
if (tm & (VFP_INFINITY | VFP_NAN)) {
vsd.exponent = 255;
if (tm == VFP_QNAN)
vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
@ -515,8 +500,7 @@ pack_nan:
return exceptions;
}
static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
struct vfp_double vdm;
u32 exceptions = 0;
u32 m = vfp_get_float(state, dm);
@ -530,8 +514,7 @@ static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32
return exceptions;
}
static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
struct vfp_double vdm;
u32 exceptions = 0;
u32 m = vfp_get_float(state, dm);
@ -545,8 +528,7 @@ static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32
return exceptions;
}
static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
struct vfp_double vdm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
@ -628,14 +610,13 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
return exceptions;
}
static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
return vfp_double_ftoui(state, sd, unused, dm,
(fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
}
static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
struct vfp_double vdm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
@ -661,7 +642,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
d = ~d;
exceptions |= FPSCR_IOC;
} else if (vdm.exponent >= 1023) {
int shift = 1023 + 63 - vdm.exponent; /* 58 */
int shift = 1023 + 63 - vdm.exponent; /* 58 */
u64 rem, incr = 0;
d = (u32)((vdm.significand << 1) >> shift);
@ -712,48 +693,46 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
return exceptions;
}
static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{
static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
return vfp_double_ftosi(state, dd, unused, dm,
(fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
}
static struct op fops_ext[] = {
{ vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY
{ vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS
{ vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG
{ vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
{ vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
{ vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
{ vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
{ vfp_double_fuito, OP_SCALAR|OP_SM }, //0x00000010 - FEXT_FUITO
{ vfp_double_fsito, OP_SCALAR|OP_SM }, //0x00000011 - FEXT_FSITO
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ vfp_double_ftoui, OP_SCALAR|OP_SD }, //0x00000018 - FEXT_FTOUI
{ vfp_double_ftouiz, OP_SCALAR|OP_SD }, //0x00000019 - FEXT_FTOUIZ
{ vfp_double_ftosi, OP_SCALAR|OP_SD }, //0x0000001A - FEXT_FTOSI
{ vfp_double_ftosiz, OP_SCALAR|OP_SD }, //0x0000001B - FEXT_FTOSIZ
{vfp_double_fcpy, 0}, // 0x00000000 - FEXT_FCPY
{vfp_double_fabs, 0}, // 0x00000001 - FEXT_FABS
{vfp_double_fneg, 0}, // 0x00000002 - FEXT_FNEG
{vfp_double_fsqrt, 0}, // 0x00000003 - FEXT_FSQRT
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{vfp_double_fcmp, OP_SCALAR}, // 0x00000008 - FEXT_FCMP
{vfp_double_fcmpe, OP_SCALAR}, // 0x00000009 - FEXT_FCMPE
{vfp_double_fcmpz, OP_SCALAR}, // 0x0000000A - FEXT_FCMPZ
{vfp_double_fcmpez, OP_SCALAR}, // 0x0000000B - FEXT_FCMPEZ
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{vfp_double_fcvts, OP_SCALAR | OP_DD}, // 0x0000000F - FEXT_FCVT
{vfp_double_fuito, OP_SCALAR | OP_SM}, // 0x00000010 - FEXT_FUITO
{vfp_double_fsito, OP_SCALAR | OP_SM}, // 0x00000011 - FEXT_FSITO
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{vfp_double_ftoui, OP_SCALAR | OP_SD}, // 0x00000018 - FEXT_FTOUI
{vfp_double_ftouiz, OP_SCALAR | OP_SD}, // 0x00000019 - FEXT_FTOUIZ
{vfp_double_ftosi, OP_SCALAR | OP_SD}, // 0x0000001A - FEXT_FTOSI
{vfp_double_ftosiz, OP_SCALAR | OP_SD}, // 0x0000001B - FEXT_FTOSIZ
};
static u32
vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
struct vfp_double *vdm, u32 fpscr)
{
struct vfp_double *vdp;
static u32 vfp_double_fadd_nonnumber(struct vfp_double* vdd, struct vfp_double* vdn,
struct vfp_double* vdm, u32 fpscr) {
struct vfp_double* vdp;
u32 exceptions = 0;
int tn, tm;
@ -791,13 +770,12 @@ vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
return exceptions;
}
u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_double *vdm, u32 fpscr)
{
u32 vfp_double_add(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm,
u32 fpscr) {
u32 exp_diff;
u64 m_sig;
if (vdn->significand & (1ULL << 63) ||
vdm->significand & (1ULL << 63)) {
if (vdn->significand & (1ULL << 63) || vdm->significand & (1ULL << 63)) {
LOG_INFO(Core_ARM11, "VFP: bad FP values in %s", __func__);
vfp_double_dump("VDN", vdn);
vfp_double_dump("VDM", vdm);
@ -841,8 +819,7 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou
vdd->sign = vfp_sign_negate(vdd->sign);
m_sig = (~m_sig + 1);
} else if (m_sig == 0) {
vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
vdd->sign = (fpscr & FPSCR_RMODE_MASK) == FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
}
} else {
m_sig += vdn->significand;
@ -852,10 +829,8 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou
return 0;
}
u32
vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
struct vfp_double *vdm, u32 fpscr)
{
u32 vfp_double_multiply(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm,
u32 fpscr) {
vfp_double_dump("VDN", vdn);
vfp_double_dump("VDM", vdm);
@ -908,12 +883,11 @@ vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
return 0;
}
#define NEG_MULTIPLY (1 << 0)
#define NEG_SUBTRACT (1 << 1)
#define NEG_MULTIPLY (1 << 0)
#define NEG_SUBTRACT (1 << 1)
static u32
vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func)
{
static u32 vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr,
u32 negate, const char* func) {
struct vfp_double vdd, vdp, vdn, vdm;
u32 exceptions = 0;
@ -949,8 +923,7 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
/*
* sd = sd + (sn * sm)
*/
static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac");
}
@ -958,8 +931,7 @@ static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
/*
* sd = sd - (sn * sm)
*/
static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
}
@ -967,8 +939,7 @@ static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
/*
* sd = -sd + (sn * sm)
*/
static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
}
@ -976,17 +947,16 @@ static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
/*
* sd = -sd - (sn * sm)
*/
static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY,
"fnmsc");
}
/*
* sd = sn * sm
*/
static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
struct vfp_double vdd, vdn, vdm;
u32 exceptions = 0;
@ -1008,8 +978,7 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
/*
* sd = -(sn * sm)
*/
static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
struct vfp_double vdd, vdn, vdm;
u32 exceptions = 0;
@ -1032,8 +1001,7 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
/*
* sd = sn + sm
*/
static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
struct vfp_double vdd, vdn, vdm;
u32 exceptions = 0;
@ -1055,8 +1023,7 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
/*
* sd = sn - sm
*/
static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
struct vfp_double vdd, vdn, vdm;
u32 exceptions = 0;
@ -1083,8 +1050,7 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
/*
* sd = sn / sm
*/
static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
{
static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
struct vfp_double vdd, vdn, vdm;
u32 exceptions = 0;
int tm, tn;
@ -1114,7 +1080,7 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
* If n and m are infinity, the result is invalid
* If n and m are zero, the result is invalid
*/
if (tm & tn & (VFP_INFINITY|VFP_ZERO))
if (tm & tn & (VFP_INFINITY | VFP_ZERO))
goto invalid;
/*
@ -1193,29 +1159,22 @@ invalid:
}
static struct op fops[] = {
{ vfp_double_fmac, 0 },
{ vfp_double_fmsc, 0 },
{ vfp_double_fmul, 0 },
{ vfp_double_fadd, 0 },
{ vfp_double_fnmac, 0 },
{ vfp_double_fnmsc, 0 },
{ vfp_double_fnmul, 0 },
{ vfp_double_fsub, 0 },
{ vfp_double_fdiv, 0 },
{vfp_double_fmac, 0}, {vfp_double_fmsc, 0}, {vfp_double_fmul, 0},
{vfp_double_fadd, 0}, {vfp_double_fnmac, 0}, {vfp_double_fnmsc, 0},
{vfp_double_fnmul, 0}, {vfp_double_fsub, 0}, {vfp_double_fdiv, 0},
};
#define FREG_BANK(x) ((x) & 0x0c)
#define FREG_IDX(x) ((x) & 3)
#define FREG_BANK(x) ((x)&0x0c)
#define FREG_IDX(x) ((x)&3)
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
{
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) {
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
unsigned int dest;
unsigned int dn = vfp_get_dn(inst);
unsigned int dm;
unsigned int vecitr, veclen, vecstride;
struct op *fop;
struct op* fop;
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
@ -1249,7 +1208,7 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
veclen = fpscr & FPSCR_LENGTH_MASK;
LOG_TRACE(Core_ARM11, "VFP: vecstride=%u veclen=%u", vecstride,
(veclen >> FPSCR_LENGTH_BIT) + 1);
(veclen >> FPSCR_LENGTH_BIT) + 1);
if (!fop->fn) {
printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst));
@ -1262,17 +1221,14 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
type = (fop->flags & OP_SD) ? 's' : 'd';
if (op == FOP_EXT)
LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)",
vecitr >> FPSCR_LENGTH_BIT,
type, dest, dn, dm);
LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)", vecitr >> FPSCR_LENGTH_BIT,
type, dest, dn, dm);
else
LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)",
vecitr >> FPSCR_LENGTH_BIT,
type, dest, dn, FOP_TO_IDX(op), dm);
vecitr >> FPSCR_LENGTH_BIT, type, dest, dn, FOP_TO_IDX(op), dm);
except = fop->fn(state, dest, dn, dm, fpscr);
LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x",
vecitr >> FPSCR_LENGTH_BIT, except);
LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x", vecitr >> FPSCR_LENGTH_BIT, except);
exceptions |= except;

File diff suppressed because it is too large Load diff

View file

@ -58,24 +58,20 @@
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
static struct vfp_single vfp_single_default_qnan = {
255,
0,
VFP_SINGLE_SIGNIFICAND_QNAN,
255, 0, VFP_SINGLE_SIGNIFICAND_QNAN,
};
static void vfp_single_dump(const char *str, struct vfp_single *s)
{
LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x",
str, s->sign != 0, s->exponent, s->significand);
static void vfp_single_dump(const char* str, struct vfp_single* s) {
LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x", str, s->sign != 0,
s->exponent, s->significand);
}
static void vfp_single_normalise_denormal(struct vfp_single *vs)
{
static void vfp_single_normalise_denormal(struct vfp_single* vs) {
int bits = 31 - fls(vs->significand);
vfp_single_dump("normalise_denormal: in", vs);
@ -88,9 +84,8 @@ static void vfp_single_normalise_denormal(struct vfp_single *vs)
vfp_single_dump("normalise_denormal: out", vs);
}
u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, const char *func)
{
u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single* vs, u32 fpscr,
const char* func) {
u32 significand, incr, rmode;
int exponent, shift, underflow;
u32 exceptions = 0;
@ -199,7 +194,7 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs,
vs->exponent = 253;
vs->significand = 0x7fffffff;
} else {
vs->exponent = 255; /* infinity */
vs->exponent = 255; /* infinity */
vs->significand = 0;
}
} else {
@ -217,8 +212,7 @@ pack:
vfp_single_dump("pack: final", vs);
{
s32 d = vfp_single_pack(vs);
LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func,
sd, d, exceptions);
LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, sd, d, exceptions);
vfp_put_float(state, d, sd);
}
@ -229,11 +223,9 @@ pack:
* Propagate the NaN, setting exceptions if it is signalling.
* 'n' is always a NaN. 'm' may be a number, NaN or infinity.
*/
static u32
vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
struct vfp_single *vsm, u32 fpscr)
{
struct vfp_single *nan;
static u32 vfp_propagate_nan(struct vfp_single* vsd, struct vfp_single* vsn, struct vfp_single* vsm,
u32 fpscr) {
struct vfp_single* nan;
int tn, tm = 0;
tn = vfp_single_type(vsn);
@ -270,40 +262,33 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
}
/*
* Extended operations
*/
static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
vfp_put_float(state, vfp_single_packed_abs(m), sd);
return 0;
}
static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
vfp_put_float(state, m, sd);
return 0;
}
static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
vfp_put_float(state, vfp_single_packed_negate(m), sd);
return 0;
}
static const u16 sqrt_oddadjust[] = {
0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0,
0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67
};
static const u16 sqrt_oddadjust[] = {0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f,
0x0236, 0x02e0, 0x039c, 0x0468, 0x0545, 0x0631,
0x072b, 0x0832, 0x0946, 0x0a67};
static const u16 sqrt_evenadjust[] = {
0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e,
0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002
};
static const u16 sqrt_evenadjust[] = {0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429,
0x0356, 0x029e, 0x0200, 0x0179, 0x0109, 0x00af,
0x0068, 0x0034, 0x0012, 0x0002};
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
{
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) {
int index;
u32 z, a;
@ -331,25 +316,24 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
}
}
static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
struct vfp_single vsm, vsd, *vsp;
int ret, tm;
u32 exceptions = 0;
exceptions |= vfp_single_unpack(&vsm, m, fpscr);
tm = vfp_single_type(&vsm);
if (tm & (VFP_NAN|VFP_INFINITY)) {
if (tm & (VFP_NAN | VFP_INFINITY)) {
vsp = &vsd;
if (tm & VFP_NAN)
ret = vfp_propagate_nan(vsp, &vsm, nullptr, fpscr);
else if (vsm.sign == 0) {
sqrt_copy:
sqrt_copy:
vsp = &vsm;
ret = 0;
} else {
sqrt_invalid:
sqrt_invalid:
vsp = &vfp_single_default_qnan;
ret = FPSCR_IOC;
}
@ -420,15 +404,15 @@ sqrt_invalid:
* Greater than := C
* Unordered := CV
*/
static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr)
{
static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr) {
s32 d;
u32 ret = 0;
d = vfp_get_float(state, sd);
if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
ret |= FPSCR_CFLAG | FPSCR_VFLAG;
if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
if (signal_on_qnan ||
!(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
/*
* Signalling NaN, or signalling on quiet NaN
*/
@ -437,7 +421,8 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
ret |= FPSCR_CFLAG | FPSCR_VFLAG;
if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
if (signal_on_qnan ||
!(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
/*
* Signalling NaN, or signalling on quiet NaN
*/
@ -479,28 +464,23 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
return ret;
}
static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
return vfp_compare(state, sd, 0, m, fpscr);
}
static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
return vfp_compare(state, sd, 1, m, fpscr);
}
static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
return vfp_compare(state, sd, 0, 0, fpscr);
}
static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
return vfp_compare(state, sd, 1, 0, fpscr);
}
static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) {
struct vfp_single vsm;
struct vfp_double vdd;
int tm;
@ -525,7 +505,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f
/*
* If we have an infinity or NaN, the exponent must be 2047.
*/
if (tm & (VFP_INFINITY|VFP_NAN)) {
if (tm & (VFP_INFINITY | VFP_NAN)) {
vdd.exponent = 2047;
if (tm == VFP_QNAN)
vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
@ -543,8 +523,7 @@ pack_nan:
return exceptions;
}
static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
struct vfp_single vs;
u32 exceptions = 0;
@ -556,8 +535,7 @@ static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 f
return exceptions;
}
static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
struct vfp_single vs;
u32 exceptions = 0;
@ -569,8 +547,7 @@ static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 f
return exceptions;
}
static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
struct vfp_single vsm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
@ -656,13 +633,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
return exceptions;
}
static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
}
static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
struct vfp_single vsm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
@ -739,51 +714,44 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
return exceptions;
}
static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
{
static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
}
static struct op fops_ext[] = {
{ vfp_single_fcpy, 0 }, //0x00000000 - FEXT_FCPY
{ vfp_single_fabs, 0 }, //0x00000001 - FEXT_FABS
{ vfp_single_fneg, 0 }, //0x00000002 - FEXT_FNEG
{ vfp_single_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ vfp_single_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
{ vfp_single_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
{ vfp_single_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
{ vfp_single_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ vfp_single_fcvtd, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
{ vfp_single_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO
{ vfp_single_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ nullptr, 0 },
{ vfp_single_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI
{ vfp_single_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ
{ vfp_single_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI
{ vfp_single_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ
{vfp_single_fcpy, 0}, // 0x00000000 - FEXT_FCPY
{vfp_single_fabs, 0}, // 0x00000001 - FEXT_FABS
{vfp_single_fneg, 0}, // 0x00000002 - FEXT_FNEG
{vfp_single_fsqrt, 0}, // 0x00000003 - FEXT_FSQRT
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{vfp_single_fcmp, OP_SCALAR}, // 0x00000008 - FEXT_FCMP
{vfp_single_fcmpe, OP_SCALAR}, // 0x00000009 - FEXT_FCMPE
{vfp_single_fcmpz, OP_SCALAR}, // 0x0000000A - FEXT_FCMPZ
{vfp_single_fcmpez, OP_SCALAR}, // 0x0000000B - FEXT_FCMPEZ
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{vfp_single_fcvtd, OP_SCALAR | OP_DD}, // 0x0000000F - FEXT_FCVT
{vfp_single_fuito, OP_SCALAR}, // 0x00000010 - FEXT_FUITO
{vfp_single_fsito, OP_SCALAR}, // 0x00000011 - FEXT_FSITO
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{nullptr, 0},
{vfp_single_ftoui, OP_SCALAR}, // 0x00000018 - FEXT_FTOUI
{vfp_single_ftouiz, OP_SCALAR}, // 0x00000019 - FEXT_FTOUIZ
{vfp_single_ftosi, OP_SCALAR}, // 0x0000001A - FEXT_FTOSI
{vfp_single_ftosiz, OP_SCALAR}, // 0x0000001B - FEXT_FTOSIZ
};
static u32
vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
struct vfp_single *vsm, u32 fpscr)
{
struct vfp_single *vsp;
static u32 vfp_single_fadd_nonnumber(struct vfp_single* vsd, struct vfp_single* vsn,
struct vfp_single* vsm, u32 fpscr) {
struct vfp_single* vsp;
u32 exceptions = 0;
int tn, tm;
@ -821,14 +789,11 @@ vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
return exceptions;
}
static u32
vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
struct vfp_single *vsm, u32 fpscr)
{
static u32 vfp_single_add(struct vfp_single* vsd, struct vfp_single* vsn, struct vfp_single* vsm,
u32 fpscr) {
u32 exp_diff, m_sig;
if (vsn->significand & 0x80000000 ||
vsm->significand & 0x80000000) {
if (vsn->significand & 0x80000000 || vsm->significand & 0x80000000) {
LOG_WARNING(Core_ARM11, "bad FP values");
vfp_single_dump("VSN", vsn);
vfp_single_dump("VSM", vsm);
@ -872,8 +837,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
vsd->sign = vfp_sign_negate(vsd->sign);
m_sig = (~m_sig + 1);
} else if (m_sig == 0) {
vsd->sign = (fpscr & FPSCR_RMODE_MASK) ==
FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
vsd->sign = (fpscr & FPSCR_RMODE_MASK) == FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
}
} else {
m_sig = vsn->significand + m_sig;
@ -883,9 +847,8 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
return 0;
}
static u32
vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr)
{
static u32 vfp_single_multiply(struct vfp_single* vsd, struct vfp_single* vsn,
struct vfp_single* vsm, u32 fpscr) {
vfp_single_dump("VSN", vsn);
vfp_single_dump("VSM", vsm);
@ -938,12 +901,11 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s
return 0;
}
#define NEG_MULTIPLY (1 << 0)
#define NEG_SUBTRACT (1 << 1)
#define NEG_MULTIPLY (1 << 0)
#define NEG_SUBTRACT (1 << 1)
static u32
vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func)
{
static u32 vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr,
u32 negate, const char* func) {
vfp_single vsd, vsp, vsn, vsm;
u32 exceptions = 0;
s32 v;
@ -985,8 +947,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
/*
* sd = sd + (sn * sm)
*/
static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
u32 exceptions = 0;
LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
@ -996,8 +957,7 @@ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
/*
* sd = sd - (sn * sm)
*/
static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
// TODO: this one has its arguments inverted, investigate.
LOG_TRACE(Core_ARM11, "s%u = %08x", sd, sn);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
@ -1006,8 +966,7 @@ static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
/*
* sd = -sd + (sn * sm)
*/
static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
}
@ -1015,17 +974,16 @@ static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
/*
* sd = -sd - (sn * sm)
*/
static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY,
"fnmsc");
}
/*
* sd = sn * sm
*/
static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
struct vfp_single vsd, vsn, vsm;
u32 exceptions = 0;
s32 n = vfp_get_float(state, sn);
@ -1049,8 +1007,7 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
/*
* sd = -(sn * sm)
*/
static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
struct vfp_single vsd, vsn, vsm;
u32 exceptions = 0;
s32 n = vfp_get_float(state, sn);
@ -1075,8 +1032,7 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
/*
* sd = sn + sm
*/
static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
struct vfp_single vsd, vsn, vsm;
u32 exceptions = 0;
s32 n = vfp_get_float(state, sn);
@ -1103,8 +1059,7 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
/*
* sd = sn - sm
*/
static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
/*
* Subtraction is addition with one sign inverted.
@ -1118,8 +1073,7 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
/*
* sd = sn / sm
*/
static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
struct vfp_single vsd, vsn, vsm;
u32 exceptions = 0;
s32 n = vfp_get_float(state, sn);
@ -1151,7 +1105,7 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
* If n and m are infinity, the result is invalid
* If n and m are zero, the result is invalid
*/
if (tm & tn & (VFP_INFINITY|VFP_ZERO))
if (tm & tn & (VFP_INFINITY | VFP_ZERO))
goto invalid;
/*
@ -1226,29 +1180,22 @@ invalid:
}
static struct op fops[] = {
{ vfp_single_fmac, 0 },
{ vfp_single_fmsc, 0 },
{ vfp_single_fmul, 0 },
{ vfp_single_fadd, 0 },
{ vfp_single_fnmac, 0 },
{ vfp_single_fnmsc, 0 },
{ vfp_single_fnmul, 0 },
{ vfp_single_fsub, 0 },
{ vfp_single_fdiv, 0 },
{vfp_single_fmac, 0}, {vfp_single_fmsc, 0}, {vfp_single_fmul, 0},
{vfp_single_fadd, 0}, {vfp_single_fnmac, 0}, {vfp_single_fnmsc, 0},
{vfp_single_fnmul, 0}, {vfp_single_fsub, 0}, {vfp_single_fdiv, 0},
};
#define FREG_BANK(x) ((x) & 0x18)
#define FREG_IDX(x) ((x) & 7)
#define FREG_BANK(x) ((x)&0x18)
#define FREG_IDX(x) ((x)&7)
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
{
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) {
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
unsigned int dest;
unsigned int sn = vfp_get_sn(inst);
unsigned int sm = vfp_get_sm(inst);
unsigned int vecitr, veclen, vecstride;
struct op *fop;
struct op* fop;
vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
@ -1274,11 +1221,11 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
else
veclen = fpscr & FPSCR_LENGTH_MASK;
LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride,
(veclen >> FPSCR_LENGTH_BIT) + 1);
LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride, (veclen >> FPSCR_LENGTH_BIT) + 1);
if (!fop->fn) {
LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), inst, state->Reg[15]);
LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst),
inst, state->Reg[15]);
Crash();
goto invalid;
}
@ -1290,17 +1237,14 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
type = (fop->flags & OP_DD) ? 'd' : 's';
if (op == FOP_EXT)
LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)",
vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
sm, m);
LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)", vecitr >> FPSCR_LENGTH_BIT,
type, dest, sn, sm, m);
else
LOG_TRACE(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)",
vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
FOP_TO_IDX(op), sm, m);
vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, FOP_TO_IDX(op), sm, m);
except = fop->fn(state, dest, sn, m, fpscr);
LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x",
vecitr >> FPSCR_LENGTH_BIT, except);
LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x", vecitr >> FPSCR_LENGTH_BIT, except);
exceptions |= except;