Signed-off-by: Mike Frysinger <vap...@gentoo.org>
---
 default-configs/bfin-linux-user.mak |   1 +
 linux-user/bfin/syscall.h           |  59 ++++++
 linux-user/bfin/syscall_nr.h        | 389 ++++++++++++++++++++++++++++++++++++
 linux-user/bfin/target_flat.h       |  92 +++++++++
 linux-user/bfin/target_sigcontext.h |  61 ++++++
 linux-user/bfin/target_signal.h     |  31 +++
 linux-user/bfin/termbits.h          | 227 +++++++++++++++++++++
 linux-user/elfload.c                |  47 +++++
 linux-user/main.c                   | 160 +++++++++++++++
 linux-user/qemu.h                   |   4 +
 linux-user/signal.c                 | 225 +++++++++++++++++++++
 linux-user/syscall.c                |   3 +-
 linux-user/syscall_defs.h           |  65 +++++-
 linux-user/target_ucontext.h        |  14 ++
 14 files changed, 1375 insertions(+), 3 deletions(-)
 create mode 100644 default-configs/bfin-linux-user.mak
 create mode 100644 linux-user/bfin/syscall.h
 create mode 100644 linux-user/bfin/syscall_nr.h
 create mode 100644 linux-user/bfin/target_flat.h
 create mode 100644 linux-user/bfin/target_sigcontext.h
 create mode 100644 linux-user/bfin/target_signal.h
 create mode 100644 linux-user/bfin/termbits.h
 create mode 100644 linux-user/target_ucontext.h

