Patchwork [PATCHv2,3/3] unicore32: necessary modifications for other files to support unicore32

login
register
mail settings
Submitter Guan Xuetao
Date March 30, 2011, 8:29 a.m.
Message ID <01e901cbeeb4$9ee89e00$dcb9da00$@mprc.pku.edu.cn>
Download mbox | patch
Permalink /patch/88897/
State New
Headers show

Comments

Guan Xuetao - March 30, 2011, 8:29 a.m.
Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
 configure                                |   11 +++-
 cpu-exec.c                               |   12 ++++-
 default-configs/unicore32-linux-user.mak |    1 +
 elf.h                                    |    2 +
 fpu/softfloat-specialize.h               |   10 ++--
 linux-user/elfload.c                     |   74 +++++++++++++++++++++++++
 linux-user/main.c                        |   89 +++++++++++++++++++++++++++++-
 linux-user/qemu.h                        |    5 +-
 linux-user/syscall_defs.h                |   10 ++-
 9 files changed, 201 insertions(+), 13 deletions(-)
 create mode 100644 default-configs/unicore32-linux-user.mak

 #define TARGET_SA_NOCLDSTOP    8u
@@ -1001,7 +1004,8 @@ struct target_winsize {
 #define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */
 #endif
 
-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
+#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
+    || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
 struct target_stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
Blue Swirl - April 10, 2011, 7:22 a.m.
On Wed, Mar 30, 2011 at 11:29 AM, Guan Xuetao <gxt@mprc.pku.edu.cn> wrote:
>
> Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
> ---
>  configure                                |   11 +++-
>  cpu-exec.c                               |   12 ++++-
>  default-configs/unicore32-linux-user.mak |    1 +
>  elf.h                                    |    2 +
>  fpu/softfloat-specialize.h               |   10 ++--
>  linux-user/elfload.c                     |   74 +++++++++++++++++++++++++
>  linux-user/main.c                        |   89 +++++++++++++++++++++++++++++-
>  linux-user/qemu.h                        |    5 +-
>  linux-user/syscall_defs.h                |   10 ++-
>  9 files changed, 201 insertions(+), 13 deletions(-)
>  create mode 100644 default-configs/unicore32-linux-user.mak
>
> diff --git a/configure b/configure
> index 598e8e1..a6633cf 100755
> --- a/configure
> +++ b/configure
> @@ -280,7 +280,7 @@ else
>  fi
>
>  case "$cpu" in
> -  alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64)
> +  alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64|unicore32)

This patch does not apply anymore because of lm32 changes. Please rebase.

