[PATCH] linux-user: target: signal: Support TARGET_SS_AUTODISARM

2020-10-07 Thread chengang
From: Chen Gang 

Add definitions to pass building.

Signed-off-by: Chen Gang 
---
 linux-user/alpha/target_signal.h  | 6 ++
 linux-user/hppa/target_signal.h   | 5 +
 linux-user/mips/target_signal.h   | 6 ++
 linux-user/mips64/target_signal.h | 5 +
 linux-user/sparc/target_signal.h  | 6 ++
 5 files changed, 28 insertions(+)

diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h
index cd63d59fde..241e207815 100644
--- a/linux-user/alpha/target_signal.h
+++ b/linux-user/alpha/target_signal.h
@@ -93,4 +93,10 @@ typedef struct target_sigaltstack {
 #define TARGET_GEN_SUBRNG7 -25
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+
+/* bit-flags */
+#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+/* mask for all SS_xxx flags */
+#define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
+
 #endif /* ALPHA_TARGET_SIGNAL_H */
diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h
index c2a0102ed7..2c9d4e611e 100644
--- a/linux-user/hppa/target_signal.h
+++ b/linux-user/hppa/target_signal.h
@@ -66,4 +66,9 @@ typedef struct target_sigaltstack {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_SIGSTKSZ8192
 
+/* bit-flags */
+#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+/* mask for all SS_xxx flags */
+#define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
+
 #endif /* HPPA_TARGET_SIGNAL_H */
diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h
index 66e1ad44a6..4fdf15e279 100644
--- a/linux-user/mips/target_signal.h
+++ b/linux-user/mips/target_signal.h
@@ -73,4 +73,10 @@ typedef struct target_sigaltstack {
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+
+/* bit-flags */
+#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+/* mask for all SS_xxx flags */
+#define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
+
 #endif /* MIPS_TARGET_SIGNAL_H */
diff --git a/linux-user/mips64/target_signal.h 
b/linux-user/mips64/target_signal.h
index 753e91fbd6..93c64df3b7 100644
--- a/linux-user/mips64/target_signal.h
+++ b/linux-user/mips64/target_signal.h
@@ -68,4 +68,9 @@ typedef struct target_sigaltstack {
 #define TARGET_MINSIGSTKSZ2048
 #define TARGET_SIGSTKSZ   8192
 
+/* bit-flags */
+#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+/* mask for all SS_xxx flags */
+#define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
+
 #endif /* MIPS64_TARGET_SIGNAL_H */
diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h
index 5cc40327d2..a465d699d2 100644
--- a/linux-user/sparc/target_signal.h
+++ b/linux-user/sparc/target_signal.h
@@ -68,4 +68,10 @@ typedef struct target_sigaltstack {
 #define TARGET_SIGSTKSZ16384
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+
+/* bit-flags */
+#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+/* mask for all SS_xxx flags */
+#define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
+
 #endif /* SPARC_TARGET_SIGNAL_H */
-- 
2.24.0.308.g228f53135a






[PATCH] linux-user: signal: Support TARGET_SS_AUTODISARM

2020-10-07 Thread chengang
From: Chen Gang 

Microsoft sqlserver 2017 x86_64 uses it. The implementation references
from the linux kernel.

Signed-off-by: Chen Gang 
---
 linux-user/generic/signal.h |  6 ++
 linux-user/signal.c | 23 ++-
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/linux-user/generic/signal.h b/linux-user/generic/signal.h
index e1083f8fba..943bc1a1e2 100644
--- a/linux-user/generic/signal.h
+++ b/linux-user/generic/signal.h
@@ -54,4 +54,10 @@
 #define TARGET_SIG_BLOCK  0/* for blocking signals */
 #define TARGET_SIG_UNBLOCK1/* for unblocking signals */
 #define TARGET_SIG_SETMASK2/* for setting the signal mask */
+
+/* bit-flags */
+#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+/* mask for all SS_xxx flags */
+#define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
+
 #endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 8cf51ffecd..b5f04ae160 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -263,6 +263,10 @@ int on_sig_stack(unsigned long sp)
 {
 TaskState *ts = (TaskState *)thread_cpu->opaque;
 
+if (ts->sigaltstack_used.ss_flags & TARGET_SS_AUTODISARM) {
+return 0;
+}
+
 return (sp - ts->sigaltstack_used.ss_sp
 < ts->sigaltstack_used.ss_size);
 }
@@ -293,8 +297,13 @@ void target_save_altstack(target_stack_t *uss, 
CPUArchState *env)
 TaskState *ts = (TaskState *)thread_cpu->opaque;
 
 __put_user(ts->sigaltstack_used.ss_sp, >ss_sp);
-__put_user(sas_ss_flags(get_sp_from_cpustate(env)), >ss_flags);
+__put_user(ts->sigaltstack_used.ss_flags, >ss_flags);
 __put_user(ts->sigaltstack_used.ss_size, >ss_size);
+if (ts->sigaltstack_used.ss_flags & TARGET_SS_AUTODISARM) {
+ts->sigaltstack_used.ss_sp = 0;
+ts->sigaltstack_used.ss_size = 0;
+ts->sigaltstack_used.ss_flags = TARGET_SS_DISABLE;
+}
 }
 
 /* siginfo conversion */
@@ -768,7 +777,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong 
uoss_addr, abi_ulong sp)
 {
 __put_user(ts->sigaltstack_used.ss_sp, _sp);
 __put_user(ts->sigaltstack_used.ss_size, _size);
-__put_user(sas_ss_flags(sp), _flags);
+__put_user(ts->sigaltstack_used.ss_flags, _flags);
 }
 
 if(uss_addr)
@@ -776,6 +785,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong 
uoss_addr, abi_ulong sp)
 struct target_sigaltstack *uss;
 struct target_sigaltstack ss;
 size_t minstacksize = TARGET_MINSIGSTKSZ;
+int ss_mode;
 
 #if defined(TARGET_PPC64)
 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
@@ -799,10 +809,12 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong 
uoss_addr, abi_ulong sp)
 goto out;
 
 ret = -TARGET_EINVAL;
-if (ss.ss_flags != TARGET_SS_DISABLE
-&& ss.ss_flags != TARGET_SS_ONSTACK
-&& ss.ss_flags != 0)
+ss_mode = ss.ss_flags & ~TARGET_SS_FLAG_BITS;
+if (ss_mode != TARGET_SS_DISABLE
+&& ss_mode != TARGET_SS_ONSTACK
+&& ss_mode != 0) {
 goto out;
+}
 
 if (ss.ss_flags == TARGET_SS_DISABLE) {
 ss.ss_size = 0;
@@ -814,6 +826,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong 
uoss_addr, abi_ulong sp)
 }
 }
 
+ts->sigaltstack_used.ss_flags = ss.ss_flags;
 ts->sigaltstack_used.ss_sp = ss.ss_sp;
 ts->sigaltstack_used.ss_size = ss.ss_size;
 }
-- 
2.24.0.308.g228f53135a






[PATCH] linux-user: i386: Use trapnr which returns from cpu_exec() instead of exception_index

2020-09-26 Thread chengang
From: Chen Gang 

After return from cpu_exec(), the exception_index is already set 0 in
cpu_handle_exception(), so we need the trapnr which returns from
cpu_exec() for trapno of target sigcontext.

Signed-off-by: Chen Gang 
---
 include/hw/core/cpu.h  |  2 ++
 linux-user/i386/cpu_loop.c | 15 +++
 linux-user/i386/signal.c   |  4 ++--
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 8f145733ce..390e27d9e1 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -458,6 +458,8 @@ struct CPUState {
 
 /* track IOMMUs whose translations we've cached in the TCG TLB */
 GArray *iommu_notifiers;
+
+int trapnr;
 };
 
 typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 70cde417e6..f0db088221 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -198,17 +198,16 @@ static void emulate_vsyscall(CPUX86State *env)
 void cpu_loop(CPUX86State *env)
 {
 CPUState *cs = env_cpu(env);
-int trapnr;
 abi_ulong pc;
 abi_ulong ret;
 
 for(;;) {
 cpu_exec_start(cs);
-trapnr = cpu_exec(cs);
+cs->trapnr = cpu_exec(cs);
 cpu_exec_end(cs);
 process_queued_cpu_work(cs);
 
-switch(trapnr) {
+switch (cs->trapnr) {
 case 0x80:
 /* linux syscall from int $0x80 */
 ret = do_syscall(env,
@@ -273,7 +272,7 @@ void cpu_loop(CPUX86State *env)
 case EXCP00_DIVZ:
 #ifndef TARGET_X86_64
 if (env->eflags & VM_MASK) {
-handle_vm86_trap(env, trapnr);
+handle_vm86_trap(env, cs->trapnr);
 break;
 }
 #endif
@@ -283,11 +282,11 @@ void cpu_loop(CPUX86State *env)
 case EXCP03_INT3:
 #ifndef TARGET_X86_64
 if (env->eflags & VM_MASK) {
-handle_vm86_trap(env, trapnr);
+handle_vm86_trap(env, cs->trapnr);
 break;
 }
 #endif
-if (trapnr == EXCP01_DB) {
+if (cs->trapnr == EXCP01_DB) {
 gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
 } else {
 gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0);
@@ -297,7 +296,7 @@ void cpu_loop(CPUX86State *env)
 case EXCP05_BOUND:
 #ifndef TARGET_X86_64
 if (env->eflags & VM_MASK) {
-handle_vm86_trap(env, trapnr);
+handle_vm86_trap(env, cs->trapnr);
 break;
 }
 #endif
@@ -318,7 +317,7 @@ void cpu_loop(CPUX86State *env)
 default:
 pc = env->segs[R_CS].base + env->eip;
 EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x - 
aborting\n",
-  (long)pc, trapnr);
+  (long)pc, cs->trapnr);
 abort();
 }
 process_pending_signals(env);
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 97a39204cc..c184d28d22 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -215,7 +215,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
 __put_user(env->regs[R_EDX], >edx);
 __put_user(env->regs[R_ECX], >ecx);
 __put_user(env->regs[R_EAX], >eax);
-__put_user(cs->exception_index, >trapno);
+__put_user(cs->trapnr, >trapno);
 __put_user(env->error_code, >err);
 __put_user(env->eip, >eip);
 __put_user(env->segs[R_CS].selector, (unsigned int *)>cs);
@@ -251,7 +251,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
 __put_user(env->regs[14], >r14);
 __put_user(env->regs[15], >r15);
 
-__put_user(cs->exception_index, >trapno);
+__put_user(cs->trapnr, >trapno);
 __put_user(env->error_code, >err);
 __put_user(env->eip, >rip);
 
-- 
2.24.0.308.g228f53135a






[PATCH v2] linux-user: syscall: ioctls: support DRM_IOCTL_I915_GETPARAM

2020-08-02 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_I915 patches will be sent next.

Signed-off-by: Chen Gang 
---
 linux-user/ioctls.h|  3 +++
 linux-user/syscall.c   | 35 +++
 linux-user/syscall_defs.h  |  8 
 linux-user/syscall_types.h |  4 
 4 files changed, 50 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0713ae1311..e2fc09b5a5 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -581,6 +581,9 @@
 #ifdef HAVE_DRM_H
   IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
 MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+
+  IOCTL_SPECIAL(DRM_IOCTL_I915_GETPARAM, IOC_RW, do_ioctl_drm_i915,
+MK_PTR(MK_STRUCT(STRUCT_drm_i915_getparam)))
 #endif
 
 #ifdef TARGET_TIOCSTART
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 945fc25279..b0e15f373c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -114,6 +114,7 @@
 #include 
 #ifdef HAVE_DRM_H
 #include 
+#include 
 #endif
 #include "linux_loop.h"
 #include "uname.h"
@@ -5413,6 +5414,40 @@ static abi_long do_ioctl_drm(const IOCTLEntry *ie, 
uint8_t *buf_temp,
 return -TARGET_ENOSYS;
 }
 
+static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
+   struct drm_i915_getparam *gparam,
+   int fd, abi_long arg)
+{
+abi_long ret;
+int value;
+struct target_drm_i915_getparam *target_gparam;
+
+if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
+return -TARGET_EFAULT;
+}
+
+__get_user(gparam->param, _gparam->param);
+gparam->value = 
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
+put_user_s32(value, target_gparam->value);
+
+unlock_user_struct(target_gparam, arg, 0);
+return ret;
+}
+
+static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
+  int fd, int cmd, abi_long arg)
+{
+switch (ie->host_cmd) {
+case DRM_IOCTL_I915_GETPARAM:
+return do_ioctl_drm_i915_getparam(ie,
+  (struct drm_i915_getparam *)buf_temp,
+  fd, arg);
+default:
+return -TARGET_ENOSYS;
+}
+}
+
 #endif
 
 IOCTLEntry ioctl_entries[] = {
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 3c261cff0e..5a1692aa26 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1170,6 +1170,9 @@ struct target_rtc_pll_info {
 /* drm ioctls */
 #define TARGET_DRM_IOCTL_VERSION  TARGET_IOWRU('d', 0x00)
 
+/* drm i915 ioctls */
+#define TARGET_DRM_IOCTL_I915_GETPARAM  TARGET_IOWRU('d', 0x46)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
@@ -2613,6 +2616,11 @@ struct target_drm_version {
 abi_ulong desc;
 };
 
+struct target_drm_i915_getparam {
+int param;
+abi_ulong value;
+};
+
 #include "socket.h"
 
 #include "errno_defs.h"
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 3f1f033464..12bf3484e2 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -325,6 +325,10 @@ STRUCT(drm_version,
TYPE_ULONG, /* desc_len */
TYPE_PTRVOID) /* desc */
 
+STRUCT(drm_i915_getparam,
+   TYPE_INT, /* param */
+   TYPE_PTRVOID) /* value */
+
 STRUCT(file_clone_range,
TYPE_LONGLONG, /* src_fd */
TYPE_ULONGLONG, /* src_offset */
-- 
2.24.0.308.g228f53135a






[PATCH] linux-user: syscall: ioctls: support DRM_IOCTL_I915_GETPARAM

2020-07-11 Thread chengang
From: Chen Gang 

It is for i915 drm command, and next, I shall send another i915 commands
implementations.

Signed-off-by: Chen Gang 
---
 linux-user/ioctls.h|  3 +++
 linux-user/syscall.c   | 39 ++
 linux-user/syscall_defs.h  |  9 +
 linux-user/syscall_types.h |  4 
 4 files changed, 55 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index f2e2fa9c87..83e045deba 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -577,6 +577,9 @@
 #ifdef HAVE_DRM_H
   IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
 MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+
+  IOCTL_SPECIAL(DRM_IOCTL_I915_GETPARAM, IOC_RW, do_ioctl_drm_i915,
+MK_PTR(MK_STRUCT(STRUCT_drm_i915_getparam)))
 #endif
 
 #ifdef TARGET_TIOCSTART
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 17ed7f8d6b..6fab9064af 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -114,6 +114,7 @@
 #include 
 #ifdef HAVE_DRM_H
 #include 
+#include 
 #endif
 #include "linux_loop.h"
 #include "uname.h"
@@ -5372,6 +5373,44 @@ static abi_long do_ioctl_drm(const IOCTLEntry *ie, 
uint8_t *buf_temp,
 return -TARGET_ENOSYS;
 }
 
+static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
+   struct drm_i915_getparam *gparam,
+   int fd, abi_long arg)
+{
+abi_long ret;
+struct target_drm_i915_getparam *target_gparam;
+
+if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
+return -TARGET_EFAULT;
+}
+__get_user(gparam->param, _gparam->param);
+gparam->value = lock_user(VERIFY_WRITE, target_gparam->value,
+ sizeof(*gparam->value), 0);
+if (!gparam->value) {
+unlock_user_struct(target_gparam, arg, 0);
+return -TARGET_EFAULT;
+}
+
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
+
+unlock_user(gparam->value, target_gparam->value, sizeof(*gparam->value));
+unlock_user_struct(target_gparam, arg, 0);
+return ret;
+}
+
+static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
+  int fd, int cmd, abi_long arg)
+{
+switch (ie->host_cmd) {
+case DRM_IOCTL_I915_GETPARAM:
+return do_ioctl_drm_i915_getparam(ie,
+  (struct drm_i915_getparam *)buf_temp,
+  fd, arg);
+default:
+return -TARGET_ENOSYS;
+}
+}
+
 #endif
 
 static IOCTLEntry ioctl_entries[] = {
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 3c261cff0e..9082f6c2bc 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1170,6 +1170,9 @@ struct target_rtc_pll_info {
 /* drm ioctls */
 #define TARGET_DRM_IOCTL_VERSION  TARGET_IOWRU('d', 0x00)
 
+/* drm i915 ioctls */
+#define TARGET_DRM_IOCTL_I915_GETPARAM  TARGET_IOWRU('d', 0x46)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
@@ -2613,6 +2616,12 @@ struct target_drm_version {
 abi_ulong desc;
 };
 
+struct target_drm_i915_getparam {
+int param;
+abi_ulong value;
+};
+
+
 #include "socket.h"
 
 #include "errno_defs.h"
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index e2b0484f50..ef60d5f38c 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -303,6 +303,10 @@ STRUCT(drm_version,
TYPE_ULONG, /* desc_len */
TYPE_PTRVOID) /* desc */
 
+STRUCT(drm_i915_getparam,
+   TYPE_INT, /* param */
+   TYPE_PTRVOID) /* value */
+
 STRUCT(file_clone_range,
TYPE_LONGLONG, /* src_fd */
TYPE_ULONGLONG, /* src_offset */
-- 
2.24.0.308.g228f53135a






[PATCH] target: i386: mem_helper: Fix ldaxr instruction 64 bit alignment issue temporarily for stable-4.1

2020-07-11 Thread chengang
From: Chen Gang 

This fix does not consider about the lock feature which may cause
another issues, but excuse me, I don't know how to fix it. At present,
the fix runs OK for my case in windows oledb32.dll in wine.

Welcome anyone to fix it, thanks.

Signed-off-by: Chen Gang 
---
 target/i386/mem_helper.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c
index d50d4b0c40..8c37b05fae 100644
--- a/target/i386/mem_helper.c
+++ b/target/i386/mem_helper.c
@@ -68,7 +68,13 @@ void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
 uint64_t *haddr = g2h(a0);
 cmpv = cpu_to_le64(cmpv);
 newv = cpu_to_le64(newv);
-oldv = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
+if ((unsigned long)haddr % 8) {
+volatile uint64_t tmp = *haddr; /* avoid compiler optimization */
+oldv = atomic_cmpxchg__nocheck(, cmpv, newv);
+*haddr = tmp;
+} else {
+oldv = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
+}
 oldv = le64_to_cpu(oldv);
 }
 #else
-- 
2.24.0.308.g228f53135a






[PATCH v7] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-06-04 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 configure  | 10 
 linux-user/ioctls.h|  5 ++
 linux-user/syscall.c   | 98 ++
 linux-user/syscall_defs.h  | 15 ++
 linux-user/syscall_types.h | 11 +
 5 files changed, 139 insertions(+)

diff --git a/configure b/configure
index f087d2bcd1..389dbb1d09 100755
--- a/configure
+++ b/configure
@@ -3136,6 +3136,13 @@ if ! check_include "ifaddrs.h" ; then
   have_ifaddrs_h=no
 fi
 
+#
+# libdrm check
+have_drm_h=no
+if check_include "libdrm/drm.h" ; then
+have_drm_h=yes
+fi
+
 ##
 # VTE probe
 
@@ -7127,6 +7134,9 @@ fi
 if test "$have_ifaddrs_h" = "yes" ; then
 echo "HAVE_IFADDRS_H=y" >> $config_host_mak
 fi
+if test "$have_drm_h" = "yes" ; then
+  echo "HAVE_DRM_H=y" >> $config_host_mak
+fi
 if test "$have_broken_size_max" = "yes" ; then
 echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak
 fi
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..f2e2fa9c87 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,11 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+#ifdef HAVE_DRM_H
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+#endif
+
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7f6700c54e..c0515c4378 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,9 @@
 #include 
 #include 
 #include 
+#ifdef HAVE_DRM_H
+#include 
+#endif
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5276,6 +5279,101 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+#ifdef HAVE_DRM_H
+
+static void unlock_drm_version(struct drm_version *host_ver,
+   struct target_drm_version *target_ver,
+   bool copy)
+{
+unlock_user(host_ver->name, target_ver->name,
+copy ? host_ver->name_len : 0);
+unlock_user(host_ver->date, target_ver->date,
+copy ? host_ver->date_len : 0);
+unlock_user(host_ver->desc, target_ver->desc,
+copy ? host_ver->desc_len : 0);
+}
+
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+  struct target_drm_version 
*target_ver)
+{
+memset(host_ver, 0, sizeof(*host_ver));
+
+__get_user(host_ver->name_len, _ver->name_len);
+if (host_ver->name_len) {
+host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
+   target_ver->name_len, 0);
+if (!host_ver->name) {
+return -EFAULT;
+}
+}
+
+__get_user(host_ver->date_len, _ver->date_len);
+if (host_ver->date_len) {
+host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
+   target_ver->date_len, 0);
+if (!host_ver->date) {
+goto err;
+}
+}
+
+__get_user(host_ver->desc_len, _ver->desc_len);
+if (host_ver->desc_len) {
+host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
+   target_ver->desc_len, 0);
+if (!host_ver->desc) {
+goto err;
+}
+}
+
+return 0;
+err:
+unlock_drm_version(host_ver, target_ver, false);
+return -EFAULT;
+}
+
+static inline void host_to_target_drmversion(
+  struct target_drm_version 
*target_ver,
+  struct drm_version *host_ver)
+{
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+__put_user(host_ver->name_len, _ver->name_len);
+__put_user(host_ver->date_len, _ver->date_len);
+__put_user(host_ver->desc_len, _ver->desc_len);
+unlock_drm_version(host_ver, target_ver, true);
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+struct target_drm_version *target_ver;
+abi_long ret;
+
+switch (ie->host_cmd) {
+case DRM_IOCTL_VERSION:
+if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
+return -TARGET_EFAULT;
+}
+ver = (struct drm_version *)buf_temp;
+ret = target_to_host_drmversion(ver, target_ver);
+if (!is_error(ret)) {
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
+if (is_error(ret)) {
+unlock_drm_version(ver, 

[PATCH] [PATCH v6] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-06-03 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 configure  | 10 
 linux-user/ioctls.h|  5 ++
 linux-user/syscall.c   | 95 ++
 linux-user/syscall_defs.h  | 15 ++
 linux-user/syscall_types.h | 11 +
 5 files changed, 136 insertions(+)

diff --git a/configure b/configure
index f087d2bcd1..389dbb1d09 100755
--- a/configure
+++ b/configure
@@ -3136,6 +3136,13 @@ if ! check_include "ifaddrs.h" ; then
   have_ifaddrs_h=no
 fi
 
+#
+# libdrm check
+have_drm_h=no
+if check_include "libdrm/drm.h" ; then
+have_drm_h=yes
+fi
+
 ##
 # VTE probe
 
@@ -7127,6 +7134,9 @@ fi
 if test "$have_ifaddrs_h" = "yes" ; then
 echo "HAVE_IFADDRS_H=y" >> $config_host_mak
 fi
+if test "$have_drm_h" = "yes" ; then
+  echo "HAVE_DRM_H=y" >> $config_host_mak
+fi
 if test "$have_broken_size_max" = "yes" ; then
 echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak
 fi
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..f2e2fa9c87 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,11 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+#ifdef HAVE_DRM_H
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+#endif
+
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7f6700c54e..1744e7acc7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,9 @@
 #include 
 #include 
 #include 
+#ifdef HAVE_DRM_H
+#include 
+#endif
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5276,6 +5279,98 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+#ifdef HAVE_DRM_H
+
+static void unlock_drm_version(struct drm_version *host_ver)
+{
+unlock_user(host_ver->name, 0UL, 0);
+unlock_user(host_ver->date, 0UL, 0);
+unlock_user(host_ver->desc, 0UL, 0);
+}
+
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+  struct target_drm_version 
*target_ver)
+{
+memset(host_ver, 0, sizeof(*host_ver));
+
+__get_user(host_ver->name_len, _ver->name_len);
+if (host_ver->name_len) {
+host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
+   target_ver->name_len, 0);
+if (!host_ver->name) {
+goto err;
+}
+}
+
+__get_user(host_ver->date_len, _ver->date_len);
+if (host_ver->date_len) {
+host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
+   target_ver->date_len, 0);
+if (!host_ver->date) {
+goto err;
+}
+}
+
+__get_user(host_ver->desc_len, _ver->desc_len);
+if (host_ver->desc_len) {
+host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
+   target_ver->desc_len, 0);
+if (!host_ver->desc) {
+goto err;
+}
+}
+
+return 0;
+err:
+unlock_drm_version(host_ver);
+return -EFAULT;
+}
+
+static inline abi_long host_to_target_drmversion(
+  struct target_drm_version 
*target_ver,
+  struct drm_version *host_ver)
+{
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+__put_user(host_ver->name_len, _ver->name_len);
+__put_user(host_ver->date_len, _ver->date_len);
+__put_user(host_ver->desc_len, _ver->desc_len);
+unlock_user(host_ver->name, target_ver->name, host_ver->name_len);
+unlock_user(host_ver->date, target_ver->date, host_ver->date_len);
+unlock_user(host_ver->desc, target_ver->desc, host_ver->desc_len);
+return 0;
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+struct target_drm_version *target_ver;
+abi_long ret;
+
+switch (ie->host_cmd) {
+case DRM_IOCTL_VERSION:
+if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
+return -TARGET_EFAULT;
+}
+ver = (struct drm_version *)buf_temp;
+ret = target_to_host_drmversion(ver, target_ver);
+if (!is_error(ret)) {
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
+if (!is_error(ret)) {
+ret = host_to_target_drmversion(target_ver, ver);
+}
+unlock_drm_version(ver);
+}
+unlock_user_struct(target_ver, arg, 0);
+return ret;
+}
+return 

[PATCH v5] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-06-02 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 configure  |  10 
 linux-user/ioctls.h|   5 ++
 linux-user/syscall.c   | 117 +
 linux-user/syscall_defs.h  |  15 +
 linux-user/syscall_types.h |  11 
 5 files changed, 158 insertions(+)

diff --git a/configure b/configure
index e225a1e3ff..3cf28a649a 100755
--- a/configure
+++ b/configure
@@ -3140,6 +3140,13 @@ if ! check_include "ifaddrs.h" ; then
   have_ifaddrs_h=no
 fi
 
+#
+# libdrm check
+have_drm_h=no
+if check_include "libdrm/drm.h" ; then
+have_drm_h=yes
+fi
+
 ##
 # VTE probe
 
@@ -7149,6 +7156,9 @@ fi
 if test "$have_ifaddrs_h" = "yes" ; then
 echo "HAVE_IFADDRS_H=y" >> $config_host_mak
 fi
+if test "$have_drm_h" = "yes" ; then
+  echo "HAVE_DRM_H=y" >> $config_host_mak
+fi
 if test "$have_broken_size_max" = "yes" ; then
 echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak
 fi
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..f2e2fa9c87 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,11 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+#ifdef HAVE_DRM_H
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+#endif
+
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5af55fca78..07b7596e0f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,9 @@
 #include 
 #include 
 #include 
+#ifdef HAVE_DRM_H
+#include 
+#endif
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5275,6 +5278,120 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+#ifdef HAVE_DRM_H
+
+static void unlock_drm_version(struct drm_version *host_ver)
+{
+if (host_ver->name) {
+unlock_user(host_ver->name, 0UL, 0);
+}
+if (host_ver->date) {
+unlock_user(host_ver->date, 0UL, 0);
+}
+if (host_ver->desc) {
+unlock_user(host_ver->desc, 0UL, 0);
+}
+}
+
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+abi_long target_addr)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_READ, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+
+memset(host_ver, 0, sizeof(*host_ver));
+
+__get_user(host_ver->name_len, _ver->name_len);
+if (host_ver->name_len) {
+host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
+   target_ver->name_len, 0);
+if (!host_ver->name) {
+goto err;
+}
+}
+
+__get_user(host_ver->date_len, _ver->date_len);
+if (host_ver->date_len) {
+host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
+   target_ver->date_len, 0);
+if (!host_ver->date) {
+goto err;
+}
+}
+
+__get_user(host_ver->desc_len, _ver->desc_len);
+if (host_ver->desc_len) {
+host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
+   target_ver->desc_len, 0);
+if (!host_ver->desc) {
+goto err;
+}
+}
+
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+err:
+unlock_drm_version(host_ver);
+unlock_user_struct(target_ver, target_addr, 0);
+return -ENOMEM;
+}
+
+static inline abi_long host_to_target_drmversion(abi_ulong target_addr,
+ struct drm_version *host_ver)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_WRITE, target_ver, target_addr, 0)) {
+unlock_drm_version(host_ver);
+return -TARGET_EFAULT;
+}
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+__put_user(host_ver->name_len, _ver->name_len);
+__put_user(host_ver->date_len, _ver->date_len);
+__put_user(host_ver->desc_len, _ver->desc_len);
+if (host_ver->name) {
+unlock_user(host_ver->name, target_ver->name, host_ver->name_len);
+}
+if (host_ver->date) {
+unlock_user(host_ver->date, target_ver->date, host_ver->date_len);
+}
+if (host_ver->desc) {
+unlock_user(host_ver->desc, target_ver->desc, host_ver->desc_len);
+}
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+abi_long ret;
+
+  

[PATCH v4] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-06-02 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 configure  | 10 ++
 linux-user/ioctls.h|  5 +++
 linux-user/syscall.c   | 67 ++
 linux-user/syscall_defs.h  | 15 +
 linux-user/syscall_types.h | 11 +++
 5 files changed, 108 insertions(+)

diff --git a/configure b/configure
index e225a1e3ff..3cf28a649a 100755
--- a/configure
+++ b/configure
@@ -3140,6 +3140,13 @@ if ! check_include "ifaddrs.h" ; then
   have_ifaddrs_h=no
 fi
 
+#
+# libdrm check
+have_drm_h=no
+if check_include "libdrm/drm.h" ; then
+have_drm_h=yes
+fi
+
 ##
 # VTE probe
 
@@ -7149,6 +7156,9 @@ fi
 if test "$have_ifaddrs_h" = "yes" ; then
 echo "HAVE_IFADDRS_H=y" >> $config_host_mak
 fi
+if test "$have_drm_h" = "yes" ; then
+  echo "HAVE_DRM_H=y" >> $config_host_mak
+fi
 if test "$have_broken_size_max" = "yes" ; then
 echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak
 fi
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..f2e2fa9c87 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,11 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+#ifdef HAVE_DRM_H
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+#endif
+
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5af55fca78..006889cea6 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,9 @@
 #include 
 #include 
 #include 
+#ifdef HAVE_DRM_H
+#include 
+#endif
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5275,6 +5278,70 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+#ifdef HAVE_DRM_H
+
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+abi_long target_addr)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_READ, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__get_user(host_ver->name_len, _ver->name_len);
+host_ver->name = host_ver->name_len ? g2h(target_ver->name) : NULL;
+__get_user(host_ver->date_len, _ver->date_len);
+host_ver->date = host_ver->date_len ? g2h(target_ver->date) : NULL;
+__get_user(host_ver->desc_len, _ver->desc_len);
+host_ver->desc = host_ver->desc_len ? g2h(target_ver->desc) : NULL;
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static inline abi_long host_to_target_drmversion(abi_ulong target_addr,
+ struct drm_version *host_ver)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_WRITE, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+__put_user(host_ver->name_len, _ver->name_len);
+__put_user(host_ver->date_len, _ver->date_len);
+__put_user(host_ver->desc_len, _ver->desc_len);
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+abi_long ret;
+
+switch (ie->host_cmd) {
+case DRM_IOCTL_VERSION:
+ver = (struct drm_version *)buf_temp;
+memset(ver, 0, sizeof(*ver));
+ret = target_to_host_drmversion(ver, arg);
+if (is_error(ret)) {
+return ret;
+}
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
+if (is_error(ret)) {
+return ret;
+}
+ret = host_to_target_drmversion(arg, ver);
+return ret;
+}
+return -TARGET_EFAULT;
+}
+
+#endif
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
 { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 152ec637cb..3c261cff0e 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1167,6 +1167,9 @@ struct target_rtc_pll_info {
 #define TARGET_DM_TARGET_MSG  TARGET_IOWRU(0xfd, 0x0e)
 #define TARGET_DM_DEV_SET_GEOMETRYTARGET_IOWRU(0xfd, 0x0f)
 
+/* drm ioctls */
+#define TARGET_DRM_IOCTL_VERSION  TARGET_IOWRU('d', 0x00)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
@@ -2598,6 +2601,18 @@ struct target_mq_attr {
 abi_long mq_curmsgs;
 };
 
+struct target_drm_version {
+int version_major;
+int version_minor;
+int version_patchlevel;
+

[PATCH v3] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-05-23 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 configure  | 18 +++
 linux-user/ioctls.h|  3 ++
 linux-user/syscall.c   | 61 ++
 linux-user/syscall_defs.h  | 15 ++
 linux-user/syscall_types.h | 11 +++
 5 files changed, 108 insertions(+)

diff --git a/configure b/configure
index e225a1e3ff..2c2c489d1e 100755
--- a/configure
+++ b/configure
@@ -3912,6 +3912,24 @@ EOF
 fi
 fi
 
+#
+# libdrm check
+
+cat > $TMPC << EOF
+#include 
+#include 
+int main(void)
+{
+struct drm_version version;
+ioctl(-1, DRM_IOCTL_VERSION, );
+return 0;
+}
+EOF
+if ! compile_prog "" ; then
+error_exit "libdrm check failed" \
+"Make sure to have the libdrm/drm.h installed."
+fi
+
 ##
 # SHA command probe for modules
 if test "$modules" = yes; then
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..c2294b48a0 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,9 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5af55fca78..de2e1e3de4 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5275,6 +5276,66 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+abi_long target_addr)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_READ, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__get_user(host_ver->name_len, _ver->name_len);
+host_ver->name = host_ver->name_len ? g2h(target_ver->name) : NULL;
+__get_user(host_ver->date_len, _ver->date_len);
+host_ver->date = host_ver->date_len ? g2h(target_ver->date) : NULL;
+__get_user(host_ver->desc_len, _ver->desc_len);
+host_ver->desc = host_ver->desc_len ? g2h(target_ver->desc) : NULL;
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static inline abi_long host_to_target_drmversion(abi_ulong target_addr,
+ struct drm_version *host_ver)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_WRITE, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+__put_user(host_ver->name_len, _ver->name_len);
+__put_user(host_ver->date_len, _ver->date_len);
+__put_user(host_ver->desc_len, _ver->desc_len);
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+abi_long ret;
+
+switch (ie->host_cmd) {
+case DRM_IOCTL_VERSION:
+ver = (struct drm_version *)buf_temp;
+memset(ver, 0, sizeof(*ver));
+ret = target_to_host_drmversion(ver, arg);
+if (is_error(ret)) {
+return ret;
+}
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
+if (is_error(ret)) {
+return ret;
+}
+ret = host_to_target_drmversion(arg, ver);
+return ret;
+}
+return -TARGET_EFAULT;
+}
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
 { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 152ec637cb..3c261cff0e 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1167,6 +1167,9 @@ struct target_rtc_pll_info {
 #define TARGET_DM_TARGET_MSG  TARGET_IOWRU(0xfd, 0x0e)
 #define TARGET_DM_DEV_SET_GEOMETRYTARGET_IOWRU(0xfd, 0x0f)
 
+/* drm ioctls */
+#define TARGET_DRM_IOCTL_VERSION  TARGET_IOWRU('d', 0x00)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
@@ -2598,6 +2601,18 @@ struct target_mq_attr {
 abi_long mq_curmsgs;
 };
 
+struct target_drm_version {
+int version_major;
+int version_minor;
+int version_patchlevel;
+abi_ulong name_len;
+abi_ulong name;
+abi_ulong date_len;
+abi_ulong date;
+abi_ulong desc_len;
+abi_ulong desc;
+};
+
 #include "socket.h"
 
 #include 

[PATCH] linux-user: main: Let each env have its own gdt table

2020-03-31 Thread chengang
From: Chen Gang 

It is a temporary fix for thread LTS which need switch the ldt related
index in gdt table for stable-4.1 branch.

Welcome anyone providing the complete fix.

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 8ffc525195..cad261fc7b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -194,12 +194,17 @@ CPUArchState *cpu_copy(CPUArchState *env)
 CPUArchState *new_env = new_cpu->env_ptr;
 CPUBreakpoint *bp;
 CPUWatchpoint *wp;
+int size = sizeof(uint64_t) * TARGET_GDT_ENTRIES;
 
 /* Reset non arch specific state */
 cpu_reset(new_cpu);
 
 memcpy(new_env, env, sizeof(CPUArchState));
 
+new_env->gdt.base = target_mmap(0, size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+memcpy(g2h(new_env->gdt.base), g2h(env->gdt.base), size);
+
 /* Clone all break/watchpoints.
Note: Once we support ptrace with hw-debug register access, make sure
BP_CPU break/watchpoints are handled correctly on clone. */
-- 
2.24.0.308.g228f53135a






[PATCH v2] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-03-15 Thread chengang
From: Chen Gang 

Another DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 linux-user/ioctls.h|  2 ++
 linux-user/syscall.c   | 62 ++
 linux-user/syscall_defs.h  | 15 +
 linux-user/syscall_types.h | 11 +++
 4 files changed, 90 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..3ae32cbfb1 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,8 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8d27d10807..2eb7c91ab4 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5196,6 +5197,67 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+abi_long target_addr)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_READ, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__get_user(host_ver->name_len, _ver->name_len);
+host_ver->name = host_ver->name_len ? g2h(target_ver->name) : NULL;
+__get_user(host_ver->date_len, _ver->date_len);
+host_ver->date = host_ver->date_len ? g2h(target_ver->date) : NULL;
+__get_user(host_ver->desc_len, _ver->desc_len);
+host_ver->desc = host_ver->desc_len ? g2h(target_ver->desc) : NULL;
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static inline abi_long host_to_target_drmversion(abi_ulong target_addr,
+ struct drm_version *host_ver)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_WRITE, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+__put_user(host_ver->name_len, _ver->name_len);
+__put_user(host_ver->date_len, _ver->date_len);
+__put_user(host_ver->desc_len, _ver->desc_len);
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+abi_long ret;
+
+switch (ie->host_cmd) {
+case DRM_IOCTL_VERSION:
+ver = (struct drm_version *)buf_temp;
+memset(ver, 0, sizeof(*ver));
+ret = target_to_host_drmversion(ver, arg);
+if (is_error(ret)) {
+return ret;
+}
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
+if (is_error(ret)) {
+return ret;
+}
+ret = host_to_target_drmversion(arg, ver);
+return ret;
+}
+return -TARGET_EFAULT;
+}
+
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
 { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 152ec637cb..3c261cff0e 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1167,6 +1167,9 @@ struct target_rtc_pll_info {
 #define TARGET_DM_TARGET_MSG  TARGET_IOWRU(0xfd, 0x0e)
 #define TARGET_DM_DEV_SET_GEOMETRYTARGET_IOWRU(0xfd, 0x0f)
 
+/* drm ioctls */
+#define TARGET_DRM_IOCTL_VERSION  TARGET_IOWRU('d', 0x00)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
@@ -2598,6 +2601,18 @@ struct target_mq_attr {
 abi_long mq_curmsgs;
 };
 
+struct target_drm_version {
+int version_major;
+int version_minor;
+int version_patchlevel;
+abi_ulong name_len;
+abi_ulong name;
+abi_ulong date_len;
+abi_ulong date;
+abi_ulong desc_len;
+abi_ulong desc;
+};
+
 #include "socket.h"
 
 #include "errno_defs.h"
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 4e12c1661e..e2b0484f50 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -292,6 +292,17 @@ STRUCT(dm_target_versions,
 STRUCT(dm_target_msg,
TYPE_ULONGLONG) /* sector */
 
+STRUCT(drm_version,
+   TYPE_INT, /* version_major */
+   TYPE_INT, /* version_minor */
+   TYPE_INT, /* version_patchlevel */
+   TYPE_ULONG, /* name_len */
+   TYPE_PTRVOID, /* name */
+   TYPE_ULONG, /* date_len */
+   TYPE_PTRVOID, /* date */
+   TYPE_ULONG, /* desc_len */
+   TYPE_PTRVOID) /* desc */
+
 

[PATCH] linux-user: syscall: ioctls: support DRM_IOCTL_VERSION

2020-02-26 Thread chengang
From: Chen Gang 

The other DRM_IOCTL_* commands will be done later.

Signed-off-by: Chen Gang 
---
 linux-user/ioctls.h|   3 +
 linux-user/syscall.c   | 134 +
 linux-user/syscall_defs.h  |  16 +
 linux-user/syscall_types.h |  12 
 4 files changed, 165 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 0defa1d8c1..c2294b48a0 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -574,6 +574,9 @@
   IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
 MK_PTR(MK_STRUCT(STRUCT_rtentry)))
 
+  IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
+MK_PTR(MK_STRUCT(STRUCT_drm_version)))
+
 #ifdef TARGET_TIOCSTART
   IOCTL_IGNORE(TIOCSTART)
   IOCTL_IGNORE(TIOCSTOP)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8d27d10807..1f5d48a0b0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -112,6 +112,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5196,6 +5197,139 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry 
*ie, uint8_t *buf_temp,
 }
 #endif
 
+static inline void free_drmversion(struct drm_version *host)
+{
+if (!host) {
+return;
+}
+if (host->name) {
+free(host->name);
+}
+if (host->date) {
+free(host->date);
+}
+if (host->desc) {
+free(host->desc);
+}
+}
+
+static inline bool t2h_drmversion_str(unsigned long *hlen,
+  char **h, abi_ulong *glen)
+{
+__get_user(*hlen, glen);
+if (*hlen) {
+*h = malloc(*hlen + 1);
+if (!*h) {
+return false;
+}
+(*h)[*hlen] = '\0';
+} else {
+*h = NULL;
+}
+return true;
+}
+
+static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
+abi_long target_addr)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_READ, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__get_user(host_ver->name_len, _ver->name_len);
+if (!t2h_drmversion_str(_ver->name_len,
+_ver->name, _ver->name_len)) {
+goto err;
+}
+if (!t2h_drmversion_str(_ver->date_len,
+_ver->date, _ver->date_len)) {
+goto err;
+}
+if (!t2h_drmversion_str(_ver->desc_len,
+_ver->desc, _ver->desc_len)) {
+goto err;
+}
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+
+err:
+free_drmversion(host_ver);
+return -TARGET_ENOMEM;
+}
+
+static inline bool h2t_drmversion_str(int hlen, char *h,
+  abi_ulong *glen, abi_ulong g)
+{
+char *target_str;
+
+if ((hlen > 0) && h) {
+target_str = lock_user(VERIFY_WRITE, g, hlen, 0);
+if (!target_str) {
+return false;
+}
+memcpy(target_str, h, hlen);
+unlock_user(target_str, g, hlen);
+}
+__put_user(hlen, glen);
+return true;
+}
+
+static inline abi_long host_to_target_drmversion(abi_ulong target_addr,
+ struct drm_version *host_ver)
+{
+struct target_drm_version *target_ver;
+
+if (!lock_user_struct(VERIFY_WRITE, target_ver, target_addr, 0)) {
+return -TARGET_EFAULT;
+}
+__put_user(host_ver->version_major, _ver->version_major);
+__put_user(host_ver->version_minor, _ver->version_minor);
+__put_user(host_ver->version_patchlevel, _ver->version_patchlevel);
+if (!h2t_drmversion_str(host_ver->name_len, host_ver->name,
+_ver->name_len, target_ver->name)) {
+return -TARGET_EFAULT;
+}
+if (!h2t_drmversion_str(host_ver->date_len, host_ver->date,
+_ver->date_len, target_ver->date)) {
+return -TARGET_EFAULT;
+}
+if (!h2t_drmversion_str(host_ver->desc_len, host_ver->desc,
+_ver->desc_len, target_ver->desc)) {
+return -TARGET_EFAULT;
+}
+
+unlock_user_struct(target_ver, target_addr, 0);
+return 0;
+}
+
+static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+struct drm_version *ver;
+abi_long ret;
+
+switch (ie->host_cmd) {
+case DRM_IOCTL_VERSION:
+ver = (struct drm_version *)buf_temp;
+memset(ver, 0, sizeof(*ver));
+ret = target_to_host_drmversion(ver, arg);
+if (is_error(ret)) {
+return ret;
+}
+ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
+if (is_error(ret)) {
+free_drmversion(ver);
+return ret;
+}
+ret = host_to_target_drmversion(arg, ver);
+free_drmversion(ver);
+return ret;
+break;
+}
+return 

[PATCH] target: i386: Check float overflow about register stack

2020-02-20 Thread chengang
From: Chen Gang 

The fxam instruction also checks the register stack overflow, which can
be get by the following fstsw instruction. The related code is below, it
works well under real x86_64 hardware, but can not work under qemu-i386.

0006b63c <_CIsqrt>:
   6b63c:   55  push   %ebp
   6b63d:   89 e5   mov%esp,%ebp
   6b63f:   83 ec 44sub$0x44,%esp
   6b642:   dd 1c 24fstpl  (%esp)
   6b645:   9b  fwait
   6b646:   e8 d5 04 00 00  call   6bb20 
   6b64b:   b9 01 00 00 00  mov$0x1,%ecx
   6b650:   d9 e5   fxam
   6b652:   9b df e0fstsw  %ax
   6b655:   66 25 00 45 and$0x4500,%ax
   6b659:   66 3d 00 41 cmp$0x4100,%ax
   6b65d:   74 07   je 6b666 <_CIsqrt+0x2a>
   6b65f:   dd 1c ccfstpl  (%esp,%ecx,8)
   6b662:   9b  fwait
   6b663:   41  inc%ecx
   6b664:   eb ea   jmp6b650 <_CIsqrt+0x14>
   6b666:   89 4d fcmov%ecx,-0x4(%ebp)
   6b669:   e8 b2 0f 00 00  call   6c620 
   6b66e:   8b 4d fcmov-0x4(%ebp),%ecx
   6b671:   dd 1c 24fstpl  (%esp)
   6b674:   49  dec%ecx
   6b675:   dd 04 ccfldl   (%esp,%ecx,8)
   6b678:   83 f9 00cmp$0x0,%ecx
   6b67b:   75 f7   jne6b674 <_CIsqrt+0x38>
   6b67d:   c9  leave
   6b67e:   c3  ret
   6b67f:   90  nop

Signed-off-by: Chen Gang 
---
 target/i386/cpu.h|  1 +
 target/i386/fpu_helper.c | 70 
 2 files changed, 44 insertions(+), 27 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 576f309bbf..3e2b719ab7 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1394,6 +1394,7 @@ typedef struct CPUX86State {
 struct {} start_init_save;
 
 /* FPU state */
+bool foverflow;
 unsigned int fpstt; /* top of stack index */
 uint16_t fpus;
 uint16_t fpuc;
diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
index 99f28f267f..81f3cefe8b 100644
--- a/target/i386/fpu_helper.c
+++ b/target/i386/fpu_helper.c
@@ -91,17 +91,31 @@ void cpu_set_ignne(void)
 }
 #endif
 
+static inline void set_fpstt(CPUX86State *env, unsigned int fpstt,
+ bool pop, bool full)
+{
+env->foverflow = (fpstt > 7) && full; /* clear the original flag */
+if (pop) {
+if (full) {
+env->fptags[env->fpstt] = 1; /* invalidate stack entry */
+}
+env->fpstt = fpstt & 7;
+} else {
+env->fpstt = fpstt & 7;
+if (full) {
+env->fptags[env->fpstt] = 0; /* validate stack entry */
+}
+}
+}
 
 static inline void fpush(CPUX86State *env)
 {
-env->fpstt = (env->fpstt - 1) & 7;
-env->fptags[env->fpstt] = 0; /* validate stack entry */
+set_fpstt(env, env->fpstt - 1, false, true);
 }
 
 static inline void fpop(CPUX86State *env)
 {
-env->fptags[env->fpstt] = 1; /* invalidate stack entry */
-env->fpstt = (env->fpstt + 1) & 7;
+set_fpstt(env, env->fpstt + 1, true, true);
 }
 
 static inline floatx80 helper_fldt(CPUX86State *env, target_ulong ptr,
@@ -211,11 +225,10 @@ void helper_flds_ST0(CPUX86State *env, uint32_t val)
 uint32_t i;
 } u;
 
-new_fpstt = (env->fpstt - 1) & 7;
+new_fpstt = env->fpstt - 1;
 u.i = val;
-env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, >fp_status);
-env->fpstt = new_fpstt;
-env->fptags[new_fpstt] = 0; /* validate stack entry */
+env->fpregs[new_fpstt & 7].d = float32_to_floatx80(u.f, >fp_status);
+set_fpstt(env, new_fpstt, false, true);
 }
 
 void helper_fldl_ST0(CPUX86State *env, uint64_t val)
@@ -226,31 +239,28 @@ void helper_fldl_ST0(CPUX86State *env, uint64_t val)
 uint64_t i;
 } u;
 
-new_fpstt = (env->fpstt - 1) & 7;
+new_fpstt = env->fpstt - 1;
 u.i = val;