diff --git a/default-configs/bfin-linux-user.mak 
b/default-configs/bfin-linux-user.mak
new file mode 100644
index 0000000..5f7aefb
--- /dev/null
+++ b/default-configs/bfin-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for bfin-linux-user
diff --git a/linux-user/bfin/syscall.h b/linux-user/bfin/syscall.h
new file mode 100644
index 0000000..892ee75
--- /dev/null
+++ b/linux-user/bfin/syscall.h
@@ -0,0 +1,59 @@
+struct target_pt_regs {
+       abi_ulong orig_pc;
+       abi_ulong ipend;
+       abi_ulong seqstat;
+       abi_ulong rete;
+       abi_ulong retn;
+       abi_ulong retx;
+       abi_ulong pc;           /* PC == RETI */
+       abi_ulong rets;
+       abi_ulong reserved;             /* Used as scratch during system calls 
*/
+       abi_ulong astat;
+       abi_ulong lb1;
+       abi_ulong lb0;
+       abi_ulong lt1;
+       abi_ulong lt0;
+       abi_ulong lc1;
+       abi_ulong lc0;
+       abi_ulong a1w;
+       abi_ulong a1x;
+       abi_ulong a0w;
+       abi_ulong a0x;
+       abi_ulong b3;
+       abi_ulong b2;
+       abi_ulong b1;
+       abi_ulong b0;
+       abi_ulong l3;
+       abi_ulong l2;
+       abi_ulong l1;
+       abi_ulong l0;
+       abi_ulong m3;
+       abi_ulong m2;
+       abi_ulong m1;
+       abi_ulong m0;
+       abi_ulong i3;
+       abi_ulong i2;
+       abi_ulong i1;
+       abi_ulong i0;
+       abi_ulong usp;
+       abi_ulong fp;
+       abi_ulong p5;
+       abi_ulong p4;
+       abi_ulong p3;
+       abi_ulong p2;
+       abi_ulong p1;
+       abi_ulong p0;
+       abi_ulong r7;
+       abi_ulong r6;
+       abi_ulong r5;
+       abi_ulong r4;
+       abi_ulong r3;
+       abi_ulong r2;
+       abi_ulong r1;
+       abi_ulong r0;
+       abi_ulong orig_r0;
+       abi_ulong orig_p0;
+       abi_ulong syscfg;
+};
+
+#define UNAME_MACHINE "blackfin"
diff --git a/linux-user/bfin/syscall_nr.h b/linux-user/bfin/syscall_nr.h
new file mode 100644
index 0000000..52ec628
--- /dev/null
+++ b/linux-user/bfin/syscall_nr.h
@@ -0,0 +1,389 @@
+/*
+ * This file contains the system call numbers.
+ */
+#define TARGET_NR_restart_syscall        0
+#define TARGET_NR_exit           1
+#define TARGET_NR_fork           2
+#define TARGET_NR_read           3
+#define TARGET_NR_write                  4
+#define TARGET_NR_open           5
+#define TARGET_NR_close                  6
+                               /* 7 TARGET_NR_waitpid obsolete */
+#define TARGET_NR_creat                  8
+#define TARGET_NR_link           9
+#define TARGET_NR_unlink                10
+#define TARGET_NR_execve                11
+#define TARGET_NR_chdir                 12
+#define TARGET_NR_time          13
+#define TARGET_NR_mknod                 14
+#define TARGET_NR_chmod                 15
+#define TARGET_NR_chown                 16
+                               /* 17 TARGET_NR_break obsolete */
+                               /* 18 TARGET_NR_oldstat obsolete */
+#define TARGET_NR_lseek                 19
+#define TARGET_NR_getpid                20
+#define TARGET_NR_mount                 21
+                               /* 22 TARGET_NR_umount obsolete */
+#define TARGET_NR_setuid                23
+#define TARGET_NR_getuid                24
+#define TARGET_NR_stime                 25
+#define TARGET_NR_ptrace                26
+#define TARGET_NR_alarm                 27
+                               /* 28 TARGET_NR_oldfstat obsolete */
+#define TARGET_NR_pause                 29
+                               /* 30 TARGET_NR_utime obsolete */
+                               /* 31 TARGET_NR_stty obsolete */
+                               /* 32 TARGET_NR_gtty obsolete */
+#define TARGET_NR_access                33
+#define TARGET_NR_nice          34
+                               /* 35 TARGET_NR_ftime obsolete */
+#define TARGET_NR_sync          36
+#define TARGET_NR_kill          37
+#define TARGET_NR_rename                38
+#define TARGET_NR_mkdir                 39
+#define TARGET_NR_rmdir                 40
+#define TARGET_NR_dup           41
+#define TARGET_NR_pipe          42
+#define TARGET_NR_times                 43
+                               /* 44 TARGET_NR_prof obsolete */
+#define TARGET_NR_brk           45
+#define TARGET_NR_setgid                46
+#define TARGET_NR_getgid                47
+                               /* 48 TARGET_NR_signal obsolete */
+#define TARGET_NR_geteuid               49
+#define TARGET_NR_getegid               50
+#define TARGET_NR_acct          51
+#define TARGET_NR_umount2               52
+                               /* 53 TARGET_NR_lock obsolete */
+#define TARGET_NR_ioctl                 54
+#define TARGET_NR_fcntl                 55
+                               /* 56 TARGET_NR_mpx obsolete */
+#define TARGET_NR_setpgid               57
+                               /* 58 TARGET_NR_ulimit obsolete */
+                               /* 59 TARGET_NR_oldolduname obsolete */
+#define TARGET_NR_umask                 60
+#define TARGET_NR_chroot                61
+#define TARGET_NR_ustat                 62
+#define TARGET_NR_dup2          63
+#define TARGET_NR_getppid               64
+#define TARGET_NR_getpgrp               65
+#define TARGET_NR_setsid                66
+                               /* 67 TARGET_NR_sigaction obsolete */
+#define TARGET_NR_sgetmask              68
+#define TARGET_NR_ssetmask              69
+#define TARGET_NR_setreuid              70
+#define TARGET_NR_setregid              71
+                               /* 72 TARGET_NR_sigsuspend obsolete */
+                               /* 73 TARGET_NR_sigpending obsolete */
+#define TARGET_NR_sethostname   74
+#define TARGET_NR_setrlimit             75
+                               /* 76 TARGET_NR_old_getrlimit obsolete */
+#define TARGET_NR_getrusage             77
+#define TARGET_NR_gettimeofday  78
+#define TARGET_NR_settimeofday  79
+#define TARGET_NR_getgroups             80
+#define TARGET_NR_setgroups             81
+                               /* 82 TARGET_NR_select obsolete */
+#define TARGET_NR_symlink               83
+                               /* 84 TARGET_NR_oldlstat obsolete */
+#define TARGET_NR_readlink              85
+                               /* 86 TARGET_NR_uselib obsolete */
+                               /* 87 TARGET_NR_swapon obsolete */
+#define TARGET_NR_reboot                88
+                               /* 89 TARGET_NR_readdir obsolete */
+                               /* 90 TARGET_NR_mmap obsolete */
+#define TARGET_NR_munmap                91
+#define TARGET_NR_truncate              92
+#define TARGET_NR_ftruncate             93
+#define TARGET_NR_fchmod                94
+#define TARGET_NR_fchown                95
+#define TARGET_NR_getpriority   96
+#define TARGET_NR_setpriority   97
+                               /* 98 TARGET_NR_profil obsolete */
+#define TARGET_NR_statfs                99
+#define TARGET_NR_fstatfs              100
+                               /* 101 TARGET_NR_ioperm */
+                               /* 102 TARGET_NR_socketcall obsolete */
+#define TARGET_NR_syslog               103
+#define TARGET_NR_setitimer            104
+#define TARGET_NR_getitimer            105
+#define TARGET_NR_stat         106
+#define TARGET_NR_lstat                107
+#define TARGET_NR_fstat                108
+                               /* 109 TARGET_NR_olduname obsolete */
+                               /* 110 TARGET_NR_iopl obsolete */
+#define TARGET_NR_vhangup              111
+                               /* 112 TARGET_NR_idle obsolete */
+                               /* 113 TARGET_NR_vm86old */
+#define TARGET_NR_wait4                114
+                               /* 115 TARGET_NR_swapoff obsolete */
+#define TARGET_NR_sysinfo              116
+                               /* 117 TARGET_NR_ipc oboslete */
+#define TARGET_NR_fsync                118
+                               /* 119 TARGET_NR_sigreturn obsolete */
+#define TARGET_NR_clone                120
+#define TARGET_NR_setdomainname        121
+#define TARGET_NR_uname                122
+                               /* 123 TARGET_NR_modify_ldt obsolete */
+#define TARGET_NR_adjtimex             124
+#define TARGET_NR_mprotect             125
+                               /* 126 TARGET_NR_sigprocmask obsolete */
+                               /* 127 TARGET_NR_create_module obsolete */
+#define TARGET_NR_init_module  128
+#define TARGET_NR_delete_module        129
+                               /* 130 TARGET_NR_get_kernel_syms obsolete */
+#define TARGET_NR_quotactl             131
+#define TARGET_NR_getpgid              132
+#define TARGET_NR_fchdir               133
+#define TARGET_NR_bdflush              134
+                               /* 135 was sysfs */
+#define TARGET_NR_personality  136
+                               /* 137 TARGET_NR_afs_syscall */
+#define TARGET_NR_setfsuid             138
+#define TARGET_NR_setfsgid             139
+#define TARGET_NR__llseek              140
+#define TARGET_NR_getdents             141
+                               /* 142 TARGET_NR__newselect obsolete */
+#define TARGET_NR_flock                143
+                               /* 144 TARGET_NR_msync obsolete */
+#define TARGET_NR_readv                145
+#define TARGET_NR_writev               146
+#define TARGET_NR_getsid               147
+#define TARGET_NR_fdatasync            148
+#define TARGET_NR__sysctl              149
+                               /* 150 TARGET_NR_mlock */
+                               /* 151 TARGET_NR_munlock */
+                               /* 152 TARGET_NR_mlockall */
+                               /* 153 TARGET_NR_munlockall */
+#define TARGET_NR_sched_setparam               154
+#define TARGET_NR_sched_getparam               155
+#define TARGET_NR_sched_setscheduler           156
+#define TARGET_NR_sched_getscheduler           157
+#define TARGET_NR_sched_yield          158
+#define TARGET_NR_sched_get_priority_max       159
+#define TARGET_NR_sched_get_priority_min       160
+#define TARGET_NR_sched_rr_get_interval        161
+#define TARGET_NR_nanosleep            162
+#define TARGET_NR_mremap               163
+#define TARGET_NR_setresuid            164
+#define TARGET_NR_getresuid            165
+                               /* 166 TARGET_NR_vm86 */
+                               /* 167 TARGET_NR_query_module */
+                               /* 168 TARGET_NR_poll */
+#define TARGET_NR_nfsservctl           169
+#define TARGET_NR_setresgid            170
+#define TARGET_NR_getresgid            171
+#define TARGET_NR_prctl                172
+#define TARGET_NR_rt_sigreturn 173
+#define TARGET_NR_rt_sigaction 174
+#define TARGET_NR_rt_sigprocmask       175
+#define TARGET_NR_rt_sigpending        176
+#define TARGET_NR_rt_sigtimedwait      177
+#define TARGET_NR_rt_sigqueueinfo      178
+#define TARGET_NR_rt_sigsuspend        179
+#define TARGET_NR_pread                180
+#define TARGET_NR_pwrite               181
+#define TARGET_NR_lchown               182
+#define TARGET_NR_getcwd               183
+#define TARGET_NR_capget               184
+#define TARGET_NR_capset               185
+#define TARGET_NR_sigaltstack  186
+#define TARGET_NR_sendfile             187
+                               /* 188 TARGET_NR_getpmsg */
+                               /* 189 TARGET_NR_putpmsg */
+#define TARGET_NR_vfork                190
+#define TARGET_NR_getrlimit            191
+#define TARGET_NR_mmap2                192     /* xxx: this is mmap2 !? */
+#define TARGET_NR_truncate64           193
+#define TARGET_NR_ftruncate64  194
+#define TARGET_NR_stat64               195
+#define TARGET_NR_lstat64              196
+#define TARGET_NR_fstat64              197
+#define TARGET_NR_chown32              198
+#define TARGET_NR_getuid32             199
+#define TARGET_NR_getgid32             200
+#define TARGET_NR_geteuid32            201
+#define TARGET_NR_getegid32            202
+#define TARGET_NR_setreuid32           203
+#define TARGET_NR_setregid32           204
+#define TARGET_NR_getgroups32  205
+#define TARGET_NR_setgroups32  206
+#define TARGET_NR_fchown32             207
+#define TARGET_NR_setresuid32  208
+#define TARGET_NR_getresuid32  209
+#define TARGET_NR_setresgid32  210
+#define TARGET_NR_getresgid32  211
+#define TARGET_NR_lchown32             212
+#define TARGET_NR_setuid32             213
+#define TARGET_NR_setgid32             214
+#define TARGET_NR_setfsuid32           215
+#define TARGET_NR_setfsgid32           216
+#define TARGET_NR_pivot_root           217
+                               /* 218 TARGET_NR_mincore */
+                               /* 219 TARGET_NR_madvise */
+#define TARGET_NR_getdents64           220
+#define TARGET_NR_fcntl64              221
+                               /* 222 reserved for TUX */
+                               /* 223 reserved for TUX */
+#define TARGET_NR_gettid               224
+#define TARGET_NR_readahead            225
+#define TARGET_NR_setxattr             226
+#define TARGET_NR_lsetxattr            227
+#define TARGET_NR_fsetxattr            228
+#define TARGET_NR_getxattr             229
+#define TARGET_NR_lgetxattr            230
+#define TARGET_NR_fgetxattr            231
+#define TARGET_NR_listxattr            232
+#define TARGET_NR_llistxattr           233
+#define TARGET_NR_flistxattr           234
+#define TARGET_NR_removexattr  235
+#define TARGET_NR_lremovexattr 236
+#define TARGET_NR_fremovexattr 237
+#define TARGET_NR_tkill                238
+#define TARGET_NR_sendfile64           239
+#define TARGET_NR_futex                240
+#define TARGET_NR_sched_setaffinity    241
+#define TARGET_NR_sched_getaffinity    242
+                               /* 243 TARGET_NR_set_thread_area */
+                               /* 244 TARGET_NR_get_thread_area */
+#define TARGET_NR_io_setup             245
+#define TARGET_NR_io_destroy           246
+#define TARGET_NR_io_getevents 247
+#define TARGET_NR_io_submit            248
+#define TARGET_NR_io_cancel            249
+                               /* 250 TARGET_NR_alloc_hugepages */
+                               /* 251 TARGET_NR_free_hugepages */
+#define TARGET_NR_exit_group           252
+#define TARGET_NR_lookup_dcookie     253
+#define TARGET_NR_bfin_spinlock      254
+
+#define TARGET_NR_epoll_create 255
+#define TARGET_NR_epoll_ctl            256
+#define TARGET_NR_epoll_wait           257
+                               /* 258 TARGET_NR_remap_file_pages */
+#define TARGET_NR_set_tid_address      259
+#define TARGET_NR_timer_create 260
+#define TARGET_NR_timer_settime        261
+#define TARGET_NR_timer_gettime        262
+#define TARGET_NR_timer_getoverrun     263
+#define TARGET_NR_timer_delete 264
+#define TARGET_NR_clock_settime        265
+#define TARGET_NR_clock_gettime        266
+#define TARGET_NR_clock_getres 267
+#define TARGET_NR_clock_nanosleep      268
+#define TARGET_NR_statfs64             269
+#define TARGET_NR_fstatfs64            270
+#define TARGET_NR_tgkill               271
+#define TARGET_NR_utimes               272
+#define TARGET_NR_fadvise64_64 273
+                               /* 274 TARGET_NR_vserver */
+                               /* 275 TARGET_NR_mbind */
+                               /* 276 TARGET_NR_get_mempolicy */
+                               /* 277 TARGET_NR_set_mempolicy */
+#define TARGET_NR_mq_open              278
+#define TARGET_NR_mq_unlink            279
+#define TARGET_NR_mq_timedsend 280
+#define TARGET_NR_mq_timedreceive      281
+#define TARGET_NR_mq_notify            282
+#define TARGET_NR_mq_getsetattr        283
+#define TARGET_NR_kexec_load           284
+#define TARGET_NR_waitid               285
+#define TARGET_NR_add_key              286
+#define TARGET_NR_request_key  287
+#define TARGET_NR_keyctl               288
+#define TARGET_NR_ioprio_set           289
+#define TARGET_NR_ioprio_get           290
+#define TARGET_NR_inotify_init 291
+#define TARGET_NR_inotify_add_watch    292
+#define TARGET_NR_inotify_rm_watch     293
+                               /* 294 TARGET_NR_migrate_pages */
+#define TARGET_NR_openat               295
+#define TARGET_NR_mkdirat              296
+#define TARGET_NR_mknodat              297
+#define TARGET_NR_fchownat             298
+#define TARGET_NR_futimesat            299
+#define TARGET_NR_fstatat64            300
+#define TARGET_NR_unlinkat             301
+#define TARGET_NR_renameat             302
+#define TARGET_NR_linkat               303
+#define TARGET_NR_symlinkat            304
+#define TARGET_NR_readlinkat           305
+#define TARGET_NR_fchmodat             306
+#define TARGET_NR_faccessat            307
+#define TARGET_NR_pselect6             308
+#define TARGET_NR_ppoll                309
+#define TARGET_NR_unshare              310
+
+/* Blackfin private syscalls */
+#define TARGET_NR_sram_alloc           311
+#define TARGET_NR_sram_free            312
+#define TARGET_NR_dma_memcpy           313
+
+/* socket syscalls */
+#define TARGET_NR_accept               314
+#define TARGET_NR_bind         315
+#define TARGET_NR_connect              316
+#define TARGET_NR_getpeername  317
+#define TARGET_NR_getsockname  318
+#define TARGET_NR_getsockopt           319
+#define TARGET_NR_listen               320
+#define TARGET_NR_recv         321
+#define TARGET_NR_recvfrom             322
+#define TARGET_NR_recvmsg              323
+#define TARGET_NR_send         324
+#define TARGET_NR_sendmsg              325
+#define TARGET_NR_sendto               326
+#define TARGET_NR_setsockopt           327
+#define TARGET_NR_shutdown             328
+#define TARGET_NR_socket               329
+#define TARGET_NR_socketpair           330
+
+/* sysv ipc syscalls */
+#define TARGET_NR_semctl               331
+#define TARGET_NR_semget               332
+#define TARGET_NR_semop                333
+#define TARGET_NR_msgctl               334
+#define TARGET_NR_msgget               335
+#define TARGET_NR_msgrcv               336
+#define TARGET_NR_msgsnd               337
+#define TARGET_NR_shmat                338
+#define TARGET_NR_shmctl               339
+#define TARGET_NR_shmdt                340
+#define TARGET_NR_shmget               341
+
+#define TARGET_NR_splice               342
+#define TARGET_NR_sync_file_range      343
+#define TARGET_NR_tee          344
+#define TARGET_NR_vmsplice             345
+
+#define TARGET_NR_epoll_pwait  346
+#define TARGET_NR_utimensat            347
+#define TARGET_NR_signalfd             348
+#define TARGET_NR_timerfd_create       349
+#define TARGET_NR_eventfd              350
+#define TARGET_NR_pread64              351
+#define TARGET_NR_pwrite64             352
+#define TARGET_NR_fadvise64            353
+#define TARGET_NR_set_robust_list      354
+#define TARGET_NR_get_robust_list      355
+#define TARGET_NR_fallocate            356
+#define TARGET_NR_semtimedop           357
+#define TARGET_NR_timerfd_settime      358
+#define TARGET_NR_timerfd_gettime      359
+#define TARGET_NR_signalfd4            360
+#define TARGET_NR_eventfd2             361
+#define TARGET_NR_epoll_create1                362
+#define TARGET_NR_dup3                 363
+#define TARGET_NR_pipe2                        364
+#define TARGET_NR_inotify_init1                365
+#define TARGET_NR_preadv               366
+#define TARGET_NR_pwritev              367
+#define TARGET_NR_rt_tgsigqueueinfo    368
+#define TARGET_NR_perf_event_open      369
+#define TARGET_NR_recvmmsg             370
+#define TARGET_NR_fanotify_init        371
+#define TARGET_NR_fanotify_mark        372
+#define TARGET_NR_prlimit64            373
+#define TARGET_NR_cacheflush           374
+
+#define TARGET_NR_syscall              375
diff --git a/linux-user/bfin/target_flat.h b/linux-user/bfin/target_flat.h
new file mode 100644
index 0000000..c694a6a
--- /dev/null
+++ b/linux-user/bfin/target_flat.h
@@ -0,0 +1,92 @@
+/*
+ * uClinux flat-format executables
+ *
+ * Copyright 2003-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2
+ */
+
+#define FLAT_BFIN_RELOC_TYPE_16_BIT  0
+#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1
+#define FLAT_BFIN_RELOC_TYPE_32_BIT  2
+
+#define flat_argvp_envp_on_stack()                0
+#define flat_reloc_valid(reloc, size)             ((reloc) <= (size))
+#define flat_old_ram_flag(flag)                   (flag)
+#define flat_get_relocate_addr(relval)            ((relval) & 0x03ffffff)
+
+static inline int flat_set_persistent(abi_ulong relval, abi_ulong *persistent)
+{
+    int type = (relval >> 26) & 7;
+    if (type == 3) {
+        *persistent = relval << 16;
+        return 1;
+    }
+    return 0;
+}
+
+static abi_ulong
+flat_get_addr_from_rp(abi_ulong ul_ptr, abi_ulong relval, abi_ulong flags, 
abi_ulong *persistent)
+{
+    int type = (relval >> 26) & 7;
+    abi_ulong val;
+
+#ifdef DEBUG
+    printf("%s:%i: ptr:%8x relval:%8x type:%x flags:%x persistent:%x",
+           __func__, __LINE__, ul_ptr, relval, type, flags, *persistent);
+#endif
+
+    switch (type) {
+    case FLAT_BFIN_RELOC_TYPE_16_BIT:
+    case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+        if (get_user_u16(val, ul_ptr)) {
+            fprintf(stderr, "BINFMT_FLAT: unable to read reloc at %#x\n", 
ul_ptr);
+            abort();
+        }
+        val += *persistent;
+        break;
+    case FLAT_BFIN_RELOC_TYPE_32_BIT:
+        if (get_user_u32(val, ul_ptr)) {
+            fprintf(stderr, "BINFMT_FLAT: unable to read reloc at %#x\n", 
ul_ptr);
+            abort();
+        }
+        break;
+    default:
+        fprintf(stderr, "BINFMT_FLAT: Unknown relocation type %x\n", type);
+        abort();
+        break;
+    }
+#ifdef DEBUG
+    printf(" val:%x\n", val);
+#endif
+
+    /*
+     * Stack-relative relocs contain the offset into the stack, we
+     * have to add the stack's start address here and return 1 from
+     * flat_addr_absolute to prevent the normal address calculations
+     */
+    if (relval & (1 << 29)) {
+        fprintf(stderr, "BINFMT_FLAT: stack relocs not supported\n");
+        abort();
+        /*return val + current->mm->context.end_brk;*/
+    }
+
+    if ((flags & FLAT_FLAG_GOTPIC) == 0)
+        val = ntohl(val);
+
+    return val;
+}
+
+static int
+flat_put_addr_at_rp(abi_ulong ptr, abi_ulong addr, abi_ulong relval)
+{
+    int type = (relval >> 26) & 7;
+
+    switch (type) {
+    case FLAT_BFIN_RELOC_TYPE_16_BIT:  return put_user_u16(addr, ptr);
+    case FLAT_BFIN_RELOC_TYPE_16H_BIT: return put_user_u16(addr >> 16, ptr);
+    case FLAT_BFIN_RELOC_TYPE_32_BIT:  return put_user_u32(addr, ptr);
+    }
+
+    abort();
+}
diff --git a/linux-user/bfin/target_sigcontext.h 
b/linux-user/bfin/target_sigcontext.h
new file mode 100644
index 0000000..10d61e2
--- /dev/null
+++ b/linux-user/bfin/target_sigcontext.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef TARGET_SIGCONTEXT_H
+#define TARGET_SIGCONTEXT_H
+
+/* Add new entries at the end of the structure only.  */
+struct target_sigcontext {
+       abi_ulong sc_r0;
+       abi_ulong sc_r1;
+       abi_ulong sc_r2;
+       abi_ulong sc_r3;
+       abi_ulong sc_r4;
+       abi_ulong sc_r5;
+       abi_ulong sc_r6;
+       abi_ulong sc_r7;
+       abi_ulong sc_p0;
+       abi_ulong sc_p1;
+       abi_ulong sc_p2;
+       abi_ulong sc_p3;
+       abi_ulong sc_p4;
+       abi_ulong sc_p5;
+       abi_ulong sc_usp;
+       abi_ulong sc_a0w;
+       abi_ulong sc_a1w;
+       abi_ulong sc_a0x;
+       abi_ulong sc_a1x;
+       abi_ulong sc_astat;
+       abi_ulong sc_rets;
+       abi_ulong sc_pc;
+       abi_ulong sc_retx;
+       abi_ulong sc_fp;
+       abi_ulong sc_i0;
+       abi_ulong sc_i1;
+       abi_ulong sc_i2;
+       abi_ulong sc_i3;
+       abi_ulong sc_m0;
+       abi_ulong sc_m1;
+       abi_ulong sc_m2;
+       abi_ulong sc_m3;
+       abi_ulong sc_l0;
+       abi_ulong sc_l1;
+       abi_ulong sc_l2;
+       abi_ulong sc_l3;
+       abi_ulong sc_b0;
+       abi_ulong sc_b1;
+       abi_ulong sc_b2;
+       abi_ulong sc_b3;
+       abi_ulong sc_lc0;
+       abi_ulong sc_lc1;
+       abi_ulong sc_lt0;
+       abi_ulong sc_lt1;
+       abi_ulong sc_lb0;
+       abi_ulong sc_lb1;
+       abi_ulong sc_seqstat;
+};
+
+#endif
diff --git a/linux-user/bfin/target_signal.h b/linux-user/bfin/target_signal.h
new file mode 100644
index 0000000..7367c0a
--- /dev/null
+++ b/linux-user/bfin/target_signal.h
@@ -0,0 +1,31 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+       abi_ulong ss_sp;
+       abi_long ss_flags;
+       abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK      1
+#define TARGET_SS_DISABLE      2
+
+#define TARGET_MINSIGSTKSZ     2048
+#define TARGET_SIGSTKSZ                8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUArchState *env)
+{
+       return env->spreg;
+}
+
+#define TARGET_SIGRETURN_STUB  0x400
+
+#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/bfin/termbits.h b/linux-user/bfin/termbits.h
new file mode 100644
index 0000000..5c5fa01
--- /dev/null
+++ b/linux-user/bfin/termbits.h
@@ -0,0 +1,227 @@
+/* from asm/termbits.h */
+/* NOTE: exactly the same as i386 */
+
+#define TARGET_NCCS 19
+
+struct target_termios {
+    uint32_t c_iflag;               /* input mode flags */
+    uint32_t c_oflag;               /* output mode flags */
+    uint32_t c_cflag;               /* control mode flags */
+    uint32_t c_lflag;               /* local mode flags */
+    uint8_t c_line;                    /* line discipline */
+    uint8_t c_cc[TARGET_NCCS];                /* control characters */
+};
+
+/* c_iflag bits */
+#define TARGET_IGNBRK  0000001
+#define TARGET_BRKINT  0000002
+#define TARGET_IGNPAR  0000004
+#define TARGET_PARMRK  0000010
+#define TARGET_INPCK   0000020
+#define TARGET_ISTRIP  0000040
+#define TARGET_INLCR   0000100
+#define TARGET_IGNCR   0000200
+#define TARGET_ICRNL   0000400
+#define TARGET_IUCLC   0001000
+#define TARGET_IXON    0002000
+#define TARGET_IXANY   0004000
+#define TARGET_IXOFF   0010000
+#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8   0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST   0000001
+#define TARGET_OLCUC   0000002
+#define TARGET_ONLCR   0000004
+#define TARGET_OCRNL   0000010
+#define TARGET_ONOCR   0000020
+#define TARGET_ONLRET  0000040
+#define TARGET_OFILL   0000100
+#define TARGET_OFDEL   0000200
+#define TARGET_NLDLY   0000400
+#define   TARGET_NL0   0000000
+#define   TARGET_NL1   0000400
+#define TARGET_CRDLY   0003000
+#define   TARGET_CR0   0000000
+#define   TARGET_CR1   0001000
+#define   TARGET_CR2   0002000
+#define   TARGET_CR3   0003000
+#define TARGET_TABDLY  0014000
+#define   TARGET_TAB0  0000000
+#define   TARGET_TAB1  0004000
+#define   TARGET_TAB2  0010000
+#define   TARGET_TAB3  0014000
+#define   TARGET_XTABS 0014000
+#define TARGET_BSDLY   0020000
+#define   TARGET_BS0   0000000
+#define   TARGET_BS1   0020000
+#define TARGET_VTDLY   0040000
+#define   TARGET_VT0   0000000
+#define   TARGET_VT1   0040000
+#define TARGET_FFDLY   0100000
+#define   TARGET_FF0   0000000
+#define   TARGET_FF1   0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD   0010017
+#define  TARGET_B0     0000000         /* hang up */
+#define  TARGET_B50    0000001
+#define  TARGET_B75    0000002
+#define  TARGET_B110   0000003
+#define  TARGET_B134   0000004
+#define  TARGET_B150   0000005
+#define  TARGET_B200   0000006
+#define  TARGET_B300   0000007
+#define  TARGET_B600   0000010
+#define  TARGET_B1200  0000011
+#define  TARGET_B1800  0000012
+#define  TARGET_B2400  0000013
+#define  TARGET_B4800  0000014
+#define  TARGET_B9600  0000015
+#define  TARGET_B19200 0000016
+#define  TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE   0000060
+#define   TARGET_CS5   0000000
+#define   TARGET_CS6   0000020
+#define   TARGET_CS7   0000040
+#define   TARGET_CS8   0000060
+#define TARGET_CSTOPB  0000100
+#define TARGET_CREAD   0000200
+#define TARGET_PARENB  0000400
+#define TARGET_PARODD  0001000
+#define TARGET_HUPCL   0002000
+#define TARGET_CLOCAL  0004000
+#define TARGET_CBAUDEX 0010000
+#define  TARGET_B57600  0010001
+#define  TARGET_B115200 0010002
+#define  TARGET_B230400 0010003
+#define  TARGET_B460800 0010004
+#define  TARGET_B500000 0010005
+#define  TARGET_B576000 0010006
+#define  TARGET_B921600 0010007
+#define  TARGET_B1000000 0010010
+#define  TARGET_B1152000 0010011
+#define  TARGET_B1500000 0010012
+#define  TARGET_B2000000 0010013
+#define  TARGET_B2500000 0010014
+#define  TARGET_B3000000 0010015
+#define  TARGET_B3500000 0010016
+#define  TARGET_B4000000 0010017
+#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */
+#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */
+#define TARGET_CRTSCTS   020000000000  /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG    0000001
+#define TARGET_ICANON  0000002
+#define TARGET_XCASE   0000004
+#define TARGET_ECHO    0000010
+#define TARGET_ECHOE   0000020
+#define TARGET_ECHOK   0000040
+#define TARGET_ECHONL  0000100
+#define TARGET_NOFLSH  0000200
+#define TARGET_TOSTOP  0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE  0004000
+#define TARGET_FLUSHO  0010000
+#define TARGET_PENDIN  0040000
+#define TARGET_IEXTEN  0100000
+
+/* c_cc character offsets */
+#define TARGET_VINTR   0
+#define TARGET_VQUIT   1
+#define TARGET_VERASE  2
+#define TARGET_VKILL   3
+#define TARGET_VEOF    4
+#define TARGET_VTIME   5
+#define TARGET_VMIN    6
+#define TARGET_VSWTC   7
+#define TARGET_VSTART  8
+#define TARGET_VSTOP   9
+#define TARGET_VSUSP   10
+#define TARGET_VEOL    11
+#define TARGET_VREPRINT        12
+#define TARGET_VDISCARD        13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT  15
+#define TARGET_VEOL2   16
+
+/* ioctls */
+
+#define TARGET_TCGETS          0x5401
+#define TARGET_TCSETS          0x5402
+#define TARGET_TCSETSW         0x5403
+#define TARGET_TCSETSF         0x5404
+#define TARGET_TCGETA          0x5405
+#define TARGET_TCSETA          0x5406
+#define TARGET_TCSETAW         0x5407
+#define TARGET_TCSETAF         0x5408
+#define TARGET_TCSBRK          0x5409
+#define TARGET_TCXONC          0x540A
+#define TARGET_TCFLSH          0x540B
+
+#define TARGET_TIOCEXCL        0x540C
+#define TARGET_TIOCNXCL        0x540D
+#define TARGET_TIOCSCTTY       0x540E
+#define TARGET_TIOCGPGRP       0x540F
+#define TARGET_TIOCSPGRP       0x5410
+#define TARGET_TIOCOUTQ        0x5411
+#define TARGET_TIOCSTI         0x5412
+#define TARGET_TIOCGWINSZ      0x5413
+#define TARGET_TIOCSWINSZ      0x5414
+#define TARGET_TIOCMGET        0x5415
+#define TARGET_TIOCMBIS        0x5416
+#define TARGET_TIOCMBIC        0x5417
+#define TARGET_TIOCMSET        0x5418
+#define TARGET_TIOCGSOFTCAR    0x5419
+#define TARGET_TIOCSSOFTCAR    0x541A
+#define TARGET_FIONREAD        0x541B
+#define TARGET_TIOCINQ         TARGET_FIONREAD
+#define TARGET_TIOCLINUX       0x541C
+#define TARGET_TIOCCONS        0x541D
+#define TARGET_TIOCGSERIAL     0x541E
+#define TARGET_TIOCSSERIAL     0x541F
+#define TARGET_TIOCPKT         0x5420
+#define TARGET_FIONBIO         0x5421
+#define TARGET_TIOCNOTTY       0x5422
+#define TARGET_TIOCSETD        0x5423
+#define TARGET_TIOCGETD        0x5424
+#define TARGET_TCSBRKP         0x5425  /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCTTYGSTRUCT  0x5426  /* For debugging only */
+#define TARGET_TIOCSBRK        0x5427  /* BSD compatibility */
+#define TARGET_TIOCCBRK        0x5428  /* BSD compatibility */
+#define TARGET_TIOCGSID        0x5429  /* Return the session ID of FD */
+#define TARGET_TIOCGPTN        TARGET_IOR('T',0x30, uint32_t) /* Get Pty 
Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK      TARGET_IOW('T',0x31, int32_t)  /* Lock/unlock 
Pty */
+
+#define TARGET_FIONCLEX        0x5450  /* these numbers need to be adjusted. */
+#define TARGET_FIOCLEX         0x5451
+#define TARGET_FIOASYNC        0x5452
+#define TARGET_TIOCSERCONFIG   0x5453
+#define TARGET_TIOCSERGWILD    0x5454
+#define TARGET_TIOCSERSWILD    0x5455
+#define TARGET_TIOCGLCKTRMIOS  0x5456
+#define TARGET_TIOCSLCKTRMIOS  0x5457
+#define TARGET_TIOCSERGSTRUCT  0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT      0x545C  /* wait for a change on serial input 
line(s) */
+#define TARGET_TIOCGICOUNT     0x545D  /* read serial port inline interrupt 
counts */
+#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA             0
+#define TARGET_TIOCPKT_FLUSHREAD        1
+#define TARGET_TIOCPKT_FLUSHWRITE       2
+#define TARGET_TIOCPKT_STOP             4
+#define TARGET_TIOCPKT_START            8
+#define TARGET_TIOCPKT_NOSTOP          16
+#define TARGET_TIOCPKT_DOSTOP          32
+
+#define TARGET_TIOCSER_TEMT    0x01    /* Transmitter physically empty */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ddef23e..b09e33e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -979,6 +979,48 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, 
const CPUM68KState *e
 
 #endif
 
+#ifdef TARGET_BFIN
+
+#define ELF_START_MMAP 0x00000000
+
+#define elf_check_arch(x) ( (x) == EM_BLACKFIN )
+#define elf_is_fdpic(e)   ( (e)->e_flags & EF_BFIN_FDPIC )
+
+#define ELF_CLASS      ELFCLASS32
+#define ELF_DATA       ELFDATA2LSB
+#define ELF_ARCH       EM_BLACKFIN
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info 
*infop)
+{
+    if (infop->personality == PER_LINUX_FDPIC) {
+        if (infop->other_info) {
+            /* dynamic */
+            regs->p0 = tswapl(infop->loadmap_addr);
+            regs->p1 = tswapl(infop->other_info->loadmap_addr);
+            regs->p2 = tswapl(infop->other_info->pt_dynamic_addr);
+        } else {
+            /* static */
+            regs->p0 = tswapl(infop->loadmap_addr);
+            regs->p1 = 0;
+            regs->p2 = tswapl(infop->pt_dynamic_addr);
+        }
+        regs->r7 = 0;
+    } else if (infop->start_code == 0) {
+        /* Must be bare metal ELF ... */
+        infop->personality = PER_MASK;
+    }
+    regs->pc = tswapl(infop->entry);
+    regs->usp = tswapl(infop->start_stack);
+}
+
+#define ELF_EXEC_PAGESIZE      4096
+
+/* See linux kernel: arch/blackfin/include/asm/elf.h.  */
+#define ELF_NREG 40
+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
+
+#endif
+
 #ifdef TARGET_ALPHA
 
 #define ELF_START_MMAP (0x30000000000ULL)