>     cpu="$cpu"
>   ;;
>   i386|i486|i586|i686|i86pc|BePC)
> @@ -793,6 +793,9 @@ case "$cpu" in
>     hppa*)
>            host_guest_base="yes"
>            ;;
> +    unicore32*)
> +           host_guest_base="yes"
> +           ;;
>  esac
>
>  [ -z "$guest_base" ] && guest_base="$host_guest_base"
> @@ -1018,6 +1021,7 @@ sh4eb-linux-user \
>  sparc-linux-user \
>  sparc64-linux-user \
>  sparc32plus-linux-user \
> +unicore32-linux-user \
>  "
>     fi
>  # the following are Darwin specific
> @@ -2495,7 +2499,7 @@ echo "docdir=$docdir" >> $config_host_mak
>  echo "confdir=$confdir" >> $config_host_mak
>
>  case "$cpu" in
> -  i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
> +  i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64|unicore32)
>     ARCH=$cpu
>   ;;
>   armv4b|armv4l)
> @@ -3007,6 +3011,9 @@ case "$target_arch2" in
>   s390x)
>     target_phys_bits=64
>   ;;
> +  unicore32)
> +    target_phys_bits=32
> +  ;;
>   *)
>     echo "Unsupported target CPU"
>     exit 1
> diff --git a/cpu-exec.c b/cpu-exec.c
> index 8c9fb8b..130e0c3 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -262,6 +262,7 @@ int cpu_exec(CPUState *env1)
>     env->cc_x = (env->sr >> 4) & 1;
>  #elif defined(TARGET_ALPHA)
>  #elif defined(TARGET_ARM)
> +#elif defined(TARGET_UNICORE32)
>  #elif defined(TARGET_PPC)
>  #elif defined(TARGET_MICROBLAZE)
>  #elif defined(TARGET_MIPS)
> @@ -326,6 +327,8 @@ int cpu_exec(CPUState *env1)
>                     do_interrupt(env);
>  #elif defined(TARGET_ARM)
>                     do_interrupt(env);
> +#elif defined(TARGET_UNICORE32)
> +                    do_interrupt(env);
>  #elif defined(TARGET_SH4)
>                    do_interrupt(env);
>  #elif defined(TARGET_ALPHA)
> @@ -363,7 +366,7 @@ int cpu_exec(CPUState *env1)
>                     }
>  #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
>     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
> -    defined(TARGET_MICROBLAZE)
> +    defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32)
>                     if (interrupt_request & CPU_INTERRUPT_HALT) {
>                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
>                         env->halted = 1;
> @@ -503,6 +506,12 @@ int cpu_exec(CPUState *env1)
>                         do_interrupt(env);
>                         next_tb = 0;
>                     }
> +#elif defined(TARGET_UNICORE32)
> +                    if (interrupt_request & CPU_INTERRUPT_HARD
> +                        && !(env->uncached_asr & ASR_I)) {
> +                        do_interrupt(env);
> +                        next_tb = 0;
> +                    }
>  #elif defined(TARGET_SH4)
>                     if (interrupt_request & CPU_INTERRUPT_HARD) {
>                         do_interrupt(env);
> @@ -653,6 +662,7 @@ int cpu_exec(CPUState *env1)
>     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
>  #elif defined(TARGET_ARM)
>     /* XXX: Save/restore host fpu exception state?.  */
> +#elif defined(TARGET_UNICORE32)
>  #elif defined(TARGET_SPARC)
>  #elif defined(TARGET_PPC)
>  #elif defined(TARGET_M68K)
> diff --git a/default-configs/unicore32-linux-user.mak b/default-configs/unicore32-linux-user.mak
> new file mode 100644
> index 0000000..6aafd21
> --- /dev/null
> +++ b/default-configs/unicore32-linux-user.mak
> @@ -0,0 +1 @@
> +# Default configuration for unicore32-linux-user
> diff --git a/elf.h b/elf.h
> index 7067c90..876c1da 100644
> --- a/elf.h
> +++ b/elf.h
> @@ -105,6 +105,8 @@ typedef int64_t  Elf64_Sxword;
>  #define EM_H8_300H      47      /* Hitachi H8/300H */
>  #define EM_H8S          48      /* Hitachi H8S     */
>
> +#define EM_UNICORE32    110     /* UniCore32 */
> +
>  /*
>  * This is an interim value that we will use until the committee comes
>  * up with a final number.
> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index eb644b2..839049d 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -30,7 +30,7 @@ these four paragraphs for those parts of this code that are retained.
>
>  =============================================================================*/
>
> -#if defined(TARGET_MIPS) || defined(TARGET_SH4)
> +#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
>  #define SNAN_BIT_IS_ONE                1
>  #else
>  #define SNAN_BIT_IS_ONE                0
> @@ -108,7 +108,7 @@ float32 float32_maybe_silence_nan( float32 a_ )
>  {
>     if (float32_is_signaling_nan(a_)) {
>  #if SNAN_BIT_IS_ONE
> -#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
> +#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
>         return float32_default_nan;
>  #  else
>  #    error Rules for silencing a signaling NaN are target-specific
> @@ -362,7 +362,7 @@ float64 float64_maybe_silence_nan( float64 a_ )
>  {
>     if (float64_is_signaling_nan(a_)) {
>  #if SNAN_BIT_IS_ONE
> -#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
> +#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
>         return float64_default_nan;
>  #  else
>  #    error Rules for silencing a signaling NaN are target-specific
> @@ -519,7 +519,7 @@ floatx80 floatx80_maybe_silence_nan( floatx80 a )
>  {
>     if (floatx80_is_signaling_nan(a)) {
>  #if SNAN_BIT_IS_ONE
> -#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
> +#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
>         a.low = floatx80_default_nan_low;
>         a.high = floatx80_default_nan_high;
>  #  else
> @@ -668,7 +668,7 @@ float128 float128_maybe_silence_nan( float128 a )
>  {
>     if (float128_is_signaling_nan(a)) {
>  #if SNAN_BIT_IS_ONE
> -#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
> +#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
>         a.low = float128_default_nan_low;
>         a.high = float128_default_nan_high;
>  #  else
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 08c44d8..0fdb2ed 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -339,6 +339,80 @@ enum
>
>  #endif
>
> +#ifdef TARGET_UNICORE32
> +
> +#define ELF_START_MMAP          0x80000000
> +
> +#define elf_check_arch(x)       ((x) == EM_UNICORE32)
> +
> +#define ELF_CLASS               ELFCLASS32
> +#define ELF_DATA                ELFDATA2LSB
> +#define ELF_ARCH                EM_UNICORE32
> +
> +static inline void init_thread(struct target_pt_regs *regs,
> +        struct image_info *infop)
> +{
> +    abi_long stack = infop->start_stack;
> +    memset(regs, 0, sizeof(*regs));
> +    regs->UC32_REG_asr = 0x10;
> +    regs->UC32_REG_pc = infop->entry & 0xfffffffe;
> +    regs->UC32_REG_sp = infop->start_stack;
> +    /* FIXME - what to for failure of get_user()? */
> +    get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */
> +    get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */
> +    /* XXX: it seems that r0 is zeroed after ! */
> +    regs->UC32_REG_00 = 0;
> +}
> +
> +#define ELF_NREG    34
> +typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
> +
> +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
> +{
> +    (*regs)[0] = env->regs[0];
> +    (*regs)[1] = env->regs[1];
> +    (*regs)[2] = env->regs[2];
> +    (*regs)[3] = env->regs[3];
> +    (*regs)[4] = env->regs[4];
> +    (*regs)[5] = env->regs[5];
> +    (*regs)[6] = env->regs[6];
> +    (*regs)[7] = env->regs[7];
> +    (*regs)[8] = env->regs[8];
> +    (*regs)[9] = env->regs[9];
> +    (*regs)[10] = env->regs[10];
> +    (*regs)[11] = env->regs[11];
> +    (*regs)[12] = env->regs[12];
> +    (*regs)[13] = env->regs[13];
> +    (*regs)[14] = env->regs[14];
> +    (*regs)[15] = env->regs[15];
> +    (*regs)[16] = env->regs[16];
> +    (*regs)[17] = env->regs[17];
> +    (*regs)[18] = env->regs[18];
> +    (*regs)[19] = env->regs[19];
> +    (*regs)[20] = env->regs[20];
> +    (*regs)[21] = env->regs[21];
> +    (*regs)[22] = env->regs[22];
> +    (*regs)[23] = env->regs[23];
> +    (*regs)[24] = env->regs[24];
> +    (*regs)[25] = env->regs[25];
> +    (*regs)[26] = env->regs[26];
> +    (*regs)[27] = env->regs[27];
> +    (*regs)[28] = env->regs[28];
> +    (*regs)[29] = env->regs[29];
> +    (*regs)[30] = env->regs[30];
> +    (*regs)[31] = env->regs[31];
> +
> +    (*regs)[32] = cpu_asr_read((CPUState *)env);
> +    (*regs)[33] = env->regs[0]; /* XXX */
> +}
> +
> +#define USE_ELF_CORE_DUMP
> +#define ELF_EXEC_PAGESIZE               4096
> +
> +#define ELF_HWCAP                       (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64)
> +
> +#endif
> +
>  #ifdef TARGET_SPARC
>  #ifdef TARGET_SPARC64
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 0d627d6..29ade8b 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -816,6 +816,83 @@ void cpu_loop(CPUARMState *env)
>
>  #endif
>
> +#ifdef TARGET_UNICORE32
> +
> +void cpu_loop(CPUState *env)
> +{
> +    int trapnr;
> +    unsigned int n, insn;
> +    target_siginfo_t info;
> +
> +    for (;;) {
> +        cpu_exec_start(env);
> +        trapnr = uc32_cpu_exec(env);
> +        cpu_exec_end(env);
> +        switch (trapnr) {
> +        case UC32_EXCP_PRIV:
> +            {
> +                /* system call */
> +                get_user_u32(insn, env->regs[31] - 4);
> +                n = insn & 0xffffff;
> +
> +                if (n >= UC32_SYSCALL_BASE) {
> +                    /* linux syscall */
> +                    n -= UC32_SYSCALL_BASE;
> +                    if (n == UC32_SYSCALL_NR_set_tls) {
> +                            cpu_set_tls(env, env->regs[0]);
> +                            env->regs[0] = 0;
> +                    } else {
> +                        env->regs[0] = do_syscall(env,
> +                                                  n,
> +                                                  env->regs[0],
> +                                                  env->regs[1],
> +                                                  env->regs[2],
> +                                                  env->regs[3],
> +                                                  env->regs[4],
> +                                                  env->regs[5]);
> +                    }
> +                } else {
> +                    goto error;
> +                }
> +            }
> +            break;
> +        case UC32_EXCP_TRAP:
> +            info.si_signo = SIGSEGV;
> +            info.si_errno = 0;
> +            /* XXX: check env->error_code */
> +            info.si_code = TARGET_SEGV_MAPERR;
> +            info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
> +            queue_signal(env, info.si_signo, &info);
> +            break;
> +        case EXCP_INTERRUPT:
> +            /* just indicate that signals should be handled asap */
> +            break;
> +        case EXCP_DEBUG:
> +            {
> +                int sig;
> +
> +                sig = gdb_handlesig(env, TARGET_SIGTRAP);
> +                if (sig) {
> +                    info.si_signo = sig;
> +                    info.si_errno = 0;
> +                    info.si_code = TARGET_TRAP_BRKPT;
> +                    queue_signal(env, info.si_signo, &info);
> +                }
> +            }
> +            break;
> +        default:
> +            goto error;
> +        }
> +        process_pending_signals(env);
> +    }
> +
> +error:
> +    fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
> +    cpu_dump_state(env, stderr, fprintf, 0);
> +    abort();
> +}
> +#endif
> +
>  #ifdef TARGET_SPARC
>  #define SPARC64_STACK_BIAS 2047
>
> @@ -2916,6 +2993,8 @@ int main(int argc, char **argv, char **envp)
>  #endif
>  #elif defined(TARGET_ARM)
>         cpu_model = "any";
> +#elif defined(TARGET_UNICORE32)
> +        cpu_model = "any";
>  #elif defined(TARGET_M68K)
>         cpu_model = "any";
>  #elif defined(TARGET_SPARC)
> @@ -3218,6 +3297,14 @@ int main(int argc, char **argv, char **envp)
>             env->regs[i] = regs->uregs[i];
>         }
>     }
> +#elif defined(TARGET_UNICORE32)
> +    {
> +        int i;
> +        cpu_asr_write(env, regs->uregs[32], 0xffffffff);
> +        for (i = 0; i < 32; i++) {
> +            env->regs[i] = regs->uregs[i];
> +        }
> +    }
>  #elif defined(TARGET_SPARC)
>     {
>         int i;
> @@ -3358,7 +3445,7 @@ int main(int argc, char **argv, char **envp)
>  #error unsupported target CPU
>  #endif
>
> -#if defined(TARGET_ARM) || defined(TARGET_M68K)
> +#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
>     ts->stack_base = info->start_stack;
>     ts->heap_base = info->brk;
>     /* This will be filled in on the first SYS_HEAPINFO call.  */
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index 32de241..39218f4 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -98,6 +98,9 @@ typedef struct TaskState {
>     FPA11 fpa;
>     int swi_errno;
>  #endif
> +#ifdef TARGET_UNICORE32
> +    int swi_errno;
> +#endif
>  #if defined(TARGET_I386) && !defined(TARGET_X86_64)
>     abi_ulong target_v86;
>     struct vm86_saved_state vm86_saved_regs;
> @@ -111,7 +114,7 @@ typedef struct TaskState {
>  #ifdef TARGET_M68K
>     int sim_syscalls;
>  #endif
> -#if defined(TARGET_ARM) || defined(TARGET_M68K)
> +#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
>     /* Extra fields for semihosted binaries.  */
>     uint32_t stack_base;
>     uint32_t heap_base;
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index d02a9bf..daa2107 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -55,7 +55,7 @@
>  #endif
>
>  #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
> -    || defined(TARGET_M68K) || defined(TARGET_CRIS)
> +    || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
>
>  #define TARGET_IOC_SIZEBITS    14
>  #define TARGET_IOC_DIRBITS     2
> @@ -315,7 +315,10 @@ struct target_sigaction;
>  int do_sigaction(int sig, const struct target_sigaction *act,
>                  struct target_sigaction *oact);
>
> -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined
> (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE)
> +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
> +    || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \
> +    || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \
> +    || defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32)
>
>  #if defined(TARGET_SPARC)
>  #define TARGET_SA_NOCLDSTOP    8u
> @@ -1001,7 +1004,8 @@ struct target_winsize {
>  #define TARGET_MAP_NONBLOCK    0x10000         /* do not block on IO */
>  #endif
>
> -#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
> +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
> +    || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
>  struct target_stat {
>        unsigned short st_dev;
>        unsigned short __pad1;
> --
> 1.6.2.2
>
>
>

Patch

diff --git a/configure b/configure
index 598e8e1..a6633cf 100755
--- a/configure
+++ b/configure
@@ -280,7 +280,7 @@  else
 fi
 
 case "$cpu" in
-  alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64)
+  alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64|unicore32)
     cpu="$cpu"
   ;;
   i386|i486|i586|i686|i86pc|BePC)
@@ -793,6 +793,9 @@  case "$cpu" in
     hppa*)
            host_guest_base="yes"
            ;;
+    unicore32*)
+           host_guest_base="yes"
+           ;;
 esac
 
 [ -z "$guest_base" ] && guest_base="$host_guest_base"
@@ -1018,6 +1021,7 @@  sh4eb-linux-user \
 sparc-linux-user \
 sparc64-linux-user \
 sparc32plus-linux-user \
+unicore32-linux-user \
 "
     fi
 # the following are Darwin specific
@@ -2495,7 +2499,7 @@  echo "docdir=$docdir" >> $config_host_mak
 echo "confdir=$confdir" >> $config_host_mak
 
 case "$cpu" in
-  i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
+  i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64|unicore32)
     ARCH=$cpu
   ;;
   armv4b|armv4l)
@@ -3007,6 +3011,9 @@  case "$target_arch2" in
   s390x)
     target_phys_bits=64
   ;;
+  unicore32)
+    target_phys_bits=32
+  ;;
   *)
     echo "Unsupported target CPU"
     exit 1
diff --git a/cpu-exec.c b/cpu-exec.c
index 8c9fb8b..130e0c3 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -262,6 +262,7 @@  int cpu_exec(CPUState *env1)
     env->cc_x = (env->sr >> 4) & 1;
 #elif defined(TARGET_ALPHA)
 #elif defined(TARGET_ARM)
+#elif defined(TARGET_UNICORE32)
 #elif defined(TARGET_PPC)
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
@@ -326,6 +327,8 @@  int cpu_exec(CPUState *env1)
                     do_interrupt(env);
 #elif defined(TARGET_ARM)
                     do_interrupt(env);
+#elif defined(TARGET_UNICORE32)
+                    do_interrupt(env);
 #elif defined(TARGET_SH4)
 		    do_interrupt(env);
 #elif defined(TARGET_ALPHA)
@@ -363,7 +366,7 @@  int cpu_exec(CPUState *env1)
                     }
 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
