mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 13:24:57 +00:00 
			
		
		
		
	target/arm: Convert T16, long branches
Backports commit 67b54c554b39fd24f0c3aabc546e83b3082ee7ff from qemu
This commit is contained in:
		
							parent
							
								
									8d2fe3f6db
								
							
						
					
					
						commit
						a91de478cc
					
				| 
						 | 
				
			
			@ -272,3 +272,10 @@ LDM_t16         1011 110 ......... \
 | 
			
		|||
%imm11_0x2      0:s11 !function=times_2
 | 
			
		||||
 | 
			
		||||
B               11100 ...........               &i imm=%imm11_0x2
 | 
			
		||||
 | 
			
		||||
# thumb_insn_is_16bit() ensures we won't be decoding these as
 | 
			
		||||
# T16 instructions for a Thumb2 CPU, so these patterns must be
 | 
			
		||||
# a Thumb1 split BL/BLX.
 | 
			
		||||
BLX_suffix      11101 imm:11                    &i
 | 
			
		||||
BL_BLX_prefix   11110 imm:s11                   &i
 | 
			
		||||
BL_suffix       11111 imm:11                    &i
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10483,6 +10483,43 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
 | 
			
		||||
{
 | 
			
		||||
    TCGContext *tcg_ctx = s->uc->tcg_ctx;
 | 
			
		||||
    assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
 | 
			
		||||
    tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], read_pc(s) + (a->imm << 12));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
 | 
			
		||||
{
 | 
			
		||||
    TCGContext *tcg_ctx = s->uc->tcg_ctx;
 | 
			
		||||
    TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
 | 
			
		||||
 | 
			
		||||
    assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
 | 
			
		||||
    tcg_gen_addi_i32(tcg_ctx, tmp, tcg_ctx->cpu_R[14], (a->imm << 1) | 1);
 | 
			
		||||
    tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], s->base.pc_next | 1);
 | 
			
		||||
    gen_bx(s, tmp);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
 | 
			
		||||
{
 | 
			
		||||
    TCGContext *tcg_ctx = s->uc->tcg_ctx;
 | 
			
		||||
    TCGv_i32 tmp;
 | 
			
		||||
 | 
			
		||||
    assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
 | 
			
		||||
    if (!ENABLE_ARCH_5) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    tmp = tcg_temp_new_i32(tcg_ctx);
 | 
			
		||||
    tcg_gen_addi_i32(tcg_ctx, tmp, tcg_ctx->cpu_R[14], a->imm << 1);
 | 
			
		||||
    tcg_gen_andi_i32(tcg_ctx, tmp, tmp, 0xfffffffc);
 | 
			
		||||
    tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], s->base.pc_next | 1);
 | 
			
		||||
    gen_bx(s, tmp);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
 | 
			
		||||
{
 | 
			
		||||
    TCGContext *tcg_ctx = s->uc->tcg_ctx;
 | 
			
		||||
| 
						 | 
				
			
			@ -11089,11 +11126,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
 | 
			
		|||
 | 
			
		||||
static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 | 
			
		||||
{
 | 
			
		||||
    TCGContext *tcg_ctx = s->uc->tcg_ctx;
 | 
			
		||||
    int32_t offset;
 | 
			
		||||
    TCGv_i32 tmp;
 | 
			
		||||
    TCGv_i32 tmp2;
 | 
			
		||||
 | 
			
		||||
    if (disas_t16(s, insn)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -11111,56 +11143,12 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 | 
			
		|||
    case 10: /* add PC/SP (immediate), in decodetree */
 | 
			
		||||
    case 11: /* misc, in decodetree */
 | 
			
		||||
    case 12: /* load/store multiple, in decodetree */
 | 
			
		||||
        goto illegal_op;
 | 
			
		||||
 | 
			
		||||
    case 13: /* conditional branch or swi, in decodetree */
 | 
			
		||||
        goto illegal_op;
 | 
			
		||||
 | 
			
		||||
    case 14:
 | 
			
		||||
        if (insn & (1 << 11)) {
 | 
			
		||||
            /* thumb_insn_is_16bit() ensures we can't get here for
 | 
			
		||||
             * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
 | 
			
		||||
             * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
 | 
			
		||||
             */
 | 
			
		||||
            assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
 | 
			
		||||
            ARCH(5);
 | 
			
		||||
            offset = ((insn & 0x7ff) << 1);
 | 
			
		||||
            tmp = load_reg(s, 14);
 | 
			
		||||
            tcg_gen_addi_i32(tcg_ctx, tmp, tmp, offset);
 | 
			
		||||
            tcg_gen_andi_i32(tcg_ctx, tmp, tmp, 0xfffffffc);
 | 
			
		||||
 | 
			
		||||
            tmp2 = tcg_temp_new_i32(tcg_ctx);
 | 
			
		||||
            tcg_gen_movi_i32(tcg_ctx, tmp2, s->base.pc_next | 1);
 | 
			
		||||
            store_reg(s, 14, tmp2);
 | 
			
		||||
            gen_bx(s, tmp);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        /* unconditional branch, in decodetree */
 | 
			
		||||
        goto illegal_op;
 | 
			
		||||
 | 
			
		||||
    case 15:
 | 
			
		||||
        /* thumb_insn_is_16bit() ensures we can't get here for
 | 
			
		||||
         * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
 | 
			
		||||
         */
 | 
			
		||||
        assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
 | 
			
		||||
 | 
			
		||||
        if (insn & (1 << 11)) {
 | 
			
		||||
            /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
 | 
			
		||||
            offset = ((insn & 0x7ff) << 1) | 1;
 | 
			
		||||
            tmp = load_reg(s, 14);
 | 
			
		||||
            tcg_gen_addi_i32(tcg_ctx, tmp, tmp, offset);
 | 
			
		||||
 | 
			
		||||
            tmp2 = tcg_temp_new_i32(tcg_ctx);
 | 
			
		||||
            tcg_gen_movi_i32(tcg_ctx, tmp2, s->base.pc_next | 1);
 | 
			
		||||
            store_reg(s, 14, tmp2);
 | 
			
		||||
            gen_bx(s, tmp);
 | 
			
		||||
        } else {
 | 
			
		||||
            /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
 | 
			
		||||
            uint32_t uoffset = ((int32_t)insn << 21) >> 9;
 | 
			
		||||
 | 
			
		||||
            tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], read_pc(s) + uoffset);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
        /* branches, in decodetree */
 | 
			
		||||
        goto illegal_op;
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
illegal_op:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue