Uses latest qemu arm thumb load store stuff (#1021)

This commit is contained in:
Catena cyber
2018-09-27 04:32:48 +02:00
committed by Nguyen Anh Quynh
parent 333bfdf65e
commit 400a0ab309

View File

@ -8532,15 +8532,49 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
} }
} else { } else {
int address_offset; int address_offset;
int load; int load = insn & (1 << 20);
int wbit = insn & (1 << 21);
int pbit = insn & (1 << 24);
int doubleword = 0;
/* Misc load/store */ /* Misc load/store */
rn = (insn >> 16) & 0xf; rn = (insn >> 16) & 0xf;
rd = (insn >> 12) & 0xf; rd = (insn >> 12) & 0xf;
if (!load && (sh & 2)) {
/* doubleword */
ARCH(5TE);
if (rd & 1) {
/* UNPREDICTABLE; we choose to UNDEF */
goto illegal_op;
}
load = (sh & 1) == 0;
doubleword = 1;
}
addr = load_reg(s, rn); addr = load_reg(s, rn);
if (insn & (1 << 24)) if (pbit)
gen_add_datah_offset(s, insn, 0, addr); gen_add_datah_offset(s, insn, 0, addr);
address_offset = 0; address_offset = 0;
if (insn & (1 << 20)) { if (doubleword) {
if (!load) {
/* store */
tmp = load_reg(s, rd);
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tcg_ctx, tmp);
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
tmp = load_reg(s, rd + 1);
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tcg_ctx, tmp);
} else {
/* load */
tmp = tcg_temp_new_i32(tcg_ctx);
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
tmp = tcg_temp_new_i32(tcg_ctx);
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
rd++;
}
address_offset = -4;
} else if (load) {
/* load */ /* load */
tmp = tcg_temp_new_i32(tcg_ctx); tmp = tcg_temp_new_i32(tcg_ctx);
switch(sh) { switch(sh) {
@ -8555,47 +8589,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
gen_aa32_ld16s(s, tmp, addr, get_mem_index(s)); gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
break; break;
} }
load = 1;
} else if (sh & 2) {
ARCH(5TE);
/* doubleword */
if (sh & 1) {
/* store */
tmp = load_reg(s, rd);
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tcg_ctx, tmp);
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
tmp = load_reg(s, rd + 1);
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tcg_ctx, tmp);
load = 0;
} else {
/* load */
tmp = tcg_temp_new_i32(tcg_ctx);
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
tmp = tcg_temp_new_i32(tcg_ctx);
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
rd++;
load = 1;
}
address_offset = -4;
} else { } else {
/* store */ /* store */
tmp = load_reg(s, rd); tmp = load_reg(s, rd);
gen_aa32_st16(s, tmp, addr, get_mem_index(s)); gen_aa32_st16(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tcg_ctx, tmp); tcg_temp_free_i32(tcg_ctx, tmp);
load = 0;
} }
/* Perform base writeback before the loaded value to /* Perform base writeback before the loaded value to
ensure correct behavior with overlapping index registers. ensure correct behavior with overlapping index registers.
ldrd with base writeback is is undefined if the ldrd with base writeback is is undefined if the
destination and index registers overlap. */ destination and index registers overlap. */
if (!(insn & (1 << 24))) { if (!pbit) {
gen_add_datah_offset(s, insn, address_offset, addr); gen_add_datah_offset(s, insn, address_offset, addr);
store_reg(s, rn, addr); store_reg(s, rn, addr);
} else if (insn & (1 << 21)) { } else if (wbit) {
if (address_offset) if (address_offset)
tcg_gen_addi_i32(tcg_ctx, addr, addr, address_offset); tcg_gen_addi_i32(tcg_ctx, addr, addr, address_offset);
store_reg(s, rn, addr); store_reg(s, rn, addr);