[Qemu-devel] [PATCH v2] target-tilegx: Implement v2mults instruction
From: Chen Gang Just according to v1multu instruction implementation. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 1 + target-tilegx/simd_helper.c | 13 + target-tilegx/translate.c | 4 3 files changed, 18 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index c58ee20..bbcc476 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -16,6 +16,7 @@ DEF_HELPER_FLAGS_2(v2int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2mults, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index 6fa6318..4f226eb 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -41,6 +41,19 @@ uint64_t helper_v1multu(uint64_t a, uint64_t b) return r; } +uint64_t helper_v2mults(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 16) { +int64_t ae = (int16_t)(a >> i); +int64_t be = (int16_t)(b >> i); +r |= ((ae * be) & 0x) << i; +} +return r; +} + uint64_t helper_v1shl(uint64_t a, uint64_t b) { uint64_t m; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 034cbc2..eb2d0b1 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1355,7 +1355,11 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V2MNZ, 0, X1): case OE_RRR(V2MULFSC, 0, X0): case OE_RRR(V2MULS, 0, X0): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2MULTS, 0, X0): +gen_helper_v2mults(tdest, tsrca, tsrcb); +mnemonic = "v2mults"; +break; case OE_RRR(V2MZ, 0, X0): case OE_RRR(V2MZ, 0, X1): case OE_RRR(V2PACKH, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH v2] target-tilegx: Use TILEGX_EXCP_OPCODE_UNKNOWN and TILEGX_EXCP_OPCODE_UNIMPLEMENTED correctly
From: Chen Gang For some cases, they are for TILEGX_EXCP_OPCODE_UNKNOWN, not for TILEGX_EXCP_OPCODE_UNIMPLEMENTED. Also for some cases, they are for TILEGX_EXCP_OPCODE_UNIMPLEMENTED, not for TILEGX_EXCP_OPCODE_UNKNOWN. When analyzing issues, the correct printing information is necessary, e.g. grep UIMP in gcc testsuite output log for finding qemu tilegx umimplementation issues, grep UNKNOWN for finding unknown instructions. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 41 - 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index eb2d0b1..ab3fc81 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -291,7 +291,7 @@ static TileExcp gen_st_opcode(DisasContext *dc, unsigned dest, unsigned srca, unsigned srcb, TCGMemOp memop, const char *name) { if (dest) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } tcg_gen_qemu_st_tl(load_gr(dc, srcb), load_gr(dc, srca), @@ -538,7 +538,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "swint1"; done0: if (srca || dest) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic); return ret; @@ -584,7 +584,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, tcg_gen_andi_tl(dc->jmp.dest, load_gr(dc, srca), ~7); done1: if (dest) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]); return ret; @@ -679,7 +679,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, case OE_RR_X1(LNK): case OE_RR_Y1(LNK): if (srca) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } tcg_gen_movi_tl(tdest, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES); mnemonic = "lnk"; @@ -723,7 +723,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "tblidxb3"; break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic, @@ -1453,7 +1453,7 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, mnemonic = "xor"; break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %s", mnemonic, @@ -1745,7 +1745,7 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext, break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %d", mnemonic, @@ -1839,7 +1839,7 @@ static TileExcp gen_bf_opcode_x0(DisasContext *dc, unsigned ext, break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %u, %u", mnemonic, @@ -1895,7 +1895,7 @@ static TileExcp gen_branch_opcode_x1(DisasContext *dc, unsigned ext, mnemonic = "blbs"; break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -1962,7 +1962,7 @@ static TileExcp gen_mtspr_x1(DisasContext *dc, unsigned spr, unsigned srca) if (def == NULL) { qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr spr[%u], %s", spr, reg_names[srca]); -return TILEGX_EXCP_OPCODE_UNKNOWN; +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; } tsrca = load_gr(dc, srca); @@ -1982,7 +1982,7 @@ static TileExcp gen_mfspr_x1(DisasContext *dc, unsigned dest, unsigned spr) if (def == NULL) { qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr %s, spr[%u]", reg_names[dest], spr); -return TILEGX_EXCP_OPCODE_UNKNOWN; +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; } tdest = dest_gr(dc, dest); @@ -2037,7 +2037,7 @@ static TileExcp decode_y0(DisasContext *dc, tilegx_bundle_bits bundle) return gen_rri_opcode(dc, OE(opc, 0, Y0), dest, srca, imm); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -2081,7 +2081,7 @@ static TileExcp decode_y1(DisasContext *dc, tilegx_bundle_bits bundle) return gen_rri_opcode(dc, OE(opc, 0, Y1), dest, srca, imm); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -
[Qemu-devel] [PATCH v2] target-tilegx: Implement v2sh* instructions
From: Chen Gang It is just according to v1sh* instructions implementation. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 6ab66f9..9bb8857 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1686,11 +1686,27 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext, break; case OE_SH(V2SHLI, X0): case OE_SH(V2SHLI, X1): +i2 = imm & 15; +i3 = 0x >> i2; +tcg_gen_andi_tl(tdest, tsrca, V2_IMM(i3)); +tcg_gen_shli_tl(tdest, tdest, i2); +mnemonic = "v2shli"; +break; case OE_SH(V2SHRSI, X0): case OE_SH(V2SHRSI, X1): +t0 = tcg_const_tl(imm & 15); +gen_helper_v2shrs(tdest, tsrca, t0); +tcg_temp_free(t0); +mnemonic = "v2shrsi"; +break; case OE_SH(V2SHRUI, X0): case OE_SH(V2SHRUI, X1): -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +i2 = imm & 15; +i3 = (0x << i2) & 0x; +tcg_gen_andi_tl(tdest, tsrca, V2_IMM(i3)); +tcg_gen_shri_tl(tdest, tdest, i2); +mnemonic = "v2shrui"; +break; case OE(ADDLI_OPCODE_X0, 0, X0): case OE(ADDLI_OPCODE_X1, 0, X1): -- 1.9.3
[Qemu-devel] [PATCH v2] target-tilegx: Implement v?int_* instructions.
From: Chen Gang Signed-off-by: Chen Gang --- target-tilegx/helper.h | 5 target-tilegx/simd_helper.c | 56 + target-tilegx/translate.c | 14 3 files changed, 75 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 82d84f1..c58ee20 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -10,6 +10,11 @@ DEF_HELPER_FLAGS_3(cmula, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_3(cmulaf, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_4(cmul2, TCG_CALL_NO_RWG_SE, i64, i64, i64, int, int) +DEF_HELPER_FLAGS_2(v1int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64) + DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index 23c20bd..6fa6318 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -102,3 +102,59 @@ uint64_t helper_v2shrs(uint64_t a, uint64_t b) } return r; } + +uint64_t helper_v1int_h(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 8) { +tmp = (uint8_t)(a >> (i + 32)); +r |= tmp << (2 * i + 8); +tmp = (uint8_t)(b >> (i + 32)); +r |= tmp << 2 * i; +} +return r; +} + +uint64_t helper_v1int_l(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 8) { +tmp = (uint8_t)(a >> i); +r |= tmp << (2 * i + 8); +tmp = (uint8_t)(b >> i); +r |= tmp << 2 * i; +} +return r; +} + +uint64_t helper_v2int_h(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 16) { +tmp = (uint16_t)(a >> (i + 32)); +r |= tmp << (2 * i + 16); +tmp = (uint16_t)(b >> (i + 32)); +r |= tmp << 2 * i; +} +return r; +} + +uint64_t helper_v2int_l(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 16) { +tmp = (uint16_t)(a >> i); +r |= tmp << (2 * i + 16); +tmp = (uint16_t)(b >> i); +r |= tmp << 2 * i; +} +return r; +} diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 9bb8857..034cbc2 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1260,10 +1260,17 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V1DOTPUS, 0, X0): case OE_RRR(V1DOTPU, 0, X0): case OE_RRR(V1DOTP, 0, X0): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1INT_H, 0, X0): case OE_RRR(V1INT_H, 0, X1): +gen_helper_v1int_h(tdest, tsrca, tsrcb); +mnemonic = "v1int_h"; +break; case OE_RRR(V1INT_L, 0, X0): case OE_RRR(V1INT_L, 0, X1): +gen_helper_v1int_l(tdest, tsrca, tsrcb); +mnemonic = "v1int_l"; +break; case OE_RRR(V1MAXU, 0, X0): case OE_RRR(V1MAXU, 0, X1): case OE_RRR(V1MINU, 0, X0): @@ -1329,10 +1336,17 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V2CMPNE, 0, X1): case OE_RRR(V2DOTPA, 0, X0): case OE_RRR(V2DOTP, 0, X0): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2INT_H, 0, X0): case OE_RRR(V2INT_H, 0, X1): +gen_helper_v2int_h(tdest, tsrca, tsrcb); +mnemonic = "v2int_h"; +break; case OE_RRR(V2INT_L, 0, X0): case OE_RRR(V2INT_L, 0, X1): +gen_helper_v2int_l(tdest, tsrca, tsrcb); +mnemonic = "v2int_l"; +break; case OE_RRR(V2MAXS, 0, X0): case OE_RRR(V2MAXS, 0, X1): case OE_RRR(V2MINS, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Implement v*shl, v*shru, and v*shrs instructions
From: Chen Gang Only according to the v1shl, v1shru, and v1shrs implementations. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 6 + target-tilegx/simd_helper.c | 62 + target-tilegx/translate.c | 20 +++ 3 files changed, 88 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 766f5f2..15093973 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -8,3 +8,9 @@ DEF_HELPER_FLAGS_3(shufflebytes, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v4shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v4shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v4shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index b931929..6546337 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -32,6 +32,24 @@ uint64_t helper_v1shl(uint64_t a, uint64_t b) return (a & m) << b; } +uint64_t helper_v2shl(uint64_t a, uint64_t b) +{ +uint64_t m; + +b &= 15; +m = 0x0001000100010001ULL * (0x >> b); +return (a & m) << b; +} + +uint64_t helper_v4shl(uint64_t a, uint64_t b) +{ +uint64_t m; + +b &= 63; +m = 0x00010001ULL * (0x >> b); +return (a & m) << b; +} + uint64_t helper_v1shru(uint64_t a, uint64_t b) { uint64_t m; @@ -41,6 +59,24 @@ uint64_t helper_v1shru(uint64_t a, uint64_t b) return (a & m) >> b; } +uint64_t helper_v2shru(uint64_t a, uint64_t b) +{ +uint64_t m; + +b &= 15; +m = 0x0001000100010001ULL * ((0x << b) & 0x); +return (a & m) >> b; +} + +uint64_t helper_v4shru(uint64_t a, uint64_t b) +{ +uint64_t m; + +b &= 63; +m = 0x00010001ULL * ((0x << b) & 0x); +return (a & m) >> b; +} + uint64_t helper_v1shrs(uint64_t a, uint64_t b) { uint64_t r = 0; @@ -53,3 +89,29 @@ uint64_t helper_v1shrs(uint64_t a, uint64_t b) } return r; } + +uint64_t helper_v2shrs(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +b &= 15; +for (i = 0; i < 64; i += 16) { +int64_t ae = (int16_t)(a >> i); +r |= ((ae >> b) & 0x) << i; +} +return r; +} + +uint64_t helper_v4shrs(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +b &= 63; +for (i = 0; i < 64; i += 32) { +int64_t ae = (int32_t)(a >> i); +r |= ((ae >> b) & 0x) << i; +} +return r; +} diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index e70c3e5..c8247ac 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1144,12 +1144,22 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V2SADU, 0, X0): case OE_RRR(V2SHLSC, 0, X0): case OE_RRR(V2SHLSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2SHL, 0, X0): case OE_RRR(V2SHL, 0, X1): +gen_helper_v2shl(tdest, tsrca, tsrcb); +mnemonic = "v2shl"; +break; case OE_RRR(V2SHRS, 0, X0): case OE_RRR(V2SHRS, 0, X1): +gen_helper_v2shrs(tdest, tsrca, tsrcb); +mnemonic = "v2shrs"; +break; case OE_RRR(V2SHRU, 0, X0): case OE_RRR(V2SHRU, 0, X1): +gen_helper_v2shru(tdest, tsrca, tsrcb); +mnemonic = "v2shru"; +break; case OE_RRR(V2SUBSC, 0, X0): case OE_RRR(V2SUBSC, 0, X1): case OE_RRR(V2SUB, 0, X0): @@ -1174,12 +1184,22 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V4PACKSC, 0, X1): case OE_RRR(V4SHLSC, 0, X0): case OE_RRR(V4SHLSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V4SHL, 0, X0): case OE_RRR(V4SHL, 0, X1): +gen_helper_v4shl(tdest, tsrca, tsrcb); +mnemonic = "v4shl"; +break; case OE_RRR(V4SHRS, 0, X0): case OE_RRR(V4SHRS, 0, X1): +gen_helper_v4shrs(tdest, tsrca, tsrcb); +mnemonic = "v4shrs"; +break; case OE_RRR(V4SHRU, 0, X0): case OE_RRR(V4SHRU, 0, X1): +gen_helper_v4shru(tdest, tsrca, tsrcb); +mnemonic = "v4shru"; +break; case OE_RRR(V4SUBSC, 0, X0): case OE_RRR(V4SUBSC, 0, X1): case OE_RRR(V4SUB, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Implement v*add and v*sub instructions
From: Chen Gang Only according to helper_v1shrs. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 8 + target-tilegx/simd_helper.c | 77 + target-tilegx/translate.c | 26 +-- 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 15093973..c366984 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -5,12 +5,20 @@ DEF_HELPER_FLAGS_1(pcnt, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(revbits, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_3(shufflebytes, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1add, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(v2add, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(v4add, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v4shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v4shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v4shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v4sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index 6546337..ec589fe 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -22,6 +22,83 @@ #include "qemu-common.h" #include "exec/helper-proto.h" +uint64_t helper_v1add(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 8) { +int64_t ae = (int8_t)(a >> i); +int64_t be = (int8_t)(b >> i); +r |= ((ae + be) & 0xff) << i; +} +return r; +} + +uint64_t helper_v2add(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 16) { +int64_t ae = (int16_t)(a >> i); +int64_t be = (int16_t)(b >> i); +r |= ((ae + be) & 0x) << i; +} +return r; +} + +uint64_t helper_v4add(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 32) { +int64_t ae = (int32_t)(a >> i); +int64_t be = (int32_t)(b >> i); +r |= ((ae + be) & 0x) << i; +} +return r; +} + +uint64_t helper_v1sub(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 8) { +int64_t ae = (int8_t)(a >> i); +int64_t be = (int8_t)(b >> i); +r |= ((ae - be) & 0xff) << i; +} +return r; +} + +uint64_t helper_v2sub(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 16) { +int64_t ae = (int16_t)(a >> i); +int64_t be = (int16_t)(b >> i); +r |= ((ae - be) & 0x) << i; +} +return r; +} + +uint64_t helper_v4sub(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 32) { +int64_t ae = (int32_t)(a >> i); +int64_t be = (int32_t)(b >> i); +r |= ((ae - be) & 0x) << i; +} +return r; +} uint64_t helper_v1shl(uint64_t a, uint64_t b) { diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index c8247ac..2246243 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1024,8 +1024,12 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V1ADDUC, 0, X0): case OE_RRR(V1ADDUC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1ADD, 0, X0): case OE_RRR(V1ADD, 0, X1): +gen_helper_v1add(tdest, tsrca, tsrcb); +mnemonic = "v1add"; +break; case OE_RRR(V1ADIFFU, 0, X0): case OE_RRR(V1AVGU, 0, X0): return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; @@ -1095,12 +1099,20 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V1SUBUC, 0, X0): case OE_RRR(V1SUBUC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1SUB, 0, X0): case OE_RRR(V1SUB, 0, X1): +gen_helper_v1sub(tdest, tsrca, tsrcb); +mnemonic = "v1sub"; +break; case OE_RRR(V2ADDSC, 0, X0): case OE_RRR(V2ADDSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2ADD, 0, X0): case OE_RRR(V2ADD, 0, X1): +gen_helper_v2add(tdest, tsrca, tsrcb); +mnemonic = "v2add"; +break; case OE_RRR(V2ADIFFS, 0, X0): case OE_RRR(V2AVGS, 0, X0): case OE_RRR(V2CMPEQ, 0, X0): @@ -1162,13 +1174,20 @@ static TileExcp gen_rrr_opcode(Di
[Qemu-devel] [PATCH] target-tilegx: Implement v1multu instruction
From: Chen Gang Only according to v1add implementation. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 1 + target-tilegx/simd_helper.c | 13 + target-tilegx/translate.c | 4 3 files changed, 18 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index c366984..0af91af 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -6,6 +6,7 @@ DEF_HELPER_FLAGS_1(revbits, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_3(shufflebytes, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_2(v1add, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index ec589fe..d1cd9bc 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -192,3 +192,16 @@ uint64_t helper_v4shrs(uint64_t a, uint64_t b) } return r; } + +uint64_t helper_v1multu(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 8) { +uint64_t ae = (uint8_t)(a >> i); +uint64_t be = (uint8_t)(b >> i); +r |= ((ae * be) & 0xff) << i; +} +return r; +} diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 2246243..4fc7cd7 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1074,7 +1074,11 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V1MINU, 0, X1): case OE_RRR(V1MNZ, 0, X0): case OE_RRR(V1MNZ, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1MULTU, 0, X0): +gen_helper_v1multu(tdest, tsrca, tsrcb); +mnemonic = "v1multu"; +break; case OE_RRR(V1MULUS, 0, X0): case OE_RRR(V1MULU, 0, X0): case OE_RRR(V1MZ, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH v2] target-tilegx: Implement v*shl, v*shru, and v*shrs instructions
From: Chen Gang v2sh* are implemented with helper fucntions, according to the v1sh* implementations. v4sh* are implmeneted in normal code. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 3 +++ target-tilegx/simd_helper.c | 31 +++ target-tilegx/translate.c | 39 +++ 3 files changed, 73 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 766f5f2..b253722 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -8,3 +8,6 @@ DEF_HELPER_FLAGS_3(shufflebytes, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index b931929..c03e31a 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -32,6 +32,15 @@ uint64_t helper_v1shl(uint64_t a, uint64_t b) return (a & m) << b; } +uint64_t helper_v2shl(uint64_t a, uint64_t b) +{ +uint64_t m; + +b &= 15; +m = 0x0001000100010001ULL * (0x >> b); +return (a & m) << b; +} + uint64_t helper_v1shru(uint64_t a, uint64_t b) { uint64_t m; @@ -41,6 +50,15 @@ uint64_t helper_v1shru(uint64_t a, uint64_t b) return (a & m) >> b; } +uint64_t helper_v2shru(uint64_t a, uint64_t b) +{ +uint64_t m; + +b &= 15; +m = 0x0001000100010001ULL * ((0x << b) & 0x); +return (a & m) >> b; +} + uint64_t helper_v1shrs(uint64_t a, uint64_t b) { uint64_t r = 0; @@ -53,3 +71,16 @@ uint64_t helper_v1shrs(uint64_t a, uint64_t b) } return r; } + +uint64_t helper_v2shrs(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +b &= 15; +for (i = 0; i < 64; i += 16) { +int64_t ae = (int16_t)(a >> i); +r |= ((ae >> b) & 0x) << i; +} +return r; +} diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index e70c3e5..9228751 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -339,6 +339,25 @@ static TileExcp gen_st_add_opcode(DisasContext *dc, unsigned srca, unsigned srcb return TILEGX_EXCP_NONE; } +static void gen_v4sh(TCGv d64, TCGv a64, TCGv b64, + void (*generate)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ +TCGv_i32 al = tcg_temp_new_i32(); +TCGv_i32 ah = tcg_temp_new_i32(); +TCGv_i32 bl = tcg_temp_new_i32(); + +tcg_gen_extr_i64_i32(al, ah, a64); +tcg_gen_extrl_i64_i32(bl, b64); +tcg_gen_andi_i32(bl, bl, 31); +generate(al, al, bl); +generate(ah, ah, bl); +tcg_gen_concat_i32_i64(d64, al, ah); + +tcg_temp_free_i32(al); +tcg_temp_free_i32(ah); +tcg_temp_free_i32(bl); +} + static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, unsigned dest, unsigned srca) { @@ -1144,12 +1163,22 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V2SADU, 0, X0): case OE_RRR(V2SHLSC, 0, X0): case OE_RRR(V2SHLSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2SHL, 0, X0): case OE_RRR(V2SHL, 0, X1): +gen_helper_v2shl(tdest, tsrca, tsrcb); +mnemonic = "v2shl"; +break; case OE_RRR(V2SHRS, 0, X0): case OE_RRR(V2SHRS, 0, X1): +gen_helper_v2shrs(tdest, tsrca, tsrcb); +mnemonic = "v2shrs"; +break; case OE_RRR(V2SHRU, 0, X0): case OE_RRR(V2SHRU, 0, X1): +gen_helper_v2shru(tdest, tsrca, tsrcb); +mnemonic = "v2shru"; +break; case OE_RRR(V2SUBSC, 0, X0): case OE_RRR(V2SUBSC, 0, X1): case OE_RRR(V2SUB, 0, X0): @@ -1174,12 +1203,22 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V4PACKSC, 0, X1): case OE_RRR(V4SHLSC, 0, X0): case OE_RRR(V4SHLSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V4SHL, 0, X0): case OE_RRR(V4SHL, 0, X1): +gen_v4sh(tdest, tsrca, tsrcb, tcg_gen_shl_i32); +mnemonic = "v4shl"; +break; case OE_RRR(V4SHRS, 0, X0): case OE_RRR(V4SHRS, 0, X1): +gen_v4sh(tdest, tsrca, tsrcb, tcg_gen_sar_i32); +mnemonic = "v4shrs"; +break; case OE_RRR(V4SHRU, 0, X0): case OE_RRR(V4SHRU, 0, X1): +gen_v4sh(tdest, tsrca, tsrcb, tcg_gen_shr_i32); +mnemonic = "v4shru"; +break; case OE_RRR(V4SUBSC, 0, X0): case OE_RRR(V4SUBSC, 0, X1): case OE_RRR(V4SUB, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH v2] target-tilegx: Implement v*add and v*sub instructions
From: Chen Gang v4* are implemented in normal code, another are implemented in helper functions. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 5 + target-tilegx/simd_helper.c | 23 +++ target-tilegx/translate.c | 46 +++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index b253722..6d98f3a 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -11,3 +11,8 @@ DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(v1add, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2add, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index c03e31a..00265fe 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -22,6 +22,29 @@ #include "qemu-common.h" #include "exec/helper-proto.h" +uint64_t helper_v1add(uint64_t a, uint64_t b) +{ +return ((a & 0x7f7f7f7f7f7f7f7fULL) + (b & 0x7f7f7f7f7f7f7f7fULL)) + ^ ((a ^ b) & 0x8080808080808080ULL); +} + +uint64_t helper_v1sub(uint64_t a, uint64_t b) +{ +return ((a & 0x7f7f7f7f7f7f7f7fULL) - (b & 0x7f7f7f7f7f7f7f7fULL)) + ^ ((a ^ ~b) & 0x8080808080808080ULL); +} + +uint64_t helper_v2add(uint64_t a, uint64_t b) +{ +return ((a & 0x7fff7fff7fff7fffULL) + (b & 0x7fff7fff7fff7fffULL)) + ^ ((a ^ b) & 0x8000800080008000ULL); +} + +uint64_t helper_v2sub(uint64_t a, uint64_t b) +{ +return ((a & 0x7fff7fff7fff7fffULL) - (b & 0x7fff7fff7fff7fffULL)) + ^ ((a ^ ~b) & 0x8000800080008000ULL); +} uint64_t helper_v1shl(uint64_t a, uint64_t b) { diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 9228751..297de5c 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -358,6 +358,26 @@ static void gen_v4sh(TCGv d64, TCGv a64, TCGv b64, tcg_temp_free_i32(bl); } +static void gen_v4op(TCGv d64, TCGv a64, TCGv b64, + void (*generate)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ +TCGv_i32 al = tcg_temp_new_i32(); +TCGv_i32 ah = tcg_temp_new_i32(); +TCGv_i32 bl = tcg_temp_new_i32(); +TCGv_i32 bh = tcg_temp_new_i32(); + +tcg_gen_extr_i64_i32(al, ah, a64); +tcg_gen_extr_i64_i32(bl, bh, b64); +generate(al, al, bl); +generate(ah, ah, bh); +tcg_gen_concat_i32_i64(d64, al, ah); + +tcg_temp_free_i32(al); +tcg_temp_free_i32(ah); +tcg_temp_free_i32(bl); +tcg_temp_free_i32(bh); +} + static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, unsigned dest, unsigned srca) { @@ -1043,8 +1063,12 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V1ADDUC, 0, X0): case OE_RRR(V1ADDUC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1ADD, 0, X0): case OE_RRR(V1ADD, 0, X1): +gen_helper_v1add(tdest, tsrca, tsrcb); +mnemonic = "v1add"; +break; case OE_RRR(V1ADIFFU, 0, X0): case OE_RRR(V1AVGU, 0, X0): return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; @@ -1114,12 +1138,20 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V1SUBUC, 0, X0): case OE_RRR(V1SUBUC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1SUB, 0, X0): case OE_RRR(V1SUB, 0, X1): +gen_helper_v1sub(tdest, tsrca, tsrcb); +mnemonic = "v1sub"; +break; case OE_RRR(V2ADDSC, 0, X0): case OE_RRR(V2ADDSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2ADD, 0, X0): case OE_RRR(V2ADD, 0, X1): +gen_helper_v2add(tdest, tsrca, tsrcb); +mnemonic = "v2add"; +break; case OE_RRR(V2ADIFFS, 0, X0): case OE_RRR(V2AVGS, 0, X0): case OE_RRR(V2CMPEQ, 0, X0): @@ -1181,13 +1213,20 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V2SUBSC, 0, X0): case OE_RRR(V2SUBSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2SUB, 0, X0): case OE_RRR(V2SUB, 0, X1): +gen_helper_v2sub(tdest, tsrca, tsrcb); +mnemonic = "v2sub"; +break; case OE_RRR(V4ADDSC, 0, X0): case OE_RRR(V4ADDSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V4ADD, 0, X0): case OE_RRR(V4ADD, 0, X1): -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +gen_v4op(tdest, tsrca, tsrcb, tcg_gen_add_i32); +mnemonic = "v4add"; +break; case OE_RRR(V4INT_H
[Qemu-devel] [PATCH v2] target-tilegx: Implement v1multu instruction
From: Chen Gang Only according to v1shrs implementation. Signed-off-by: Chen Gang Reviewed-by: Richard Henderson --- target-tilegx/helper.h | 2 ++ target-tilegx/simd_helper.c | 13 + target-tilegx/translate.c | 4 3 files changed, 19 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 6d98f3a..90e558d 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -16,3 +16,5 @@ DEF_HELPER_FLAGS_2(v1add, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2add, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index 00265fe..b98573e 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -107,3 +107,16 @@ uint64_t helper_v2shrs(uint64_t a, uint64_t b) } return r; } + +uint64_t helper_v1multu(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 8) { +uint64_t ae = (uint8_t)(a >> i); +uint64_t be = (uint8_t)(b >> i); +r |= ((ae * be) & 0xff) << i; +} +return r; +} diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 297de5c..a9fc4ce 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1113,7 +1113,11 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V1MINU, 0, X1): case OE_RRR(V1MNZ, 0, X0): case OE_RRR(V1MNZ, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1MULTU, 0, X0): +gen_helper_v1multu(tdest, tsrca, tsrcb); +mnemonic = "v1multu"; +break; case OE_RRR(V1MULUS, 0, X0): case OE_RRR(V1MULU, 0, X0): case OE_RRR(V1MZ, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH v3] target-tilegx: Implement v*add and v*sub instructions
From: Chen Gang v4* are implemented in normal code, another are implemented in helper functions. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 5 + target-tilegx/simd_helper.c | 23 +++ target-tilegx/translate.c | 46 +++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index b253722..6d98f3a 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -11,3 +11,8 @@ DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(v1add, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2add, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2sub, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index c03e31a..1cc9620 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -22,6 +22,29 @@ #include "qemu-common.h" #include "exec/helper-proto.h" +uint64_t helper_v1add(uint64_t a, uint64_t b) +{ +return ((a & 0x7f7f7f7f7f7f7f7fULL) + (b & 0x7f7f7f7f7f7f7f7fULL)) + ^ ((a ^ b) & 0x8080808080808080ULL); +} + +uint64_t helper_v1sub(uint64_t a, uint64_t b) +{ +return ((a | 0x8080808080808080ULL) - (b & 0x7f7f7f7f7f7f7f7fULL)) + ^ ((a ^ ~b) & 0x8080808080808080ULL); +} + +uint64_t helper_v2add(uint64_t a, uint64_t b) +{ +return ((a & 0x7fff7fff7fff7fffULL) + (b & 0x7fff7fff7fff7fffULL)) + ^ ((a ^ b) & 0x8000800080008000ULL); +} + +uint64_t helper_v2sub(uint64_t a, uint64_t b) +{ +return ((a | 0x8000800080008000ULL) - (b & 0x7fff7fff7fff7fffULL)) + ^ ((a ^ ~b) & 0x8000800080008000ULL); +} uint64_t helper_v1shl(uint64_t a, uint64_t b) { diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 9228751..297de5c 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -358,6 +358,26 @@ static void gen_v4sh(TCGv d64, TCGv a64, TCGv b64, tcg_temp_free_i32(bl); } +static void gen_v4op(TCGv d64, TCGv a64, TCGv b64, + void (*generate)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ +TCGv_i32 al = tcg_temp_new_i32(); +TCGv_i32 ah = tcg_temp_new_i32(); +TCGv_i32 bl = tcg_temp_new_i32(); +TCGv_i32 bh = tcg_temp_new_i32(); + +tcg_gen_extr_i64_i32(al, ah, a64); +tcg_gen_extr_i64_i32(bl, bh, b64); +generate(al, al, bl); +generate(ah, ah, bh); +tcg_gen_concat_i32_i64(d64, al, ah); + +tcg_temp_free_i32(al); +tcg_temp_free_i32(ah); +tcg_temp_free_i32(bl); +tcg_temp_free_i32(bh); +} + static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, unsigned dest, unsigned srca) { @@ -1043,8 +1063,12 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V1ADDUC, 0, X0): case OE_RRR(V1ADDUC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1ADD, 0, X0): case OE_RRR(V1ADD, 0, X1): +gen_helper_v1add(tdest, tsrca, tsrcb); +mnemonic = "v1add"; +break; case OE_RRR(V1ADIFFU, 0, X0): case OE_RRR(V1AVGU, 0, X0): return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; @@ -1114,12 +1138,20 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V1SUBUC, 0, X0): case OE_RRR(V1SUBUC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1SUB, 0, X0): case OE_RRR(V1SUB, 0, X1): +gen_helper_v1sub(tdest, tsrca, tsrcb); +mnemonic = "v1sub"; +break; case OE_RRR(V2ADDSC, 0, X0): case OE_RRR(V2ADDSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2ADD, 0, X0): case OE_RRR(V2ADD, 0, X1): +gen_helper_v2add(tdest, tsrca, tsrcb); +mnemonic = "v2add"; +break; case OE_RRR(V2ADIFFS, 0, X0): case OE_RRR(V2AVGS, 0, X0): case OE_RRR(V2CMPEQ, 0, X0): @@ -1181,13 +1213,20 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, break; case OE_RRR(V2SUBSC, 0, X0): case OE_RRR(V2SUBSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2SUB, 0, X0): case OE_RRR(V2SUB, 0, X1): +gen_helper_v2sub(tdest, tsrca, tsrcb); +mnemonic = "v2sub"; +break; case OE_RRR(V4ADDSC, 0, X0): case OE_RRR(V4ADDSC, 0, X1): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V4ADD, 0, X0): case OE_RRR(V4ADD, 0, X1): -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +gen_v4op(tdest, tsrca, tsrcb, tcg_gen_add_i32); +mnemonic = "v4add"; +break; case OE_RRR(V4INT_H
[Qemu-devel] [PATCH] target-tilegx: Let x1 pipe process bpt instruction only
From: Chen Gang According to the related document, bpt can be only in x1 pipe. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index a9fc4ce..6622aeb 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -407,8 +407,14 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "flushwb"; goto done0; case OE_RR_X1(ILL): +if (dest == 0x1c && srca == 0x25) { +mnemonic = "bpt"; +goto done2; +} +/* Fall through */ case OE_RR_Y1(ILL): -mnemonic = (dest == 0x1c && srca == 0x25 ? "bpt" : "ill"); +mnemonic = "ill"; +done2: qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic); return TILEGX_EXCP_OPCODE_UNKNOWN; case OE_RR_X1(MF): -- 1.9.3
[Qemu-devel] [PATCH] linux-user/syscall_defs.h: Sync the latest si_code from Linux kernel
From: Chen Gang They content several new macro members, also contents TARGET_N*. Signed-off-by: Chen Gang --- linux-user/syscall_defs.h | 44 ++-- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index cdc8db4..6bec3f2 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -736,14 +736,21 @@ typedef struct target_siginfo { /* * SIGILL si_codes */ -#define TARGET_ILL_ILLOPC (1) /* illegal opcode */ -#define TARGET_ILL_ILLOPN (2) /* illegal operand */ -#define TARGET_ILL_ILLADR (3) /* illegal addressing mode */ -#define TARGET_ILL_ILLTRP (4) /* illegal trap */ -#define TARGET_ILL_PRVOPC (5) /* privileged opcode */ -#define TARGET_ILL_PRVREG (6) /* privileged register */ -#define TARGET_ILL_COPROC (7) /* coprocessor error */ -#define TARGET_ILL_BADSTK (8) /* internal stack error */ +#define TARGET_ILL_ILLOPC (1) /* illegal opcode */ +#define TARGET_ILL_ILLOPN (2) /* illegal operand */ +#define TARGET_ILL_ILLADR (3) /* illegal addressing mode */ +#define TARGET_ILL_ILLTRP (4) /* illegal trap */ +#define TARGET_ILL_PRVOPC (5) /* privileged opcode */ +#define TARGET_ILL_PRVREG (6) /* privileged register */ +#define TARGET_ILL_COPROC (7) /* coprocessor error */ +#define TARGET_ILL_BADSTK (8) /* internal stack error */ +#ifdef TARGET_TILEGX +#define TARGET_ILL_DBLFLT (9) /* double fault */ +#define TARGET_ILL_HARDWALL (10)/* user networks hardwall violation */ +#define TARGET_NSIGILL 10 +#else +#define TARGET_NSIGILL 8 +#endif /* * SIGFPE si_codes @@ -763,19 +770,28 @@ typedef struct target_siginfo { */ #define TARGET_SEGV_MAPERR (1) /* address not mapped to object */ #define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */ +#define TARGET_SEGV_BNDERR (3) /* failed address bound checks */ +#define TARGET_NSIGSEGV3 /* * SIGBUS si_codes */ -#define TARGET_BUS_ADRALN (1)/* invalid address alignment */ -#define TARGET_BUS_ADRERR (2)/* non-existent physical address */ -#define TARGET_BUS_OBJERR (3)/* object specific hardware error */ - +#define TARGET_BUS_ADRALN (1) /* invalid address alignment */ +#define TARGET_BUS_ADRERR (2) /* non-existent physical address */ +#define TARGET_BUS_OBJERR (3) /* object specific hardware error */ +/* hardware memory error consumed on a machine check: action required */ +#define TARGET_BUS_MCEERR_AR(4) +/* hardware memory error detected in process but not consumed: action optional*/ +#define TARGET_BUS_MCEERR_AO(5) +#define TARGET_NSIGBUS 5 /* * SIGTRAP si_codes */ -#define TARGET_TRAP_BRKPT (1) /* process breakpoint */ -#define TARGET_TRAP_TRACE (2) /* process trace trap */ +#define TARGET_TRAP_BRKPT (1) /* process breakpoint */ +#define TARGET_TRAP_TRACE (2) /* process trace trap */ +#define TARGET_TRAP_BRANCH (3) /* process taken branch trap */ +#define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */ +#define TARGET_NSIGTRAP 4 #endif /* defined(TARGET_I386) || defined(TARGET_ARM) */ -- 1.9.3
[Qemu-devel] [PATCH] tilegx: Generate ill related instructions according to Linux kernel
From: Chen Gang At present, tilegx qemu will abort for "setup_frame: not implemented", when meet raise instruction. Signed-off-by: Chen Gang --- linux-user/main.c | 14 target-tilegx/cpu.h | 3 ++ target-tilegx/translate.c | 89 +++ 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 782037d..7e49931 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3436,6 +3436,17 @@ static void gen_sigill_reg(CPUTLGState *env) queue_signal(env, info.si_signo, &info); } +static void gen_sigill(CPUTLGState *env) +{ +target_siginfo_t info; + +info.si_signo = env->signo; +info.si_errno = 0; +info.si_code = env->sigcode; +info._sifields._sigfault._addr = env->pc; +queue_signal(env, info.si_signo, &info); +} + static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val) { if (unlikely(reg >= TILEGX_R_COUNT)) { @@ -3622,6 +3633,9 @@ void cpu_loop(CPUTLGState *env) case TILEGX_EXCP_OPCODE_FETCHOR4: do_fetch(env, trapnr, false); break; +case TILEGX_EXCP_OPCODE_ILL: +gen_sigill(env); +break; case TILEGX_EXCP_REG_IDN_ACCESS: case TILEGX_EXCP_REG_UDN_ACCESS: gen_sigill_reg(env); diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h index b9f5082..72a1878 100644 --- a/target-tilegx/cpu.h +++ b/target-tilegx/cpu.h @@ -75,6 +75,7 @@ typedef enum { TILEGX_EXCP_OPCODE_FETCHAND4 = 0x10c, TILEGX_EXCP_OPCODE_FETCHOR = 0x10d, TILEGX_EXCP_OPCODE_FETCHOR4 = 0x10e, +TILEGX_EXCP_OPCODE_ILL = 0x10f, TILEGX_EXCP_REG_IDN_ACCESS = 0x181, TILEGX_EXCP_REG_UDN_ACCESS = 0x182, TILEGX_EXCP_UNALIGNMENT = 0x201, @@ -86,6 +87,8 @@ typedef struct CPUTLGState { uint64_t spregs[TILEGX_SPR_COUNT]; /* Special used registers by outside */ uint64_t pc; /* Current pc */ +uint64_t signo;/* Signal number */ +uint64_t sigcode; /* Signal code */ #if defined(CONFIG_USER_ONLY) uint64_t atomic_srca; /* Arguments to atomic "exceptions" */ uint64_t atomic_srcb; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 6622aeb..969c66e 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -23,6 +23,8 @@ #include "disas/disas.h" #include "tcg-op.h" #include "exec/cpu_ldst.h" +#include "linux-user/syscall_defs.h" + #include "opcode_tilegx.h" #include "spr_def_64.h" @@ -378,8 +380,74 @@ static void gen_v4op(TCGv d64, TCGv a64, TCGv b64, tcg_temp_free_i32(bh); } +static TileExcp gen_ill(DisasContext *dc, int signo, int sigcode, +const char *mnemonic) +{ +TCGv t0 = tcg_const_tl(signo); +TCGv t1 = tcg_const_tl(sigcode); + +tcg_gen_st_tl(t0, cpu_env, offsetof(CPUTLGState, signo)); +tcg_gen_st_tl(t1, cpu_env, offsetof(CPUTLGState, sigcode)); + +tcg_temp_free(t1); +tcg_temp_free(t0); + +qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic); +return TILEGX_EXCP_OPCODE_ILL; +} + +static int parse_from_addli(uint64_t bundle, int *signo, int *sigcode) +{ +if ((get_Opcode_X0(bundle) != ADDLI_OPCODE_X0) +|| (get_Dest_X0(bundle) != TILEGX_R_ZERO) +|| (get_SrcA_X0(bundle) != TILEGX_R_ZERO)) { +return 0; +} + +*signo = get_Imm16_X0(bundle) & 0x3f; +*sigcode = (get_Imm16_X0(bundle) >> 6) & 0xf; + +switch (*signo) { +case TARGET_SIGILL: +return *sigcode <= TARGET_NSIGILL; +case TARGET_SIGFPE: +return *sigcode <= TARGET_NSIGFPE; +case TARGET_SIGSEGV: +return *sigcode <= TARGET_NSIGSEGV; +case TARGET_SIGBUS: +return *sigcode <= TARGET_NSIGBUS; +case TARGET_SIGTRAP: +return *sigcode <= TARGET_NSIGTRAP; +default: +return 0; +} +} + +static TileExcp gen_specill(DisasContext *dc, unsigned dest, unsigned srca, +uint64_t bundle) +{ +const char *mnemonic; +int signo; +int sigcode; + +if (dest == 0x1c && srca == 0x25) { +signo = TARGET_SIGTRAP; +sigcode = TARGET_TRAP_BRKPT; +mnemonic = "bpt"; +} else if (dest == 0x1d && srca == 0x25 + && parse_from_addli(bundle, &signo, &sigcode)) { +mnemonic = "raise"; +} else { +signo = TARGET_SIGILL; +sigcode = TARGET_ILL_ILLOPC; +mnemonic = "ill"; +} + +return gen_ill(dc, signo, sigcode, mnemonic); +} + static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, - unsigned dest, unsigned srca) + unsigned dest, unsigned srca, uint64_t bundle) { TCGv tdest, tsrca; const char *mnemonic; @@ -407,16 +475,9 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "flushwb"; goto done0; case OE_RR_X1
[Qemu-devel] [PATCH] tilegx: Implement tilegx signal features
From: Chen Gang After this patch, tilegx can handle raise instruction succesfully. Signed-off-by: Chen Gang --- linux-user/signal.c | 171 +++- linux-user/tilegx/syscall.h | 4 ++ target-tilegx/cpu.h | 3 +- 3 files changed, 176 insertions(+), 2 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 502efd9..31f8fb0 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5543,6 +5543,174 @@ long do_rt_sigreturn(CPUAlphaState *env) force_sig(TARGET_SIGSEGV); } +#elif defined(TARGET_TILEGX) + +struct target_sigcontext { +union { +/* General-purpose registers. */ +abi_ulong gregs[56]; +struct { +abi_ulong __gregs[53]; +abi_ulong tp;/* Aliases gregs[TREG_TP]. */ +abi_ulong sp;/* Aliases gregs[TREG_SP]. */ +abi_ulong lr;/* Aliases gregs[TREG_LR]. */ +}; +}; +abi_ulong pc;/* Program counter. */ +abi_ulong ics; /* In Interrupt Critical Section? */ +abi_ulong faultnum; /* Fault number. */ +abi_ulong pad[5]; +}; + +struct target_ucontext { +abi_ulong tuc_flags; +abi_ulong tuc_link; +target_stack_t tuc_stack; +struct target_sigcontext tuc_mcontext; +target_sigset_t tuc_sigmask; /* mask last for extensibility */ +}; + +struct target_rt_sigframe { +unsigned char save_area[16]; /* caller save area */ +struct target_siginfo info; +struct target_ucontext uc; +}; + +static void setup_sigcontext(struct target_sigcontext *sc, + CPUArchState *env, int signo) +{ +int i; + +for (i = 0; i < TILEGX_R_COUNT; ++i) { +__put_user(env->regs[i], &sc->gregs[i]); +} + +__put_user(env->pc, &sc->pc); +__put_user(0, &sc->ics); +__put_user(signo, &sc->faultnum); +env->spregs[TILEGX_SPR_EX_CONTEXT_1] = 1 << SPR_EX_CONTEXT_1_1__ICS_SHIFT; +} + +static uint64_t restore_spreg_ex1(uint64_t ex1) +{ +return ((ex1 >> SPR_EX_CONTEXT_1_1__ICS_SHIFT) +& SPR_EX_CONTEXT_1_1__ICS_RMASK) + << SPR_EX_CONTEXT_1_1__ICS_SHIFT; +} + +static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc) +{ +int i; + +for (i = 0; i < TILEGX_R_COUNT; ++i) { +__get_user(env->regs[i], &sc->gregs[i]); +} + +__get_user(env->pc, &sc->pc); +env->signo = TARGET_INT_SWINT_1_SIGRETURN; +env->spregs[TILEGX_SPR_EX_CONTEXT_1] = + restore_spreg_ex1(env->spregs[TILEGX_SPR_EX_CONTEXT_1]); +} + +static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env, + size_t frame_size) +{ +unsigned long sp = env->regs[TILEGX_R_SP]; + +if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) { +return -1UL; +} + +if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) { +sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +} + +sp -= frame_size; +sp &= -16UL; +return sp; +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUArchState *env) +{ +abi_ulong frame_addr; +struct target_rt_sigframe *frame; +unsigned long restorer; + +frame_addr = get_sigframe(ka, env, sizeof(*frame)); +if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +goto give_sigsegv; +} + +/* Always write at least the signal number for the stack backtracer. */ +if (ka->sa_flags & TARGET_SA_SIGINFO) { +/* At sigreturn time, restore the callee-save registers too. */ +tswap_siginfo(&frame->info, info); +/* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */ +} else { +__put_user(info->si_signo, &frame->info.si_signo); +} + +/* Create the ucontext. */ +__put_user(0, &frame->uc.tuc_flags); +__put_user(0, &frame->uc.tuc_link); +__put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); +__put_user(sas_ss_flags(env->regs[TILEGX_R_SP]), + &frame->uc.tuc_stack.ss_flags); +__put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); +setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo); + +restorer = (unsigned long) do_rt_sigreturn; +if (ka->sa_flags & TARGET_SA_RESTORER) { +restorer = (unsigned long) ka->sa_restorer; +} +env->pc = (unsigned long) ka->_sa_handler; +env->regs[TILEGX_R_SP] = (unsigned long) frame; +env->regs[TILEGX_R_LR] = restorer; +env->regs[0] = (unsigned long) sig; +env->regs[1] = (unsigned long) &frame->info; +env->regs[2] = (unsigned long) &frame->uc; +/* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */ + +unlock_user_struct(frame, frame_addr, 1); +return; + +give_sigsegv: +if (sig == TARGET_SIGS
[Qemu-devel] [PATCH] target-tilegx: Let v1addi call its own implementation
From: Chen Gang Original implementation let v1addi instruction call v1cmpeqi. It will cause gcc testsuite fail: the relate test is for mm instruction, tilegx qemu implement mm instruction correctly, but its 'v1addi' causes test abort. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 5 + 1 file changed, 5 insertions(+) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 969c66e..86da6b5 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1477,6 +1477,11 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext, break; case OE_IM(V1ADDI, X0): case OE_IM(V1ADDI, X1): +t0 = tcg_const_tl(V1_IMM(imm)); +gen_helper_v1add(tdest, tsrca, t0); +tcg_temp_free(t0); +mnemonic = "v1addi"; +break; case OE_IM(V1CMPEQI, X0): case OE_IM(V1CMPEQI, X1): tcg_gen_xori_tl(tdest, tsrca, V1_IMM(imm)); -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Check zero dest register for ld instructions
From: Chen Gang At present, qemu x86_64 host backend can not remove the related dummy instructions. Even the worse, sometimes, it will generate the incorrect instructions which will cause segment fault for prefetch_l3 instruction. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 86da6b5..7232361 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -620,7 +620,9 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, memop = MO_TEQ; mnemonic = "ld"; do_load: -tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop); +if (dest != TILEGX_R_ZERO) { +tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop); +} break; case OE_RR_X1(LDNA): tcg_gen_andi_tl(tdest, tsrca, ~7); @@ -1987,8 +1989,10 @@ static TileExcp decode_y2(DisasContext *dc, tilegx_bundle_bits bundle) memop = MO_TEQ; mnemonic = "ld"; do_load: -tcg_gen_qemu_ld_tl(dest_gr(dc, srcbdest), load_gr(dc, srca), - dc->mmuidx, memop); +if (srcbdest != TILEGX_R_ZERO) { +tcg_gen_qemu_ld_tl(dest_gr(dc, srcbdest), load_gr(dc, srca), + dc->mmuidx, memop); +} qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic, reg_names[srcbdest], reg_names[srca]); return TILEGX_EXCP_NONE; -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Support iret instruction and related special registers
From: Chen Gang Acording to the __longjmp tilegx libc implementation, and reference from tilegx ISA document, we can left iret instruction empty. The related code is below: ENTRY (__longjmp) FEEDBACK_ENTER(__longjmp) #define RESTORE(r) { LD r, r0 ; ADDI_PTR r0, r0, REGSIZE } FOR_EACH_CALLEE_SAVED_REG(RESTORE) { LD r2, r0 ; retrieve ICS bit from jmp_buf movei r3, 1 CMPEQI r0, r1, 0 } { mtspr INTERRUPT_CRITICAL_SECTION, r3 shli r2, r2, SPR_EX_CONTEXT_0_1__ICS_SHIFT } { mtspr EX_CONTEXT_0_0, lr ori r2, r2, RETURN_PL } { or r0, r1, r0 mtspr EX_CONTEXT_0_1, r2 } iret jrp lr So can let busybox sh run correctly. Signed-off-by: Chen Gang --- target-tilegx/cpu.h | 2 ++ target-tilegx/translate.c | 8 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h index 4b05cd2..02e1a18 100644 --- a/target-tilegx/cpu.h +++ b/target-tilegx/cpu.h @@ -54,6 +54,8 @@ enum { TILEGX_SPR_CRITICAL_SEC = 1, TILEGX_SPR_SIM_CONTROL = 2, TILEGX_SPR_EX_CONTEXT_1 = 3, +TILEGX_SPR_EX_CONTEXT_0_0 = 4, +TILEGX_SPR_EX_CONTEXT_0_1 = 5, TILEGX_SPR_COUNT }; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 7232361..77447ec 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -562,8 +562,10 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, break; case OE_RR_X0(FSINGLE_PACK1): case OE_RR_Y0(FSINGLE_PACK1): -case OE_RR_X1(IRET): return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +case OE_RR_X1(IRET): +mnemonic = "iret"; +break; case OE_RR_X1(LD1S): memop = MO_SB; mnemonic = "ld1s"; @@ -1813,6 +1815,10 @@ static const TileSPR *find_spr(unsigned spr) offsetof(CPUTLGState, spregs[TILEGX_SPR_CRITICAL_SEC]), 0, 0) D(SIM_CONTROL, offsetof(CPUTLGState, spregs[TILEGX_SPR_SIM_CONTROL]), 0, 0) +D(EX_CONTEXT_0_0, + offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_0]), 0, 0) +D(EX_CONTEXT_0_1, + offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_1]), 0, 0) } #undef D -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Fix a typo for mnemonic about "ld_add"
From: Chen Gang Signed-off-by: Chen Gang --- target-tilegx/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index d2b2b6e..251b254 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1500,7 +1500,7 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext, goto do_load_add; case OE_IM(LD_ADD, X1): memop = MO_TEQ; -mnemonic = "ldnt_add"; +mnemonic = "ld_add"; do_load_add: tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop); tcg_gen_addi_tl(dest_gr(dc, srca), tsrca, imm); -- 1.9.3
[Qemu-devel] [PATCH v2] target-tilegx: Support iret instruction and related special registers
From: Chen Gang Acording to the __longjmp tilegx libc implementation, and reference from tilegx ISA document, we can left iret instruction empty. The related code is below: ENTRY (__longjmp) FEEDBACK_ENTER(__longjmp) #define RESTORE(r) { LD r, r0 ; ADDI_PTR r0, r0, REGSIZE } FOR_EACH_CALLEE_SAVED_REG(RESTORE) { LD r2, r0 ; retrieve ICS bit from jmp_buf movei r3, 1 CMPEQI r0, r1, 0 } { mtspr INTERRUPT_CRITICAL_SECTION, r3 shli r2, r2, SPR_EX_CONTEXT_0_1__ICS_SHIFT } { mtspr EX_CONTEXT_0_0, lr ori r2, r2, RETURN_PL } { or r0, r1, r0 mtspr EX_CONTEXT_0_1, r2 } iret jrp lr Until now, EX_CONTEXT_0_0 and EX_CONTEXT_0_1 are only used in mtspr, so just skip them, at present. After this patch, busybox sh can run correctly. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 421766b..3ae59fe 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -563,8 +563,10 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, break; case OE_RR_X0(FSINGLE_PACK1): case OE_RR_Y0(FSINGLE_PACK1): -case OE_RR_X1(IRET): return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +case OE_RR_X1(IRET): +mnemonic = "iret"; +break; case OE_RR_X1(LD1S): memop = MO_SB; mnemonic = "ld1s"; /* prefetch_l1_fault */ @@ -1823,6 +1825,8 @@ static const TileSPR *find_spr(unsigned spr) offsetof(CPUTLGState, spregs[TILEGX_SPR_CRITICAL_SEC]), 0, 0) D(SIM_CONTROL, offsetof(CPUTLGState, spregs[TILEGX_SPR_SIM_CONTROL]), 0, 0) +D(EX_CONTEXT_0_0, -1, 0, 0) /* Skip it */ +D(EX_CONTEXT_0_1, -1, 0, 0) /* Skip it */ } #undef D @@ -1836,9 +1840,11 @@ static TileExcp gen_mtspr_x1(DisasContext *dc, unsigned spr, unsigned srca) const TileSPR *def = find_spr(spr); TCGv tsrca; -if (def == NULL) { +if (!def) { qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr spr[%u], %s", spr, reg_names[srca]); return TILEGX_EXCP_OPCODE_UNKNOWN; +} else if (def->offset == -1) { +goto tail; } tsrca = load_gr(dc, srca); @@ -1847,6 +1853,8 @@ static TileExcp gen_mtspr_x1(DisasContext *dc, unsigned spr, unsigned srca) } else { tcg_gen_st_tl(tsrca, cpu_env, def->offset); } + +tail: qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr %s, %s", def->name, reg_names[srca]); return TILEGX_EXCP_NONE; } @@ -1856,7 +1864,7 @@ static TileExcp gen_mfspr_x1(DisasContext *dc, unsigned dest, unsigned spr) const TileSPR *def = find_spr(spr); TCGv tdest; -if (def == NULL) { +if (!def || def->offset == -1) { qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr %s, spr[%u]", reg_names[dest], spr); return TILEGX_EXCP_OPCODE_UNKNOWN; } -- 1.9.3
[Qemu-devel] [PATCH v3] target-tilegx: Support iret instruction and related special registers
From: Chen Gang Acording to the __longjmp tilegx libc implementation, and reference from tilegx ISA document, and suggested by tilegx architecture member, we can treat iret instruction as "jrp lr". The related code is below: ENTRY (__longjmp) FEEDBACK_ENTER(__longjmp) #define RESTORE(r) { LD r, r0 ; ADDI_PTR r0, r0, REGSIZE } FOR_EACH_CALLEE_SAVED_REG(RESTORE) { LD r2, r0 ; retrieve ICS bit from jmp_buf movei r3, 1 CMPEQI r0, r1, 0 } { mtspr INTERRUPT_CRITICAL_SECTION, r3 shli r2, r2, SPR_EX_CONTEXT_0_1__ICS_SHIFT } { mtspr EX_CONTEXT_0_0, lr ori r2, r2, RETURN_PL } { or r0, r1, r0 mtspr EX_CONTEXT_0_1, r2 } iret jrp lr Until now, EX_CONTEXT_0_0 and EX_CONTEXT_0_1 are only used in mtspr, so just skip them, at present. "jrp lr" in __longjmp is for historical reasons, and might get removed in the future. After this patch, busybox sh can run correctly. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 421766b..b7bb4f3 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -563,8 +563,14 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, break; case OE_RR_X0(FSINGLE_PACK1): case OE_RR_Y0(FSINGLE_PACK1): -case OE_RR_X1(IRET): return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +case OE_RR_X1(IRET): +if (srca) { +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +} +srca = TILEGX_R_LR; +mnemonic = "iret"; +goto do_jr; case OE_RR_X1(LD1S): memop = MO_SB; mnemonic = "ld1s"; /* prefetch_l1_fault */ @@ -1823,6 +1829,8 @@ static const TileSPR *find_spr(unsigned spr) offsetof(CPUTLGState, spregs[TILEGX_SPR_CRITICAL_SEC]), 0, 0) D(SIM_CONTROL, offsetof(CPUTLGState, spregs[TILEGX_SPR_SIM_CONTROL]), 0, 0) +D(EX_CONTEXT_0_0, -1, 0, 0) /* Skip it */ +D(EX_CONTEXT_0_1, -1, 0, 0) /* Skip it */ } #undef D @@ -1836,9 +1844,11 @@ static TileExcp gen_mtspr_x1(DisasContext *dc, unsigned spr, unsigned srca) const TileSPR *def = find_spr(spr); TCGv tsrca; -if (def == NULL) { +if (!def) { qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr spr[%u], %s", spr, reg_names[srca]); return TILEGX_EXCP_OPCODE_UNKNOWN; +} else if (def->offset == -1) { +goto tail; } tsrca = load_gr(dc, srca); @@ -1847,6 +1857,8 @@ static TileExcp gen_mtspr_x1(DisasContext *dc, unsigned spr, unsigned srca) } else { tcg_gen_st_tl(tsrca, cpu_env, def->offset); } + +tail: qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr %s, %s", def->name, reg_names[srca]); return TILEGX_EXCP_NONE; } @@ -1856,7 +1868,7 @@ static TileExcp gen_mfspr_x1(DisasContext *dc, unsigned dest, unsigned spr) const TileSPR *def = find_spr(spr); TCGv tdest; -if (def == NULL) { +if (!def || def->offset == -1) { qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr %s, spr[%u]", reg_names[dest], spr); return TILEGX_EXCP_OPCODE_UNKNOWN; } -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Call dest_gr() later when have to use it
From: Chen Gang When a nop instruction is generated, but the 'dest' is a valid (e.g. for any qemu skipped instructions, but still be useful in real machine), always allocate dest_gr() will cause issue for these nop instructions. After fix this issue, the temporary implementation of floating point instructions (which have skipped instructions) can work correctlly. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 214 +++--- 1 file changed, 127 insertions(+), 87 deletions(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index b7bb4f3..2ca5d43 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -30,6 +30,8 @@ #define FMT64X "%016" PRIx64 +#define TDEST dest_gr(dc, dest) + static TCGv_ptr cpu_env; static TCGv cpu_pc; static TCGv cpu_regs[TILEGX_R_COUNT]; @@ -547,18 +549,17 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, return ret; } -tdest = dest_gr(dc, dest); tsrca = load_gr(dc, srca); switch (opext) { case OE_RR_X0(CNTLZ): case OE_RR_Y0(CNTLZ): -gen_helper_cntlz(tdest, tsrca); +gen_helper_cntlz(TDEST, tsrca); mnemonic = "cntlz"; break; case OE_RR_X0(CNTTZ): case OE_RR_Y0(CNTTZ): -gen_helper_cnttz(tdest, tsrca); +gen_helper_cnttz(TDEST, tsrca); mnemonic = "cnttz"; break; case OE_RR_X0(FSINGLE_PACK1): @@ -631,10 +632,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "ld"; do_load: if (!prefetch_nofault) { -tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop); +tcg_gen_qemu_ld_tl(TDEST, tsrca, dc->mmuidx, memop); } break; case OE_RR_X1(LDNA): +tdest = dest_gr(dc, dest); tcg_gen_andi_tl(tdest, tsrca, ~7); tcg_gen_qemu_ld_tl(tdest, tdest, dc->mmuidx, MO_TEQ); mnemonic = "ldna"; @@ -644,22 +646,22 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, if (srca) { return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; } -tcg_gen_movi_tl(tdest, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES); +tcg_gen_movi_tl(TDEST, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES); mnemonic = "lnk"; break; case OE_RR_X0(PCNT): case OE_RR_Y0(PCNT): -gen_helper_pcnt(tdest, tsrca); +gen_helper_pcnt(TDEST, tsrca); mnemonic = "pcnt"; break; case OE_RR_X0(REVBITS): case OE_RR_Y0(REVBITS): -gen_helper_revbits(tdest, tsrca); +gen_helper_revbits(TDEST, tsrca); mnemonic = "revbits"; break; case OE_RR_X0(REVBYTES): case OE_RR_Y0(REVBYTES): -tcg_gen_bswap64_tl(tdest, tsrca); +tcg_gen_bswap64_tl(TDEST, tsrca); mnemonic = "revbytes"; break; case OE_RR_X0(TBLIDXB0): @@ -682,7 +684,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, unsigned dest, unsigned srca, unsigned srcb) { -TCGv tdest = dest_gr(dc, dest); +TCGv tdest; TCGv tsrca = load_gr(dc, srca); TCGv tsrcb = load_gr(dc, srcb); TCGv t0; @@ -691,13 +693,14 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, switch (opext) { case OE_RRR(ADDXSC, 0, X0): case OE_RRR(ADDXSC, 0, X1): -gen_saturate_op(tdest, tsrca, tsrcb, tcg_gen_add_tl); +gen_saturate_op(TDEST, tsrca, tsrcb, tcg_gen_add_tl); mnemonic = "addxsc"; break; case OE_RRR(ADDX, 0, X0): case OE_RRR(ADDX, 0, X1): case OE_RRR(ADDX, 0, Y0): case OE_RRR(ADDX, 0, Y1): +tdest = dest_gr(dc, dest); tcg_gen_add_tl(tdest, tsrca, tsrcb); tcg_gen_ext32s_tl(tdest, tdest); mnemonic = "addx"; @@ -706,25 +709,25 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(ADD, 0, X1): case OE_RRR(ADD, 0, Y0): case OE_RRR(ADD, 0, Y1): -tcg_gen_add_tl(tdest, tsrca, tsrcb); +tcg_gen_add_tl(TDEST, tsrca, tsrcb); mnemonic = "add"; break; case OE_RRR(AND, 0, X0): case OE_RRR(AND, 0, X1): case OE_RRR(AND, 5, Y0): case OE_RRR(AND, 5, Y1): -tcg_gen_and_tl(tdest, tsrca, tsrcb); +tcg_gen_and_tl(TDEST, tsrca, tsrcb); mnemonic = "and"; break; case OE_RRR(CMOVEQZ, 0, X0): case OE_RRR(CMOVEQZ, 4, Y0): -tcg_gen_movcond_tl(TCG_COND_EQ, tdest, tsrca, load_zero(dc), +tcg_gen_movcond_tl(TCG_COND_EQ, TDEST, tsrca, load_zero(dc), tsrcb, load_gr(dc, dest)); mnemonic = "cmoveqz"; break; case OE_RRR(CMOVNEZ, 0, X0): case OE_RRR(CMOVNEZ, 4, Y0): -tcg_gen_movcond_tl(TCG_COND_NE, tdest, tsrca, load_zero(dc),
[Qemu-devel] [PATCH] target-tilegx: Implement v2sh* instructions
From: Chen Gang It is just according to v1sh* instructions implementation. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index f711c18..03c8e76 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1769,11 +1769,29 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext, break; case OE_SH(V2SHLI, X0): case OE_SH(V2SHLI, X1): +tdest = dest_gr(dc, dest); +i2 = imm & 15; +i3 = 0x >> i2; +tcg_gen_andi_tl(tdest, tsrca, V2_IMM(i3)); +tcg_gen_shli_tl(tdest, tdest, i2); +mnemonic = "v2shli"; +break; case OE_SH(V2SHRSI, X0): case OE_SH(V2SHRSI, X1): +t0 = tcg_const_tl(imm & 15); +gen_helper_v2shrs(TDEST, tsrca, t0); +tcg_temp_free(t0); +mnemonic = "v2shrsi"; +break; case OE_SH(V2SHRUI, X0): case OE_SH(V2SHRUI, X1): -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +tdest = dest_gr(dc, dest); +i2 = imm & 15; +i3 = (0x << i2) & 0x; +tcg_gen_andi_tl(tdest, tsrca, V2_IMM(i3)); +tcg_gen_shri_tl(tdest, tdest, i2); +mnemonic = "v2shrui"; +break; case OE(ADDLI_OPCODE_X0, 0, X0): case OE(ADDLI_OPCODE_X1, 0, X1): -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Implement v?int_* instructions.
From: Chen Gang Signed-off-by: Chen Gang --- target-tilegx/helper.h | 5 target-tilegx/simd_helper.c | 56 + target-tilegx/translate.c | 14 3 files changed, 75 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index dc865bb..3f4fa3c 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -10,6 +10,11 @@ DEF_HELPER_FLAGS_3(cmula, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_3(cmulaf, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_4(cmul2, TCG_CALL_NO_RWG_SE, i64, i64, i64, int, int) +DEF_HELPER_FLAGS_2(v1int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v1int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64) + DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index 23c20bd..6fa6318 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -102,3 +102,59 @@ uint64_t helper_v2shrs(uint64_t a, uint64_t b) } return r; } + +uint64_t helper_v1int_h(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 8) { +tmp = (uint8_t)(a >> (i + 32)); +r |= tmp << (2 * i + 8); +tmp = (uint8_t)(b >> (i + 32)); +r |= tmp << 2 * i; +} +return r; +} + +uint64_t helper_v1int_l(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 8) { +tmp = (uint8_t)(a >> i); +r |= tmp << (2 * i + 8); +tmp = (uint8_t)(b >> i); +r |= tmp << 2 * i; +} +return r; +} + +uint64_t helper_v2int_h(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 16) { +tmp = (uint16_t)(a >> (i + 32)); +r |= tmp << (2 * i + 16); +tmp = (uint16_t)(b >> (i + 32)); +r |= tmp << 2 * i; +} +return r; +} + +uint64_t helper_v2int_l(uint64_t a, uint64_t b) +{ +uint64_t r = 0, tmp; +int i; + +for (i = 0; i < 32; i += 16) { +tmp = (uint16_t)(a >> i); +r |= tmp << (2 * i + 16); +tmp = (uint16_t)(b >> i); +r |= tmp << 2 * i; +} +return r; +} diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 03c8e76..6853628 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -1334,10 +1334,17 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V1DOTPUS, 0, X0): case OE_RRR(V1DOTPU, 0, X0): case OE_RRR(V1DOTP, 0, X0): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V1INT_H, 0, X0): case OE_RRR(V1INT_H, 0, X1): +gen_helper_v1int_h(TDEST, tsrca, tsrcb); +mnemonic = "v1int_h"; +break; case OE_RRR(V1INT_L, 0, X0): case OE_RRR(V1INT_L, 0, X1): +gen_helper_v1int_l(TDEST, tsrca, tsrcb); +mnemonic = "v1int_l"; +break; case OE_RRR(V1MAXU, 0, X0): case OE_RRR(V1MAXU, 0, X1): case OE_RRR(V1MINU, 0, X0): @@ -1403,10 +1410,17 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V2CMPNE, 0, X1): case OE_RRR(V2DOTPA, 0, X0): case OE_RRR(V2DOTP, 0, X0): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2INT_H, 0, X0): case OE_RRR(V2INT_H, 0, X1): +gen_helper_v2int_h(TDEST, tsrca, tsrcb); +mnemonic = "v2int_h"; +break; case OE_RRR(V2INT_L, 0, X0): case OE_RRR(V2INT_L, 0, X1): +gen_helper_v2int_l(TDEST, tsrca, tsrcb); +mnemonic = "v2int_l"; +break; case OE_RRR(V2MAXS, 0, X0): case OE_RRR(V2MAXS, 0, X1): case OE_RRR(V2MINS, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Implement v2mults instruction
From: Chen Gang Just according to v1multu instruction implementation. Signed-off-by: Chen Gang --- target-tilegx/helper.h | 1 + target-tilegx/simd_helper.c | 13 + target-tilegx/translate.c | 5 + 3 files changed, 19 insertions(+) diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 3f4fa3c..ff280ac 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -16,6 +16,7 @@ DEF_HELPER_FLAGS_2(v2int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v2int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(v2mults, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c index 6fa6318..4f226eb 100644 --- a/target-tilegx/simd_helper.c +++ b/target-tilegx/simd_helper.c @@ -41,6 +41,19 @@ uint64_t helper_v1multu(uint64_t a, uint64_t b) return r; } +uint64_t helper_v2mults(uint64_t a, uint64_t b) +{ +uint64_t r = 0; +int i; + +for (i = 0; i < 64; i += 16) { +int64_t ae = (int16_t)(a >> i); +int64_t be = (int16_t)(b >> i); +r |= ((ae * be) & 0x) << i; +} +return r; +} + uint64_t helper_v1shl(uint64_t a, uint64_t b) { uint64_t m; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 6853628..40f9b12 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -990,6 +990,7 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, mnemonic = "fsingle_mul1"; break; case OE_RRR(FSINGLE_MUL2, 0, X0): +tcg_gen_mov_i64(TDEST, tsrca); mnemonic = "fsingle_mul2"; break; case OE_RRR(FSINGLE_PACK2, 0, X0): @@ -1429,7 +1430,11 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext, case OE_RRR(V2MNZ, 0, X1): case OE_RRR(V2MULFSC, 0, X0): case OE_RRR(V2MULS, 0, X0): +return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; case OE_RRR(V2MULTS, 0, X0): +gen_helper_v2mults(TDEST, tsrca, tsrcb); +mnemonic = "v2shl"; +break; case OE_RRR(V2MZ, 0, X0): case OE_RRR(V2MZ, 0, X1): case OE_RRR(V2PACKH, 0, X0): -- 1.9.3
[Qemu-devel] [PATCH] target-tilegx: Use TILEGX_EXCP_OPCODE_UNKNOWN instead of TILEGX_EXCP_OPCODE_UNIMPLEMENTED for some cases
From: Chen Gang For some cases, they are for TILEGX_EXCP_OPCODE_UNKNOWN, not for TILEGX_EXCP_OPCODE_UNIMPLEMENTED. When analyzing issues, the related output is incorrect (e.g. grep UIMP in the output log for finding qemu tilegx umimplementation issues). Signed-off-by: Chen Gang --- target-tilegx/translate.c | 35 +-- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 40f9b12..d2aeae0 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -293,7 +293,7 @@ static TileExcp gen_st_opcode(DisasContext *dc, unsigned dest, unsigned srca, unsigned srcb, TCGMemOp memop, const char *name) { if (dest) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } tcg_gen_qemu_st_tl(load_gr(dc, srcb), load_gr(dc, srca), @@ -540,7 +540,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "swint1"; done0: if (srca || dest) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic); return ret; @@ -586,7 +586,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, tcg_gen_andi_tl(dc->jmp.dest, load_gr(dc, srca), ~7); done1: if (dest) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]); return ret; @@ -688,7 +688,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, case OE_RR_X1(LNK): case OE_RR_Y1(LNK): if (srca) { -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } tcg_gen_movi_tl(TDEST, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES); mnemonic = "lnk"; @@ -735,7 +735,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "tblidxb3"; break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic, @@ -1833,7 +1833,7 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext, break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %d", mnemonic, @@ -1927,7 +1927,7 @@ static TileExcp gen_bf_opcode_x0(DisasContext *dc, unsigned ext, break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %u, %u", mnemonic, @@ -1983,7 +1983,7 @@ static TileExcp gen_branch_opcode_x1(DisasContext *dc, unsigned ext, mnemonic = "blbs"; break; default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -2131,7 +2131,7 @@ static TileExcp decode_y0(DisasContext *dc, tilegx_bundle_bits bundle) return gen_rri_opcode(dc, OE(opc, 0, Y0), dest, srca, imm); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -2175,7 +2175,7 @@ static TileExcp decode_y1(DisasContext *dc, tilegx_bundle_bits bundle) return gen_rri_opcode(dc, OE(opc, 0, Y1), dest, srca, imm); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -2233,7 +2233,7 @@ static TileExcp decode_y2(DisasContext *dc, tilegx_bundle_bits bundle) return gen_st_opcode(dc, 0, srca, srcbdest, MO_TEQ, "st"); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -2278,7 +2278,7 @@ static TileExcp decode_x0(DisasContext *dc, tilegx_bundle_bits bundle) return gen_rri_opcode(dc, OE(opc, 0, X0), dest, srca, imm); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -2368,7 +2368,7 @@ static TileExcp decode_x1(DisasContext *dc, tilegx_bundle_bits bundle) return gen_rri_opcode(dc, OE(opc, 0, X1), dest, srca, imm); default: -return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +return TILEGX_EXCP_OPCODE_UNKNOWN; } } @@ -2379,8 +2379,15 @@ static void notice_excp(DisasContext *dc, uint64_t bundle, return; } gen_exception(dc, excp); -if (excp == TILEGX_EXCP_OPCODE_UNIMPLEMENTED) { +switch (excp) { +case TILEGX_EXCP_OPCODE_UNIMPLEMENTED: qemu_log_mask(LOG_UNIMP, "UNIMP %s, [" FMT64X "]\n", type, bundle); +
[Qemu-devel] [PATCH] linux-user/main.c: Always set QEMU_LD_PREFIX when interp_prefix is changed
From: Chen Gang If qemu sets interp_prfix via command line '-L' instead of environments variable QEMU_LD_PREFIX, it will cause syscall execve() failed. Because the 2nd qemu has no command line '-L'. So qemu need always set QEMU_LD_PREFIX when interp_prefix is changed. Signed-off-by: Chen Gang --- linux-user/main.c | 4 1 file changed, 4 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index 06dd296..2f31ea6 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3539,7 +3539,11 @@ static void handle_arg_stack_size(const char *arg) static void handle_arg_ld_prefix(const char *arg) { +char *buf = g_strdup_printf("QEMU_LD_PREFIX=%s", arg); + interp_prefix = strdup(arg); +(void) envlist_setenv(envlist, buf); +g_free(buf); } static void handle_arg_pagesize(const char *arg) -- 1.9.1
[Qemu-devel] [PATCH v2] linux-user/main.c: Set environments variables from command line options
From: Chen Gang When qemu execute execve() system call, the related command line options can not be passed to the second qemu process, which causes the second process fail. Signed-off-by: Chen Gang --- linux-user/main.c | 4 1 file changed, 4 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index 06dd296..f1f5496 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3767,6 +3767,7 @@ static void usage(void) static int parse_args(int argc, char **argv) { const char *r; +char *buf; int optind; const struct qemu_argument *arginfo; @@ -3802,6 +3803,9 @@ static int parse_args(int argc, char **argv) if (optind >= argc) { usage(); } +buf = g_strdup_printf("%s=%s", arginfo->env, argv[optind]); +(void) envlist_setenv(envlist, buf); +g_free(buf); arginfo->handle_opt(argv[optind]); optind++; } else { -- 1.9.1
[Qemu-devel] [PATCH v3] linux-user/main.c: Set environments variables from command line options
From: Chen Gang When qemu execute execve() system call, the related command line options can not be passed to the second qemu process, which causes the second process fail. Signed-off-by: Chen Gang --- linux-user/main.c | 5 + 1 file changed, 5 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index 06dd296..dfbccbe 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3767,6 +3767,7 @@ static void usage(void) static int parse_args(int argc, char **argv) { const char *r; +char *buf; int optind; const struct qemu_argument *arginfo; @@ -3802,11 +3803,15 @@ static int parse_args(int argc, char **argv) if (optind >= argc) { usage(); } +buf = g_strdup_printf("%s=%s", arginfo->env, argv[optind]); arginfo->handle_opt(argv[optind]); optind++; } else { +buf = g_strdup_printf("%s=", arginfo->env); arginfo->handle_opt(NULL); } +(void) envlist_setenv(envlist, buf); +g_free(buf); break; } } -- 1.9.1
[Qemu-devel] [PATCH] linux-user/signal.c: Use setup_rt_frame() instead of setup_frame() for target openrisc
From: Chen Gang qemu has already considered about some targets may have no traditional signals. And openrisc's setup_frame() is dummy, but it can be supported by setup_rt_frame(). Signed-off-by: Chen Gang --- linux-user/signal.c | 9 ++--- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 502efd9..ac82baa 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -3900,12 +3900,6 @@ static inline abi_ulong get_sigframe(struct target_sigaction *ka, return sp; } -static void setup_frame(int sig, struct target_sigaction *ka, -target_sigset_t *set, CPUOpenRISCState *env) -{ -qemu_log("Not implement.\n"); -} - static void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUOpenRISCState *env) @@ -5662,7 +5656,8 @@ void process_pending_signals(CPUArchState *cpu_env) } #endif /* prepare the stack frame of the virtual CPU */ -#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) +#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \ +|| defined(TARGET_OPENRISC) /* These targets do not have traditional signals. */ setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); #else -- 1.9.3
[Qemu-devel] [PATCH] linux-user/signal.c: Skip calling unlock_user_struct() when lock_user_struct() failed for target m68k
From: Chen Gang For target m68k, setup_rt_frame() and do_rt_sigreturn() have this issue. Signed-off-by: Chen Gang --- linux-user/signal.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index cead97b..0265c46 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5160,7 +5160,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, frame_addr = get_sigframe(ka, env, sizeof *frame); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) - goto give_sigsegv; +goto err; __put_user(sig, &frame->sig); @@ -5215,6 +5215,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, give_sigsegv: unlock_user_struct(frame, frame_addr, 1); +err: force_sig(TARGET_SIGSEGV); } @@ -5261,7 +5262,7 @@ long do_rt_sigreturn(CPUM68KState *env) int d0; if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) -goto badframe; +goto err; target_to_host_sigset_internal(&set, &target_set); do_sigprocmask(SIG_SETMASK, &set, NULL); @@ -5281,6 +5282,7 @@ long do_rt_sigreturn(CPUM68KState *env) badframe: unlock_user_struct(frame, frame_addr, 0); +err: force_sig(TARGET_SIGSEGV); return 0; } -- 1.9.3
[Qemu-devel] [PATCH] linux-user/signal.c: Skip calling unlock_user_struct() when lock_user_struct() failed for target ppc and ppc64
From: Chen Gang For target ppc and ppc64, all related funcitons have this issue. Signed-off-by: Chen Gang --- linux-user/signal.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 0265c46..61f98e7 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4666,7 +4666,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, frame_addr = get_sigframe(ka, env, sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) -goto sigsegv; +goto err; sc = &frame->sctx; __put_user(ka->_sa_handler, &sc->handler); @@ -4729,6 +4729,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, sigsegv: unlock_user_struct(frame, frame_addr, 1); +err: qemu_log("segfaulting from setup_frame\n"); force_sig(TARGET_SIGSEGV); } @@ -4748,7 +4749,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf)); if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1)) -goto sigsegv; +goto err; tswap_siginfo(&rt_sf->info, info); @@ -4825,6 +4826,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, sigsegv: unlock_user_struct(rt_sf, rt_sf_addr, 1); +err: qemu_log("segfaulting from setup_rt_frame\n"); force_sig(TARGET_SIGSEGV); @@ -4840,7 +4842,7 @@ long do_sigreturn(CPUPPCState *env) sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE; if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) -goto sigsegv; +goto err; #if defined(TARGET_PPC64) set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32); @@ -4861,8 +4863,8 @@ long do_sigreturn(CPUPPCState *env) return -TARGET_QEMU_ESIGRETURN; sigsegv: -unlock_user_struct(sr, sr_addr, 1); unlock_user_struct(sc, sc_addr, 1); +err: qemu_log("segfaulting from do_sigreturn\n"); force_sig(TARGET_SIGSEGV); return 0; @@ -4905,7 +4907,7 @@ long do_rt_sigreturn(CPUPPCState *env) rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16; if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1)) -goto sigsegv; +goto err; if (do_setcontext(&rt_sf->uc, env, 1)) goto sigsegv; @@ -4919,6 +4921,7 @@ long do_rt_sigreturn(CPUPPCState *env) sigsegv: unlock_user_struct(rt_sf, rt_sf_addr, 1); +err: qemu_log("segfaulting from do_rt_sigreturn\n"); force_sig(TARGET_SIGSEGV); return 0; -- 1.9.3
[Qemu-devel] [PATCH v2] linux-user/signal.c: Fix several issues for target alpha
From: Chen Gang Remove useless variable err in setup_frame() and setup_rt_frame(). Add unlock_user_struct() for setup_rt_frame(). Do not call unlock_user_struct() when lock_user_struct() failed in do_rt_sigreturn(). Remove white space of label badframe in do_sigreturn(). Signed-off-by: Chen Gang --- linux-user/signal.c | 41 - 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 502efd9..e188931 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5396,7 +5396,6 @@ static void setup_frame(int sig, struct target_sigaction *ka, { abi_ulong frame_addr, r26; struct target_sigframe *frame; -int err = 0; frame_addr = get_sigframe(ka, env, sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { @@ -5418,20 +5417,19 @@ static void setup_frame(int sig, struct target_sigaction *ka, unlock_user_struct(frame, frame_addr, 1); -if (err) { -give_sigsegv: -if (sig == TARGET_SIGSEGV) { -ka->_sa_handler = TARGET_SIG_DFL; -} -force_sig(TARGET_SIGSEGV); -} - env->ir[IR_RA] = r26; env->ir[IR_PV] = env->pc = ka->_sa_handler; env->ir[IR_A0] = sig; env->ir[IR_A1] = 0; env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc); env->ir[IR_SP] = frame_addr; +return; + +give_sigsegv: +if (sig == TARGET_SIGSEGV) { +ka->_sa_handler = TARGET_SIG_DFL; +} +force_sig(TARGET_SIGSEGV); } static void setup_rt_frame(int sig, struct target_sigaction *ka, @@ -5440,7 +5438,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, { abi_ulong frame_addr, r26; struct target_rt_sigframe *frame; -int i, err = 0; +int i; frame_addr = get_sigframe(ka, env, sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { @@ -5474,13 +5472,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, r26 = frame_addr; } -if (err) { -give_sigsegv: - if (sig == TARGET_SIGSEGV) { -ka->_sa_handler = TARGET_SIG_DFL; -} -force_sig(TARGET_SIGSEGV); -} +unlock_user_struct(frame, frame_addr, 1); env->ir[IR_RA] = r26; env->ir[IR_PV] = env->pc = ka->_sa_handler; @@ -5488,6 +5480,13 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info); env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc); env->ir[IR_SP] = frame_addr; +return; + +give_sigsegv: + if (sig == TARGET_SIGSEGV) { +ka->_sa_handler = TARGET_SIG_DFL; +} +force_sig(TARGET_SIGSEGV); } long do_sigreturn(CPUAlphaState *env) @@ -5511,7 +5510,7 @@ long do_sigreturn(CPUAlphaState *env) unlock_user_struct(sc, sc_addr, 0); return env->ir[IR_V0]; - badframe: +badframe: force_sig(TARGET_SIGSEGV); } @@ -5522,7 +5521,7 @@ long do_rt_sigreturn(CPUAlphaState *env) sigset_t set; if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { -goto badframe; +goto err; } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); do_sigprocmask(SIG_SETMASK, &set, NULL); @@ -5537,9 +5536,9 @@ long do_rt_sigreturn(CPUAlphaState *env) unlock_user_struct(frame, frame_addr, 0); return env->ir[IR_V0]; - - badframe: +badframe: unlock_user_struct(frame, frame_addr, 0); +err: force_sig(TARGET_SIGSEGV); } -- 1.9.3
[Qemu-devel] [PATCH] linux-user/syscall.c: Fix issue for checking ptr in different address spaces in TARGET_CMSG_NXTHDR
From: Chen Gang After fix this issue, qemu can run i386 wine notepad.exe successfully. But the initialization performance is not quite well. Signed-off-by: Chen Gang --- linux-user/syscall.c | 30 +- linux-user/syscall_defs.h | 20 +--- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 973cc2f..521749c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1181,17 +1181,18 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); abi_long msg_controllen; abi_ulong target_cmsg_addr; -struct target_cmsghdr *target_cmsg; +struct target_cmsghdr *target_cmsg, *base; socklen_t space = 0; msg_controllen = tswapal(target_msgh->msg_controllen); if (msg_controllen < sizeof (struct target_cmsghdr)) goto the_end; target_cmsg_addr = tswapal(target_msgh->msg_control); -target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); -if (!target_cmsg) +base = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); +if (!base) { return -TARGET_EFAULT; - +} +target_cmsg = base; while (cmsg && target_cmsg) { void *data = CMSG_DATA(cmsg); void *target_data = TARGET_CMSG_DATA(target_cmsg); @@ -1247,7 +1248,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, } cmsg = CMSG_NXTHDR(msgh, cmsg); -target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); +target_cmsg = TARGET_CMSG_NXTHDR(base, msg_controllen, target_cmsg); } unlock_user(target_cmsg, target_cmsg_addr, 0); the_end: @@ -1259,19 +1260,22 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, struct msghdr *msgh) { struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); -abi_long msg_controllen; +abi_long msg_controllen, size; abi_ulong target_cmsg_addr; -struct target_cmsghdr *target_cmsg; +struct target_cmsghdr *target_cmsg, *base; socklen_t space = 0; -msg_controllen = tswapal(target_msgh->msg_controllen); -if (msg_controllen < sizeof (struct target_cmsghdr)) +size = tswapal(target_msgh->msg_controllen); +if (size < sizeof(struct target_cmsghdr)) { goto the_end; +} target_cmsg_addr = tswapal(target_msgh->msg_control); -target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0); -if (!target_cmsg) +base = lock_user(VERIFY_WRITE, target_cmsg_addr, size, 0); +if (!base) { return -TARGET_EFAULT; - +} +msg_controllen = size; +target_cmsg = base; while (cmsg && target_cmsg) { void *data = CMSG_DATA(cmsg); void *target_data = TARGET_CMSG_DATA(target_cmsg); @@ -1389,7 +1393,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, msg_controllen -= tgt_space; space += tgt_space; cmsg = CMSG_NXTHDR(msgh, cmsg); -target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); +target_cmsg = TARGET_CMSG_NXTHDR(base, size, target_cmsg); } unlock_user(target_cmsg, target_cmsg_addr, space); the_end: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 5256fe5..aec2f23 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -234,7 +234,8 @@ struct target_cmsghdr { }; #define TARGET_CMSG_DATA(cmsg) ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1)) -#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg) +#define TARGET_CMSG_NXTHDR(base, size, cmsg) __target_cmsg_nxthdr(base, size, \ + cmsg) #define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \ & (size_t) ~(sizeof (abi_long) - 1)) #define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \ @@ -242,17 +243,14 @@ struct target_cmsghdr { #define TARGET_CMSG_LEN(len) (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len)) static __inline__ struct target_cmsghdr * -__target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cmsg) +__target_cmsg_nxthdr(void *base, abi_long size, struct target_cmsghdr *msg) { - struct target_cmsghdr *__ptr; - - __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg -+ TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len))); - if ((unsigned long)((char *)(__ptr+1) - (char *)(size_t)tswapal(__mhdr->msg_control)) - > tswapal(__mhdr->msg_controllen)) -/* No more entries. */ -return (struct target_cmsghdr *)0; - return __cmsg; +msg = (struct target_cmsghdr *)((unsigned char *)msg + +TARGET_CMSG_ALIGN(tswapal(msg->cmsg_len))); +if ((unsigned long)((char *)(msg + 1)
Re: [Qemu-devel] Subject: [PATCH 01/16] linux-user: tilegx: Firstly add architecture related features
At present, I can send mail through git client directly with my qq mail address, I reply this mail again to test whether our qemu mailing list can accept qq mail address or not. If it can accept qq mail address, I shall send mail through git client directly. > OK, thanks. I guess I should send mail through git client directly, > instead of my thunder bird (I shall try to config it). > > Thanks. -- Chen Gang Open, share, and attitude like air, water, and life which God blessed
Re: [Qemu-devel] Subject: [PATCH 01/16] linux-user: tilegx: Firstly add architecture related features
At present, I can send mail through git client directly with my qq mail address, I reply this mail again to test whether our qemu mailing list can accept qq mail address or not. If it can accept qq mail address, I shall send mail through git client directly. > OK, thanks. I guess I should send mail through git client directly, > instead of my thunder bird (I shall try to config it). > > Thanks. -- Chen Gang Open, share, and attitude like air, water, and life which God blessed
Re: [Qemu-devel] Subject: [PATCH 01/16] linux-user: tilegx: Firstly add architecture related features
At present, I can send mail through git client directly with my qq mail address, I reply this mail again to test whether our qemu mailing list can accept qq mail address or not. If it can accept qq mail address, I shall send mail through git client directly. > OK, thanks. I guess I should send mail through git client directly, > instead of my thunder bird (I shall try to config it). > > Thanks. -- Chen Gang Open, share, and attitude like air, water, and life which God blessed
[Qemu-devel] [PATCH 0/2] alpha-host: Add Alpha host tcg backend to latest QEMU
From: Chen Gang It is only for version merging, no any functional modification. Chen Gang (2): alpha-host: Add Alpha host tcg backend. alpha-host: Fix alpha host related merging issues. configure | 16 +- include/exec/exec-all.h | 11 +- include/qemu-common.h |4 +- tcg/alpha/tcg-target.c | 1934 +++ tcg/alpha/tcg-target.h | 169 + translate-all.c |2 + user-exec.c |4 +- 7 files changed, 2128 insertions(+), 12 deletions(-) create mode 100644 tcg/alpha/tcg-target.c create mode 100644 tcg/alpha/tcg-target.h -- 1.9.1
[Qemu-devel] [PATCH 2/2] alpha-host: Fix alpha host related merging issues.
From: Chen Gang It can pass simple test for i386-linux-user under ALpha VM: run i386 bash successfully (let pagesize be TARGET_PAGE_SIZE, temporary). Signed-off-by: Chen Gang --- tcg/alpha/tcg-target.c | 139 +++-- tcg/alpha/tcg-target.h | 8 ++- 2 files changed, 71 insertions(+), 76 deletions(-) diff --git a/tcg/alpha/tcg-target.c b/tcg/alpha/tcg-target.c index 3fdfbe7..b21d52c 100644 --- a/tcg/alpha/tcg-target.c +++ b/tcg/alpha/tcg-target.c @@ -151,10 +151,7 @@ static const int tcg_target_call_oarg_regs[1] = { * If the guest base gets placed in high memory, it's more efficient * to use a register to hold the address. */ -#ifndef CONFIG_USE_GUEST_BASE -#define GUEST_BASE 0 -#endif -#define USE_GUEST_BASE_REG (GUEST_BASE > 0x7fff) +#define USE_GUEST_BASE_REG (guest_base > 0x7fff) #define TCG_GUEST_BASE_REG TCG_REG_S5 /* @@ -258,6 +255,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) const char *ct_str = *pct_str; switch (ct_str[0]) { +case 'R': case 'r': /* Constaint 'r' means any register is okay. */ ct->ct |= TCG_CT_REG; @@ -360,14 +358,14 @@ static int tcg_match_andi(tcg_target_long val) } } -static inline int tcg_target_const_match(tcg_target_long val, +static inline int tcg_target_const_match(tcg_target_long val, TCGType type, const TCGArgConstraint *arg_ct) { int ct = arg_ct->ct; if (ct & TCG_CT_CONST) { return 1; } -if (ct & TCG_CT_CONST_IS32) { +if (type == TCG_TYPE_I32) { val = (int32_t)val; } if ((ct & TCG_CT_CONST_U8) && val == (uint8_t)val) { @@ -718,20 +716,17 @@ static void tcg_out_st_sz(TCGContext *s, TCGMemOp memop, TCGReg ra, TCGReg rb, tcg_out_mem_long(s, st_opc[memop & MO_SIZE], ra, rb, disp); } -static void patch_reloc(uint8_t *x_ptr, int type, -tcg_target_long value, tcg_target_long addend) +static void patch_reloc(tcg_insn_unit *code_ptr, int type, +intptr_t value, intptr_t addend) { -uint32_t *code_ptr = (uint32_t *)x_ptr; -uint32_t insn = *code_ptr; - -value += addend; switch (type) { case R_ALPHA_BRADDR: -value -= (intptr_t)x_ptr + 4; +value += addend; +value -= (intptr_t)code_ptr + 4; if ((value & 3) || value < -0x40 || value >= 0x40) { tcg_abort(); } -*code_ptr = (insn & ~0x1f) | INSN_DISP21(value >> 2); +*code_ptr = (*code_ptr & ~0x1f) | INSN_DISP21(value >> 2); break; default: @@ -756,13 +751,12 @@ static inline void tcg_out_br_direct(TCGContext *s, AlphaOpcode opc, TCGReg ra, } static inline void tcg_out_br_label(TCGContext *s, AlphaOpcode opc, TCGReg ra, -int label_index) +TCGLabel *l) { -TCGLabel *l = &s->labels[label_index]; if (l->has_value) { tcg_out_br_direct(s, opc, ra, l->u.value); } else { -tcg_out_reloc(s, s->code_ptr, R_ALPHA_BRADDR, label_index, 0); +tcg_out_reloc(s, s->code_ptr, R_ALPHA_BRADDR, l, 0); tcg_out_br_noaddr(s, opc, ra); } } @@ -788,8 +782,9 @@ static inline void tcg_out_reset_tb(TCGContext *s, TCGReg reg) } } -static void tcg_out_const_call(TCGContext *s, intptr_t dest) +static void tcg_out_call(TCGContext *s, tcg_insn_unit *target) { +intptr_t dest = (intptr_t)target; const uint16_t *check = (const uint16_t *) dest; uint16_t check1 = check[1]; uint16_t check3 = check[3]; @@ -930,7 +925,7 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg dest, } static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, - TCGArg arg2, int const_arg2, int label_index) + TCGArg arg2, int const_arg2, TCGLabel *l) { /* Note that unsigned comparisons are not present here, which means that their entries will contain zeros. */ @@ -964,7 +959,7 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, arg1 = TMP_REG1; } -tcg_out_br_label(s, opc, arg1, label_index); +tcg_out_br_label(s, opc, arg1, l); } /* Note that these functions don't have normal C calling conventions. */ @@ -1069,37 +1064,38 @@ static TCGReg tcg_out_tlb_cmp(TCGContext *s, TCGMemOp memop, TCGReg addr_reg, /* Record the context of a call to the out of line helper code for the slow path for a load or store, so that we can later generate the correct helper code. */ -static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc, -TCGReg data_reg, TCGReg addr_reg, int mem_idx, -uint8_t *raddr, uint8_t *label_ptr) +static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, +
[Qemu-devel] [PATCH 1/2] alpha-host: Add Alpha host tcg backend.
From: Chen Gang It is merged from git://github.com/rth7680/qemu.git tcg-alpha-2 Signed-off-by: Richard Henderson Signed-off-by: Chen Gang --- configure | 16 +- include/exec/exec-all.h | 11 +- include/qemu-common.h |4 +- tcg/alpha/tcg-target.c | 1945 +++ tcg/alpha/tcg-target.h | 163 translate-all.c |2 + user-exec.c |4 +- 7 files changed, 2133 insertions(+), 12 deletions(-) create mode 100644 tcg/alpha/tcg-target.c create mode 100644 tcg/alpha/tcg-target.h diff --git a/configure b/configure index 9d24d59..c3683f7 100755 --- a/configure +++ b/configure @@ -524,6 +524,8 @@ elif check_define __aarch64__ ; then cpu="aarch64" elif check_define __hppa__ ; then cpu="hppa" +elif check_define __alpha__ ; then + cpu="alpha" else cpu=`uname -m` fi @@ -553,6 +555,9 @@ case "$cpu" in sparc|sun4[cdmuv]) cpu="sparc" ;; + alpha*) +cpu="alpha" + ;; *) # This will result in either an error or falling back to TCI later ARCH=unknown @@ -1171,6 +1176,10 @@ if $python -B -c 'import sys; sys.exit(0)' 2>/dev/null; then fi case "$cpu" in +alpha) + CPU_CFLAGS="-msmall-data $CPU_CFLAGS" + LDFLAGS="-Wl,--warn-multiple-gp $LDFLAGS" + ;; ppc) CPU_CFLAGS="-m32" LDFLAGS="-m32 $LDFLAGS" @@ -5570,13 +5579,6 @@ if test "$tcg_interpreter" = "yes" ; then echo "CONFIG_TCI_DIS=y" >> config-all-disas.mak fi -case "$ARCH" in -alpha) - # Ensure there's only a single GP - cflags="-msmall-data $cflags" -;; -esac - if test "$gprof" = "yes" ; then echo "TARGET_GPROF=yes" >> $config_target_mak if test "$target_linux_user" = "yes" ; then diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 83b9251..afc9714 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -178,7 +178,7 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...) #define CODE_GEN_AVG_BLOCK_SIZE 64 #endif -#if defined(__arm__) || defined(_ARCH_PPC) \ +#if defined(__alpha__) || defined(__arm__) || defined(_ARCH_PPC) \ || defined(__x86_64__) || defined(__i386__) \ || defined(__sparc__) || defined(__aarch64__) \ || defined(__s390x__) || defined(__mips__) \ @@ -302,17 +302,24 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); #endif } +#elif defined(__alpha__) +void tb_set_jmp_target2(TranslationBlock *tb, uintptr_t, uintptr_t); +#define tb_set_jmp_target2 tb_set_jmp_target2 #elif defined(__sparc__) || defined(__mips__) void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr); #else #error tb_set_jmp_target1 is missing #endif +#ifndef tb_set_jmp_target2 +# define tb_set_jmp_target2(TB, JA, A) tb_set_jmp_target1(JA, A) +#endif + static inline void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) { uint16_t offset = tb->tb_jmp_offset[n]; -tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr); +tb_set_jmp_target2(tb, (uintptr_t)(tb->tc_ptr + offset), addr); } #else diff --git a/include/qemu-common.h b/include/qemu-common.h index bbaffd1..a223759 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -16,7 +16,9 @@ #include "qemu/typedefs.h" #include "qemu/fprintf-fn.h" -#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__) +#if defined(__alpha__) || defined(__arm__) \ +|| defined(__sparc__) || defined(__mips__) \ +|| defined(__hppa__) || defined(__ia64__) #define WORDS_ALIGNED #endif diff --git a/tcg/alpha/tcg-target.c b/tcg/alpha/tcg-target.c new file mode 100644 index 000..3fdfbe7 --- /dev/null +++ b/tcg/alpha/tcg-target.c @@ -0,0 +1,1945 @@ +/* + * Tiny Code Generator for QEMU on ALPHA platform. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFT
[Qemu-devel] [PATCH] linux-user/syscall.c: Add EAGAIN to host_to_target_errno_table for
From: Chen Gang Under Alpha host, EAGAIN is redefined to 35, so it need be remapped too. Signed-off-by: Chen Gang --- linux-user/syscall.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f62c698..380f5a8 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -457,6 +457,7 @@ static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = { * minus the errnos that are not actually generic to all archs. */ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = { +[EAGAIN] = TARGET_EAGAIN, [EIDRM]= TARGET_EIDRM, [ECHRNG] = TARGET_ECHRNG, [EL2NSYNC] = TARGET_EL2NSYNC, -- 1.7.3.4