Re: [Qemu-devel] [PATCH] linux-user, fix getgroups/getgroups32 when both args are zero.
Hi, My version of patch to fix same problem: Oh, yes. You are right. I have read manpage again, and I found it says, if size is zero, list is not modified, but ... So, mine is wrong. We should check only size. /yoshii
[Qemu-devel] [PATCH] SH4,linux-user, Add pipe syscall support.
This one should be applied to run sh4-linux userland. /yoshii --- add handling of return values of pipe syscall for SH4. diff --git a/linux-user/syscall.c b/linux-user/syscall.c --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3514,6 +3514,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, CPUMIPSState *env = (CPUMIPSState*)cpu_env; env-gpr[env-current_tc][3] = host_pipe[1]; ret = host_pipe[0]; +#elif defined(TARGET_SH4) + ((CPUSH4State*)cpu_env)-gregs[1] = host_pipe[1]; + ret = host_pipe[0]; #else if (put_user_s32(host_pipe[0], arg1) || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
[Qemu-devel] [PATCH] linux-user, fix getgroups/getgroups32 when both args are zero.
getgroups() and getgroups32() returns NGROUPS_MAX when both its two args are zero. But because we pass a ptr to allocated space as 2nd arg, this function are interfered. The patch attached fixed it. /yoshii --- linux-user/syscall.c: fix getgroups{,32} when both args are zero. diff --git a/linux-user/syscall.c b/linux-user/syscall.c --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5185,7 +5185,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); break; case TARGET_NR_getgroups: -{ +if (arg1 == 0 arg2 == 0) +ret = get_errno(getgroups(0, 0)); +else { int gidsetsize = arg1; uint16_t *target_grouplist; gid_t *grouplist; @@ -5335,7 +5337,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_getgroups32 case TARGET_NR_getgroups32: -{ +if (arg1 == 0 arg2 == 0) +ret = get_errno(getgroups(0, 0)); +else { int gidsetsize = arg1; uint32_t *target_grouplist; gid_t *grouplist;
[Qemu-devel] [PATCH] SH4, fix several instructions.
Hi, I succeeded to build system set of packages on Gentoo Linux, which is a small root filesystem with toolchain(because it is essential for Gentoo), inside a chroot environment with qemu-linux-user emu. Several instructions for sh4 need to be fixed/added. Some fixes and workarounds are needed in other part of qemu, too. # Some seems to be too dirty to be merged, though. Anyway, with a patch attached, {op,translate}.c are functional enough to run userland. Please apply. I found some optimization for code can be done, but maybe later. I believe we need a formal test for all instructions, first. But it looks a long way(,and I'm lazy:). Any idea? /yoshii --- fix instruction code for frchg, fschg, ocbp. fix addressing mode handling for @Rn+, @-Rn, @(disp,gbr). fix operation for div0s. fix comments for mov imm, add imm, @(r0+,gbr), mac.l @Rm+,@Rn+. fix ldb to ldub for or/tst/xor.b #imm,@(r0,gbr). add fmov extended operations. add fcmp/eq, fcmp/gt, fneg, fabs, fsqrt, fcnvsd, fcnvds. diff --git a/target-sh4/op.c b/target-sh4/op.c index 955610a..615d30a 100644 --- a/target-sh4/op.c +++ b/target-sh4/op.c @@ -45,13 +45,7 @@ void OPPROTO op_movl_imm_T0(void) void OPPROTO op_movl_imm_T1(void) { -T0 = (uint32_t) PARAM1; -RETURN(); -} - -void OPPROTO op_movl_imm_T2(void) -{ -T0 = (uint32_t) PARAM1; +T1 = (uint32_t) PARAM1; RETURN(); } @@ -240,6 +234,12 @@ void OPPROTO op_xtrct_T0_T1(void) RETURN(); } +void OPPROTO op_add_T0_T1(void) +{ +T1 += T0; +RETURN(); +} + void OPPROTO op_addc_T0_T1(void) { helper_addc_T0_T1(); @@ -355,13 +355,13 @@ void OPPROTO op_mull_T0_T1(void) void OPPROTO op_mulsw_T0_T1(void) { -env-macl = (int32_t) T0 *(int32_t) T1; +env-macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1; RETURN(); } void OPPROTO op_muluw_T0_T1(void) { -env-macl = (uint32_t) T0 *(uint32_t) T1; +env-macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1; RETURN(); } @@ -382,7 +382,7 @@ void OPPROTO op_shad_T0_T1(void) if ((T0 0x8000) == 0) T1 = (T0 0x1f); else if ((T0 0x1f) == 0) - T1 = 0; + T1 = (T1 0x8000)? 0x : 0; else T1 = ((int32_t) T1) ((~T0 0x1f) + 1); RETURN(); @@ -539,7 +539,7 @@ void OPPROTO op_shal_Rn(void) void OPPROTO op_shar_Rn(void) { cond_t(env-gregs[PARAM1] 1); -env-gregs[PARAM1] = 1; +*(int32_t *)env-gregs[PARAM1] = 1; RETURN(); } @@ -767,6 +767,30 @@ void OPPROTO op_fdiv_DT(void) RETURN(); } +void OPPROTO op_fcmp_eq_FT(void) +{ +cond_t(float32_compare(FT0, FT1, env-fp_status) == 0); +RETURN(); +} + +void OPPROTO op_fcmp_eq_DT(void) +{ +cond_t(float64_compare(DT0, DT1, env-fp_status) == 0); +RETURN(); +} + +void OPPROTO op_fcmp_gt_FT(void) +{ +cond_t(float32_compare(FT0, FT1, env-fp_status) == 1); +RETURN(); +} + +void OPPROTO op_fcmp_gt_DT(void) +{ +cond_t(float64_compare(DT0, DT1, env-fp_status) == 1); +RETURN(); +} + void OPPROTO op_float_FT(void) { FT0 = int32_to_float32(env-fpul, env-fp_status); @@ -791,9 +815,51 @@ void OPPROTO op_ftrc_DT(void) RETURN(); } +void OPPROTO op_fneg_frN(void) +{ +env-fregs[PARAM1] = float32_chs(env-fregs[PARAM1]); +RETURN(); +} + +void OPPROTO op_fabs_FT(void) +{ +FT0 = float32_abs(FT0); +RETURN(); +} + +void OPPROTO op_fabs_DT(void) +{ +DT0 = float64_abs(DT0); +RETURN(); +} + +void OPPROTO op_fcnvsd_FT_DT(void) +{ +DT0 = float32_to_float64(FT0, env-fp_status); +RETURN(); +} + +void OPPROTO op_fcnvds_DT_FT(void) +{ +FT0 = float64_to_float32(DT0, env-fp_status); +RETURN(); +} + +void OPPROTO op_fsqrt_FT(void) +{ +FT0 = float32_sqrt(FT0, env-fp_status); +RETURN(); +} + +void OPPROTO op_fsqrt_DT(void) +{ +DT0 = float64_sqrt(DT0, env-fp_status); +RETURN(); +} + void OPPROTO op_fmov_T0_frN(void) { -*(unsigned int *)env-fregs[PARAM1] = T0; +*(uint32_t *)env-fregs[PARAM1] = T0; RETURN(); } diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 0c66e0b..0aacc98 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -268,11 +268,11 @@ void _decode_opc(DisasContext * ctx) case 0x0018: /* sett */ gen_op_sett(); return; -case 0xfbfb: /* frchg */ +case 0xfbfd: /* frchg */ gen_op_frchg(); ctx-bstate = BS_STOP; return; -case 0xf3fb: /* fschg */ +case 0xf3fd: /* fschg */ gen_op_fschg(); ctx-bstate = BS_STOP; return; @@ -296,7 +296,7 @@ void _decode_opc(DisasContext * ctx) gen_op_ldl_T0_T0(ctx); gen_op_movl_T0_rN(REG(B11_8)); return; -case 0xe000: /* mov.l #imm,Rn */ +case 0xe000: /* mov #imm,Rn */ gen_op_movl_imm_rN(B7_0s, REG(B11_8)); return; case 0x9000: /* mov.w
[Qemu-devel] [PATCH] linux-user, Add missing break just before execve.
Small patch around execve again. Now unlinkat() goes through into execve. Here is the fix. /yoshii diff -u -p -r1.157 syscall.c --- a/linux-user/syscall.c 9 Dec 2007 23:12:55 - 1.157 +++ b/linux-user/syscall.c 11 Dec 2007 17:02:11 - @@ -3177,6 +3176,7 @@ abi_long do_syscall(void *cpu_env, int n goto efault; ret = get_errno(sys_unlinkat(arg1, p, arg3)); unlock_user(p, arg2, 0); +break; #endif case TARGET_NR_execve: {
[Qemu-devel] [PATCH] SH4, Add more float instructions.
Hi, I found some instructions missing on SH4, and added some. Graphics extentions(like sin/cos/sqrt/vector op) are still missing, but I believe no one need them, at least, so far. fneg is implemented as 32bit op, according to the programming manual. /yoshii diff -u -p -r1.10 op.c --- a/target-sh4/op.c 2 Dec 2007 06:18:24 - 1.10 +++ b/target-sh4/op.c 11 Dec 2007 17:24:31 - @@ -797,6 +797,36 @@ void OPPROTO op_ftrc_DT(void) RETURN(); } +void OPPROTO op_fneg_frN(void) +{ +env-fregs[PARAM1] = float32_chs(env-fregs[PARAM1]); +RETURN(); +} + +void OPPROTO op_fabs_FT(void) +{ +FT0 = float32_abs(FT0); +RETURN(); +} + +void OPPROTO op_fabs_DT(void) +{ +DT0 = float64_abs(DT0); +RETURN(); +} + +void OPPROTO op_fcnvsd_DT(void) +{ +DT0 = float32_to_float64(env-fpul, env-fp_status); +RETURN(); +} + +void OPPROTO op_fcnvds_DT(void) +{ +env-fpul = float64_to_float32(DT0, env-fp_status); +RETURN(); +} + void OPPROTO op_fmov_T0_frN(void) { *(unsigned int *)env-fregs[PARAM1] = T0; diff -u -p -r1.21 translate.c --- a/target-sh4/translate.c2 Dec 2007 06:10:04 - 1.21 +++ b/target-sh4/translate.c11 Dec 2007 17:24:31 - @@ -1123,6 +1123,23 @@ void _decode_opc(DisasContext * ctx) gen_op_ftrc_FT(); } return; +case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ + gen_op_fneg_frN(FREG(B11_8)); + return; +case 0xf05d: /* fabs FRn/DRn */ + if (ctx-fpscr FPSCR_PR) { + if (ctx-opcode 0x0100) + break; /* illegal instruction */ + gen_op_fmov_drN_DT0(DREG(B11_8)); + gen_op_fabs_DT(); + gen_op_fmov_DT0_drN(DREG(B11_8)); + } + else { + gen_op_fmov_frN_FT0(FREG(B11_8)); + gen_op_fabs_FT(); + gen_op_fmov_FT0_frN(FREG(B11_8)); + } + return; case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ if (!(ctx-fpscr FPSCR_PR)) { gen_op_movl_imm_T0(0); @@ -1137,6 +1154,14 @@ void _decode_opc(DisasContext * ctx) return; } break; +case 0xf0ad: /* cnvsd FPUL,DRn */ + gen_op_fcnvsd_DT(); + gen_op_fmov_DT0_drN(DREG(B11_8)); + return; +case 0xf0bd: /* cnvds DRn,FPUL */ + gen_op_fmov_drN_DT0(DREG(B11_8)); + gen_op_fcnvds_DT(); + return; } fprintf(stderr, unknown instruction 0x%04x at pc 0x%08x\n,
[Qemu-devel] [PATCH] linux-user, Fix execve argc/envc counting.
In execve code for linux-user emulation, address increment steps seems to be wrong when counting argc/envc. /yoshii Index: linux-user/syscall.c === RCS file: /sources/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.156 diff -u -p -r1.156 syscall.c --- a/linux-user/syscall.c 9 Dec 2007 02:37:05 - 1.156 +++ b/linux-user/syscall.c 9 Dec 2007 20:44:05 - @@ -3190,7 +3189,7 @@ abi_long do_syscall(void *cpu_env, int n argc = 0; guest_argp = arg2; -for (gp = guest_argp; ; gp++) { +for (gp = guest_argp; ; gp += sizeof(abi_ulong)) { if (get_user_ual(addr, gp)) goto efault; if (!addr) @@ -3199,7 +3198,7 @@ abi_long do_syscall(void *cpu_env, int n } envc = 0; guest_envp = arg3; -for (gp = guest_envp; ; gp++) { +for (gp = guest_envp; ; gp += sizeof(abi_ulong)) { if (get_user_ual(addr, gp)) goto efault; if (!addr)