2019-10-02 23:10:59 +00:00
|
|
|
#ifndef ARMJIT_INTERNAL_H
|
|
|
|
#define ARMJIT_INTERNAL_H
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include <stdint.h>
|
2020-06-14 19:04:25 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
#include "ARMJIT.h"
|
2020-06-14 19:04:25 +00:00
|
|
|
#include "ARMJIT_Memory.h"
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
// here lands everything which doesn't fit into ARMJIT.h
|
|
|
|
// where it would be included by pretty much everything
|
|
|
|
namespace ARMJIT
|
|
|
|
{
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
branch_IdleBranch = 1 << 0,
|
|
|
|
branch_FollowCondTaken = 1 << 1,
|
2020-04-25 11:40:51 +00:00
|
|
|
branch_FollowCondNotTaken = 1 << 2,
|
|
|
|
branch_StaticTarget = 1 << 3,
|
2019-10-02 23:10:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct FetchedInstr
|
|
|
|
{
|
|
|
|
u32 A_Reg(int pos) const
|
|
|
|
{
|
|
|
|
return (Instr >> pos) & 0xF;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 T_Reg(int pos) const
|
|
|
|
{
|
|
|
|
return (Instr >> pos) & 0x7;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 Cond() const
|
|
|
|
{
|
|
|
|
return Instr >> 28;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 BranchFlags;
|
|
|
|
u8 SetFlags;
|
|
|
|
u32 Instr;
|
|
|
|
u32 Addr;
|
|
|
|
|
|
|
|
u8 DataCycles;
|
2020-04-16 14:40:29 +00:00
|
|
|
u16 CodeCycles;
|
|
|
|
u32 DataRegion;
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
ARMInstrInfo::Info Info;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
TinyVector
|
|
|
|
- because reinventing the wheel is the best!
|
|
|
|
|
|
|
|
- meant to be used very often, with not so many elements
|
|
|
|
max 1 << 16 elements
|
|
|
|
- doesn't allocate while no elements are inserted
|
|
|
|
- not stl confirmant of course
|
|
|
|
- probably only works with POD types
|
|
|
|
- remove operations don't preserve order, but O(1)!
|
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
struct __attribute__((packed)) TinyVector
|
|
|
|
{
|
|
|
|
T* Data = NULL;
|
|
|
|
u16 Capacity = 0;
|
2019-11-03 14:33:20 +00:00
|
|
|
u16 Length = 0;
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
~TinyVector()
|
|
|
|
{
|
|
|
|
delete[] Data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MakeCapacity(u32 capacity)
|
|
|
|
{
|
|
|
|
assert(capacity <= UINT16_MAX);
|
|
|
|
assert(capacity > Capacity);
|
|
|
|
T* newMem = new T[capacity];
|
|
|
|
if (Data != NULL)
|
2020-04-25 11:40:51 +00:00
|
|
|
memcpy(newMem, Data, sizeof(T) * Length);
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
T* oldData = Data;
|
|
|
|
Data = newMem;
|
|
|
|
if (oldData != NULL)
|
|
|
|
delete[] oldData;
|
|
|
|
|
|
|
|
Capacity = capacity;
|
|
|
|
}
|
|
|
|
|
2020-04-06 10:25:35 +00:00
|
|
|
void SetLength(u16 length)
|
|
|
|
{
|
|
|
|
if (Capacity < length)
|
|
|
|
MakeCapacity(length);
|
|
|
|
|
|
|
|
Length = length;
|
|
|
|
}
|
|
|
|
|
2019-10-02 23:10:59 +00:00
|
|
|
void Clear()
|
|
|
|
{
|
|
|
|
Length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(T element)
|
|
|
|
{
|
|
|
|
assert(Length + 1 <= UINT16_MAX);
|
|
|
|
if (Length + 1 > Capacity)
|
|
|
|
MakeCapacity(((Capacity + 4) * 3) / 2);
|
|
|
|
|
|
|
|
Data[Length++] = element;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Remove(int index)
|
|
|
|
{
|
|
|
|
assert(index >= 0 && index < Length);
|
|
|
|
|
|
|
|
Length--;
|
|
|
|
Data[index] = Data[Length];
|
|
|
|
/*for (int i = index; i < Length; i++)
|
|
|
|
Data[i] = Data[i + 1];*/
|
|
|
|
}
|
|
|
|
|
|
|
|
int Find(T needle)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < Length; i++)
|
|
|
|
{
|
|
|
|
if (Data[i] == needle)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RemoveByValue(T needle)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < Length; i++)
|
|
|
|
{
|
|
|
|
if (Data[i] == needle)
|
|
|
|
{
|
|
|
|
Remove(i);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
T& operator[](int index)
|
|
|
|
{
|
|
|
|
assert(index >= 0 && index < Length);
|
|
|
|
return Data[index];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class JitBlock
|
|
|
|
{
|
|
|
|
public:
|
2020-05-08 22:45:05 +00:00
|
|
|
JitBlock(u32 num, u32 literalHash, u32 numAddresses, u32 numLiterals)
|
2019-10-02 23:10:59 +00:00
|
|
|
{
|
2020-05-08 22:45:05 +00:00
|
|
|
Num = num;
|
2019-10-02 23:10:59 +00:00
|
|
|
NumAddresses = numAddresses;
|
2020-05-08 22:45:05 +00:00
|
|
|
NumLiterals = numLiterals;
|
|
|
|
Data.SetLength(numAddresses * 2 + numLiterals);
|
2019-10-02 23:10:59 +00:00
|
|
|
}
|
|
|
|
|
2020-06-14 19:04:25 +00:00
|
|
|
u32 StartAddr;
|
|
|
|
u32 StartAddrLocal;
|
2020-05-08 22:45:05 +00:00
|
|
|
u32 InstrHash, LiteralHash;
|
|
|
|
u8 Num;
|
|
|
|
u16 NumAddresses;
|
|
|
|
u16 NumLiterals;
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
JitBlockEntry EntryPoint;
|
|
|
|
|
|
|
|
u32* AddressRanges()
|
2020-05-08 22:45:05 +00:00
|
|
|
{ return &Data[0]; }
|
|
|
|
u32* AddressMasks()
|
|
|
|
{ return &Data[NumAddresses]; }
|
|
|
|
u32* Literals()
|
|
|
|
{ return &Data[NumAddresses * 2]; }
|
2019-10-02 23:10:59 +00:00
|
|
|
|
|
|
|
private:
|
2020-04-06 10:25:35 +00:00
|
|
|
TinyVector<u32> Data;
|
2019-10-02 23:10:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// size should be 16 bytes because I'm to lazy to use mul and whatnot
|
|
|
|
struct __attribute__((packed)) AddressRange
|
|
|
|
{
|
|
|
|
TinyVector<JitBlock*> Blocks;
|
2020-05-08 22:45:05 +00:00
|
|
|
u32 Code;
|
2019-10-02 23:10:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*InterpreterFunc)(ARM* cpu);
|
|
|
|
extern InterpreterFunc InterpretARM[];
|
|
|
|
extern InterpreterFunc InterpretTHUMB[];
|
|
|
|
|
2020-05-08 22:45:05 +00:00
|
|
|
extern TinyVector<u32> InvalidLiterals;
|
2020-04-16 14:40:29 +00:00
|
|
|
|
2020-06-14 19:04:25 +00:00
|
|
|
extern AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count];
|
2020-04-25 11:40:51 +00:00
|
|
|
|
2020-06-14 19:04:25 +00:00
|
|
|
inline bool PageContainsCode(AddressRange* range)
|
2020-05-08 22:45:05 +00:00
|
|
|
{
|
2020-06-14 19:04:25 +00:00
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (range[i].Blocks.Length > 0)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 LocaliseCodeAddress(u32 num, u32 addr);
|
2020-05-08 22:45:05 +00:00
|
|
|
|
2020-06-14 19:04:25 +00:00
|
|
|
template <u32 Num>
|
|
|
|
void LinkBlock(ARM* cpu, u32 codeOffset);
|
2020-05-08 22:45:05 +00:00
|
|
|
|
2020-06-14 19:04:25 +00:00
|
|
|
template <typename T> T SlowRead9(u32 addr, ARMv5* cpu);
|
|
|
|
template <typename T> void SlowWrite9(u32 addr, ARMv5* cpu, T val);
|
2020-05-08 22:45:05 +00:00
|
|
|
template <typename T> T SlowRead7(u32 addr);
|
|
|
|
template <typename T> void SlowWrite7(u32 addr, T val);
|
|
|
|
|
|
|
|
template <bool PreInc, bool Write> void SlowBlockTransfer9(u32 addr, u64* data, u32 num, ARMv5* cpu);
|
|
|
|
template <bool PreInc, bool Write> void SlowBlockTransfer7(u32 addr, u64* data, u32 num);
|
|
|
|
|
2019-10-02 23:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|