-env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, >fp_status);
-env->fpstt = new_fpstt;
-env->fptags[new_fpstt] = 0; /* validate stack entry */
+env->fpregs[new_fpstt & 7].d = float64_to_floatx80(u.f, >fp_status);
+set_fpstt(env, new_fpstt, false, true);
 }
 
 void helper_fildl_ST0(CPUX86State *env, int32_t val)
 {
 int new_fpstt;
 
-new_fpstt = (env->fpstt - 1) & 7;
-env->fpregs[new_fpstt].d = int32_to_floatx80(val, >fp_status);
-env->fpstt = new_fpstt;
-env->fptags[new_fpstt] = 0; /* validate stack entry */
+new_fpstt = env->fpstt - 1;
+env->fpregs[new_fpstt & 7].d = int32_to_floatx80(val, >fp_status);
+set_fpstt(env, new_fpstt, false, true);
 }
 
 void helper_fildll_ST0(CPUX86State *env, int64_t val)
 {
  

[Qemu-devel] [PATCH v6 4/5] target-tilegx/helper-fdouble.c: Implement double floating point

2016-05-14 Thread chengang
From: Chen Gang 

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fdouble.c | 365 +
 1 file changed, 365 insertions(+)
 create mode 100644 target-tilegx/helper-fdouble.c

diff --git a/target-tilegx/helper-fdouble.c b/target-tilegx/helper-fdouble.c
new file mode 100644
index 000..5147583
--- /dev/null
+++ b/target-tilegx/helper-fdouble.c
@@ -0,0 +1,365 @@
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+/*
+ * FDouble instructions implemenation:
+ *
+ * fdouble_unpack_min   ; srca and srcb are float_64 value.
+ *  ; get the min absolute value's mantissa.
+ *  ; move "mantissa >> (exp_max - exp_min)" to dest.
+ *
+ * fdouble_unpack_max   ; srca and srcb are float_64 value.
+ *  ; get the max absolute value's mantissa.
+ *  ; move mantissa to dest.
+ *
+ * fdouble_add_flags; srca and srcb are float_64 value.
+ *  ; calc exp (exp_max), sign, and comp bits for flags.
+ *  ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_sub_flags; srca and srcb are float_64 value.
+ *  ; calc exp (exp_max), sign, and comp bits for flags.
+ *  ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_addsub:  ; dest, srca (max, min mantissa), and srcb (flags).
+ *  ; "dest +/- srca" depend on the add/sub bit of flags.
+ *  ; move result mantissa to dest.
+ *
+ * fdouble_mul_flags:   ; srca and srcb are float_64 value.
+ *  ; calc sign (xor), exp (min + max), and comp bits.
+ *  ; mix sign, exp, and comp bits as flags to dest.
+ *
+ * fdouble_pack1; move srcb (flags) to dest.
+ *
+ * fdouble_pack2; srca, srcb (high, low mantissa), and dest (flags)
+ *  ; normalize and pack result from srca, srcb, and dest.
+ *  ; move result to dest.
+ */
+
+#define TILEGX_F_EXP_DZERO  0x3ff /* Zero exp for double 11-bits */
+#define TILEGX_F_EXP_DMAX   0x7fe /* max exp for double 11-bits */
+#define TILEGX_F_EXP_DUF0x1000/* underflow exp bit for double */
+
+#define TILEGX_F_MAN_HBIT   (1ULL << 59)
+
+#define TILEGX_F_CALC_ADD   1 /* Perform absolute add operation */
+#define TILEGX_F_CALC_SUB   2 /* Perform absolute sub operation */
+#define TILEGX_F_CALC_MUL   3 /* Perform absolute mul operation */
+
+static uint32_t get_f64_exp(float64 d)
+{
+return extract64(float64_val(d), 52, 11);
+}
+
+static uint64_t get_f64_man(float64 d)
+{
+return extract64(float64_val(d), 0, 52);
+}
+
+static uint64_t fr_to_man(float64 d)
+{
+uint64_t val = get_f64_man(d) << 7;
+
+if (get_f64_exp(d)) {
+val |= TILEGX_F_MAN_HBIT; /* Restore HBIT for the next calculation */
+}
+
+return val;
+}
+
+static uint64_t get_fdouble_man(uint64_t n)
+{
+return extract64(n, 0, 60);
+}
+
+static void set_fdouble_man(uint64_t *n, uint64_t man)
+{
+*n = deposit64(*n, 0, 60, man);
+}
+
+static uint64_t get_fdouble_man_of(uint64_t n)
+{
+return test_bit(60, );
+}
+
+static void clear_fdouble_man_of(uint64_t *n)
+{
+return clear_bit(60, n);
+}
+
+static uint32_t get_fdouble_nan(uint64_t n)
+{
+return test_bit(24, );
+}
+
+static void set_fdouble_nan(uint64_t *n)
+{
+set_bit(24, n);
+}
+
+static uint32_t get_fdouble_inf(uint64_t n)
+{
+return test_bit(23, );
+}
+
+static void set_fdouble_inf(uint64_t *n)
+{
+set_bit(23, n);
+}
+
+static uint32_t get_fdouble_calc(uint64_t n)
+{
+return extract32(n, 21, 2);
+}
+
+static void set_fdouble_calc(uint64_t *n, uint32_t calc)
+{
+*n = deposit64(*n, 21, 2, calc);
+}
+
+static uint32_t get_fdouble_sign(uint64_t n)
+{
+return test_bit(20, );
+}
+
+static void set_fdouble_sign(uint64_t *n)
+{
+set_bit(20, n);
+}
+
+static uint32_t get_fdouble_vexp(uint64_t n)
+{
+return extract32(n, 7, 13);
+}
+
+static void set_fdouble_vexp(uint64_t *n, uint32_t vexp)

[Qemu-devel] [PATCH v6 5/5] target-tilegx: Integrate floating pointer implementation

2016-05-14 Thread chengang
From: Chen Gang 

It passes normal building, and related test.

Signed-off-by: Chen Gang 
---
 target-tilegx/Makefile.objs |  3 ++-
 target-tilegx/helper.h  | 12 +
 target-tilegx/translate.c   | 66 ++---
 3 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/target-tilegx/Makefile.objs b/target-tilegx/Makefile.objs
index 0db778f..136ad60 100644
--- a/target-tilegx/Makefile.objs
+++ b/target-tilegx/Makefile.objs
@@ -1 +1,2 @@
-obj-y += cpu.o translate.o helper.o simd_helper.o
+obj-y += cpu.o translate.o helper.o simd_helper.o \
+   helper-fsingle.o helper-fdouble.o
diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h
index 9281d0f..3471fe3 100644
--- a/target-tilegx/helper.h
+++ b/target-tilegx/helper.h
@@ -24,3 +24,15 @@ 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_2(fsingle_add1, i64, i64, i64)
+DEF_HELPER_2(fsingle_sub1, i64, i64, i64)
+DEF_HELPER_2(fsingle_mul1, i64, i64, i64)
+DEF_HELPER_1(fsingle_pack2, i64, i64)
+DEF_HELPER_2(fdouble_unpack_min, i64, i64, i64)
+DEF_HELPER_2(fdouble_unpack_max, i64, i64, i64)
+DEF_HELPER_2(fdouble_add_flags, i64, i64, i64)
+DEF_HELPER_2(fdouble_sub_flags, i64, i64, i64)
+DEF_HELPER_3(fdouble_addsub, i64, i64, i64, i64)
+DEF_HELPER_2(fdouble_mul_flags, i64, i64, i64)
+DEF_HELPER_3(fdouble_pack2, i64, i64, i64, i64)
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 03918eb..c0b64e9 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -599,6 +599,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 }
 qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
 return ret;
+
+case OE_RR_X0(FSINGLE_PACK1):
+case OE_RR_Y0(FSINGLE_PACK1):
+mnemonic = "fsingle_pack1";
+goto done2;
 }
 
 tdest = dest_gr(dc, dest);
@@ -615,9 +620,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 gen_helper_cnttz(tdest, tsrca);
 mnemonic = "cnttz";
 break;
-case OE_RR_X0(FSINGLE_PACK1):
-case OE_RR_Y0(FSINGLE_PACK1):
-return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
 case OE_RR_X1(LD1S):
 memop = MO_SB;
 mnemonic = "ld1s"; /* prefetch_l1_fault */
@@ -736,6 +738,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 return TILEGX_EXCP_OPCODE_UNKNOWN;
 }
 
+done2:
 qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
   reg_names[dest], reg_names[srca]);
 return ret;
@@ -744,13 +747,21 @@ 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 tsrca = load_gr(dc, srca);
-TCGv tsrcb = load_gr(dc, srcb);
+TCGv tdest, tsrca, tsrcb;
 TCGv t0;
 const char *mnemonic;
 
 switch (opext) {
+case OE_RRR(FSINGLE_ADDSUB2, 0, X0):
+mnemonic = "fsingle_addsub2";
+goto done2;
+}
+
+tdest = dest_gr(dc, dest);
+tsrca = load_gr(dc, srca);
+tsrcb = load_gr(dc, srcb);
+
+switch (opext) {
 case OE_RRR(ADDXSC, 0, X0):
 case OE_RRR(ADDXSC, 0, X1):
 gen_saturate_op(tdest, tsrca, tsrcb, tcg_gen_add_tl);
@@ -908,14 +919,37 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned 
opext,
 mnemonic = "exch";
 break;
 case OE_RRR(FDOUBLE_ADDSUB, 0, X0):
+gen_helper_fdouble_addsub(tdest, load_gr(dc, dest), tsrca, tsrcb);
+mnemonic = "fdouble_addsub";
+break;
 case OE_RRR(FDOUBLE_ADD_FLAGS, 0, X0):
+gen_helper_fdouble_add_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_add_flags";
+break;
 case OE_RRR(FDOUBLE_MUL_FLAGS, 0, X0):
+gen_helper_fdouble_mul_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_mul_flags";
+break;
 case OE_RRR(FDOUBLE_PACK1, 0, X0):
+tcg_gen_mov_i64(tdest, tsrcb);
+mnemonic = "fdouble_pack1";
+break;
 case OE_RRR(FDOUBLE_PACK2, 0, X0):
+gen_helper_fdouble_pack2(tdest, load_gr(dc, dest), tsrca, tsrcb);
+mnemonic = "fdouble_pack2";
+break;
 case OE_RRR(FDOUBLE_SUB_FLAGS, 0, X0):
+gen_helper_fdouble_sub_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_sub_flags";
+break;
 case OE_RRR(FDOUBLE_UNPACK_MAX, 0, X0):
+gen_helper_fdouble_unpack_max(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_unpack_max";
+break;
 case OE_RRR(FDOUBLE_UNPACK_MIN, 0, X0):
-return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+

[Qemu-devel] [PATCH v6 1/5] fpu: softfloat: Add normalize_roundpack_float[32|64] functions

2016-05-14 Thread chengang
From: Chen Gang 

normalize_roundpack_float32 is based on (u)int32_to_float32 function to
support float32 packing.

normalize_roundpack_float64 is the special case of roundAndPackFloat64.

Signed-off-by: Chen Gang 
---
 fpu/softfloat.c | 65 +
 include/fpu/softfloat.h | 15 
 2 files changed, 80 insertions(+)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 166c48e..ecdfa7f 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1516,6 +1516,16 @@ float64 uint64_to_float64(uint64_t a, float_status 
*status)
 return roundAndPackFloat64(0, exp - shiftcount, a, status);
 }
 
+/*
+ * The mantissa contents the hide bit (60-bit), which is the special case of
+ * roundAndPackFloat64().
+ */
+float64 normalize_roundpack_float64(flag sign, int_fast16_t exp, uint64_t sig,
+float_status *status)
+{
+return roundAndPackFloat64(sign, exp - 1, sig << 3, status);
+}
+
 /*
 | Returns the result of converting the 64-bit unsigned integer `a'
 | to the quadruple-precision floating-point format.  The conversion is 
performed
@@ -7090,6 +7100,61 @@ float64 uint32_to_float64(uint32_t a, float_status 
*status)
 return int64_to_float64(a, status);
 }
 
+/*
+ * The mantissa contents the hide bit, e.g. exp: 0x9e with sig: 1 means 1.0f.
+ *
+ * It references from int32_to_float32() and uint32_to_float32()
+ */
+float32 normalize_roundpack_float32(flag sign, int_fast16_t exp, uint32_t sig,
+float_status *status)
+{
+uint64_t absa = sig;
+int8_t scount;
+
+if (exp >= 0xff) {
+return packFloat32(sign, 0xFF, 0);
+} else if (exp <= 0) {
+shift32RightJamming(sig, 0 - exp, );
+return packFloat32(sign, 0, sig);
+}
+
+if (sign) {
+if (sig & 0x7FFF) {
+return normalizeRoundAndPackFloat32(1, exp - 2, sig, status);
+}
+if (sig) {
+return packFloat32(1, exp, 0);
+} else {
+return float32_zero;
+}
+}
+
+if (!sig) {
+return float32_zero;
+}
+
+scount = countLeadingZeros64(absa) - 40;
+if (scount >= 0) {
+exp -= 7 + scount + 2;
+if (exp <= 0) {
+return packFloat32(0, 0, absa);
+}
+return packFloat32(0, exp, absa << scount);
+}
+
+scount += 7;
+exp -= scount + 2;
+if (exp <= 0) {
+return packFloat32(0, 0, absa);
+}
+if (scount < 0) {
+shift64RightJamming(absa, 0 - scount, );
+} else {
+absa <<= scount;
+}
+return roundAndPackFloat32(0, exp, absa, status);
+}
+
 uint32_t float32_to_uint32(float32 a, float_status *status)
 {
 int64_t v;
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index c937062..d4246a1 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -409,6 +409,14 @@ int float32_is_signaling_nan( float32 );
 float32 float32_maybe_silence_nan( float32 );
 float32 float32_scalbn(float32, int, float_status *status);
 
+/*
+ * The mantissa contents the hide bit, e.g. exp: 0x9e with sig: 1 means 1.0f.
+ *
+ * It references from int32_to_float32() and uint32_to_float32()
+ */
+float32 normalize_roundpack_float32(flag sign, int_fast16_t exp, uint32_t sig,
+float_status *status);
+
 static inline float32 float32_abs(float32 a)
 {
 /* Note that abs does *not* handle NaN specially, nor does
@@ -521,6 +529,13 @@ int float64_is_signaling_nan( float64 );
 float64 float64_maybe_silence_nan( float64 );
 float64 float64_scalbn(float64, int, float_status *status);
 
+/*
+ * The mantissa contents the hide bit (60-bit), which is the special case of
+ * roundAndPackFloat64().
+ */
+float64 normalize_roundpack_float64(flag sign, int_fast16_t exp, uint64_t sig,
+float_status *status);
+
 static inline float64 float64_abs(float64 a)
 {
 /* Note that abs does *not* handle NaN specially, nor does
-- 
1.9.3




[Qemu-devel] [PATCH v6 2/5] target-tilegx/helper-fshared.h: Add floating point shared function

2016-05-14 Thread chengang
From: Chen Gang 

It is used by fsingle and fdouble helpers.

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fshared.h | 56 ++
 1 file changed, 56 insertions(+)
 create mode 100644 target-tilegx/helper-fshared.h

diff --git a/target-tilegx/helper-fshared.h b/target-tilegx/helper-fshared.h
new file mode 100644
index 000..bcd673e
--- /dev/null
+++ b/target-tilegx/helper-fshared.h
@@ -0,0 +1,56 @@
+/*
+ *  TILE-Gx virtual Floating point shared functions
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#define DEC_INIT_FPSTATUS \
+float_status fp_status = {.float_rounding_mode = float_round_nearest_even};
+
+static inline uint64_t create_fsfd_flag_un(void)
+{
+return 1 << 25;
+}
+
+static inline uint64_t create_fsfd_flag_lt(void)
+{
+return 1 << 26;
+}
+
+static inline uint64_t create_fsfd_flag_le(void)
+{
+return 1 << 27;
+}
+
+static inline uint64_t create_fsfd_flag_gt(void)
+{
+return 1 << 28;
+}
+
+static inline uint64_t create_fsfd_flag_ge(void)
+{
+return 1 << 29;
+}
+
+static inline uint64_t create_fsfd_flag_eq(void)
+{
+return 1 << 30;
+}
+
+static inline uint64_t create_fsfd_flag_ne(void)
+{
+return 1ULL << 31;
+}
-- 
1.9.3




[Qemu-devel] [PATCH v6 0/5] target-tilegx: Implement floating point instructions

2016-05-14 Thread chengang
From: Chen Gang 

These patches are the normal floating point implementation, instead of
the original temporary one.

It passes building, and gcc testsuite. 


Chen Gang (5):
  fpu: softfloat: Add normalize_roundpack_float[32|64] functions
  target-tilegx/helper-fshared.h: Add floating point shared function
  target-tilegx/helper-fsingle.c: Implement single floating point
  target-tilegx/helper-fdouble.c: Implement double floating point
  target-tilegx: Integrate floating pointer implementation

 fpu/softfloat.c|  65 
 include/fpu/softfloat.h|  15 ++
 target-tilegx/Makefile.objs|   3 +-
 target-tilegx/helper-fdouble.c | 365 +
 target-tilegx/helper-fshared.h |  56 +++
 target-tilegx/helper-fsingle.c | 201 +++
 target-tilegx/helper.h |  12 ++
 target-tilegx/translate.c  |  66 +++-
 8 files changed, 773 insertions(+), 10 deletions(-)
 create mode 100644 target-tilegx/helper-fdouble.c
 create mode 100644 target-tilegx/helper-fshared.h
 create mode 100644 target-tilegx/helper-fsingle.c

-- 
1.9.3




[Qemu-devel] [PATCH v6 3/5] target-tilegx/helper-fsingle.c: Implement single floating point

2016-05-14 Thread chengang
From: Chen Gang 

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fsingle.c | 201 +
 1 file changed, 201 insertions(+)
 create mode 100644 target-tilegx/helper-fsingle.c

diff --git a/target-tilegx/helper-fsingle.c b/target-tilegx/helper-fsingle.c
new file mode 100644
index 000..68b0396
--- /dev/null
+++ b/target-tilegx/helper-fsingle.c
@@ -0,0 +1,201 @@
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+#define IMPL_FULL
+
+/*
+ * FSingle instructions implemenation:
+ *
+ * fsingle_add1 ; calc srca and srcb,
+ *  ; convert float_32 to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_sub1 ; calc srca and srcb.
+ *  ; convert float_32 to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_addsub2  ; nop.
+ *
+ * fsingle_mul1 ; calc srca and srcb.
+ *  ; convert float_32 value to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_mul2 ; move srca to dest.
+ *
+ * fsingle_pack1; nop
+ *
+ * fsingle_pack2; treate srca as TileGXFPSFmt result.
+ *  ; convert TileGXFPSFmt result to float_32 value.
+ *  ; move float_32 value to dest.
+ */
+
+static inline uint32_t get_fsingle_exp(uint64_t n)
+{
+return n & 0xff;
+}
+
+static inline uint32_t get_fsingle_sign(uint64_t n)
+{
+return test_bit(10, );
+}
+
+static inline unsigned int get_fsingle_man(uint64_t n)
+{
+return n >> 32;
+}
+
+#ifdef IMPL_FULL
+
+static uint32_t get_f32_exp(float32 f)
+{
+return extract32(float32_val(f), 23, 8);
+}
+
+static uint32_t get_f32_man(float32 f)
+{
+return float32_val(f) & 0x7f;
+}
+
+static inline void set_fsingle_sign(uint64_t *n)
+{
+set_bit(10, n);
+}
+
+static inline uint64_t create_fsingle_exp(float32 f)
+{
+return  get_f32_exp(f) & 0xff;
+}
+
+static inline uint64_t create_fsingle_man(float32 f)
+{
+if (get_f32_exp(f)) {
+return (uint64_t)get_f32_man(f) << 40 | (1ULL << 63);
+}
+return (uint64_t)get_f32_man(f) << 32;
+}
+
+static uint64_t float32_to_sfmt(float32 f)
+{
+uint64_t sfmt = 0;
+
+if (float32_is_neg(f)) {
+set_fsingle_sign();
+}
+sfmt |= create_fsingle_exp(f);
+sfmt |= create_fsingle_man(f);
+
+return sfmt;
+}
+
+#else
+
+#define TILEGX_F_CALC_CVT   0 /* convert int to fsingle */
+#define TILEGX_F_CALC_NCVT  1 /* Not convertion */
+
+static inline unsigned int get_fsingle_calc(uint64_t n)
+{
+return test_bit(11, );
+}
+
+static inline void set_fsingle_calc(uint64_t *n, uint32_t calc)
+{
+set_bit(11, n);
+}
+
+static uint64_t float32_to_sfmt(float32 f)
+{
+return (uint64_t)float32_val(f) << 32;
+}
+
+#endif
+
+uint64_t helper_fsingle_pack2(uint64_t srca)
+{
+DEC_INIT_FPSTATUS;
+
+#ifndef IMPL_FULL
+if (get_fsingle_calc(srca) == TILEGX_F_CALC_NCVT) {
+return srca >> 32;
+}
+#endif
+return float32_val(normalize_roundpack_float32(get_fsingle_sign(srca),
+   get_fsingle_exp(srca),
+   get_fsingle_man(srca),
+   _status));
+}
+
+static uint64_t main_calc(float32 fsrca, float32 fsrcb,
+  float32 (*calc)(float32, float32, float_status*))
+{
+DEC_INIT_FPSTATUS;
+uint64_t sfmt = float32_to_sfmt(calc(fsrca, fsrcb, _status));
+
+if (float32_eq(fsrca, fsrcb, _status)) {
+sfmt |= create_fsfd_flag_eq();
+} else {
+sfmt |= create_fsfd_flag_ne();
+}
+
+if (float32_lt(fsrca, fsrcb, _status)) {
+sfmt |= create_fsfd_flag_lt();
+}
+if (float32_le(fsrca, fsrcb, _status)) {
+sfmt |= create_fsfd_flag_le();
+}
+
+if (float32_lt(fsrcb, fsrca, _status)) {
+sfmt |= create_fsfd_flag_gt();
+}
+if 

[Qemu-devel] [PATCH v2] Use frame->retcode instead of frame address for alpha target restorer

2016-03-30 Thread chengang
From: Chen Gang 

The restorer needs the return code address which is frame->retcode, not
frame itself.

Signed-off-by: Chen Gang 
---
 linux-user/signal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index e487f9e..34367ce 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5396,7 +5396,7 @@ static void setup_frame(int sig, struct target_sigaction 
*ka,
>retcode[1]);
 __put_user(INSN_CALLSYS, >retcode[2]);
 /* imb() */
-r26 = frame_addr;
+r26 = frame_addr + offsetof(struct target_sigframe, retcode);
 }
 
 unlock_user_struct(frame, frame_addr, 1);
@@ -5455,7 +5455,7 @@ static void setup_rt_frame(int sig, struct 
target_sigaction *ka,
>retcode[1]);
 __put_user(INSN_CALLSYS, >retcode[2]);
 /* imb(); */
-r26 = frame_addr;
+r26 = frame_addr + offsetof(struct target_rt_sigframe, retcode);
 }
 
 if (err) {
-- 
1.9.3




[Qemu-devel] [PATCH] linux-user/signal.c: Use s390 target space address instead of host space address for restorer

2016-03-29 Thread chengang
From: Chen Gang 

The return address is in target space, so the restorer address needs to
be target space, too.

Signed-off-by: Chen Gang 
---
 linux-user/signal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index c0a6f7e..6a73321 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4117,8 +4117,8 @@ static void setup_frame(int sig, struct target_sigaction 
*ka,
 env->regs[14] = (unsigned long)
 ka->sa_restorer | PSW_ADDR_AMODE;
 } else {
-env->regs[14] = (unsigned long)
-frame->retcode | PSW_ADDR_AMODE;
+env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
+| PSW_ADDR_AMODE;
 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
(uint16_t *)(frame->retcode));
 }
-- 
1.9.3




[Qemu-devel] [PATCH] linux-user/signal.c: Use target address instead of host address for microblaze restorer

2016-03-29 Thread chengang
From: Chen Gang 

The return address is in target space, so the restorer address needs to
be target space, too.

Signed-off-by: Chen Gang 
---
 linux-user/signal.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 4157154..c0a6f7e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3532,7 +3532,8 @@ static void setup_frame(int sig, struct target_sigaction 
*ka,
 
 /* Return from sighandler will jump to the tramp.
Negative 8 offset because return is rtsd r15, 8 */
-env->regs[15] = ((unsigned long)frame->tramp) - 8;
+env->regs[15] = frame_addr + offsetof(struct target_signal_frame, 
tramp)
+   - 8;
 }
 
 /* Set up registers for signal handler */
-- 
1.9.3




[Qemu-devel] [PATCH] linux-user/signal.c: Use frame->retcode instead of frame address for alpha target restorer

2016-03-29 Thread chengang
From: Chen Gang 

The restorer needs the return code address which is frame->retcode, not
frame itself.

Signed-off-by: Chen Gang 
---
 linux-user/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index e487f9e..4157154 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5455,7 +5455,7 @@ static void setup_rt_frame(int sig, struct 
target_sigaction *ka,
>retcode[1]);
 __put_user(INSN_CALLSYS, >retcode[2]);
 /* imb(); */
-r26 = frame_addr;
+r26 = frame_addr + offsetof(struct target_rt_sigframe, retcode);
 }
 
 if (err) {
-- 
1.9.3




[Qemu-devel] [PATCH v2] linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame

2016-03-29 Thread chengang
From: Chen Gang 

Original implementation uses do_rt_sigreturn directly in host space,
when a guest program is in unwind procedure in guest space, it will get
an incorrect restore address, then causes unwind failure.

Also cleanup the original incorrect indentation.

Signed-off-by: Chen Gang 
---
 linux-user/signal.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 96e86c0..e487f9e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5559,8 +5559,13 @@ struct target_rt_sigframe {
 unsigned char save_area[16]; /* caller save area */
 struct target_siginfo info;
 struct target_ucontext uc;
+abi_ulong retcode[2];
 };
 
+#define INSN_MOVELI_R10_139  0x00045fe551483000ULL /* { moveli r10, 139 } */
+#define INSN_SWINT1  0x286b180051485000ULL /* { swint1 } */
+
+
 static void setup_sigcontext(struct target_sigcontext *sc,
  CPUArchState *env, int signo)
 {
@@ -5636,9 +5641,12 @@ static void setup_rt_frame(int sig, struct 
target_sigaction *ka,
 __put_user(target_sigaltstack_used.ss_size, >uc.tuc_stack.ss_size);
 setup_sigcontext(>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;
+restorer = (unsigned long) ka->sa_restorer;
+} else {
+__put_user(INSN_MOVELI_R10_139, >retcode[0]);
+__put_user(INSN_SWINT1, >retcode[1]);
+restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
 }
 env->pc = (unsigned long) ka->_sa_handler;
 env->regs[TILEGX_R_SP] = (unsigned long) frame;
-- 
1.9.3




[Qemu-devel] [PATCH] target-tilegx: Support dumping working flow instructions and registers

2016-03-19 Thread chengang
From: Chen Gang 

It is only for debug and analyzing tilegx qemu related issues.

Signed-off-by: Chen Gang 
---
 target-tilegx/helper.c| 34 ++
 target-tilegx/helper.h|  2 ++
 target-tilegx/translate.c | 37 +
 3 files changed, 73 insertions(+)

diff --git a/target-tilegx/helper.c b/target-tilegx/helper.c
index 616c5c7..c7cfe66 100644
--- a/target-tilegx/helper.c
+++ b/target-tilegx/helper.c
@@ -160,3 +160,37 @@ uint64_t helper_cmul2(uint64_t srca, uint64_t srcb, int 
shift, int round)
 
 return deposit32(realr >> shift, 16, 16, imagr >> shift);
 }
+
+extern char **debug_buf;
+
+#define DEBUG_DUMP_REGS
+
+static void dump_regs(CPUTLGState *env, int idx)
+{
+#ifdef DEBUG_DUMP_REGS
+int i;
+
+if (debug_buf[idx][2] == '\n') {
+for (i = 0; i < TILEGX_R_COUNT; i++) {
+if (!(i % 4)) {
+fprintf(stderr, "\n");
+}
+fprintf(stderr, "r%2.2u = %16.16lx, ", i, env->regs[i]);
+}
+fprintf(stderr, "\n");
+for (i = 0; i < TILEGX_SPR_COUNT; i++) {
+if (!(i % 8)) {
+fprintf(stderr, "\n");
+}
+fprintf(stderr, "s%2.2u = %16.16lx, ", i, env->spregs[i]);
+}
+fprintf(stderr, "\n");
+}
+#endif
+}
+
+void helper_print_step(CPUTLGState *env, int idx)
+{
+fprintf(stderr, "%s", debug_buf[idx]);
+dump_regs(env, idx);
+}
diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h
index 9281d0f..74f796a 100644
--- a/target-tilegx/helper.h
+++ b/target-tilegx/helper.h
@@ -24,3 +24,5 @@ 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_2(print_step, void, env, int)
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 03918eb..8489494 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -47,6 +47,43 @@ static const char * const reg_names[64] = {
 "sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn2", "zero"
 };
 
+#define STATIC_DEBUG
+
+char **debug_buf;
+
+#ifdef STATIC_DEBUG
+
+#include 
+
+#define qemu_log_mask(flag, fmt, ...)  debug_print(flag, fmt, ##__VA_ARGS__)
+
+static int debug_idx;
+
+extern void debug_print(int flag, const char *fmt, ...);
+
+void debug_print(int flag, const char *fmt, ...)
+{
+va_list args;
+char buf[0x400];
+TCGv_i32 tmp;
+
+va_start(args, fmt);
+vsprintf(buf, fmt, args);
+va_end(args);
+
+if (!debug_buf) {
+debug_buf = malloc(sizeof(char *) * 0x40);
+}
+debug_buf[debug_idx] = malloc(strlen(buf) + 1);
+strcpy(debug_buf[debug_idx], buf);
+
+tmp = tcg_const_i32(debug_idx++);
+gen_helper_print_step(cpu_env, tmp);
+tcg_temp_free_i32(tmp);
+}
+
+#endif
+
 /* Modified registers are cached in temporaries until the end of the bundle. */
 typedef struct {
 unsigned reg;
-- 
1.9.3




[Qemu-devel] [PATCH] linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame

2016-03-14 Thread chengang
From: Chen Gang 

Original implementation uses do_rt_sigreturn directly in host space,
when a guest program is in unwind procedure in guest space, it will get
an incorrect restore address, then causes unwind failure.

Also cleanup the original incorrect indentation.

Signed-off-by: Chen Gang 
---
 linux-user/signal.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 919aa83..0e3b1c6 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5566,8 +5566,13 @@ struct target_rt_sigframe {
 unsigned char save_area[16]; /* caller save area */
 struct target_siginfo info;
 struct target_ucontext uc;
+abi_ulong retcode[2];
 };
 
+#define INSN_MOVELI_R10_139  0x00045fe551483000ULL /* { moveli r10, 139 } */
+#define INSN_SWINT1  0x286b180051485000ULL /* { swint1 } */
+
+
 static void setup_sigcontext(struct target_sigcontext *sc,
  CPUArchState *env, int signo)
 {
@@ -5643,9 +5648,12 @@ static void setup_rt_frame(int sig, struct 
target_sigaction *ka,
 __put_user(target_sigaltstack_used.ss_size, >uc.tuc_stack.ss_size);
 setup_sigcontext(>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;
+restorer = (unsigned long) ka->sa_restorer;
+} else {
+__put_user(INSN_MOVELI_R10_139, >retcode[0]);
+__put_user(INSN_SWINT1, >retcode[1]);
+restorer = (unsigned long)frame->retcode;
 }
 env->pc = (unsigned long) ka->_sa_handler;
 env->regs[TILEGX_R_SP] = (unsigned long) frame;
-- 
1.9.3




[Qemu-devel] [PATCH] linux-user/syscall.c: Let lv always match val in do_getsockopt()

2016-01-13 Thread chengang
From: Chen Gang 

After host_to_target_sock_type(), the length of val may be changed, so
calculate the related lv, too.

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fcdca2a..0e95f35 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1841,6 +1841,7 @@ static abi_long do_getsockopt(int sockfd, int level, int 
optname,
 return ret;
 if (optname == SO_TYPE) {
 val = host_to_target_sock_type(val);
+lv = (val >> 8) ? 4 : 1;
 }
 if (len > lv)
 len = lv;
-- 
1.9.1




[Qemu-devel] [PATCH] translate-all.c: Remove writable protection feature for tb_alloc_page()

2016-01-13 Thread chengang
From: Chen Gang 

Guest may allocate a readable, writable, and executable page, then write
data on the page, and execute data as code on the page too, then write
anther data still within the page.

So remove this feature from linux-user: it not only consumes a little
performance, but also causes issue with the old Linux kernel under some
of architectures (they will directly generate segment fault for it).

Signed-off-by: Chen Gang 
---
 translate-all.c | 29 +
 1 file changed, 1 insertion(+), 28 deletions(-)

diff --git a/translate-all.c b/translate-all.c
index 042a857..1b6e95d 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1430,34 +1430,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
 p->first_tb = (TranslationBlock *)((uintptr_t)tb | n);
 invalidate_page_bitmap(p);
 
-#if defined(CONFIG_USER_ONLY)
-if (p->flags & PAGE_WRITE) {
-target_ulong addr;
-PageDesc *p2;
-int prot;
-
-/* force the host page as non writable (writes will have a
-   page fault + mprotect overhead) */
-page_addr &= qemu_host_page_mask;
-prot = 0;
-for (addr = page_addr; addr < page_addr + qemu_host_page_size;
-addr += TARGET_PAGE_SIZE) {
-
-p2 = page_find(addr >> TARGET_PAGE_BITS);
-if (!p2) {
-continue;
-}
-prot |= p2->flags;
-p2->flags &= ~PAGE_WRITE;
-  }
-mprotect(g2h(page_addr), qemu_host_page_size,
- (prot & PAGE_BITS) & ~PAGE_WRITE);
-#ifdef DEBUG_TB_INVALIDATE
-printf("protecting code page: 0x" TARGET_FMT_lx "\n",
-   page_addr);
-#endif
-}
-#else
+#if !defined(CONFIG_USER_ONLY)
 /* if some code is already present, then the pages are already
protected. So we handle the case where only the first TB is
allocated in a physical page */
-- 
1.9.1




[Qemu-devel] [PATCH v2 1/3] linux-user/mmap.c: Set prot page flags for the correct region in mmap_frag()

2016-01-11 Thread chengang
From: Chen Gang 

mmap() size in mmap_frag() is qemu_host_page_size, but the outside calls
page_set_flags() may be not with qemu_host_page_size. So after mmap(),
call page_set_flags() in time.

After this fix,  for the next call for the same region, prot1 will be
PAGE_VALID (not 0), so can avoid to enter "if (prot1 == 0)" case, again.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 445e8c6..7807ed0 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -162,6 +162,8 @@ static int mmap_frag(abi_ulong real_start,
flags | MAP_ANONYMOUS, -1, 0);
 if (p == MAP_FAILED)
 return -1;
+page_set_flags(real_start, real_start + qemu_host_page_size,
+   PAGE_VALID);
 prot1 = prot;
 }
 prot1 &= PAGE_BITS;
-- 
1.9.1




[Qemu-devel] [PATCH v2 3/3] linux-user/mmap.c: Use TARGET_PAGE_SIZE as the increasing step

2016-01-11 Thread chengang
From: Chen Gang 

Just like another areas have done.
---
 linux-user/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 51c381d..86c270b 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -151,7 +151,7 @@ static int mmap_frag(abi_ulong real_start,
 
 /* get the protection of the target pages outside the mapping */
 prot1 = 0;
-for(addr = real_start; addr < real_end; addr++) {
+for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
 if (addr < start || addr >= end)
 prot1 |= page_get_flags(addr);
 }
-- 
1.9.1




[Qemu-devel] [PATCH v2 2/3] linux-user/mmap.c: Remove useless variable p for mmap_frag

2016-01-11 Thread chengang
From: Chen Gang 

It is useless.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7807ed0..51c381d 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -158,10 +158,10 @@ static int mmap_frag(abi_ulong real_start,
 
 if (prot1 == 0) {
 /* no page was there, so we allocate one */
-void *p = mmap(host_start, qemu_host_page_size, prot,
-   flags | MAP_ANONYMOUS, -1, 0);
-if (p == MAP_FAILED)
+if (mmap(host_start, qemu_host_page_size, prot, flags | MAP_ANONYMOUS,
+ -1, 0) == MAP_FAILED) {
 return -1;
+}
 page_set_flags(real_start, real_start + qemu_host_page_size,
PAGE_VALID);
 prot1 = prot;
-- 
1.9.1




[Qemu-devel] [PATCH v2] linux-user/syscall.c: Add SO_RCVTIMEO and SO_SNDTIMEO for getsockopt

2016-01-11 Thread chengang
From: Chen Gang 

Implement them according to the other features implementations.

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 44485f2..4c68800 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1687,6 +1687,7 @@ static abi_long do_getsockopt(int sockfd, int level, int 
optname,
 abi_long ret;
 int len, val;
 socklen_t lv;
+struct timeval tv;
 
 switch(level) {
 case TARGET_SOL_SOCKET:
@@ -1694,10 +1695,32 @@ static abi_long do_getsockopt(int sockfd, int level, 
int optname,
 switch (optname) {
 /* These don't just return a single integer */
 case TARGET_SO_LINGER:
-case TARGET_SO_RCVTIMEO:
-case TARGET_SO_SNDTIMEO:
 case TARGET_SO_PEERNAME:
 goto unimplemented;
+case TARGET_SO_RCVTIMEO:
+optname = SO_RCVTIMEO;
+goto time_case;
+case TARGET_SO_SNDTIMEO:
+optname = SO_SNDTIMEO;
+time_case:
+if (get_user_u32(len, optlen)) {
+return -TARGET_EFAULT;
+}
+if (len < sizeof(struct target_timeval)) {
+return -TARGET_EINVAL;
+}
+lv = sizeof(tv);
+ret = get_errno(getsockopt(sockfd, level, optname, , ));
+if (ret < 0) {
+return ret;
+}
+if (copy_to_user_timeval(optval_addr, )) {
+return -TARGET_EFAULT;
+}
+if (put_user_u32(sizeof(struct target_timeval), optlen)) {
+return -TARGET_EFAULT;
+}
+break;
 case TARGET_SO_PEERCRED: {
 struct ucred cr;
 socklen_t crlen;
-- 
1.9.1




[Qemu-devel] [PATCH] linux-user/syscall.c: Use SOL_SOCKET instead of level for setsockopt()

2016-01-10 Thread chengang
From: Chen Gang 

In this case, level is TARGET_SOL_SOCKET, but we need SOL_SOCKET for
setsockopt().

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 95b1762..44485f2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1596,7 +1596,8 @@ set_timeout:
addr_ifname = alloca(IFNAMSIZ);
memcpy(addr_ifname, dev_ifname, optlen);
addr_ifname[optlen] = 0;
-   ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, 
optlen));
+   ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
+   addr_ifname, optlen));
unlock_user (dev_ifname, optval_addr, 0);
return ret;
}
-- 
1.9.1




[Qemu-devel] [PATCH v2] linux-user: syscall: Add SO_LINGER for setsockopt

2016-01-10 Thread chengang
From: Chen Gang 

Just implement it according to the other features implementations.

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c  | 18 +-
 linux-user/syscall_defs.h |  5 +
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4c68800..fcdca2a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1410,6 +1410,9 @@ static abi_long do_setsockopt(int sockfd, int level, int 
optname,
 int val;
 struct ip_mreqn *ip_mreq;
 struct ip_mreq_source *ip_mreq_source;
+struct linger lg;
+struct target_linger *tlg;
+
 
 switch(level) {
 case SOL_TCP:
@@ -1661,7 +1664,20 @@ set_timeout:
 case TARGET_SO_RCVLOWAT:
optname = SO_RCVLOWAT;
break;
-break;
+case TARGET_SO_LINGER:
+optname = SO_LINGER;
+if (optlen != sizeof(struct target_linger)) {
+return -TARGET_EINVAL;
+}
+if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
+return -TARGET_EFAULT;
+}
+__get_user(lg.l_onoff, >l_onoff);
+__get_user(lg.l_linger, >l_linger);
+ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
+, sizeof(lg)));
+unlock_user_struct(tlg, optval_addr, 0);
+return ret;
 default:
 goto unimplemented;
 }
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index f996acf..6591e74 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -166,6 +166,11 @@ struct target_ip_mreq_source {
 uint32_t imr_sourceaddr;
 };
 
+struct target_linger {
+abi_int l_onoff;/* Linger active*/
+abi_int l_linger;   /* How long to linger for   */
+};
+
 struct target_timeval {
 abi_long tv_sec;
 abi_long tv_usec;
-- 
1.9.1




[Qemu-devel] [PATCH] linux-user/syscall.c: Let tilegx support sigaltstack

2016-01-09 Thread chengang
From: Chen Gang 

Simply enable it, and notice about 80 columns coding styles.

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6c64ba6..8d4bcf6 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8294,7 +8294,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 case TARGET_NR_sigaltstack:
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
-defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
+defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_TILEGX) || 
\
+defined(TARGET_OPENRISC)
 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState 
*)cpu_env));
 break;
 #else
-- 
1.9.3




[Qemu-devel] [PATCH] linux-user/syscall.c: Add SO_RCVTIMEO and SO_SNDTIMEO for getsockopt

2016-01-07 Thread chengang
From: Chen Gang 

Just implement them according to the other features implementations.

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c | 25 +++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 12a6cd2..f27148a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1685,6 +1685,7 @@ static abi_long do_getsockopt(int sockfd, int level, int 
optname,
 abi_long ret;
 int len, val;
 socklen_t lv;
+struct timeval tv;
 
 switch(level) {
 case TARGET_SOL_SOCKET:
@@ -1692,10 +1693,30 @@ static abi_long do_getsockopt(int sockfd, int level, 
int optname,
 switch (optname) {
 /* These don't just return a single integer */
 case TARGET_SO_LINGER:
-case TARGET_SO_RCVTIMEO:
-case TARGET_SO_SNDTIMEO:
 case TARGET_SO_PEERNAME:
 goto unimplemented;
+
+case TARGET_SO_RCVTIMEO:
+optname = SO_RCVTIMEO;
+goto time_case;
+case TARGET_SO_SNDTIMEO:
+optname = SO_SNDTIMEO;
+time_case:
+if (optlen < sizeof(struct target_timeval)) {
+return -TARGET_EINVAL;
+}
+lv = sizeof(tv);
+ret = get_errno(getsockopt(sockfd, level, optname, , ));
+if (ret < 0) {
+return ret;
+}
+if (copy_to_user_timeval(optval_addr, )) {
+return -TARGET_EFAULT;
+}
+if (put_user_u32(sizeof(struct target_timeval), optlen)) {
+return -TARGET_EFAULT;
+}
+break;
 case TARGET_SO_PEERCRED: {
 struct ucred cr;
 socklen_t crlen;
-- 
1.9.1




[Qemu-devel] [PATCH] linux-user: syscall: Add SO_LINGER for setsockopt

2016-01-07 Thread chengang
From: Chen Gang 

Just implement it according to the other features implementations.

Signed-off-by: Chen Gang 
---
 linux-user/syscall.c  | 16 +++-
 linux-user/syscall_defs.h |  5 +
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f27148a..9f2c871 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1409,6 +1409,9 @@ static abi_long do_setsockopt(int sockfd, int level, int 
optname,
 int val;
 struct ip_mreqn *ip_mreq;
 struct ip_mreq_source *ip_mreq_source;
+struct linger lg;
+struct target_linger *tlg;
+
 
 switch(level) {
 case SOL_TCP:
@@ -1659,7 +1662,19 @@ set_timeout:
 case TARGET_SO_RCVLOWAT:
optname = SO_RCVLOWAT;
break;
-break;
+case TARGET_SO_LINGER:
+optname = SO_LINGER;
+if (optlen != sizeof(struct target_linger)) {
+return -TARGET_EINVAL;
+}
+if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
+return -TARGET_EFAULT;
+}
+__get_user(lg.l_onoff, >l_onoff);
+__get_user(lg.l_linger, >l_linger);
+unlock_user_struct(tlg, optval_addr, 0);
+return get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
+ , sizeof(lg)));
 default:
 goto unimplemented;
 }
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 9d3c537..5a4d565 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -165,6 +165,11 @@ struct target_ip_mreq_source {
 uint32_t imr_sourceaddr;
 };
 
+struct target_linger {
+int l_onoff;/* Linger active*/
+int l_linger;   /* How long to linger for   */
+};
+
 struct target_timeval {
 abi_long tv_sec;
 abi_long tv_usec;
-- 
1.9.1




[Qemu-devel] [PATCH v5 0/5] target-tilegx: Implement floating point instructions

2016-01-02 Thread chengang
From: Chen Gang 

These patches are the normal floating point implementation, instead of
the original temporary one.

It passes building, and gcc testsuite.

Chen Gang (5):
  fpu: softfloat: Add normalize_roundpack_float32 function
  target-tilegx/helper-fshared.h: Add floating point shared function
  target-tilegx/helper-fsingle.c: Implement single floating point
  target-tilegx/helper-fdouble.c: Implement double floating point
  target-tilegx: Integrate floating pointer implementation

 fpu/softfloat.c|  55 ++
 include/fpu/softfloat.h|   8 +
 target-tilegx/Makefile.objs|   3 +-
 target-tilegx/helper-fdouble.c | 384 +
 target-tilegx/helper-fshared.h |  56 ++
 target-tilegx/helper-fsingle.c | 200 +
 target-tilegx/helper.h |  12 ++
 target-tilegx/translate.c  |  66 ++-
 8 files changed, 774 insertions(+), 10 deletions(-)
 create mode 100644 target-tilegx/helper-fdouble.c
 create mode 100644 target-tilegx/helper-fshared.h
 create mode 100644 target-tilegx/helper-fsingle.c

-- 
1.9.3




[Qemu-devel] [PATCH v5 3/5] target-tilegx/helper-fsingle.c: Implement single floating point

2016-01-02 Thread chengang
From: Chen Gang 

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fsingle.c | 200 +
 1 file changed, 200 insertions(+)
 create mode 100644 target-tilegx/helper-fsingle.c

diff --git a/target-tilegx/helper-fsingle.c b/target-tilegx/helper-fsingle.c
new file mode 100644
index 000..997d40e
--- /dev/null
+++ b/target-tilegx/helper-fsingle.c
@@ -0,0 +1,200 @@
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+#define IMPL_FULL
+
+/*
+ * FSingle instructions implemenation:
+ *
+ * fsingle_add1 ; calc srca and srcb,
+ *  ; convert float_32 to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_sub1 ; calc srca and srcb.
+ *  ; convert float_32 to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_addsub2  ; nop.
+ *
+ * fsingle_mul1 ; calc srca and srcb.
+ *  ; convert float_32 value to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_mul2 ; move srca to dest.
+ *
+ * fsingle_pack1; nop
+ *
+ * fsingle_pack2; treate srca as TileGXFPSFmt result.
+ *  ; convert TileGXFPSFmt result to float_32 value.
+ *  ; move float_32 value to dest.
+ */
+
+static inline uint32_t get_fsingle_exp(uint64_t n)
+{
+return n & 0xff;
+}
+
+static inline uint32_t get_fsingle_sign(uint64_t n)
+{
+return test_bit(10, );
+}
+
+static inline unsigned int get_fsingle_man(uint64_t n)
+{
+return n >> 32;
+}
+
+#ifdef IMPL_FULL
+
+static uint32_t get_f32_exp(float32 f)
+{
+return extract32(float32_val(f), 23, 8);
+}
+
+static uint32_t get_f32_man(float32 f)
+{
+return float32_val(f) & 0x7f;
+}
+
+static inline void set_fsingle_sign(uint64_t *n)
+{
+set_bit(10, n);
+}
+
+static inline uint64_t create_fsingle_exp(float32 f)
+{
+return  get_f32_exp(f) & 0xff;
+}
+
+static inline uint64_t create_fsingle_man(float32 f)
+{
+if (get_f32_exp(f)) {
+return (uint64_t)get_f32_man(f) << 40 | (1ULL << 63);
+}
+return (uint64_t)get_f32_man(f) << 32;
+}
+
+static uint64_t float32_to_sfmt(float32 f)
+{
+uint64_t sfmt = 0;
+
+if (float32_is_neg(f)) {
+set_fsingle_sign();
+}
+sfmt |= create_fsingle_exp(f);
+sfmt |= create_fsingle_man(f);
+
+return sfmt;
+}
+
+#else
+
+#define TILEGX_F_CALC_CVT   0 /* convert int to fsingle */
+#define TILEGX_F_CALC_NCVT  1 /* Not convertion */
+
+static inline unsigned int get_fsingle_calc(uint64_t n)
+{
+return test_bit(11, );
+}
+
+static inline void set_fsingle_calc(uint64_t *n, uint32_t calc)
+{
+set_bit(11, n);
+}
+
+static uint64_t float32_to_sfmt(float32 f)
+{
+return (uint64_t)float32_val(f) << 32;
+}
+
+#endif
+
+uint64_t helper_fsingle_pack2(uint64_t srca)
+{
+DEC_INIT_FPSTATUS;
+
+#ifndef IMPL_FULL
+if (get_fsingle_calc(srca) == TILEGX_F_CALC_NCVT) {
+return srca >> 32;
+}
+#endif
+return float32_val(normalize_roundpack_float32(get_fsingle_sign(srca),
+   get_fsingle_exp(srca),
+   get_fsingle_man(srca),
+   _status));
+}
+
+static uint64_t main_calc(float32 fsrca, float32 fsrcb,
+  float32 (*calc)(float32, float32, float_status*))
+{
+DEC_INIT_FPSTATUS;
+uint64_t sfmt = float32_to_sfmt(calc(fsrca, fsrcb, _status));
+
+if (float32_eq(fsrca, fsrcb, _status)) {
+sfmt |= create_fsfd_flag_eq();
+} else {
+sfmt |= create_fsfd_flag_ne();
+}
+
+if (float32_lt(fsrca, fsrcb, _status)) {
+sfmt |= create_fsfd_flag_lt();
+}
+if (float32_le(fsrca, fsrcb, _status)) {
+sfmt |= create_fsfd_flag_le();
+}
+
+if (float32_lt(fsrcb, fsrca, _status)) {
+sfmt |= create_fsfd_flag_gt();
+}
+if (float32_le(fsrcb, fsrca, _status)) {
+   

[Qemu-devel] [PATCH v5 4/5] target-tilegx/helper-fdouble.c: Implement double floating point

2016-01-02 Thread chengang
From: Chen Gang 

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fdouble.c | 383 +
 1 file changed, 384 insertions(+)
 create mode 100644 target-tilegx/helper-fdouble.c

diff --git a/target-tilegx/helper-fdouble.c b/target-tilegx/helper-fdouble.c
new file mode 100644
index 000..9aab3ac
--- /dev/null
+++ b/target-tilegx/helper-fdouble.c
@@ -0,0 +1,383 @@
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+/*
+ * FDouble instructions implemenation:
+ *
+ * fdouble_unpack_min   ; srca and srcb are float_64 value.
+ *  ; get the min absolute value's mantissa.
+ *  ; move "mantissa >> (exp_max - exp_min)" to dest.
+ *
+ * fdouble_unpack_max   ; srca and srcb are float_64 value.
+ *  ; get the max absolute value's mantissa.
+ *  ; move mantissa to dest.
+ *
+ * fdouble_add_flags; srca and srcb are float_64 value.
+ *  ; calc exp (exp_max), sign, and comp bits for flags.
+ *  ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_sub_flags; srca and srcb are float_64 value.
+ *  ; calc exp (exp_max), sign, and comp bits for flags.
+ *  ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_addsub:  ; dest, srca (max, min mantissa), and srcb (flags).
+ *  ; "dest +/- srca" depend on the add/sub bit of flags.
+ *  ; move result mantissa to dest.
+ *
+ * fdouble_mul_flags:   ; srca and srcb are float_64 value.
+ *  ; calc sign (xor), exp (min + max), and comp bits.
+ *  ; mix sign, exp, and comp bits as flags to dest.
+ *
+ * fdouble_pack1; move srcb (flags) to dest.
+ *
+ * fdouble_pack2; srca, srcb (high, low mantissa), and dest (flags)
+ *  ; normalize and pack result from srca, srcb, and dest.
+ *  ; move result to dest.
+ */
+
+#define TILEGX_F_EXP_DZERO  0x3ff /* Zero exp for double 11-bits */
+#define TILEGX_F_EXP_DMAX   0x7fe /* max exp for double 11-bits */
+#define TILEGX_F_EXP_DUF0x1000/* underflow exp bit for double */
+
+#define TILEGX_F_MAN_HBIT   (1ULL << 59)
+
+#define TILEGX_F_CALC_ADD   1 /* Perform absolute add operation */
+#define TILEGX_F_CALC_SUB   2 /* Perform absolute sub operation */
+#define TILEGX_F_CALC_MUL   3 /* Perform absolute mul operation */
+
+static uint32_t get_f64_exp(float64 d)
+{
+return extract64(float64_val(d), 52, 11);
+}
+
+static void set_f64_exp(float64 *d, uint32_t exp)
+{
+*d = make_float64(deposit64(float64_val(*d), 52, 11, exp));
+}
+
+static uint64_t get_f64_man(float64 d)
+{
+return extract64(float64_val(d), 0, 52);
+}
+
+static uint64_t fr_to_man(float64 d)
+{
+uint64_t val = get_f64_man(d) << 7;
+
+if (get_f64_exp(d)) {
+val |= TILEGX_F_MAN_HBIT; /* Restore HBIT for the next calculation */
+}
+
+return val;
+}
+
+static uint64_t get_fdouble_man(uint64_t n)
+{
+return extract64(n, 0, 60);
+}
+
+static void set_fdouble_man(uint64_t *n, uint64_t man)
+{
+*n = deposit64(*n, 0, 60, man);
+}
+
+static uint64_t get_fdouble_man_of(uint64_t n)
+{
+return test_bit(60, );
+}
+
+static void clear_fdouble_man_of(uint64_t *n)
+{
+return clear_bit(60, n);
+}
+
+static uint32_t get_fdouble_nan(uint64_t n)
+{
+return test_bit(24, );
+}
+
+static void set_fdouble_nan(uint64_t *n)
+{
+set_bit(24, n);
+}
+
+static uint32_t get_fdouble_inf(uint64_t n)
+{
+return test_bit(23, );
+}
+
+static void set_fdouble_inf(uint64_t *n)
+{
+set_bit(23, n);
+}
+
+static uint32_t get_fdouble_calc(uint64_t n)
+{
+return extract32(n, 21, 2);
+}
+
+static void set_fdouble_calc(uint64_t *n, uint32_t calc)
+{
+*n = deposit64(*n, 21, 2, calc);
+}
+
+static uint32_t get_fdouble_sign(uint64_t n)
+{
+return test_bit(20, );
+}
+
+static void set_fdouble_sign(uint64_t *n)
+{
+set_bit(20, n);
+}
+
+static uint32_t get_fdouble_vexp(uint64_t n)

[Qemu-devel] [PATCH v5 5/5] target-tilegx: Integrate floating pointer implementation

2016-01-02 Thread chengang
From: Chen Gang 

It passes normal building, and gcc testsuite.

Signed-off-by: Chen Gang 
---
 target-tilegx/Makefile.objs |  3 ++-
 target-tilegx/helper.h  | 12 +
 target-tilegx/translate.c   | 66 ++---
 3 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/target-tilegx/Makefile.objs b/target-tilegx/Makefile.objs
index 0db778f..136ad60 100644
--- a/target-tilegx/Makefile.objs
+++ b/target-tilegx/Makefile.objs
@@ -1 +1,2 @@
-obj-y += cpu.o translate.o helper.o simd_helper.o
+obj-y += cpu.o translate.o helper.o simd_helper.o \
+   helper-fsingle.o helper-fdouble.o
diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h
index 9281d0f..3471fe3 100644
--- a/target-tilegx/helper.h
+++ b/target-tilegx/helper.h
@@ -24,3 +24,15 @@ 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_2(fsingle_add1, i64, i64, i64)
+DEF_HELPER_2(fsingle_sub1, i64, i64, i64)
+DEF_HELPER_2(fsingle_mul1, i64, i64, i64)
+DEF_HELPER_1(fsingle_pack2, i64, i64)
+DEF_HELPER_2(fdouble_unpack_min, i64, i64, i64)
+DEF_HELPER_2(fdouble_unpack_max, i64, i64, i64)
+DEF_HELPER_2(fdouble_add_flags, i64, i64, i64)
+DEF_HELPER_2(fdouble_sub_flags, i64, i64, i64)
+DEF_HELPER_3(fdouble_addsub, i64, i64, i64, i64)
+DEF_HELPER_2(fdouble_mul_flags, i64, i64, i64)
+DEF_HELPER_3(fdouble_pack2, i64, i64, i64, i64)
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 354f25a..924eece 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -597,6 +597,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 }
 qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
 return ret;
+
+case OE_RR_X0(FSINGLE_PACK1):
+case OE_RR_Y0(FSINGLE_PACK1):
+mnemonic = "fsingle_pack1";
+goto done2;
 }
 
 tdest = dest_gr(dc, dest);
@@ -613,9 +618,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 gen_helper_cnttz(tdest, tsrca);
 mnemonic = "cnttz";
 break;
-case OE_RR_X0(FSINGLE_PACK1):
-case OE_RR_Y0(FSINGLE_PACK1):
-return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
 case OE_RR_X1(LD1S):
 memop = MO_SB;
 mnemonic = "ld1s"; /* prefetch_l1_fault */
@@ -734,6 +736,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 return TILEGX_EXCP_OPCODE_UNKNOWN;
 }
 
+done2:
 qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
   reg_names[dest], reg_names[srca]);
 return ret;
@@ -742,13 +745,21 @@ 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 tsrca = load_gr(dc, srca);
-TCGv tsrcb = load_gr(dc, srcb);
+TCGv tdest, tsrca, tsrcb;
 TCGv t0;
 const char *mnemonic;
 
 switch (opext) {
+case OE_RRR(FSINGLE_ADDSUB2, 0, X0):
+mnemonic = "fsingle_addsub2";
+goto done2;
+}
+
+tdest = dest_gr(dc, dest);
+tsrca = load_gr(dc, srca);
+tsrcb = load_gr(dc, srcb);
+
+switch (opext) {
 case OE_RRR(ADDXSC, 0, X0):
 case OE_RRR(ADDXSC, 0, X1):
 gen_saturate_op(tdest, tsrca, tsrcb, tcg_gen_add_tl);
@@ -906,14 +917,37 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned 
opext,
 mnemonic = "exch";
 break;
 case OE_RRR(FDOUBLE_ADDSUB, 0, X0):
+gen_helper_fdouble_addsub(tdest, load_gr(dc, dest), tsrca, tsrcb);
+mnemonic = "fdouble_addsub";
+break;
 case OE_RRR(FDOUBLE_ADD_FLAGS, 0, X0):
+gen_helper_fdouble_add_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_add_flags";
+break;
 case OE_RRR(FDOUBLE_MUL_FLAGS, 0, X0):
+gen_helper_fdouble_mul_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_mul_flags";
+break;
 case OE_RRR(FDOUBLE_PACK1, 0, X0):
+tcg_gen_mov_i64(tdest, tsrcb);
+mnemonic = "fdouble_pack1";
+break;
 case OE_RRR(FDOUBLE_PACK2, 0, X0):
+gen_helper_fdouble_pack2(tdest, load_gr(dc, dest), tsrca, tsrcb);
+mnemonic = "fdouble_pack2";
+break;
 case OE_RRR(FDOUBLE_SUB_FLAGS, 0, X0):
+gen_helper_fdouble_sub_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_sub_flags";
+break;
 case OE_RRR(FDOUBLE_UNPACK_MAX, 0, X0):
+gen_helper_fdouble_unpack_max(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_unpack_max";
+break;
 case OE_RRR(FDOUBLE_UNPACK_MIN, 0, X0):
-return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+

[Qemu-devel] [PATCH v5 1/5] fpu: softfloat: Add normalize_roundpack_float32 function

2016-01-02 Thread chengang
From: Chen Gang 

It is based on (u)int32_to_float32 function to support float32 packing.

Signed-off-by: Chen Gang 
---
 fpu/softfloat.c | 55 +
 include/fpu/softfloat.h |  8 +++
 2 files changed, 63 insertions(+)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index f1170fe..dba8566 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -7080,6 +7080,61 @@ float64 uint32_to_float64(uint32_t a, float_status 
*status)
 return int64_to_float64(a, status);
 }
 
+/*
+ * The mantissa contents the hide bit, e.g. exp: 0x9e with sig: 1 means 1.0f.
+ *
+ * It references from int32_to_float32() and uint32_to_float32()
+ */
+float32 normalize_roundpack_float32(flag sign, int_fast16_t exp, uint32_t sig,
+float_status *status)
+{
+uint64_t absa = sig;
+int8_t scount;
+
+if (exp >= 0xff) {
+return packFloat32(sign, 0xFF, 0);
+} else if (exp <= 0) {
+shift32RightJamming(sig, 0 - exp, );
+return packFloat32(sign, 0, sig);
+}
+
+if (sign) {
+if (sig & 0x7FFF) {
+return normalizeRoundAndPackFloat32(1, exp - 2, sig, status);
+}
+if (sig) {
+return packFloat32(1, exp, 0);
+} else {
+return float32_zero;
+}
+}
+
+if (!sig) {
+return float32_zero;
+}
+
+scount = countLeadingZeros64(absa) - 40;
+if (scount >= 0) {
+exp -= 7 + scount + 2;
+if (exp <= 0) {
+return packFloat32(0, 0, absa);
+}
+return packFloat32(0, exp, absa << scount);
+}
+
+scount += 7;
+exp -= scount + 2;
+if (exp <= 0) {
+return packFloat32(0, 0, absa);
+}
+if (scount < 0) {
+shift64RightJamming(absa, 0 - scount, );
+} else {
+absa <<= scount;
+}
+return roundAndPackFloat32(0, exp, absa, status);
+}
+
 uint32 float32_to_uint32(float32 a, float_status *status)
 {
 int64_t v;
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index ded34eb..4995a15 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -422,6 +422,14 @@ int float32_is_signaling_nan( float32 );
 float32 float32_maybe_silence_nan( float32 );
 float32 float32_scalbn(float32, int, float_status *status);
 
+/*
+ * The mantissa contents the hide bit, e.g. exp: 0x9e with sig: 1 means 1.0f.
+ *
+ * It references from int32_to_float32() and uint32_to_float32()
+ */
+float32 normalize_roundpack_float32(flag sign, int_fast16_t exp, uint32_t sig,
+float_status *status);
+
 static inline float32 float32_abs(float32 a)
 {
 /* Note that abs does *not* handle NaN specially, nor does
-- 
1.9.3




[Qemu-devel] [PATCH v5 2/5] target-tilegx/helper-fshared.h: Add floating point shared function

2016-01-02 Thread chengang
From: Chen Gang 

It is used by fsingle and fdouble helpers.

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fshared.h | 56 ++
 1 file changed, 56 insertions(+)
 create mode 100644 target-tilegx/helper-fshared.h

diff --git a/target-tilegx/helper-fshared.h b/target-tilegx/helper-fshared.h
new file mode 100644
index 000..bcd673e
--- /dev/null
+++ b/target-tilegx/helper-fshared.h
@@ -0,0 +1,56 @@
+/*
+ *  TILE-Gx virtual Floating point shared functions
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#define DEC_INIT_FPSTATUS \
+float_status fp_status = {.float_rounding_mode = float_round_nearest_even};
+
+static inline uint64_t create_fsfd_flag_un(void)
+{
+return 1 << 25;
+}
+
+static inline uint64_t create_fsfd_flag_lt(void)
+{
+return 1 << 26;
+}
+
+static inline uint64_t create_fsfd_flag_le(void)
+{
+return 1 << 27;
+}
+
+static inline uint64_t create_fsfd_flag_gt(void)
+{
+return 1 << 28;
+}
+
+static inline uint64_t create_fsfd_flag_ge(void)
+{
+return 1 << 29;
+}
+
+static inline uint64_t create_fsfd_flag_eq(void)
+{
+return 1 << 30;
+}
+
+static inline uint64_t create_fsfd_flag_ne(void)
+{
+return 1ULL << 31;
+}
-- 
1.9.3




[Qemu-devel] [PATCH v2] linux-user/mmap.c: Set prot page flags for the correct region in mmap_frag()

2015-12-31 Thread chengang
From: Chen Gang 

mmap() size in mmap_frag() is qemu_host_page_size, but the outside calls
page_set_flags() may be not with qemu_host_page_size. So after mmap(),
call page_set_flags() in time.

Also let addr increasing step be TARGET_PAGE_SIZE, just like another
areas have done.

Also remove useless variable p.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 445e8c6..7920c5e 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -151,17 +151,19 @@ static int mmap_frag(abi_ulong real_start,
 
 /* get the protection of the target pages outside the mapping */
 prot1 = 0;
-for(addr = real_start; addr < real_end; addr++) {
+for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
 if (addr < start || addr >= end)
 prot1 |= page_get_flags(addr);
 }
 
 if (prot1 == 0) {
 /* no page was there, so we allocate one */
-void *p = mmap(host_start, qemu_host_page_size, prot,
-   flags | MAP_ANONYMOUS, -1, 0);
-if (p == MAP_FAILED)
+if (mmap(host_start, qemu_host_page_size, prot, flags | MAP_ANONYMOUS,
+ -1, 0) == MAP_FAILED) {
 return -1;
+}
+page_set_flags(real_start, real_start + qemu_host_page_size,
+   prot | PAGE_VALID);
 prot1 = prot;
 }
 prot1 &= PAGE_BITS;
-- 
1.7.3.4




[Qemu-devel] [PATCH] linux-user/mmap.c: Set prot page flags for the correct region in mmap_frag()

2015-12-30 Thread chengang
From: Chen Gang 

mmap() size in mmap_frag() is qemu_host_page_size, but the outside calls
page_set_flags() may be not with qemu_host_page_size. So after mmap(),
call page_set_flags() in time.

Also let addr increasing step be TARGET_PAGE_SIZE, just like another
areas have done.

Also remote redundant varialbe p.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 445e8c6..7920c5e 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -151,17 +151,19 @@ static int mmap_frag(abi_ulong real_start,
 
 /* get the protection of the target pages outside the mapping */
 prot1 = 0;
-for(addr = real_start; addr < real_end; addr++) {
+for(addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
 if (addr < start || addr >= end)
 prot1 |= page_get_flags(addr);
 }
 
 if (prot1 == 0) {
 /* no page was there, so we allocate one */
-void *p = mmap(host_start, qemu_host_page_size, prot,
-   flags | MAP_ANONYMOUS, -1, 0);
-if (p == MAP_FAILED)
+if (mmap(host_start, qemu_host_page_size, prot, flags | MAP_ANONYMOUS,
+ -1, 0) == MAP_FAILED) {
 return -1;
+}
+page_set_flags(real_start, real_start + qemu_host_page_size,
+   prot | PAGE_VALID);
 prot1 = prot;
 }
 prot1 &= PAGE_BITS;
-- 
1.7.3.4




[Qemu-devel] [PATCH] linux-user/mmap.c: Support shared memory mapping in mmap_frag()

2015-12-29 Thread chengang
From: Chen Gang 

It is a temporary fix for i386 target system running Windows.

Also remove useless variable 'p'.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c |   22 +++---
 1 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 445e8c6..07758d4 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -156,12 +156,28 @@ static int mmap_frag(abi_ulong real_start,
 prot1 |= page_get_flags(addr);
 }
 
+/*
+ * It is a temporary fix. Normally, target system will let shared memory
+ * aligned with 64KB, and allocate them near with each other, no any other
+ * kinds of mapping regions nearby. e.g. Windows on i386.
+ */
+if ((start == real_start) && (flags & MAP_SHARED)) {
+if (prot1) {
+munmap(host_start, qemu_host_page_size);
+}
+if (mmap(host_start, qemu_host_page_size, prot, flags, fd, offset)
+== MAP_FAILED) {
+return -1;
+}
+return 0;
+}
+
 if (prot1 == 0) {
 /* no page was there, so we allocate one */
-void *p = mmap(host_start, qemu_host_page_size, prot,
-   flags | MAP_ANONYMOUS, -1, 0);
-if (p == MAP_FAILED)
+if (mmap(host_start, qemu_host_page_size, prot, flags | MAP_ANONYMOUS,
+ -1, 0) == MAP_FAILED) {
 return -1;
+}
 prot1 = prot;
 }
 prot1 &= PAGE_BITS;
-- 
1.7.3.4




[Qemu-devel] [PATCH v3] linux-user/mmap.c: Always zero MAP_ANONYMOUS memory in mmap_frag()

2015-12-29 Thread chengang
From: Chen Gang 

When mapping MAP_ANONYMOUS memory fragments, still need notice about to
set it zero, or it will cause issues.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7b459d5..c6c478e 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -186,10 +186,12 @@ static int mmap_frag(abi_ulong real_start,
 if (prot_new != (prot1 | PROT_WRITE))
 mprotect(host_start, qemu_host_page_size, prot_new);
 } else {
-/* just update the protection */
 if (prot_new != prot1) {
 mprotect(host_start, qemu_host_page_size, prot_new);
 }
+if (prot_new & PROT_WRITE) {
+memset(g2h(start), 0, end - start);
+}
 }
 return 0;
 }
-- 
1.7.3.4




[Qemu-devel] [PATCH] linux-user/mmap.c: Use end instead of real_end in target_mmap

2015-12-23 Thread chengang
From: Chen Gang 

In this case, real_end is larger than end, which may cause mmap_frag
process the incorrect memory region.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7b459d5..57b0361 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -536,7 +536,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 /* handle the end of the mapping */
 if (end < real_end) {
 ret = mmap_frag(real_end - qemu_host_page_size,
-real_end - qemu_host_page_size, real_end,
+real_end - qemu_host_page_size, end,
 prot, flags, fd,
 offset + real_end - qemu_host_page_size - start);
 if (ret == -1)
-- 
1.9.1




[Qemu-devel] [PATCH v4 1/4] target-tilegx: Add floating point shared functions

2015-12-23 Thread chengang
From: Chen Gang 

They are used by fsingle and fdouble helpers.

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fshared.c | 22 +
 target-tilegx/helper-fshared.h | 55 ++
 2 files changed, 77 insertions(+)
 create mode 100644 target-tilegx/helper-fshared.c
 create mode 100644 target-tilegx/helper-fshared.h

diff --git a/target-tilegx/helper-fshared.c b/target-tilegx/helper-fshared.c
new file mode 100644
index 000..bad1c9a
--- /dev/null
+++ b/target-tilegx/helper-fshared.c
@@ -0,0 +1,22 @@
+/*
+ *  TILE-Gx virtual Floating point shared functions
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "fpu/softfloat.h"
+
+float_status fp_status;
diff --git a/target-tilegx/helper-fshared.h b/target-tilegx/helper-fshared.h
new file mode 100644
index 000..5f4926e
--- /dev/null
+++ b/target-tilegx/helper-fshared.h
@@ -0,0 +1,55 @@
+/*
+ *  TILE-Gx virtual Floating point shared functions
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+static inline uint64_t create_fsfd_flag_un(void)
+{
+return 1 << 25;
+}
+
+static inline uint64_t create_fsfd_flag_lt(void)
+{
+return 1 << 26;
+}
+
+static inline uint64_t create_fsfd_flag_le(void)
+{
+return 1 << 27;
+}
+
+static inline uint64_t create_fsfd_flag_gt(void)
+{
+return 1 << 28;
+}
+
+static inline uint64_t create_fsfd_flag_ge(void)
+{
+return 1 << 29;
+}
+
+static inline uint64_t create_fsfd_flag_eq(void)
+{
+return 1 << 30;
+}
+
+static inline uint64_t create_fsfd_flag_ne(void)
+{
+return 1ULL << 31;
+}
+
+extern float_status fp_status;
-- 
1.9.3




[Qemu-devel] [PATCH v4 3/4] target-tilegx: Add double floating point implementation

2015-12-23 Thread chengang
From: Chen Gang 

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fdouble.c | 382 +
 1 file changed, 382 insertions(+)
 create mode 100644 target-tilegx/helper-fdouble.c

diff --git a/target-tilegx/helper-fdouble.c b/target-tilegx/helper-fdouble.c
new file mode 100644
index 000..da09fe7
--- /dev/null
+++ b/target-tilegx/helper-fdouble.c
@@ -0,0 +1,382 @@
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+/*
+ * FDouble instructions implemenation:
+ *
+ * fdouble_unpack_min   ; srca and srcb are float_64 value.
+ *  ; get the min absolute value's mantissa.
+ *  ; move "mantissa >> (exp_max - exp_min)" to dest.
+ *
+ * fdouble_unpack_max   ; srca and srcb are float_64 value.
+ *  ; get the max absolute value's mantissa.
+ *  ; move mantissa to dest.
+ *
+ * fdouble_add_flags; srca and srcb are float_64 value.
+ *  ; calc exp (exp_max), sign, and comp bits for flags.
+ *  ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_sub_flags; srca and srcb are float_64 value.
+ *  ; calc exp (exp_max), sign, and comp bits for flags.
+ *  ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_addsub:  ; dest, srca (max, min mantissa), and srcb (flags).
+ *  ; "dest +/- srca" depend on the add/sub bit of flags.
+ *  ; move result mantissa to dest.
+ *
+ * fdouble_mul_flags:   ; srca and srcb are float_64 value.
+ *  ; calc sign (xor), exp (min + max), and comp bits.
+ *  ; mix sign, exp, and comp bits as flags to dest.
+ *
+ * fdouble_pack1; move srcb (flags) to dest.
+ *
+ * fdouble_pack2; srca, srcb (high, low mantissa), and dest (flags)
+ *  ; normalize and pack result from srca, srcb, and dest.
+ *  ; move result to dest.
+ */
+
+#define TILEGX_F_EXP_DZERO  0x3ff /* Zero exp for double 11-bits */
+#define TILEGX_F_EXP_DMAX   0x7fe /* max exp for double 11-bits */
+#define TILEGX_F_EXP_DUF0x1000/* underflow exp bit for double */
+
+#define TILEGX_F_MAN_HBIT   (1ULL << 59)
+
+#define TILEGX_F_CALC_ADD   1 /* Perform absolute add operation */
+#define TILEGX_F_CALC_SUB   2 /* Perform absolute sub operation */
+#define TILEGX_F_CALC_MUL   3 /* Perform absolute mul operation */
+
+static uint32_t get_f64_exp(float64 d)
+{
+return extract64(float64_val(d), 52, 11);
+}
+
+static void set_f64_exp(float64 *d, uint32_t exp)
+{
+*d = make_float64(deposit64(float64_val(*d), 52, 11, exp));
+}
+
+static uint64_t get_f64_man(float64 d)
+{
+return extract64(float64_val(d), 0, 52);
+}
+
+static uint64_t fr_to_man(float64 d)
+{
+uint64_t val = get_f64_man(d) << 7;
+
+if (get_f64_exp(d)) {
+val |= TILEGX_F_MAN_HBIT; /* Restore HBIT for the next calculation */
+}
+
+return val;
+}
+
+static uint64_t get_fdouble_man(uint64_t n)
+{
+return extract64(n, 0, 60);
+}
+
+static void set_fdouble_man(uint64_t *n, uint64_t man)
+{
+*n = deposit64(*n, 0, 60, man);
+}
+
+static uint64_t get_fdouble_man_of(uint64_t n)
+{
+return test_bit(60, );
+}
+
+static void clear_fdouble_man_of(uint64_t *n)
+{
+return clear_bit(60, n);
+}
+
+static uint32_t get_fdouble_nan(uint64_t n)
+{
+return test_bit(24, );
+}
+
+static void set_fdouble_nan(uint64_t *n)
+{
+set_bit(24, n);
+}
+
+static uint32_t get_fdouble_inf(uint64_t n)
+{
+return test_bit(23, );
+}
+
+static void set_fdouble_inf(uint64_t *n)
+{
+set_bit(23, n);
+}
+
+static uint32_t get_fdouble_calc(uint64_t n)
+{
+return extract32(n, 21, 2);
+}
+
+static void set_fdouble_calc(uint64_t *n, uint32_t calc)
+{
+*n = deposit64(*n, 21, 2, calc);
+}
+
+static uint32_t get_fdouble_sign(uint64_t n)
+{
+return test_bit(20, );
+}
+
+static void set_fdouble_sign(uint64_t *n)
+{
+set_bit(20, n);
+}
+
+static uint32_t get_fdouble_vexp(uint64_t n)

[Qemu-devel] [PATCH v4 4/4] target-tilegx: Integrate floating pointer implementation

2015-12-23 Thread chengang
From: Chen Gang 

It passes normal building, and gcc testsuite.

Signed-off-by: Chen Gang 
---
 target-tilegx/Makefile.objs |  3 ++-
 target-tilegx/helper.h  | 12 +
 target-tilegx/translate.c   | 66 ++---
 3 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/target-tilegx/Makefile.objs b/target-tilegx/Makefile.objs
index 0db778f..2f4ea92 100644
--- a/target-tilegx/Makefile.objs
+++ b/target-tilegx/Makefile.objs
@@ -1 +1,2 @@
-obj-y += cpu.o translate.o helper.o simd_helper.o
+obj-y += cpu.o translate.o helper.o simd_helper.o \
+   helper-fsingle.o helper-fdouble.o helper-fshared.o
diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h
index 9281d0f..3471fe3 100644
--- a/target-tilegx/helper.h
+++ b/target-tilegx/helper.h
@@ -24,3 +24,15 @@ 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_2(fsingle_add1, i64, i64, i64)
+DEF_HELPER_2(fsingle_sub1, i64, i64, i64)
+DEF_HELPER_2(fsingle_mul1, i64, i64, i64)
+DEF_HELPER_1(fsingle_pack2, i64, i64)
+DEF_HELPER_2(fdouble_unpack_min, i64, i64, i64)
+DEF_HELPER_2(fdouble_unpack_max, i64, i64, i64)
+DEF_HELPER_2(fdouble_add_flags, i64, i64, i64)
+DEF_HELPER_2(fdouble_sub_flags, i64, i64, i64)
+DEF_HELPER_3(fdouble_addsub, i64, i64, i64, i64)
+DEF_HELPER_2(fdouble_mul_flags, i64, i64, i64)
+DEF_HELPER_3(fdouble_pack2, i64, i64, i64, i64)
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 354f25a..924eece 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -597,6 +597,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 }
 qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
 return ret;
+
+case OE_RR_X0(FSINGLE_PACK1):
+case OE_RR_Y0(FSINGLE_PACK1):
+mnemonic = "fsingle_pack1";
+goto done2;
 }
 
 tdest = dest_gr(dc, dest);
@@ -613,9 +618,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 gen_helper_cnttz(tdest, tsrca);
 mnemonic = "cnttz";
 break;
-case OE_RR_X0(FSINGLE_PACK1):
-case OE_RR_Y0(FSINGLE_PACK1):
-return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
 case OE_RR_X1(LD1S):
 memop = MO_SB;
 mnemonic = "ld1s"; /* prefetch_l1_fault */
@@ -734,6 +736,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
 return TILEGX_EXCP_OPCODE_UNKNOWN;
 }
 
+done2:
 qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
   reg_names[dest], reg_names[srca]);
 return ret;
@@ -742,13 +745,21 @@ 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 tsrca = load_gr(dc, srca);
-TCGv tsrcb = load_gr(dc, srcb);
+TCGv tdest, tsrca, tsrcb;
 TCGv t0;
 const char *mnemonic;
 
 switch (opext) {
+case OE_RRR(FSINGLE_ADDSUB2, 0, X0):
+mnemonic = "fsingle_addsub2";
+goto done2;
+}
+
+tdest = dest_gr(dc, dest);
+tsrca = load_gr(dc, srca);
+tsrcb = load_gr(dc, srcb);
+
+switch (opext) {
 case OE_RRR(ADDXSC, 0, X0):
 case OE_RRR(ADDXSC, 0, X1):
 gen_saturate_op(tdest, tsrca, tsrcb, tcg_gen_add_tl);
@@ -906,14 +917,37 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned 
opext,
 mnemonic = "exch";
 break;
 case OE_RRR(FDOUBLE_ADDSUB, 0, X0):
+gen_helper_fdouble_addsub(tdest, load_gr(dc, dest), tsrca, tsrcb);
+mnemonic = "fdouble_addsub";
+break;
 case OE_RRR(FDOUBLE_ADD_FLAGS, 0, X0):
+gen_helper_fdouble_add_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_add_flags";
+break;
 case OE_RRR(FDOUBLE_MUL_FLAGS, 0, X0):
+gen_helper_fdouble_mul_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_mul_flags";
+break;
 case OE_RRR(FDOUBLE_PACK1, 0, X0):
+tcg_gen_mov_i64(tdest, tsrcb);
+mnemonic = "fdouble_pack1";
+break;
 case OE_RRR(FDOUBLE_PACK2, 0, X0):
+gen_helper_fdouble_pack2(tdest, load_gr(dc, dest), tsrca, tsrcb);
+mnemonic = "fdouble_pack2";
+break;
 case OE_RRR(FDOUBLE_SUB_FLAGS, 0, X0):
+gen_helper_fdouble_sub_flags(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_sub_flags";
+break;
 case OE_RRR(FDOUBLE_UNPACK_MAX, 0, X0):
+gen_helper_fdouble_unpack_max(tdest, tsrca, tsrcb);
+mnemonic = "fdouble_unpack_max";
+break;
 case OE_RRR(FDOUBLE_UNPACK_MIN, 0, X0):
-return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+  

[Qemu-devel] [PATCH v4 0/4] target-tilegx: Implement floating point instructions

2015-12-23 Thread chengang
From: Chen Gang 

These patches are the normal floating point implementation, instead of
the original temporary one.

It passes building, and gcc testsuite.

Chen Gang (4):
  target-tilegx: Add floating point shared functions
  target-tilegx: Add single floating point implementation
  target-tilegx: Add double floating point implementation
  target-tilegx: Integrate floating pointer implementation

 target-tilegx/Makefile.objs|   3 +-
 target-tilegx/helper-fdouble.c | 382 +
 target-tilegx/helper-fshared.c |  22 +++
 target-tilegx/helper-fshared.h |  55 ++
 target-tilegx/helper-fsingle.c | 211 +++
 target-tilegx/helper.h |  12 ++
 target-tilegx/translate.c  |  66 ++-
 7 files changed, 741 insertions(+), 10 deletions(-)
 create mode 100644 target-tilegx/helper-fdouble.c
 create mode 100644 target-tilegx/helper-fshared.c
 create mode 100644 target-tilegx/helper-fshared.h
 create mode 100644 target-tilegx/helper-fsingle.c

-- 
1.9.3




[Qemu-devel] [PATCH v4 2/4] target-tilegx: Add single floating point implementation

2015-12-23 Thread chengang
From: Chen Gang 

Signed-off-by: Chen Gang 
---
 target-tilegx/helper-fsingle.c | 211 +
 1 file changed, 211 insertions(+)
 create mode 100644 target-tilegx/helper-fsingle.c

diff --git a/target-tilegx/helper-fsingle.c b/target-tilegx/helper-fsingle.c
new file mode 100644
index 000..b6c3b0e
--- /dev/null
+++ b/target-tilegx/helper-fsingle.c
@@ -0,0 +1,211 @@
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+/*
+ * FSingle instructions implemenation:
+ *
+ * fsingle_add1 ; calc srca and srcb,
+ *  ; convert float_32 to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_sub1 ; calc srca and srcb.
+ *  ; convert float_32 to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_addsub2  ; nop.
+ *
+ * fsingle_mul1 ; calc srca and srcb.
+ *  ; convert float_32 value to TileGXFPSFmt result.
+ *  ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_mul2 ; move srca to dest.
+ *
+ * fsingle_pack1; nop
+ *
+ * fsingle_pack2; treate srca as TileGXFPSFmt result.
+ *  ; convert TileGXFPSFmt result to float_32 value.
+ *  ; move float_32 value to dest.
+ */
+
+#define TILEGX_F_CALC_CVT   0 /* convert int to fsingle */
+#define TILEGX_F_CALC_NCVT  1 /* Not convertion */
+
+static uint32_t get_f32_exp(float32 f)
+{
+return extract32(float32_val(f), 23, 8);
+}
+
+static void set_f32_exp(float32 *f, uint32_t exp)
+{
+*f = make_float32(deposit32(float32_val(*f), 23, 8, exp));
+}
+
+static uint32_t get_f32_man(float32 f)
+{
+return float32_val(f) & 0x7f;
+}
+
+static float32 create_f32_man(uint32_t man)
+{
+ return make_float32(man & 0x7f);
+}
+
+static inline uint32_t get_fsingle_exp(uint64_t n)
+{
+return n & 0xff;
+}
+
+static inline uint64_t create_fsingle_exp(uint32_t exp)
+{
+return exp & 0xff;
+}
+
+static inline uint32_t get_fsingle_sign(uint64_t n)
+{
+return test_bit(10, );
+}
+
+static inline void set_fsingle_sign(uint64_t *n)
+{
+set_bit(10, n);
+}
+
+static inline unsigned int get_fsingle_calc(uint64_t n)
+{
+return test_bit(11, );
+}
+
+static inline void set_fsingle_calc(uint64_t *n, uint32_t calc)
+{
+set_bit(11, n);
+}
+
+static inline unsigned int get_fsingle_man(uint64_t n)
+{
+return n >> 32;
+}
+
+static inline uint64_t create_fsingle_man(uint32_t man)
+{
+return (uint64_t)man << 32;
+}
+
+static uint64_t float32_to_sfmt(float32 f)
+{
+uint64_t sfmt = 0;
+
+if (float32_is_neg(f)) {
+set_fsingle_sign();
+}
+sfmt |= create_fsingle_exp(get_f32_exp(f));
+sfmt |= create_fsingle_man((get_f32_man(f) << 8) | (1 << 31));
+
+return sfmt;
+}
+
+static float32 sfmt_to_float32(uint64_t sfmt)
+{
+uint32_t sign = get_fsingle_sign(sfmt);
+uint32_t man = get_fsingle_man(sfmt);
+uint32_t exp = get_fsingle_exp(sfmt);
+float32 f;
+
+if (get_fsingle_calc(sfmt) == TILEGX_F_CALC_CVT) {
+if (sign) {
+f = int32_to_float32(0 - man, _status);
+} else {
+f = uint32_to_float32(man, _status);
+}
+exp += get_f32_exp(f) - 0x9e;
+if ((int32_t) exp < 0) {
+return float32_infinity | float32_set_sign(float32_zero, sign);
+} else if (exp >= 0xff) {
+return float32_zero | float32_set_sign(float32_zero, sign);
+} else {
+set_f32_exp(, exp);
+}
+} else {
+f = create_f32_man(man >> 8);
+set_f32_exp(, exp);
+}
+
+f = float32_set_sign(f, sign);
+return f;
+}
+
+uint64_t helper_fsingle_pack2(uint64_t srca)
+{
+return float32_val(sfmt_to_float32(srca));
+}
+
+static uint64_t main_calc(float32 fsrca, float32 fsrcb,
+  float32 (*calc)(float32, float32, float_status *))
+{
+uint64_t sfmt = float32_to_sfmt(calc(fsrca, fsrcb, _status));
+
+if 

[Qemu-devel] [PATCH v2] linux-user/mmap.c: Always zero MAP_ANONYMOUS memory in mmap_frag()

2015-12-20 Thread chengang
From: Chen Gang 

When mapping MAP_ANONYMOUS memory fragments, still need notice about to
set it zero, or it will cause issues.

Signed-off-by: Chen Gang 
---
 linux-user/mmap.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7b459d5..29fe646 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -186,10 +186,12 @@ static int mmap_frag(abi_ulong real_start,
 if (prot_new != (prot1 | PROT_WRITE))
 mprotect(host_start, qemu_host_page_size, prot_new);
 } else {
-/* just update the protection */
 if (prot_new != prot1) {
 mprotect(host_start, qemu_host_page_size, prot_new);
 }
+if ((prot_new & PROT_WRITE) && ((flags & MAP_PRIVATE) || (fd == -1))) {
+memset(g2h(start), 0, end - start);
+}
 }
 return 0;
 }
-- 
1.7.3.4