-    defined(TARGET_MICROBLAZE)
+    defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                         env->halted = 1;
@@ -503,6 +506,12 @@  int cpu_exec(CPUState *env1)
                         do_interrupt(env);
                         next_tb = 0;
                     }
+#elif defined(TARGET_UNICORE32)
+                    if (interrupt_request & CPU_INTERRUPT_HARD
+                        && !(env->uncached_asr & ASR_I)) {
+                        do_interrupt(env);
+                        next_tb = 0;
+                    }
 #elif defined(TARGET_SH4)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         do_interrupt(env);
@@ -653,6 +662,7 @@  int cpu_exec(CPUState *env1)
     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
+#elif defined(TARGET_UNICORE32)
 #elif defined(TARGET_SPARC)
 #elif defined(TARGET_PPC)
 #elif defined(TARGET_M68K)
diff --git a/default-configs/unicore32-linux-user.mak b/default-configs/unicore32-linux-user.mak
new file mode 100644
index 0000000..6aafd21
--- /dev/null
+++ b/default-configs/unicore32-linux-user.mak
@@ -0,0 +1 @@ 
+# Default configuration for unicore32-linux-user
diff --git a/elf.h b/elf.h
index 7067c90..876c1da 100644
--- a/elf.h
+++ b/elf.h
@@ -105,6 +105,8 @@  typedef int64_t  Elf64_Sxword;
 #define EM_H8_300H      47      /* Hitachi H8/300H */
 #define EM_H8S          48      /* Hitachi H8S     */
 