@@ -1677,6 +1719,11 @@ static void load_elf_image(const char *image_name, int 
image_fd,
            address does not conflict with MMAP_MIN_ADDR or the
            QEMU application itself.  */
         probe_guest_base(image_name, loaddr, hiaddr);
+#ifdef TARGET_BFIN
+        /* Make space for the fixed code region */
+        if (elf_is_fdpic(ehdr) && load_addr < 0x1000)
+            load_addr += 0x1000;
+#endif
     }
     load_bias = load_addr - loaddr;
 
diff --git a/linux-user/main.c b/linux-user/main.c
index b97b8cf..bb5d032 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2795,6 +2795,115 @@ void cpu_loop(CPUM68KState *env)
 }
 #endif /* TARGET_M68K */
 
+#ifdef TARGET_BFIN
+
+#include "disas/disas.h"
+
+void cpu_loop(CPUArchState *env)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+    int trapnr, gdbsig;
+    target_siginfo_t info;
+
+    for (;;) {
+        cpu_exec_start(cs);
+        trapnr = cpu_exec(env);
+        cpu_exec_end(cs);
+        gdbsig = 0;
+
+        switch (trapnr) {
+        case EXCP_SYSCALL:
+            env->pc += 2;
+            env->dreg[0] = do_syscall(env,
+                                      env->preg[0],
+                                      env->dreg[0],
+                                      env->dreg[1],
+                                      env->dreg[2],
+                                      env->dreg[3],
+                                      env->dreg[4],
+                                      env->dreg[5], 0, 0);
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_DEBUG:
+            /* XXX: does this handle hwloops ? */
+            /*env->pc += 2;*/
+            /* EMUEXCPT signals debugger only if attached; NOP otherwise */
+            gdbsig = TARGET_SIGTRAP;
+            break;
+        case EXCP_SOFT_BP:
+            {
+                int 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;
+        case EXCP_HLT:
+            do_syscall(env, TARGET_NR_exit, 0, 0, 0, 0, 0, 0, 0, 0);
+            break;
+        case EXCP_ABORT:
+            do_syscall(env, TARGET_NR_exit, 1, 0, 0, 0, 0, 0, 0, 0);
+            break;
+        case EXCP_DBGA:
+            fprintf(stderr, "qemu: DBGA failed\n");
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGABRT;
+            break;
+        case EXCP_UNDEF_INST:
+            fprintf(stderr, "qemu: unhandled insn @ %#x\n", env->pc);
+            log_target_disas(env, env->pc, 8, 0);
+            gdbsig = TARGET_SIGILL;
+            break;
+        case EXCP_DCPLB_VIOLATE:
+            fprintf(stderr, "qemu: memory violation @ %#x\n", env->pc);
+            log_target_disas(env, env->pc, 8, 0);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGSEGV;
+            break;
+        case EXCP_ILL_SUPV:
+            fprintf(stderr, "qemu: supervisor mode required @ %#x\n", env->pc);
+            log_target_disas(env, env->pc, 8, 0);
+            gdbsig = TARGET_SIGILL;
+            break;
+        case EXCP_MISALIG_INST:
+            fprintf(stderr, "qemu: unaligned insn fetch @ %#x\n", env->pc);
+            log_target_disas(env, env->pc, 8, 0);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGSEGV;
+            break;
+        case EXCP_DATA_MISALGIN:
+            fprintf(stderr, "qemu: unaligned data fetch @ %#x\n", env->pc);
+            log_target_disas(env, env->pc, 8, 0);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGSEGV;
+            break;
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception %#x - aborting\n",
+                    trapnr);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGILL;
+            break;
+        }
+
+        if (gdbsig) {
+            gdb_handlesig(env, gdbsig);
+            /* XXX: should we let people continue if gdb handles the signal ? 
*/
+            if (gdbsig != TARGET_SIGTRAP) {
+                exit(1);
+            }
+        }
+
+        process_pending_signals(env);
+    }
+}
+
+#endif
+
 #ifdef TARGET_ALPHA
 static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
 {
@@ -4013,6 +4122,57 @@ int main(int argc, char **argv, char **envp)
         }
         env->pc = regs->pc;
     }
