📄 ldst.cpp
字号:
}
#if 0
void impl_st1_reg(IMPL_FORMALS)
{
UInt32 offset = shifter_operand(IMPL_ARGS);
UInt32 address;
if (PFLD) /*preindex*/
address = UFLD?RN+offset:RN-offset;
else
address = RN;
if (BFLD)
MEM_WRITE_BYTE(address, RD);
else
MEM_WRITE_WORD(address, RD);
if (!PFLD)
WRITE_REG(RNFLD, UFLD?RN+offset:RN-offset);
else if (WFLD)
WRITE_REG(RNFLD, address);
}
#endif
/*p==0, b==0*/
void impl_st1_reg(IMPL_FORMALS)
{
UInt32 offset = shifter_operand(IMPL_ARGS);
UInt32 address;
address = RN;
MEM_WRITE_WORD(address, RD);
WRITE_REG(RNFLD, UFLD?RN+offset:RN-offset);
EMULATOR_STUB(st1_reg,inst);
}
/*p==1, b==0*/
void impl_st1_reg_p(IMPL_FORMALS)
{
UInt32 offset = shifter_operand(IMPL_ARGS);
UInt32 address;
address = UFLD?RN+offset:RN-offset;
MEM_WRITE_WORD(address, RD);
if (WFLD)
WRITE_REG(RNFLD, address);
EMULATOR_STUB(st1_reg_p,inst);
}
/*p==0, b==1*/
void impl_st1_reg_b(IMPL_FORMALS)
{
UInt32 offset = shifter_operand(IMPL_ARGS);
UInt32 address;
address = RN;
MEM_WRITE_BYTE(address, RD);
WRITE_REG(RNFLD, UFLD?RN+offset:RN-offset);
EMULATOR_STUB(st1_reg_b,inst);
}
/*p==1, b==1*/
void impl_st1_reg_pb(IMPL_FORMALS)
{
UInt32 offset = shifter_operand(IMPL_ARGS);
UInt32 address;
address = UFLD?RN+offset:RN-offset;
MEM_WRITE_BYTE(address, RD);
if (WFLD)
WRITE_REG(RNFLD, address);
EMULATOR_STUB(st1_reg_pb,inst);
}
void impl_st2_imm(IMPL_FORMALS)
{
UInt32 offset = ((inst>>4) & 0xF0) | (inst & 0xF);
UInt32 address, towrite;
if (PFLD) /*preindex*/
address = UFLD?RN+offset:RN-offset;
else
address = RN;
if (address&0x1)
towrite = 0xCCCCCCCC; /*unpredictable*/
else
towrite = RD;
MEM_WRITE_HALF_WORD(address, towrite);
if (!PFLD) /*post index always updates*/
WRITE_REG(RNFLD, UFLD?RN+offset:RN-offset);
else if (WFLD) /*preindex and update*/
WRITE_REG(RNFLD, address);
EMULATOR_STUB(st2_imm,inst);
}
void impl_st2_reg(IMPL_FORMALS)
{
UInt32 offset = RM;
UInt32 address, towrite;
if (PFLD) /*preindex*/
address = UFLD?RN+offset:RN-offset;
else
address = RN;
if (address&0x1)
towrite = 0xCCCCCCCC; /*unpredictable*/
else
towrite = RD;
MEM_WRITE_HALF_WORD(address, towrite);
if (!PFLD)
WRITE_REG(RNFLD, UFLD?RN+offset:RN-offset);
else if (WFLD)
WRITE_REG(RNFLD, address);
EMULATOR_STUB(st2_reg,inst);
}
void impl_swap(IMPL_FORMALS)
{
UInt32 address = RN;
UInt32 val = MEM_READ_WORD(address), towrite=RM;
WRITE_REG(RDFLD, rotate_right(val, (address&0x3)<<3));
MEM_WRITE_WORD(address, towrite);
EMULATOR_STUB(swap,inst);
}
void impl_swap_byte(IMPL_FORMALS)
{
UInt32 address = RN;
UInt32 val = MEM_READ_BYTE(address);
UInt8 towrite = RM;
WRITE_REG(RDFLD, val);
MEM_WRITE_BYTE(address, towrite);
EMULATOR_STUB(swap_byte,inst);
}
/* Since ldm/stm were used almost only on the stack,
* it is possible to shortcut page table lookup
* by applying the similar method used in fetch.
* However, the instruction frequency of ldm/stm is low and
* the gain is only <=1%. To keep code clean, nothing is done.
*/
void impl_ldm(IMPL_FORMALS)
{
UInt32 start_addr, end_addr, address, i;
SInt32 j, pcount = popcount16(inst)*4;
if (!PFLD && UFLD) {
start_addr = RN;
end_addr = RN + pcount - 4;
if (WFLD) WRITE_REG(RNFLD, RN + pcount);
}
else if (PFLD && UFLD) {
start_addr = RN+4;
end_addr = RN + pcount;
if (WFLD) WRITE_REG(RNFLD, RN + pcount);
}
else if (!PFLD && !UFLD) {
start_addr = RN - pcount + 4;
end_addr = RN;
if (WFLD) WRITE_REG(RNFLD, RN - pcount);
}
else {
start_addr = RN - pcount;
end_addr = RN - 4;
if (WFLD) WRITE_REG(RNFLD, RN - pcount);
}
/*ignore the last two bits of the address*/
address = end_addr - (end_addr & 0x3);
j = inst<<16; i=15;
while (j) {
if (j<0) {
word_t val;
/*WRITE_REG(i, MEM_READ_WORD(address));*/
val = MEM_READ_WORD(address);
WRITE_REG(i, val);
address -= 4;
}
j = j<<1; i--;
}
assert(start_addr-(start_addr&0x3) == address+4);
if (BITn(inst, 15) & BITn(inst, 22))
WRITE_CPSR(SPSR);
EMULATOR_STUB(ldm,inst);
}
void impl_stm(IMPL_FORMALS)
{
UInt32 start_addr, end_addr, address, i;
SInt32 j, pcount = popcount16(inst)*4;
if (!PFLD && UFLD) {
start_addr = RN;
end_addr = RN + pcount - 4;
if (WFLD) WRITE_REG(RNFLD, RN + pcount);
}
else if (PFLD && UFLD) {
start_addr = RN+4;
end_addr = RN + pcount;
if (WFLD) WRITE_REG(RNFLD, RN + pcount);
}
else if (!PFLD && !UFLD) {
start_addr = RN - pcount + 4;;
end_addr = RN;
if (WFLD) WRITE_REG(RNFLD, RN - pcount);
}
else {
start_addr = RN - pcount;
end_addr = RN - 4;
if (WFLD) WRITE_REG(RNFLD, RN - pcount);
}
/*ignore the last two bits of the address*/
address = end_addr - (end_addr & 0x3);
j = inst<<16; i=15;
while (j) {
if (j<0) {
word_t val=READ_REG(i);
MEM_WRITE_WORD(address, val);
/*MEM_WRITE_WORD(address, READ_REG(i));*/
address -= 4;
}
j = j<<1; i--;
}
assert(start_addr - (start_addr&0x3) == address+4);
EMULATOR_STUB(stm,inst);
}
char *disasm_ldst1_imm(arm_inst_t inst, arm_addr_t addr, char *buf)
{
buf += sprintf(buf, "%s%s%s%s %s, ",
LFLD?"ldr":"str", arm_conditional[COND], BFLD?"b":"",
(!PFLD&&WFLD)?"t":"", arm_regnames[RDFLD]);
/*immediate offset*/
if (PFLD) {
buf += sprintf(buf, "[%s, #%s%d]",
arm_regnames[RNFLD], UFLD?"":"-", inst&0xFFF);
if (WFLD)
buf += sprintf(buf, "!");
}
else {
buf += sprintf(buf, "[%s], #%s%d",
arm_regnames[RNFLD], UFLD?"":"-", inst&0xFFF);
}
buf += sprintf(buf, ";\n");
return buf;
}
char *disasm_ldst1_reg(arm_inst_t inst, arm_addr_t addr, char *buf)
{
UInt32 shift_imm = (inst>>7) & 0x01f;
UInt8 type = (inst>>5) & 0x03;
buf += sprintf(buf, "%s%s%s%s %s, ",
LFLD?"ldr":"str", arm_conditional[COND], BFLD?"b":"",
(!PFLD&&WFLD)?"t":"", arm_regnames[RDFLD]);
/*register offset*/
if (PFLD) {
buf += sprintf(buf, "[%s, %s%s",
arm_regnames[RNFLD], UFLD?"":"-", arm_regnames[RMFLD]);
if (shift_imm==0 && type==0)
buf += sprintf(buf, "]");
else if (shift_imm==0 && type==3)
buf += sprintf(buf, ", rrx]");
else
buf += sprintf(buf, ", %s #%d]", arm_shift[type], shift_imm);
if (WFLD)
buf += sprintf(buf, "!");
}
else {
buf += sprintf(buf, "[%s], %s%s",
arm_regnames[RNFLD], UFLD?"":"-", arm_regnames[RMFLD]);
if (shift_imm==0 && type==3)
buf += sprintf(buf, ", rrx");
else if (shift_imm || type)
buf += sprintf(buf, ", %s #%d", arm_shift[type], shift_imm);
}
buf += sprintf(buf, ";\n");
return buf;
}
char *disasm_ldst2_imm(arm_inst_t inst, arm_addr_t addr, char *buf)
{
UInt32 offset = ((inst>>4) & 0xF0) | (inst & 0xF);
buf += sprintf(buf, "%s%s%s%s %s, ",
LFLD?"ldr":"str", arm_conditional[COND], SIGN?"s":"", HFLD?"h":"b",
arm_regnames[RDFLD]);
/*immediate offset*/
if (PFLD) {
buf += sprintf(buf, "[%s, #%s%d]",
arm_regnames[RNFLD], UFLD?"":"-", offset);
if (WFLD)
buf += sprintf(buf, "!");
}
else {
buf += sprintf(buf, "[%s], #%s%d",
arm_regnames[RNFLD], UFLD?"":"-", offset);
}
buf += sprintf(buf, ";\n");
return buf;
}
char *disasm_ldst2_reg(arm_inst_t inst, arm_addr_t addr, char *buf)
{
buf += sprintf(buf, "%s%s%s%s %s, ",
LFLD?"ldr":"str", arm_conditional[COND], SIGN?"s":"", HFLD?"h":"b",
arm_regnames[RDFLD]);
/*immediate offset*/
if (PFLD) {
buf += sprintf(buf, "[%s, %s%s]",
arm_regnames[RNFLD], UFLD?"":"-", arm_regnames[RMFLD]);
if (WFLD)
buf += sprintf(buf, "!");
}
else {
buf += sprintf(buf, "[%s], %s%s",
arm_regnames[RNFLD], UFLD?"":"-", arm_regnames[RMFLD]);
}
buf += sprintf(buf, ";\n");
return buf;
}
char *disasm_swap(arm_inst_t inst, arm_addr_t addr, char *buf)
{
buf += sprintf(buf, "swp%s %s, %s, [%s];\n",
arm_conditional[COND],
arm_regnames[RDFLD], arm_regnames[RMFLD], arm_regnames[RNFLD]);
return buf;
}
char *disasm_swap_byte(arm_inst_t inst, arm_addr_t addr, char *buf)
{
buf += sprintf(buf, "swp%sb %s, %s, [%s];\n",
arm_conditional[COND],
arm_regnames[RDFLD], arm_regnames[RMFLD], arm_regnames[RNFLD]);
return buf;
}
char *disasm_ldstm(arm_inst_t inst, arm_addr_t addr, char *buf)
{
UInt32 i, first = 1;
buf += sprintf(buf, "%s%s%s%s %s%s, {",
LFLD?"ldm":"stm", arm_conditional[COND], UFLD?"i":"d", PFLD?"b":"a",
arm_regnames[RNFLD], WFLD?"!":"");
for (i = 0; i<16; i++) {
if ((1<<i) & inst) {
buf += sprintf(buf, "%s%s", first?"":", ", arm_regnames[i]);
first = 0;
}
}
buf += sprintf(buf, "}");
if (BITn(inst,22))
buf += sprintf(buf, "^");
buf += sprintf(buf, ";\n");
return buf;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -