CR16C: Implement cmp opcodes

This commit is contained in:
Jonas Bewig 2025-05-05 11:19:09 +02:00
parent df4af6231c
commit 4d7152ee96
No known key found for this signature in database
GPG key ID: 8D99867797A4886F
3 changed files with 426 additions and 35 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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