summaryrefslogtreecommitdiff
path: root/target-sparc
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-09-04 07:43:50 -0700
committerRichard Henderson <rth@twiddle.net>2016-07-12 11:02:43 -0700
commit7705091ca4a20c8c2d20e2af5d0a1bcb17296657 (patch)
tree88b997a4b1d2a77d36acf3377c787bcb85977dbf /target-sparc
parent6850811e7c56403b0d225a1bffd096abf2ff06f9 (diff)
downloadqemu-7705091ca4a20c8c2d20e2af5d0a1bcb17296657.tar.gz
qemu-7705091ca4a20c8c2d20e2af5d0a1bcb17296657.tar.bz2
qemu-7705091ca4a20c8c2d20e2af5d0a1bcb17296657.zip
target-sparc: Directly implement easy ldf/stf asis
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-sparc')
-rw-r--r--target-sparc/translate.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0b29aff68f..2ea6964d9e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2282,10 +2282,33 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr,
int insn, int size, int rd)
{
DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
+ TCGv_i32 d32;
switch (da.type) {
case GET_ASI_EXCP:
break;
+
+ case GET_ASI_DIRECT:
+ gen_address_mask(dc, addr);
+ switch (size) {
+ case 4:
+ d32 = gen_dest_fpr_F(dc);
+ tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop);
+ gen_store_fpr_F(dc, rd, d32);
+ break;
+ case 8:
+ tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+ break;
+ case 16:
+ tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+ tcg_gen_addi_tl(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+
default:
{
TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2306,10 +2329,32 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
int insn, int size, int rd)
{
DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
+ TCGv_i32 d32;
switch (da.type) {
case GET_ASI_EXCP:
break;
+
+ case GET_ASI_DIRECT:
+ gen_address_mask(dc, addr);
+ switch (size) {
+ case 4:
+ d32 = gen_load_fpr_F(dc, rd);
+ tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop);
+ break;
+ case 8:
+ tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+ break;
+ case 16:
+ tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+ tcg_gen_addi_tl(addr, addr, 8);
+ tcg_gen_qemu_st_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+
default:
{
TCGv_i32 r_asi = tcg_const_i32(da.asi);