Commit 43f7e42c authored by Richard Henderson's avatar Richard Henderson Committed by Peter Maydell
Browse files

target/arm: Convert T16, Miscellaneous 16-bit instructions



Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-64-richard.henderson@linaro.org
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 629fcaa7
Loading
Loading
Loading
Loading
+21 −10
Original line number Diff line number Diff line
@@ -210,6 +210,7 @@ REVSH 1011 1010 11 ... ... @rdm

# Hints

{
  {
    YIELD       1011 1111 0001 0000
    WFE         1011 1111 0010 0000
@@ -223,6 +224,16 @@ REVSH 1011 1010 11 ... ... @rdm
    # rest of the space is a reserved hint, behaves as nop.
    NOP         1011 1111 ---- 0000
  }
  IT            1011 1111 cond_mask:8
}

# Miscellaneous 16-bit instructions

%imm6_9_3       9:1 3:5 !function=times_2

HLT             1011 1010 10 imm:6              &i
BKPT            1011 1110 imm:8                 &i
CBZ             1011 nz:1 0.1 ..... rn:3        imm=%imm6_9_3

# Push and Pop

+34 −77
Original line number Diff line number Diff line
@@ -10196,6 +10196,18 @@ static bool trans_TBH(DisasContext *s, arg_tbranch *a)
    return op_tbranch(s, a, true);
}

static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
{
    TCGv_i32 tmp = load_reg(s, a->rn);

    arm_gen_condlabel(s);
    tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
                        tmp, 0, s->condlabel);
    tcg_temp_free_i32(tmp);
    gen_jmp(s, read_pc(s) + a->imm);
    return true;
}

/*
 * Supervisor call
 */
@@ -10417,6 +10429,27 @@ static bool trans_PLI(DisasContext *s, arg_PLD *a)
    return ENABLE_ARCH_7;
}

/*
 * If-then
 */

static bool trans_IT(DisasContext *s, arg_IT *a)
{
    int cond_mask = a->cond_mask;

    /*
     * No actual code generated for this insn, just setup state.
     *
     * Combinations of firstcond and mask which set up an 0b1111
     * condition are UNPREDICTABLE; we take the CONSTRAINED
     * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
     * i.e. both meaning "execute always".
     */
    s->condexec_cond = (cond_mask >> 4) & 0xe;
    s->condexec_mask = cond_mask & 0x1f;
    return true;
}

/*
 * Legacy decoder.
 */
@@ -10783,83 +10816,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
    case 8: /* load/store halfword immediate offset, in decodetree */
    case 9: /* load/store from stack, in decodetree */
    case 10: /* add PC/SP (immediate), in decodetree */
    case 11: /* misc, in decodetree */
    case 12: /* load/store multiple, in decodetree */
        goto illegal_op;

    case 11:
        /* misc */
        op = (insn >> 8) & 0xf;
        switch (op) {
        case 0: /* add/sub (sp, immediate), in decodetree */
        case 2: /* sign/zero extend, in decodetree */
            goto illegal_op;

        case 4: case 5: case 0xc: case 0xd:
            /* push/pop, in decodetree */
            goto illegal_op;

        case 1: case 3: case 9: case 11: /* czb */
            rm = insn & 7;
            tmp = load_reg(s, rm);
            arm_gen_condlabel(s);
            if (insn & (1 << 11))
                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
            else
                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
            tcg_temp_free_i32(tmp);
            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
            gen_jmp(s, read_pc(s) + offset);
            break;

        case 15: /* IT, nop-hint.  */
            if ((insn & 0xf) == 0) {
                goto illegal_op; /* nop hint, in decodetree */
            }
            /*
             * IT (If-Then)
             *
             * Combinations of firstcond and mask which set up an 0b1111
             * condition are UNPREDICTABLE; we take the CONSTRAINED
             * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
             * i.e. both meaning "execute always".
             */
            s->condexec_cond = (insn >> 4) & 0xe;
            s->condexec_mask = insn & 0x1f;
            /* No actual code generated for this insn, just setup state.  */
            break;

        case 0xe: /* bkpt */
        {
            int imm8 = extract32(insn, 0, 8);
            ARCH(5);
            gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm8, true));
            break;
        }

        case 0xa: /* rev, and hlt */
        {
            int op1 = extract32(insn, 6, 2);

            if (op1 == 2) {
                /* HLT */
                int imm6 = extract32(insn, 0, 6);

                gen_hlt(s, imm6);
                break;
            }

            /* Otherwise this is rev, in decodetree */
            goto illegal_op;
        }

        case 6: /* setend, cps; in decodetree */
            goto illegal_op;

        default:
            goto undef;
        }
        break;

    case 13: /* conditional branch or swi, in decodetree */
        goto illegal_op;

@@ -10915,7 +10873,6 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
    }
    return;
illegal_op:
undef:
    unallocated_encoding(s);
}