+#define EM_UNICORE32    110     /* UniCore32 */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index eb644b2..839049d 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -30,7 +30,7 @@  these four paragraphs for those parts of this code that are retained.
 
 =============================================================================*/
 
-#if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
 #define SNAN_BIT_IS_ONE		1
 #else
 #define SNAN_BIT_IS_ONE		0
@@ -108,7 +108,7 @@  float32 float32_maybe_silence_nan( float32 a_ )
 {
     if (float32_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float32_default_nan;
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -362,7 +362,7 @@  float64 float64_maybe_silence_nan( float64 a_ )
 {
     if (float64_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float64_default_nan;
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -519,7 +519,7 @@  floatx80 floatx80_maybe_silence_nan( floatx80 a )
 {
     if (floatx80_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a.low = floatx80_default_nan_low;
         a.high = floatx80_default_nan_high;
 #  else
@@ -668,7 +668,7 @@  float128 float128_maybe_silence_nan( float128 a )
 {
     if (float128_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a.low = float128_default_nan_low;
         a.high = float128_default_nan_high;
 #  else
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 08c44d8..0fdb2ed 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -339,6 +339,80 @@  enum
 
 #endif
 
+#ifdef TARGET_UNICORE32
+
+#define ELF_START_MMAP          0x80000000
+
+#define elf_check_arch(x)       ((x) == EM_UNICORE32)
+
+#define ELF_CLASS               ELFCLASS32
+#define ELF_DATA                ELFDATA2LSB
+#define ELF_ARCH                EM_UNICORE32
+
+static inline void init_thread(struct target_pt_regs *regs,
+        struct image_info *infop)
+{
+    abi_long stack = infop->start_stack;
+    memset(regs, 0, sizeof(*regs));
+    regs->UC32_REG_asr = 0x10;
+    regs->UC32_REG_pc = infop->entry & 0xfffffffe;
+    regs->UC32_REG_sp = infop->start_stack;
+    /* FIXME - what to for failure of get_user()? */
+    get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */
+    get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */
+    /* XXX: it seems that r0 is zeroed after ! */
+    regs->UC32_REG_00 = 0;
+}
+
+#define ELF_NREG    34
+typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
+
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+{
+    (*regs)[0] = env->regs[0];
+    (*regs)[1] = env->regs[1];
+    (*regs)[2] = env->regs[2];
+    (*regs)[3] = env->regs[3];
+    (*regs)[4] = env->regs[4];
+    (*regs)[5] = env->regs[5];
+    (*regs)[6] = env->regs[6];
+    (*regs)[7] = env->regs[7];
+    (*regs)[8] = env->regs[8];
+    (*regs)[9] = env->regs[9];
+    (*regs)[10] = env->regs[10];
+    (*regs)[11] = env->regs[11];
+    (*regs)[12] = env->regs[12];
+    (*regs)[13] = env->regs[13];
+    (*regs)[14] = env->regs[14];
+    (*regs)[15] = env->regs[15];
+    (*regs)[16] = env->regs[16];
+    (*regs)[17] = env->regs[17];
+    (*regs)[18] = env->regs[18];
+    (*regs)[19] = env->regs[19];
+    (*regs)[20] = env->regs[20];
+    (*regs)[21] = env->regs[21];
+    (*regs)[22] = env->regs[22];
+    (*regs)[23] = env->regs[23];
+    (*regs)[24] = env->regs[24];
+    (*regs)[25] = env->regs[25];
+    (*regs)[26] = env->regs[26];
+    (*regs)[27] = env->regs[27];
+    (*regs)[28] = env->regs[28];
+    (*regs)[29] = env->regs[29];
+    (*regs)[30] = env->regs[30];
+    (*regs)[31] = env->regs[31];
+
+    (*regs)[32] = cpu_asr_read((CPUState *)env);
+    (*regs)[33] = env->regs[0]; /* XXX */
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE               4096
+
+#define ELF_HWCAP                       (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64)
+
+#endif
+
 #ifdef TARGET_SPARC
 #ifdef TARGET_SPARC64
 
diff --git a/linux-user/main.c b/linux-user/main.c
index 0d627d6..29ade8b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -816,6 +816,83 @@  void cpu_loop(CPUARMState *env)
 
 #endif
 
+#ifdef TARGET_UNICORE32
+
+void cpu_loop(CPUState *env)
+{
+    int trapnr;
+    unsigned int n, insn;
+    target_siginfo_t info;
+
+    for (;;) {
+        cpu_exec_start(env);
+        trapnr = uc32_cpu_exec(env);
+        cpu_exec_end(env);
+        switch (trapnr) {
+        case UC32_EXCP_PRIV:
+            {
+                /* system call */
+                get_user_u32(insn, env->regs[31] - 4);
+                n = insn & 0xffffff;
+
+                if (n >= UC32_SYSCALL_BASE) {
+                    /* linux syscall */
+                    n -= UC32_SYSCALL_BASE;
+                    if (n == UC32_SYSCALL_NR_set_tls) {
+                            cpu_set_tls(env, env->regs[0]);
+                            env->regs[0] = 0;
+                    } else {
+                        env->regs[0] = do_syscall(env,
+                                                  n,
+                                                  env->regs[0],
+                                                  env->regs[1],
+                                                  env->regs[2],
+                                                  env->regs[3],
+                                                  env->regs[4],
+                                                  env->regs[5]);
+                    }
+                } else {
+                    goto error;
+                }
+            }
+            break;
+        case UC32_EXCP_TRAP:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            /* XXX: check env->error_code */
+            info.si_code = TARGET_SEGV_MAPERR;
+            info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
+            queue_signal(env, info.si_signo, &info);
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.si_signo, &info);
+                }
+            }
+            break;
+        default:
+            goto error;
+        }
+        process_pending_signals(env);
+    }
+
+error:
+    fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
+    cpu_dump_state(env, stderr, fprintf, 0);
+    abort();
+}
+#endif
+
 #ifdef TARGET_SPARC
 #define SPARC64_STACK_BIAS 2047
 
@@ -2916,6 +2993,8 @@  int main(int argc, char **argv, char **envp)
 #endif
 #elif defined(TARGET_ARM)
         cpu_model = "any";
+#elif defined(TARGET_UNICORE32)
+        cpu_model = "any";
 #elif defined(TARGET_M68K)
         cpu_model = "any";
 #elif defined(TARGET_SPARC)
@@ -3218,6 +3297,14 @@  int main(int argc, char **argv, char **envp)
             env->regs[i] = regs->uregs[i];
         }
     }
+#elif defined(TARGET_UNICORE32)
+    {
+        int i;
+        cpu_asr_write(env, regs->uregs[32], 0xffffffff);
+        for (i = 0; i < 32; i++) {
+            env->regs[i] = regs->uregs[i];
+        }
+    }
 #elif defined(TARGET_SPARC)
     {
         int i;
@@ -3358,7 +3445,7 @@  int main(int argc, char **argv, char **envp)
 #error unsupported target CPU
 #endif
 
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
     ts->stack_base = info->start_stack;
     ts->heap_base = info->brk;
     /* This will be filled in on the first SYS_HEAPINFO call.  */
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 32de241..39218f4 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -98,6 +98,9 @@  typedef struct TaskState {
     FPA11 fpa;
     int swi_errno;
 #endif
+#ifdef TARGET_UNICORE32
+    int swi_errno;
+#endif
 #if defined(TARGET_I386) && !defined(TARGET_X86_64)
     abi_ulong target_v86;
     struct vm86_saved_state vm86_saved_regs;
@@ -111,7 +114,7 @@  typedef struct TaskState {
 #ifdef TARGET_M68K
     int sim_syscalls;
 #endif
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
     /* Extra fields for semihosted binaries.  */
     uint32_t stack_base;
     uint32_t heap_base;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index d02a9bf..daa2107 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -55,7 +55,7 @@ 
 #endif
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
-    || defined(TARGET_M68K) || defined(TARGET_CRIS)
+    || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
 
 #define TARGET_IOC_SIZEBITS	14
 #define TARGET_IOC_DIRBITS	2
@@ -315,7 +315,10 @@  struct target_sigaction;
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact);
 
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined
(TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
+    || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \
+    || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \
+    || defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32)
 
 #if defined(TARGET_SPARC)