310 lines
11 KiB
C++
310 lines
11 KiB
C++
/*
|
|
* E_LoadStore.h
|
|
*
|
|
* LDR|STR{<cond>}{B}{T} Rd, <addressing_mode>
|
|
*
|
|
*/
|
|
#pragma once
|
|
|
|
|
|
|
|
namespace ARM
|
|
{
|
|
|
|
|
|
enum AddrMode {
|
|
|
|
Offset, // [Rn, offset] - Base:Offset used for access, no writeback
|
|
PostIndexed, // [Rn, offset] ! - Base:Offset used for access, written back to Base reg.
|
|
PreIndexed // [Rn],offset - Base used then Base:Offset written back to Base reg.
|
|
|
|
// offset: imm{8,12}, Rm, Rm <Shifter> #Shift
|
|
};
|
|
|
|
|
|
#define SET_Rn I |= (Rn&15)<<16
|
|
#define SET_Rt I |= (Rt&15)<<12
|
|
#define SET_Rm I |= (Rm&15)
|
|
|
|
|
|
#define SET_Rtn SET_Rt; SET_Rn
|
|
#define SET_Rtnm SET_Rt; SET_Rn; SET_Rm
|
|
|
|
|
|
|
|
#define SET_I I |= (1<<25) // Sets Register (Rather than Immediate) Addressing
|
|
#define SET_P I |= (1<<24) // If NOT Set: post-indexed, else offset||pre-indexed (W. determines which)
|
|
#define SET_U I |= (1<<23) // If SET: Offset is added to base, else its subtracted (Sign of sImm12)
|
|
#define SET_B I |= (1<<22) // If SET: Access is a byte access, else its a word access.
|
|
#define SET_W I |= (1<<21) // (P==0) [ W==0: reg. post indexed, W==1: Unprivileged T variant ] (P==1) [ W==0: Offset , W==1: Pre-indexed ]
|
|
#define SET_L I |= (1<<20) // (L==1) Load / Store
|
|
|
|
|
|
#define SET_AddrMode \
|
|
if(mode==Offset) { SET_P; } \
|
|
else if(mode==PreIndexed) { SET_P; SET_W; }
|
|
|
|
/*
|
|
#define SET_AddrMode \
|
|
\
|
|
switch(mode) { \
|
|
case PostIndexed: break; \
|
|
case Offset: SET_P; break; \
|
|
case PreIndexed: SET_P; SET_W; break; \
|
|
}
|
|
*/
|
|
|
|
|
|
#define SET_sImm12 \
|
|
\
|
|
if (0 != sImm12) { \
|
|
if (sImm12 > 0) { SET_U; } \
|
|
I |= (abs(sImm12) &0xFFF); \
|
|
}
|
|
|
|
#define SET_sImm8 \
|
|
\
|
|
if(0 != sImm8) { \
|
|
verify(is_s8(sImm8)); \
|
|
if(sImm8 > 0) { SET_U; } \
|
|
sImm8 = abs(sImm8); \
|
|
I |= ((u32)sImm8 &0x0F); \
|
|
I |= ((u32)sImm8 &0xF0)<<4; \
|
|
}
|
|
|
|
|
|
#define SET_Imm5 I |= ((Imm5&0x1F)<<7)
|
|
#define SET_type I |= ((type&3)<<5)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* - Load/Store Encoding
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
cond 01-IPUBWL Rn Rt addr_mode -- Load/Store Word || Unsigned Byte
|
|
|
|
I,P,U,W - Specify type of addressing mode
|
|
L - Specify Load (L==1), else Store
|
|
B - Specify Byte (B==1), else Word
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
cond 000-PUIWL Rn Rt addr_mode 1SH1 addr_mode -- Load/Store Halfword || Signed byte
|
|
|
|
I,P,U,W - Specify type of addressing mode
|
|
L - Specify Load (L==1), else Store
|
|
S - Specify signed (S==1), else unsigned access
|
|
H - Specify Halfword access, else signed byte
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
|
|
cond 010-PUBWL Rn Rt sImm12-iiii-iiii Imm Offset
|
|
cond 011-PUBWL Rn Rt #sft sft_op 0 Rm Reg Offset
|
|
|
|
cond 000 PU1WL Rn Rt imHI 1011 imLO Imm Offset - halfword
|
|
cond 000 PU0WL Rn Rt SBZ 1011 Rm Reg Offset - halfword
|
|
cond 000 PU1W1 Rn Rt imHI 11H1 imLO Imm Offset - signed halfword/byte
|
|
cond 000 PU0W1 Rn Rt SBZ 11H1 Rm Reg Offset - signed halfword/byte
|
|
cond 000 PU1W0 Rn Rt imHI 11S1 imLO Imm Offset - two words
|
|
cond 000 PU0W0 Rn Rt SBZ 11S1 Rm Reg Offset - two words
|
|
|
|
cond 100-PUSWL Rn Register-list Multiple
|
|
cond 110-PUNWL Rn CRd cp_num offs8 COP & double reg xfer
|
|
|
|
cond 0001 0B00 Rn Rt SBZ 1001 Rm Swap [byte]
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
LDR L 010 1U001 11 Rt imm12 - *no literal stores*
|
|
LDR I 010 PU0W1 Rn Rt imm12 - STR I 010 PU0W0 Rn Rt imm12
|
|
LDR R 011 PU0W1 Rn Rt imm5 type 0 Rm - STR R 011 PU0W0 Rn Rt imm5 type 0 Rm
|
|
|
|
LDRT I 010 0U011 Rn Rt imm12 - STRT I 010 0U010 Rn Rt imm12
|
|
LDRT R 011 0U011 Rn Rt imm5 type 0 Rm - STRT R 011 0U010 Rn Rt imm5 type 0 Rm
|
|
|
|
LDRB L 010 1U101 11 Rt imm12 - *^^
|
|
LDRB I 010 PU1W1 Rn Rt imm12 - STRB I 010 PU1W0 Rn Rt imm12
|
|
LDRB R 011 PU1W1 Rn Rt imm5 type 0 Rm - STRB R 011 PU1W0 Rn Rt imm5 type 0 Rm
|
|
|
|
LDRBT I
|
|
LDRBT R
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
LDRH L 000 1U101 11 Rt imm4H 1011 imm4L - *^^
|
|
LDRH I 000 PU1W1 Rn Rt imm4H 1011 imm4L - STRH I 000 PU1W0 Rn Rt imm4H 1011 imm4L
|
|
LDRH R 000 PU0W1 Rn Rt 0000 1011 Rm - STRH R 000 PU0W0 Rn Rt 0000 1011 Rm
|
|
|
|
LDRD L 000 1U100 11 Rt imm4H 1101 imm4L - *^^
|
|
LDRD I 000 PU1W0 Rn Rt imm4H 1101 imm4L - STRD I 000 PU1W0 Rn Rt imm4H 1111 imm4L
|
|
LDRD R 000 PU0W0 Rn Rt 0000 1101 Rm - STRD R 000 PU0W0 Rn Rt 0000 1111 Rm
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
LDRHT/STRHT
|
|
|
|
LDREX/STREX
|
|
LDREXB/STREXB
|
|
LDREXH/STREXH
|
|
LDREXD/STREXD
|
|
--------------------------------------------------------------------------------------
|
|
|
|
|
|
EAPI LDR 0x04100000 // These were all the A1 Versions for Imm IIRC
|
|
EAPI LDRB 0x04500000
|
|
EAPI LDRBT 0x06700000
|
|
EAPI LDRD 0x00000000
|
|
EAPI LDREX 0x01900090
|
|
EAPI LDRH 0x00100090
|
|
EAPI LDRSB 0x00100000
|
|
EAPI LDRSH 0x00100000
|
|
EAPI LDRT 0x04300000
|
|
|
|
EAPI STR 0x04000000
|
|
EAPI STRB 0x04400000
|
|
EAPI STRBT 0x06600000
|
|
EAPI STRD 0x00000000
|
|
EAPI STREX 0x01800090
|
|
EAPI STRH 0x00000090
|
|
EAPI STRT 0x04200000
|
|
|
|
*/
|
|
|
|
|
|
extern u8* emit_opt;
|
|
extern eReg reg_addr;
|
|
extern eReg reg_dst;
|
|
extern s32 imma;
|
|
|
|
EAPI LDR (eReg Rt, eReg Rn, s32 sImm12=0, AddrMode mode=Offset, ConditionCode CC=AL)
|
|
{
|
|
if (emit_opt+4==(u8*)EMIT_GET_PTR() && reg_addr==Rn && imma==sImm12)
|
|
{
|
|
if (reg_dst!=Rt)
|
|
MOV(Rt,reg_dst);
|
|
}
|
|
else
|
|
{
|
|
DECL_Id(0x04100000); SET_CC; SET_Rtn; SET_AddrMode; SET_sImm12; EMIT_I;
|
|
}
|
|
}
|
|
EAPI STR (eReg Rt, eReg Rn, s32 sImm12=0, AddrMode mode=Offset, ConditionCode CC=AL)
|
|
{
|
|
emit_opt=0;//(u8*)EMIT_GET_PTR();
|
|
reg_addr=Rn;
|
|
reg_dst=Rt;
|
|
imma=sImm12;
|
|
DECL_Id(0x04000000); SET_CC; SET_Rtn; SET_AddrMode; SET_sImm12; EMIT_I;
|
|
}
|
|
EAPI LDRB(eReg Rt, eReg Rn, s32 sImm12=0, AddrMode mode=Offset, ConditionCode CC=AL) { DECL_Id(0x04500000); SET_CC; SET_Rtn; SET_AddrMode; SET_sImm12; SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
EAPI STRB(eReg Rt, eReg Rn, s32 sImm12=0, AddrMode mode=Offset, ConditionCode CC=AL) { DECL_Id(0x04400000); SET_CC; SET_Rtn; SET_AddrMode; SET_sImm12; SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
|
|
EAPI LDRT (eReg Rt, eReg Rn, s32 sImm12=0, ConditionCode CC=AL) { DECL_Id(0x04300000); SET_CC; SET_Rtn; SET_sImm12; EMIT_I; }
|
|
EAPI STRT (eReg Rt, eReg Rn, s32 sImm12=0, ConditionCode CC=AL) { DECL_Id(0x04200000); SET_CC; SET_Rtn; SET_sImm12; EMIT_I; }
|
|
EAPI LDRBT(eReg Rt, eReg Rn, s32 sImm12=0, ConditionCode CC=AL) { DECL_Id(0x04700000); SET_CC; SET_Rtn; SET_sImm12; SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
EAPI STRBT(eReg Rt, eReg Rn, s32 sImm12=0, ConditionCode CC=AL) { DECL_Id(0x04600000); SET_CC; SET_Rtn; SET_sImm12; SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
|
|
// LDR(r1,r2,r3, Offset, true, L_LSL, 5, EQ); ... LDR r1, r2, +r3 LSL #5
|
|
EAPI LDR (eReg Rt, eReg Rn, eReg Rm, AddrMode mode=Offset, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06100000); SET_CC; SET_Rtnm; SET_AddrMode; SET_Imm5; SET_type; if(Add){ SET_U; } EMIT_I; }
|
|
EAPI STR (eReg Rt, eReg Rn, eReg Rm, AddrMode mode=Offset, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06000000); SET_CC; SET_Rtnm; SET_AddrMode; SET_Imm5; SET_type; if(Add){ SET_U; } EMIT_I; }
|
|
EAPI LDRB(eReg Rt, eReg Rn, eReg Rm, AddrMode mode=Offset, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06500000); SET_CC; SET_Rtnm; SET_AddrMode; SET_Imm5; SET_type; if(Add){ SET_U; } SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
EAPI STRB(eReg Rt, eReg Rn, eReg Rm, AddrMode mode=Offset, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06400000); SET_CC; SET_Rtnm; SET_AddrMode; SET_Imm5; SET_type; if(Add){ SET_U; } SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
|
|
EAPI LDRT (eReg Rt, eReg Rn, eReg Rm, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06300000); SET_CC; SET_Rtnm; SET_Imm5; SET_type; if(Add){ SET_U; } EMIT_I; }
|
|
EAPI STRT (eReg Rt, eReg Rn, eReg Rm, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06200000); SET_CC; SET_Rtnm; SET_Imm5; SET_type; if(Add){ SET_U; } EMIT_I; }
|
|
EAPI LDRBT(eReg Rt, eReg Rn, eReg Rm, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06700000); SET_CC; SET_Rtnm; SET_Imm5; SET_type; if(Add){ SET_U; } SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
EAPI STRBT(eReg Rt, eReg Rn, eReg Rm, bool Add=false, ShiftOp type=S_LSL, u32 Imm5=0, ConditionCode CC=AL) { DECL_Id(0x06600000); SET_CC; SET_Rtnm; SET_Imm5; SET_type; if(Add){ SET_U; } SET_B; EMIT_I; } // Prob don't need SET_B, in iID
|
|
|
|
|
|
|
|
// LDR Rt,[PC, #(s:+/-)Imm12] *Special Case - Literal / PC Relative
|
|
EAPI LDR(eReg Rt, s32 sImm12, ConditionCode CC=AL) {
|
|
DECL_Id(0x051F0000); SET_CC; SET_Rt; SET_sImm12; EMIT_I;
|
|
}
|
|
|
|
// LDRB Rt,[PC, #(s:+/-)Imm12] *Special Case - Literal / PC Relative
|
|
EAPI LDRB(eReg Rt, s32 sImm12, ConditionCode CC=AL) {
|
|
DECL_Id(0x055F0000); SET_CC; SET_Rt; SET_sImm12; EMIT_I;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Note: Following support Post-Indexed addressing only //
|
|
|
|
|
|
EAPI LDRH(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x005000B0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
|
EAPI STRH(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x004000B0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
|
EAPI LDRD(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x004000D0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
|
EAPI STRD(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x004000F0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
|
|
|
EAPI LDRH(eReg Rt, eReg Rn, eReg Rm, bool Add=true,ConditionCode CC=AL) { DECL_Id(0x001000B0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
|
EAPI STRH(eReg Rt, eReg Rn, eReg Rm, bool Add=true,ConditionCode CC=AL) { DECL_Id(0x000000B0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
|
EAPI LDRD(eReg Rt, eReg Rn, eReg Rm, bool Add=true, ConditionCode CC=AL) { DECL_Id(0x000000D0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
|
EAPI STRD(eReg Rt, eReg Rn, eReg Rm, bool Add=true, ConditionCode CC=AL) { DECL_Id(0x000000F0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
|
|
|
EAPI LDRSB(eReg Rt, eReg Rn, eReg Rm, bool Add=true,ConditionCode CC=AL) { DECL_Id(0x001000D0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
|
EAPI LDRSH(eReg Rt, eReg Rn, eReg Rm, bool Add=true,ConditionCode CC=AL) { DECL_Id(0x001000F0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
|
|
|
|
|
EAPI LDRH(eReg Rt, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x015F00B0); SET_CC; SET_Rt; SET_sImm8; EMIT_I; } // *Special Case - Literal / PC Relative
|
|
EAPI STRH(eReg Rt, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x014F00D0); SET_CC; SET_Rt; SET_sImm8; EMIT_I; } // *Special Case - Literal / PC Relative
|
|
|
|
|
|
|
|
// TODO: {LD,ST}R{SB,EX*} && friends (If required).
|
|
|
|
|
|
// Must use _Reg format
|
|
EAPI PUSH(u32 RegList, ConditionCode CC=AL)
|
|
{
|
|
DECL_Id(0x092D0000);
|
|
|
|
SET_CC;
|
|
I |= (RegList&0xFFFF);
|
|
EMIT_I;
|
|
}
|
|
|
|
|
|
EAPI POP(u32 RegList, ConditionCode CC=AL)
|
|
{
|
|
DECL_Id(0x08BD0000);
|
|
|
|
SET_CC;
|
|
I |= (RegList&0xFFFF);
|
|
EMIT_I;
|
|
}
|
|
|
|
|
|
#undef SET_Rtn
|
|
#undef SET_Rtnm
|
|
|
|
#undef SET_Rn
|
|
#undef SET_Rt
|
|
#undef SET_Rm
|
|
|
|
#undef SET_I
|
|
#undef SET_P
|
|
#undef SET_U
|
|
#undef SET_B
|
|
#undef SET_W
|
|
#undef SET_L
|
|
|
|
#undef SET_AddrMode
|
|
|
|
#undef SET_sImm12
|
|
#undef SET_sImm8
|
|
#undef SET_Imm5
|
|
#undef SET_type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}; |