+#elif defined(TARGET_BFIN)
+    {
+        env->personality = info->personality;
+        env->dreg[0] = regs->r0;
+        env->dreg[1] = regs->r1;
+        env->dreg[2] = regs->r2;
+        env->dreg[3] = regs->r3;
+        env->dreg[4] = regs->r4;
+        env->dreg[5] = regs->r5;
+        env->dreg[6] = regs->r6;
+        env->dreg[7] = regs->r7;
+        env->preg[0] = regs->p0;
+        env->preg[1] = regs->p1;
+        env->preg[2] = regs->p2;
+        env->preg[3] = regs->p3;
+        env->preg[4] = regs->p4;
+        env->preg[5] = regs->p5;
+        env->spreg = regs->usp;
+        env->fpreg = regs->fp;
+        env->uspreg = regs->usp;
+        env->breg[0] = regs->b0;
+        env->breg[1] = regs->b1;
+        env->breg[2] = regs->b2;
+        env->breg[3] = regs->b3;
+        env->lreg[0] = regs->l0;
+        env->lreg[1] = regs->l1;
+        env->lreg[2] = regs->l2;
+        env->lreg[3] = regs->l3;
+        env->mreg[0] = regs->m0;
+        env->mreg[1] = regs->m1;
+        env->mreg[2] = regs->m2;
+        env->mreg[3] = regs->m3;
+        env->ireg[0] = regs->i0;
+        env->ireg[1] = regs->i1;
+        env->ireg[2] = regs->i2;
+        env->ireg[3] = regs->i3;
+        env->lcreg[0] = regs->lc0;
+        env->ltreg[0] = regs->lt0;
+        env->lbreg[0] = regs->lb0;
+        env->lcreg[1] = regs->lc1;
+        env->ltreg[1] = regs->lt1;
+        env->lbreg[1] = regs->lb1;
+        env->areg[0] = ((uint64_t)regs->a0x << 32) | regs->a0w;
+        env->areg[1] = ((uint64_t)regs->a1x << 32) | regs->a1w;
+        env->rets = regs->rets;
+        env->rete = regs->rete;
+        env->retn = regs->retn;
+        env->retx = regs->retx;
+        env->pc = regs->pc;
+        bfin_astat_write(env, regs->astat);
+    }
 #elif defined(TARGET_ALPHA)
     {
         int i;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index b10e957..819f268 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -26,6 +26,10 @@
 #define THREAD
 #endif
 
+#ifdef TARGET_BFIN
+#define CONFIG_USE_FDPIC
+#endif
+
 /* This struct is used to hold certain information about the image.
  * Basically, it replicates in user space what would be certain
  * task_struct fields in the kernel
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 5da8452..6e2d613 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5353,6 +5353,231 @@ long do_rt_sigreturn(CPUAlphaState *env)
     force_sig(TARGET_SIGSEGV);
 }
 
+#elif defined(TARGET_BFIN)
+
+#include "target_sigcontext.h"
+#include "target_ucontext.h"
+
+struct target_rt_sigframe {
+    int32_t sig;
+    abi_ulong pinfo;
+    abi_ulong puc;
+    /* This is no longer needed by the kernel, but unfortunately userspace
+     * code expects it to be there.  */
+    char retcode[8];
+    target_siginfo_t info;
+    struct target_ucontext uc;
+};
+
+struct fdpic_func_descriptor {
+    abi_ulong text;
+    abi_ulong GOT;
+};
+
+#define rreg dreg
+
+static inline int
+target_rt_restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc, 
long *ret)
+{
+    uint32_t reg;
+    int err = 0;
+
+#define RESTORE2(e, x) err |= __get_user(env->e, &sc->sc_##x)
+#define RESTOREA(r, i) RESTORE2(r##reg[i], r##i)
+#define RESTORE(x) RESTORE2(x, x)
+
+    /* restore passed registers */
+    RESTOREA(r, 0); RESTOREA(r, 1); RESTOREA(r, 2); RESTOREA(r, 3);
+    RESTOREA(r, 4); RESTOREA(r, 5); RESTOREA(r, 6); RESTOREA(r, 7);
+    RESTOREA(p, 0); RESTOREA(p, 1); RESTOREA(p, 2); RESTOREA(p, 3);
+    RESTOREA(p, 4); RESTOREA(p, 5);
+    RESTORE2(spreg, usp);
+    err |= __get_user(reg, &sc->sc_a0x);
+    env->areg[0] = reg;
+    err |= __get_user(reg, &sc->sc_a0w);
+    env->areg[0] = (env->areg[0] << 32) | reg;
+    err |= __get_user(reg, &sc->sc_a1x);
+    env->areg[1] = reg;
+    err |= __get_user(reg, &sc->sc_a1w);
+    env->areg[1] = (env->areg[1] << 32) | reg;
+    err |= __get_user(reg, &sc->sc_astat);
+    bfin_astat_write(env, reg);
+    RESTORE(rets);
+    RESTORE(pc);
+    RESTORE(retx);
+    RESTORE2(fpreg, fp);
+    RESTOREA(i, 0); RESTOREA(i, 1); RESTOREA(i, 2); RESTOREA(i, 3);
+    RESTOREA(m, 0); RESTOREA(m, 1); RESTOREA(m, 2); RESTOREA(m, 3);
+    RESTOREA(l, 0); RESTOREA(l, 1); RESTOREA(l, 2); RESTOREA(l, 3);
+    RESTOREA(b, 0); RESTOREA(b, 1); RESTOREA(b, 2); RESTOREA(b, 3);
+    RESTOREA(lc, 0); RESTOREA(lc, 1);
+    RESTOREA(lt, 0); RESTOREA(lt, 1);
+    RESTOREA(lb, 0); RESTOREA(lb, 1);
+    RESTORE(seqstat);
+
+    *ret = env->dreg[0];
+    return err;
+}
+
+static inline int
+target_rt_setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
+{
+    int err = 0;
+
+#define SETUP2(e, x) err |= __put_user(env->e, &sc->sc_##x)
+#define SETUPA(r, i) SETUP2(r##reg[i], r##i)
+#define SETUP(x) SETUP2(x, x)
+
+    SETUPA(r, 0); SETUPA(r, 1); SETUPA(r, 2); SETUPA(r, 3);
+    SETUPA(r, 4); SETUPA(r, 5); SETUPA(r, 6); SETUPA(r, 7);
+    SETUPA(p, 0); SETUPA(p, 1); SETUPA(p, 2); SETUPA(p, 3);
+    SETUPA(p, 4); SETUPA(p, 5);
+    SETUP2(spreg, usp);
+    err |= __put_user((uint32_t)env->areg[0], &sc->sc_a0w);
+    err |= __put_user((uint32_t)env->areg[1], &sc->sc_a1w);
+    err |= __put_user((uint32_t)(env->areg[0] >> 32), &sc->sc_a0x);
+    err |= __put_user((uint32_t)(env->areg[1] >> 32), &sc->sc_a1x);
+    err |= __put_user(bfin_astat_read(env), &sc->sc_astat);
+    SETUP(rets);
+    SETUP(pc);
+    SETUP(retx);
+    SETUP2(fpreg, fp);
+    SETUPA(i, 0); SETUPA(i, 1); SETUPA(i, 2); SETUPA(i, 3);
+    SETUPA(m, 0); SETUPA(m, 1); SETUPA(m, 2); SETUPA(m, 3);
+    SETUPA(l, 0); SETUPA(l, 1); SETUPA(l, 2); SETUPA(l, 3);
+    SETUPA(b, 0); SETUPA(b, 1); SETUPA(b, 2); SETUPA(b, 3);
+    SETUPA(lc, 0); SETUPA(lc, 1);
+    SETUPA(lt, 0); SETUPA(lt, 1);
+    SETUPA(lb, 0); SETUPA(lb, 1);
+    SETUP(seqstat);
+
+    return err;
+}
+
+#undef rreg
+
+static inline abi_ulong
+get_sigframe(struct target_sigaction *ka, CPUArchState *env, size_t frame_size)
+{
+    abi_ulong usp;
+
+    /* Default to using normal stack.  */
+    usp = env->spreg;
+
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(usp) == 0)) {
+        usp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+
+    return ((usp - frame_size) & -8UL);
+}
+
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+                           target_siginfo_t *info,
+                           target_sigset_t *set, CPUArchState *env)
+{
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    abi_ulong info_addr;
+    abi_ulong uc_addr;
+    int err = 0;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
+
+    err |= __put_user(sig, &frame->sig);
+
+    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
+    err |= __put_user(info_addr, &frame->pinfo);
+    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
+    err |= __put_user(uc_addr, &frame->puc);
+    err |= copy_siginfo_to_user(&frame->info, info);
+
+    /* Create the ucontext.  */
+    err |= __put_user(0, &frame->uc.tuc_flags);
+    err |= __put_user(0, &frame->uc.tuc_link);
+    err |= __put_user(target_sigaltstack_used.ss_sp, 
&frame->uc.tuc_stack.ss_sp);
+    err |= __put_user(sas_ss_flags(env->spreg), &frame->uc.tuc_stack.ss_flags);
+    err |= __put_user(target_sigaltstack_used.ss_size, 
&frame->uc.tuc_stack.ss_size);
+    err |= target_rt_setup_sigcontext(&frame->uc.tuc_mcontext, env);
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
+            goto give_sigsegv;
+    }
+
+    if (err)
+        goto give_sigsegv;
+
+    /* Set up registers for signal handler */
+    env->spreg = frame_addr;
+    if (env->personality & 0x0080000/*FDPIC_FUNCPTRS*/) {
+        struct fdpic_func_descriptor *funcptr;
+        if (!lock_user_struct(VERIFY_READ, funcptr, ka->_sa_handler, 1))
+            goto give_sigsegv;
+        __get_user(env->pc, &funcptr->text);
+        __get_user(env->preg[3], &funcptr->GOT);
+        unlock_user_struct(funcptr, ka->_sa_handler, 0);
+    } else
+        env->pc = ka->_sa_handler;
+    env->rets = TARGET_SIGRETURN_STUB;
+
+    env->dreg[0] = frame->sig;
+    env->dreg[1] = info_addr;
+    env->dreg[2] = uc_addr;
+
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+
+ give_sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    force_sig(TARGET_SIGSEGV);
+}
+
+static void setup_frame(int sig, struct target_sigaction *ka,
+                        target_sigset_t *set, CPUArchState *env)
+{
+    target_siginfo_t info;
+    setup_rt_frame(sig, ka, &info, set, env);
+}
+
+long do_sigreturn(CPUArchState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -TARGET_ENOSYS;
+}
+
+/* NB: This version should work for any arch ... */
+long do_rt_sigreturn(CPUArchState *env)
+{
+    long ret;
+    abi_ulong frame_addr = env->spreg;
+    struct target_rt_sigframe *frame;
+    sigset_t host_set;
+
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+        goto badframe;
+
+    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
+    sigprocmask(SIG_SETMASK, &host_set, NULL);
+
+    if (target_rt_restore_sigcontext(env, &frame->uc.tuc_mcontext, &ret))
+        goto badframe;
+
+    if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, 
uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
+        goto badframe;
+
+    unlock_user_struct(frame, frame_addr, 0);
+    return ret;
+
+ badframe:
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV);
+    return 0;
+}
+
 #else
 
 static void setup_frame(int sig, struct target_sigaction *ka,
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cdd0c28..a9dce35 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7444,7 +7444,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_OPENRISC) 
|| \
+    defined(TARGET_BFIN)
         ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState 
