diff --git a/target/cr16c/insn.decode b/target/cr16c/insn.decode index 874a361056..39863de46d 100644 --- a/target/cr16c/insn.decode +++ b/target/cr16c/insn.decode @@ -69,8 +69,13 @@ SUBW_reg 0011 1011 .... .... @p ### Integer Comparison -CMPW_imm4_16 0101 0010 .... .... @param44_cmp_imm -CMPW_reg 0101 0011 .... .... @param44_cmp +CMPB_imm4_16 0101 0000 .... .... @param44_cmp_imm +CMPB_reg 0101 0001 .... .... @param44_cmp +CMPD_imm32 0000 0000 1001 .... .... .... .... .... .... .... .... .... @param4_32 +CMPD_imm4_16 0101 0110 .... .... @param44_cmp_imm +CMPD_reg 0101 0111 .... .... @param44_cmp +CMPW_imm4_16 0101 0010 .... .... @param44_cmp_imm +CMPW_reg 0101 0011 .... .... @param44_cmp ### Jumps and Linkeage diff --git a/target/cr16c/translate.c b/target/cr16c/translate.c index 9830ba8924..6327a4d4bb 100644 --- a/target/cr16c/translate.c +++ b/target/cr16c/translate.c @@ -82,9 +82,12 @@ static uint64_t decode_load_bytes(DisasContext *ctx, uint64_t insn, int i, int n // Include generated decodetree function declarations #include "decode-insn.c.inc" -static uint32_t get_imm4(DisasContext* ctx, uint8_t imm) { +static uint16_t get_imm4(DisasContext* ctx, uint8_t imm) { if (imm == 11) { uint16_t imm_esc = cpu_lduw_code(ctx->env, ctx->base.pc_next); + if (imm_esc << 15 == 1) { + imm_esc = -((~imm_esc)+1); + } ctx->base.pc_next += 2; return imm_esc; } @@ -96,6 +99,13 @@ static uint32_t get_imm4(DisasContext* ctx, uint8_t imm) { } } +static int16_t u16_to_s16(uint16_t num) { + if ((num >> 15) == 1) { + return -((~num)+1); + } + return num; +} + static bool trans_MOVB_imm4_16(DisasContext* ctx, arg_MOVB_imm4_16* a) { uint32_t imm = get_imm4(ctx, a->imm) & 0xFF; @@ -122,7 +132,7 @@ static bool trans_MOVD_imm32(DisasContext* ctx, arg_MOVD_imm32* a) { } static bool trans_MOVD_imm4_16(DisasContext* ctx, arg_MOVD_imm4_16* a) { - uint32_t imm = get_imm4(ctx, a->imm); + uint32_t imm = u16_to_s16(get_imm4(ctx, a->imm)); tcg_gen_movi_i32(r[a->rd], imm); tcg_gen_movi_i32(r[a->rd + 1], 0); @@ -393,7 +403,7 @@ static bool trans_ADDD_imm32(DisasContext *ctx, arg_ADDD_imm32 *a) { } static bool trans_ADDD_imm4_16(DisasContext *ctx, arg_ADDD_imm4_16 *a) { - uint32_t imm = get_imm4(ctx, a->imm); + uint32_t imm = u16_to_s16(get_imm4(ctx, a->imm)); return gen_ADDD_imm(r[a->rd], r[a->rd+1], imm); } @@ -713,25 +723,88 @@ static bool trans_SUBW_reg(DisasContext *ctx, arg_SUBW_reg *a) { /* Integer Comparison */ +static void gen_cmp(TCGv_i32 src1, TCGv_i32 src2) { + tcg_gen_setcond_i32(TCG_COND_EQ, f_z, src1, src2); + tcg_gen_setcond_i32(TCG_COND_GT, f_n, src1, src2); + tcg_gen_setcond_i32(TCG_COND_GTU, f_l, src1, src2); +} + +static bool trans_CMPB_imm4_16(DisasContext *ctx, arg_CMPB_imm4_16 *a) { + int32_t imm = get_imm4(ctx, a->imm) & 0xFF; + TCGv_i32 temp = tcg_temp_new_i32(); + + tcg_gen_ext8s_i32(temp, r[a->rs]); + + gen_cmp(tcg_constant_i32(imm), temp); + + return true; +} + +static bool trans_CMPB_reg(DisasContext *ctx, arg_CMPB_reg *a) { + TCGv_i32 temp1 = tcg_temp_new_i32(); + TCGv_i32 temp2 = tcg_temp_new_i32(); + + tcg_gen_ext8s_i32(temp1, r[a->rs1]); + tcg_gen_ext8s_i32(temp2, r[a->rs2]); + + gen_cmp(temp1, temp2); + + return true; +} + +static bool trans_CMPD_imm4_16(DisasContext *ctx, arg_CMPD_imm4_16 *a) { + int32_t imm = u16_to_s16(get_imm4(ctx, a->imm)); + TCGv_i32 temp_rs = tcg_temp_new_i32(); + + tcg_gen_shli_i32(temp_rs, r[a->rs+1], 16); + tcg_gen_deposit_i32(temp_rs, temp_rs, r[a->rs], 0, 16); + + gen_cmp(tcg_constant_i32(imm), temp_rs); + + return true; +} + +static bool trans_CMPD_imm32(DisasContext *ctx, arg_CMPD_imm32 *a) { + int32_t imm = get_imm4(ctx, a->imm); + TCGv_i32 temp_rs = tcg_temp_new_i32(); + + tcg_gen_shli_i32(temp_rs, r[a->rd+1], 16); + tcg_gen_deposit_i32(temp_rs, temp_rs, r[a->rd], 0, 16); + + gen_cmp(tcg_constant_i32(imm), temp_rs); + + return true; +} + +static bool trans_CMPD_reg(DisasContext *ctx, arg_CMPD_reg *a) { + TCGv_i32 temp1 = tcg_temp_new_i32(); + TCGv_i32 temp2 = tcg_temp_new_i32(); + + tcg_gen_shli_i32(temp1, r[a->rs1+1], 16); + tcg_gen_deposit_i32(temp1, temp1, r[a->rs1], 0, 16); + tcg_gen_shli_i32(temp2, r[a->rs2], 16); + tcg_gen_deposit_i32(temp2, temp2, r[a->rs2], 0, 16); + + gen_cmp(temp1, temp2); + + return true; +} + static bool trans_CMPW_imm4_16(DisasContext *ctx, arg_CMPW_imm4_16 *a) { - uint32_t imm = get_imm4(ctx, a->imm) & 0xFFFF; + int32_t imm = u16_to_s16(get_imm4(ctx, a->imm)); - tcg_gen_andi_i32(r[a->rs], r[a->rs], 0xFFFF); + tcg_gen_ext16s_i32(r[a->rs], r[a->rs]); - tcg_gen_setcondi_i32(TCG_COND_EQ, f_z, r[a->rs], imm); - tcg_gen_setcondi_i32(TCG_COND_LT, f_n, r[a->rs], imm); - tcg_gen_setcondi_i32(TCG_COND_LTU, f_l, r[a->rs], imm); + gen_cmp(tcg_constant_i32(imm), r[a->rs]); return true; } static bool trans_CMPW_reg(DisasContext *ctx, arg_CMPW_reg *a) { - tcg_gen_andi_i32(r[a->rs1], r[a->rs1], 0xFFFF); - tcg_gen_andi_i32(r[a->rs2], r[a->rs1], 0xFFFF); + tcg_gen_ext16s_i32(r[a->rs1], r[a->rs1]); + tcg_gen_ext16s_i32(r[a->rs2], r[a->rs2]); - tcg_gen_setcond_i32(TCG_COND_EQ, f_z, r[a->rs1], r[a->rs2]); - tcg_gen_setcond_i32(TCG_COND_LT, f_n, r[a->rs1], r[a->rs2]); - tcg_gen_setcond_i32(TCG_COND_LTU, f_l, r[a->rs1], r[a->rs2]); + gen_cmp(r[a->rs1], r[a->rs2]); return true; } @@ -776,67 +849,67 @@ static bool trans_BRCOND_disp8(DisasContext* ctx, arg_BRCOND_disp8 *a) { switch (a->cond) { case CR16C_COND_EQ: - tcg_gen_brcondi_i32(TCG_COND_EQ, f_z, 0, l); + tcg_gen_brcondi_i32(TCG_COND_EQ, f_z, 1, l); break; case CR16C_COND_NE: - tcg_gen_brcondi_i32(TCG_COND_NE, f_z, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, f_z, 1, l); break; case CR16C_COND_CS: - tcg_gen_brcondi_i32(TCG_COND_EQ, f_c, 0, l); + tcg_gen_brcondi_i32(TCG_COND_EQ, f_c, 1, l); break; case CR16C_COND_CC: - tcg_gen_brcondi_i32(TCG_COND_NE, f_c, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, f_c, 1, l); break; case CR16C_COND_HI: - tcg_gen_brcondi_i32(TCG_COND_EQ, f_l, 0, l); + tcg_gen_brcondi_i32(TCG_COND_EQ, f_l, 1, l); break; case CR16C_COND_LS: - tcg_gen_brcondi_i32(TCG_COND_NE, f_l, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, f_l, 1, l); break; case CR16C_COND_GT: - tcg_gen_brcondi_i32(TCG_COND_EQ, f_l, 0, l); + tcg_gen_brcondi_i32(TCG_COND_EQ, f_n, 1, l); break; case CR16C_COND_LE: - tcg_gen_brcondi_i32(TCG_COND_NE, f_l, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, f_l, 1, l); break; case CR16C_COND_FS: - tcg_gen_brcondi_i32(TCG_COND_EQ, f_f, 0, l); + tcg_gen_brcondi_i32(TCG_COND_EQ, f_f, 1, l); break; case CR16C_COND_FC: - tcg_gen_brcondi_i32(TCG_COND_NE, f_f, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, f_f, 1, l); break; case CR16C_COND_LO: temp = tcg_temp_new_i32(); - tcg_gen_and_i32(temp, f_z, f_l); + tcg_gen_or_i32(temp, f_z, f_l); tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l); break; case CR16C_COND_HS: temp = tcg_temp_new_i32(); tcg_gen_and_i32(temp, f_z, f_l); - tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, temp, 1, l); break; case CR16C_COND_LT: temp = tcg_temp_new_i32(); - tcg_gen_and_i32(temp, f_z, f_l); + tcg_gen_or_i32(temp, f_z, f_n); tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l); break; case CR16C_COND_GE: temp = tcg_temp_new_i32(); tcg_gen_and_i32(temp, f_z, f_n); - tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l); + tcg_gen_brcondi_i32(TCG_COND_NE, temp, 1, l); break; } - tcg_gen_movi_i32(f_f, 1); - tcg_gen_movi_i32(pc, dest); - tcg_gen_exit_tb(ctx->base.tb, 0); - - gen_set_label(l); - tcg_gen_movi_i32(f_c, 1); tcg_gen_movi_i32(pc, ctx->base.pc_next); tcg_gen_exit_tb(ctx->base.tb, 1); + gen_set_label(l); + + tcg_gen_movi_i32(f_f, 1); + tcg_gen_movi_i32(pc, dest); + tcg_gen_exit_tb(ctx->base.tb, 0); + return true; } diff --git a/tests/tcg/cr16c/test04-cmps.S b/tests/tcg/cr16c/test04-cmps.S new file mode 100644 index 0000000000..851d73bd43 --- /dev/null +++ b/tests/tcg/cr16c/test04-cmps.S @@ -0,0 +1,313 @@ +#include "macros.inc" + +.global _start + +.text +_start: + /* Initialize registers */ + RESET + + /*** CMPB imm4/16 ***/ + /* Unsigned */ + cmpb $1, r1 + EXPECT_COND eq + cmpb $0, r1 + EXPECT_COND ne + cmpb $2, r1 + EXPECT_COND gt + cmpb $0, r1 + EXPECT_COND le + cmpb $2, r1 + EXPECT_COND hi + cmpb $0, r1 + EXPECT_COND ls + /* Immidiate signed */ + cmpb $-2, r1 + EXPECT_COND ls + cmpb $-2, r1 + EXPECT_COND gt + EXPECT 0x0A01, r1 + /* Reg signed */ + movw $0x00FF, r1 + cmpb $1, r1 + EXPECT_COND hi + cmpb $1, r1 + EXPECT_COND le + cmpb $-2, r1 + EXPECT_COND ls + cmpb $-2, r1 + EXPECT_COND le + EXPECT 0x00FF, r1 + RESET + + + /*** CMPB reg ***/ + /* Unsigned */ + movw $0x2201, r2 + cmpb r2, r1 + EXPECT_COND eq + cmpb r0, r1 + EXPECT_COND ne + cmpb r3, r1 + EXPECT_COND gt + cmpb r0, r1 + EXPECT_COND le + cmpb r2, r1 + EXPECT_COND hi + cmpb r0, r1 + EXPECT_COND ls + EXPECT 0x0B00, r0 + EXPECT 0x0A01, r1 + EXPECT 0x2201, r2 + /* Src1 signed */ + movw $0x22FF, r2 + cmpb r2, r1 + EXPECT_COND ls + cmpb r2, r1 + EXPECT_COND gt + EXPECT 0x0A01, r1 + EXPECT 0x22FF, r2 + /* Src2 signed */ + cmpb r3, r2 + EXPECT_COND hi + cmpb r3, r2 + EXPECT_COND le + movw $0x22FE, r4 + cmpb r4, r2 + EXPECT_COND ls + cmpb r4, r2 + EXPECT_COND le + EXPECT 0x22FF, r2 + EXPECT 0x0803, r3 + EXPECT 0x22FE, r4 + /* Same register */ + cmpb r0, r0 + EXPECT_COND eq + EXPECT 0x0B00, r0 + RESET + + + /*** CMPD imm32 ***/ + /* Unsigned */ + cmpd $0x0A010B00, (r1,r0) + EXPECT_COND eq + cmpd $0, (r1,r0) + EXPECT_COND ne + cmpd $0x10000000, (r1,r0) + EXPECT_COND gt + cmpd $0x09000000, (r1,r0) + EXPECT_COND le + cmpd $0x10000000, (r1,r0) + EXPECT_COND hi + cmpd $0x09000000, (r1,r0) + EXPECT_COND ls + /* Immidiate signed */ + cmpd $-0x09000000, (r1,r0) + EXPECT_COND ls + cmpd $-0x09000000, (r1,r0) + EXPECT_COND gt + EXPECT 0x0B00, r0 + EXPECT 0x0A01, r1 + /* Reg signed */ + movw $-1, r0 + movw $-1, r1 + cmpd $0x10000000, (r1,r0) + EXPECT_COND hi + cmpd $0x10000000, (r1,r0) + EXPECT_COND le + cmpd $-0x09000000, (r1,r0) + EXPECT_COND ls + cmpd $-0x09000000, (r1,r0) + EXPECT_COND le + EXPECT -1, r0 + EXPECT -1, r1 + RESET + + + /*** CMPD imm4/16 ***/ + /* Unsigned */ + movw $0, r5 + cmpd $0x0704, (r5,r4) + EXPECT_COND eq + cmpd $0, (r5,r4) + EXPECT_COND ne + cmpd $0x0705, (r5,r4) + EXPECT_COND gt + cmpd $0xEFFF, (r1,r0) + EXPECT_COND le + cmpd $0x0705, (r5,r4) + EXPECT_COND hi + cmpd $0x0703, (r5,r4) + EXPECT_COND ls + /* Immidiate signed */ + cmpd $-2, (r1,r0) + EXPECT_COND ls + cmpd $-2, (r1,r0) + EXPECT_COND gt + EXPECT 0x0B00, r0 + EXPECT 0x0A01, r1 + EXPECT 0x0704, r4 + EXPECT 0x0000, r5 + /* Reg signed */ + movw $-1, r0 + movw $-1, r1 + cmpd $1, (r1,r0) + EXPECT_COND hi + cmpd $1, (r1,r0) + EXPECT_COND le + cmpd $-2, (r1,r0) + EXPECT_COND ls + cmpd $-2, (r1,r0) + EXPECT_COND le + EXPECT -1, r0 + EXPECT -1, r1 + RESET + + + /*** CMPD reg ***/ + /* Unsigned */ + movw $0x0B00, r2 + movw $0x0A01, r3 + movw $-1, r0 /* Only comparing the lower half should fail */ + cmpd (r3,r2), (r1,r0) + EXPECT_COND eq + cmpd (r5,r4), (r1,r0) + EXPECT_COND ne + cmpd (r1,r0), (r5,r4) + EXPECT_COND gt + cmpd (r5,r4), (r1,r0) + EXPECT_COND le + cmpd (r2,r1), (r4,r3) + EXPECT_COND hi + cmpd (r4,r3), (r2,r1) + EXPECT_COND ls + EXPECT -1, r0 + EXPECT 0x0A01, r1 + EXPECT 0x0B00, r2 + EXPECT 0x0A01, r3 + EXPECT 0x0704, r4 + EXPECT 0x0605, r5 + /* Src1 signed */ + movw $-1, r2 + movw $-1, r3 + cmpd (r3,r2), (r1,r0) + EXPECT_COND ls + cmpd (r3,r2), (r1,r0) + EXPECT_COND gt + EXPECT -1, r0 + EXPECT 0x0A01, r1 + EXPECT -1, r2 + EXPECT -1, r3 + /* Src2 signed */ + cmpd (r1,r0), (r3,r2) + EXPECT_COND hi + cmpd (r1,r0), (r3,r2) + EXPECT_COND le + movw $-1, r5 + movw $-2, r4 + cmpd (r5,r4), (r3,r2) + EXPECT_COND ls + cmpd (r5,r4), (r3,r2) + EXPECT_COND le + EXPECT -1, r0 + EXPECT 0x0A01, r1 + EXPECT -1, r2 + EXPECT -1, r3 + EXPECT -2, r4 + EXPECT -1, r5 + RESET + /* Same register */ + cmpd (r1,r0), (r1,r0) + EXPECT_COND eq + EXPECT 0x0B00, r0 + EXPECT 0x0A01, r1 + /* Overlapping */ + cmpd (r1,r0), (r2,r1) + EXPECT_COND gt + EXPECT 0x0B00, r0 + EXPECT 0x0A01, r1 + EXPECT 0x0902, r2 + RESET + + + /*** CMPW imm4/16 ***/ + /* Unsigned */ + cmpw $0x0A01, r1 + EXPECT_COND eq + cmpw $0x0A00, r1 + EXPECT_COND ne + cmpw $0x0A02, r1 + EXPECT_COND gt + cmpw $0x0A00, r1 + EXPECT_COND le + cmpw $0x0A02, r1 + EXPECT_COND hi + cmpw $0x0A00, r1 + EXPECT_COND ls + /* Immidiate signed */ + cmpw $-2, r1 + EXPECT_COND ls + cmpw $-2, r1 + EXPECT_COND gt + EXPECT 0x0A01, r1 + /* Reg signed */ + movw $-1, r1 + cmpw $1, r1 + EXPECT_COND hi + cmpw $1, r1 + EXPECT_COND le + cmpw $-2, r1 + EXPECT_COND ls + cmpw $-2, r1 + EXPECT_COND le + EXPECT -1, r1 + RESET + + + /*** CMPW reg ***/ + /* Unsigned */ + movw $0x0A01, r2 + cmpw r2, r1 + EXPECT_COND eq + cmpw r0, r1 + EXPECT_COND ne + cmpw r0, r1 + EXPECT_COND gt + cmpw r1, r0 + EXPECT_COND le + cmpw r0, r1 + EXPECT_COND hi + cmpw r1, r0 + EXPECT_COND ls + EXPECT 0x0B00, r0 + EXPECT 0x0A01, r1 + EXPECT 0x0A01, r2 + /* Src1 signed */ + movw $-1, r2 + cmpw r2, r1 + EXPECT_COND ls + cmpw r2, r1 + EXPECT_COND gt + EXPECT 0x0A01, r1 + EXPECT -1, r2 + /* Src2 signed */ + cmpw r3, r2 + EXPECT_COND hi + cmpw r3, r2 + EXPECT_COND le + movw $-2, r4 + cmpw r4, r2 + EXPECT_COND ls + cmpw r4, r2 + EXPECT_COND le + EXPECT -1, r2 + EXPECT 0x0803, r3 + EXPECT -2, r4 + /* Same register */ + cmpw r0, r0 + EXPECT_COND eq + EXPECT 0x0B00, r0 + RESET + + ENDING + FAIL_HANDLER