diff mbox

[3/5] Blackfin: add linux-user support

Message ID 1371453383-11484-2-git-send-email-vapier@gentoo.org
State New
Headers show

Commit Message

Mike Frysinger June 17, 2013, 7:16 a.m. UTC
Signed-off-by: Mike Frysinger <vapier@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 mbox

Patch

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