*)cpu_env));
         break;
 #else
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 92c01a9..362cd2d 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -63,7 +63,7 @@
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
     || defined(TARGET_M68K) || defined(TARGET_CRIS) || 
defined(TARGET_UNICORE32) \
-    || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
+    || defined(TARGET_S390X) || defined(TARGET_OPENRISC) || 
defined(TARGET_BFIN)
 
 #define TARGET_IOC_SIZEBITS    14
 #define TARGET_IOC_DIRBITS     2
@@ -327,7 +327,7 @@ int do_sigaction(int sig, const struct target_sigaction 
*act,
     || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \
     || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \
     || defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32) \
-    || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
+    || defined(TARGET_S390X) || defined(TARGET_OPENRISC) || 
defined(TARGET_BFIN)
 
 #if defined(TARGET_SPARC)
 #define TARGET_SA_NOCLDSTOP    8u
@@ -1689,6 +1689,67 @@ struct target_stat64 {
        int64_t         st_blocks;
 };
 
+#elif defined(TARGET_BFIN)
+
+struct target_stat {
+    uint16_t st_dev;
+    uint16_t __pad1;
+    abi_ulong st_ino;
+    uint16_t st_mode;
+    uint16_t st_nlink;
+    uint16_t st_uid;
+    uint16_t st_gid;
+    uint16_t st_rdev;
+    uint16_t __pad2;
+    abi_ulong st_size;
+    abi_ulong st_blksize;
+    abi_ulong st_blocks;
+    abi_ulong target_st_atime;
+    abi_ulong __unused1;
+    abi_ulong target_st_mtime;
+    abi_ulong __unused2;
+    abi_ulong target_st_ctime;
+    abi_ulong __unused3;
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+} __attribute__((packed));
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct target_stat64 {
+    uint64_t st_dev;
+    unsigned char __pad1[4];
+
+#define STAT64_HAS_BROKEN_ST_INO 1
+    abi_ulong __st_ino;
+
+    uint32_t st_mode;
+    uint32_t st_nlink;
+
+    abi_ulong st_uid;
+    abi_ulong st_gid;
+
+    uint64_t st_rdev;
+    unsigned char __pad2[4];
+
+    int64_t st_size;
+    abi_ulong st_blksize;
+
+    int64_t st_blocks; /* Number 512-byte blocks allocated. */
+
+    abi_ulong target_st_atime;
+    abi_ulong target_st_atime_nsec;
+
+    abi_ulong target_st_mtime;
+    abi_ulong target_st_mtime_nsec;
+
+    abi_ulong target_st_ctime;
+    abi_ulong target_st_ctime_nsec;
+
+    uint64_t st_ino;
+} __attribute__((packed));
+
 #elif defined(TARGET_ALPHA)
 
 struct target_stat {
diff --git a/linux-user/target_ucontext.h b/linux-user/target_ucontext.h
new file mode 100644
index 0000000..49706b4
--- /dev/null
+++ b/linux-user/target_ucontext.h
@@ -0,0 +1,14 @@
+/* This is the asm-generic/ucontext.h version */
+
+#ifndef TARGET_UCONTEXT_H
+#define TARGET_UCONTEXT_H
+
+struct target_ucontext {
+    abi_ulong                tuc_flags;
+    abi_ulong                tuc_link;
+    target_stack_t           tuc_stack;
+    struct target_sigcontext tuc_mcontext;
+    target_sigset_t          tuc_sigmask;    /* mask last for extensibility */
+};
+
+#endif
-- 
1.8.2.1


Reply via email to