Skip to content

Commit

Permalink
[arc64] semantic: add lddl
Browse files Browse the repository at this point in the history
  • Loading branch information
Shahab Vahedi authored and shahab-vahedi committed Apr 22, 2021
1 parent 3346737 commit 368f6ed
Show file tree
Hide file tree
Showing 4 changed files with 436 additions and 0 deletions.
4 changes: 4 additions & 0 deletions target/arc/extra_mapping.def
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,14 @@ SEMANTIC_FUNCTION(MPYML, 3)
SEMANTIC_FUNCTION(MPYMUL, 3)
SEMANTIC_FUNCTION(MPYMSUL, 3)
SEMANTIC_FUNCTION(ADDHL, 3)
SEMANTIC_FUNCTION(LDDL, 3)

CONSTANT(LDDL, lddl, 2, 0)

MAPPING(mpyl, MPYL, 3, 0, 1, 2)
MAPPING(mpyml, MPYML, 3, 0, 1, 2)
MAPPING(mpymul, MPYMUL, 3, 0, 1, 2)
MAPPING(mpymsul, MPYMSUL, 3, 0, 1, 2)
MAPPING(addhl, ADDHL, 3, 0, 1, 2)
MAPPING(lddl, LDDL, 3, 1, 2, 0)
#endif
96 changes: 96 additions & 0 deletions target/arc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,102 @@ arc_gen_ADDHL(DisasCtxt *ctx, TCGv a, TCGv b, TCGv c)
return DISAS_NEXT;
}

/*
* 128-bit load.
* FIXME: There is a mixture of decoder stuffs in here.
* The logic must be moved to a decoding layer.
*/
int
arc_gen_LDDL(DisasCtxt *ctx, TCGv base, TCGv offset, TCGv dest_lo)
{
TCGv dest_hi = NULL;

/*
* The destiantion can be a register or immediate (0).
* Look for next register pair if "dest" is a register.
* Will raise an exception if "dest" is an odd register.
*/
if (ctx->insn.operands[0].type & ARC_OPERAND_IR) {
dest_hi = nextReg(dest_lo);
if (dest_hi == NULL) {
return DISAS_NORETURN;
}
}

/*
* Address writebacks for 128-bit loads.
* ,----.----------.
* | aa | mnemonic |
* |----+----------|
* | 0 | none |
* | 1 | as |
* | 2 | a/aw |
* | 3 | ab |
* `----^----------'
*/
/* A non-register operand cannot be incremented. */
if (ctx->insn.aa == 2 || ctx->insn.aa == 3)
{
if (!(ctx->insn.operands[1].type & ARC_OPERAND_IR)) {
arc_gen_excp(ctx, EXCP_INST_ERROR, 0, 0);
return DISAS_NORETURN;
}
}

/* Only defined after possible exception routine codes. */
TCGv addr = tcg_temp_local_new();
TCGv data_hi = tcg_temp_local_new();
TCGv data_lo = tcg_temp_local_new();

switch (ctx->insn.aa) {
case 0: /* Simple base+offset access. */
tcg_gen_add_tl(addr, base, offset);
break;
case 1: /* Address scaling. */
tcg_gen_shli_tl(offset, offset, 3);
tcg_gen_add_tl(addr, base, offset);
break;
case 2: /* Pre memory access increment. */
tcg_gen_add_tl(addr, base, offset);
tcg_gen_mov_tl(base, addr);
break;
case 3: /* Post memory access increment. */
tcg_gen_mov_tl(addr, base);
break;
default:
g_assert_not_reached();
}

/* Load the data. */
if (ctx->insn.operands[0].type & ARC_OPERAND_IR) {
tcg_gen_qemu_ld_tl(data_lo, addr, ctx->mem_idx, MO_Q);
tcg_gen_addi_tl(addr, addr, 8);
tcg_gen_qemu_ld_tl(data_hi, addr, ctx->mem_idx, MO_Q);
}

/*
* If "dest" and "base" are pointing to the same register,
* the register will end up with the loaded data; not the
* updated pointer. Therefore the "base" must be updated
* before the "dest".
*/
if (ctx->insn.aa == 3) { /* Post-memory access increment. */
tcg_gen_add_tl(addr, base, offset);
tcg_gen_mov_tl(base, addr);
}

if (ctx->insn.operands[0].type & ARC_OPERAND_IR) {
tcg_gen_mov_tl(dest_lo, data_lo);
tcg_gen_mov_tl(dest_hi, data_hi);
}

tcg_temp_free(data_lo);
tcg_temp_free(data_hi);
tcg_temp_free(addr);

return DISAS_NEXT;
}

#endif
#ifdef TARGET_ARCV2

Expand Down
2 changes: 2 additions & 0 deletions tests/tcg/arc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ TESTCASES += check_vsub.tst
TESTCASES += check_mpyd.tst
TESTCASES += check_bi.tst
TESTCASES += check_bih.tst
# arc64
#TESTCASES += check_lddl.tst

all: $(TESTCASES)
OBJECTS = ivt.o
Expand Down
Loading

0 comments on commit 368f6ed

Please sign in to comment.