|
1 /* |
|
2 * m68k simulator syscall interface |
|
3 * |
|
4 * Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook. |
|
5 * |
|
6 * This program is free software; you can redistribute it and/or modify |
|
7 * it under the terms of the GNU General Public License as published by |
|
8 * the Free Software Foundation; either version 2 of the License, or |
|
9 * (at your option) any later version. |
|
10 * |
|
11 * This program is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 * GNU General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License |
|
17 * along with this program; if not, write to the Free Software |
|
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
19 */ |
|
20 |
|
21 #include <sys/types.h> |
|
22 #include <sys/stat.h> |
|
23 #include <errno.h> |
|
24 #include <fcntl.h> |
|
25 #include <unistd.h> |
|
26 #include <stdlib.h> |
|
27 #include <stdio.h> |
|
28 #include <time.h> |
|
29 |
|
30 #include "qemu.h" |
|
31 |
|
32 #define SYS_EXIT 1 |
|
33 #define SYS_READ 3 |
|
34 #define SYS_WRITE 4 |
|
35 #define SYS_OPEN 5 |
|
36 #define SYS_CLOSE 6 |
|
37 #define SYS_BRK 17 |
|
38 #define SYS_FSTAT 28 |
|
39 #define SYS_ISATTY 29 |
|
40 #define SYS_LSEEK 199 |
|
41 |
|
42 struct m86k_sim_stat { |
|
43 uint16_t sim_st_dev; |
|
44 uint16_t sim_st_ino; |
|
45 uint32_t sim_st_mode; |
|
46 uint16_t sim_st_nlink; |
|
47 uint16_t sim_st_uid; |
|
48 uint16_t sim_st_gid; |
|
49 uint16_t sim_st_rdev; |
|
50 uint32_t sim_st_size; |
|
51 uint32_t sim_st_atime; |
|
52 uint32_t sim_st_mtime; |
|
53 uint32_t sim_st_ctime; |
|
54 uint32_t sim_st_blksize; |
|
55 uint32_t sim_st_blocks; |
|
56 }; |
|
57 |
|
58 static inline uint32_t check_err(CPUM68KState *env, uint32_t code) |
|
59 { |
|
60 env->dregs[0] = code; |
|
61 if (code == (uint32_t)-1) { |
|
62 env->dregs[1] = errno; |
|
63 } else { |
|
64 env->dregs[1] = 0; |
|
65 } |
|
66 return code; |
|
67 } |
|
68 |
|
69 #define SIM_O_APPEND 0x0008 |
|
70 #define SIM_O_CREAT 0x0200 |
|
71 #define SIM_O_TRUNC 0x0400 |
|
72 #define SIM_O_EXCL 0x0800 |
|
73 #define SIM_O_NONBLOCK 0x4000 |
|
74 #define SIM_O_NOCTTY 0x8000 |
|
75 #define SIM_O_SYNC 0x2000 |
|
76 |
|
77 static int translate_openflags(int flags) |
|
78 { |
|
79 int hf; |
|
80 |
|
81 switch (flags & 3) { |
|
82 case 0: hf = O_RDONLY; break; |
|
83 case 1: hf = O_WRONLY; break; |
|
84 case 2: hf = O_RDWR; break; |
|
85 default: hf = O_RDWR; break; |
|
86 } |
|
87 |
|
88 if (flags & SIM_O_APPEND) hf |= O_APPEND; |
|
89 if (flags & SIM_O_CREAT) hf |= O_CREAT; |
|
90 if (flags & SIM_O_TRUNC) hf |= O_TRUNC; |
|
91 if (flags & SIM_O_EXCL) hf |= O_EXCL; |
|
92 if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK; |
|
93 if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY; |
|
94 if (flags & SIM_O_SYNC) hf |= O_SYNC; |
|
95 |
|
96 return hf; |
|
97 } |
|
98 |
|
99 #define ARG(x) tswap32(args[x]) |
|
100 void do_m68k_simcall(CPUM68KState *env, int nr) |
|
101 { |
|
102 uint32_t *args; |
|
103 |
|
104 args = (uint32_t *)(unsigned long)(env->aregs[7] + 4); |
|
105 switch (nr) { |
|
106 case SYS_EXIT: |
|
107 exit(ARG(0)); |
|
108 case SYS_READ: |
|
109 check_err(env, read(ARG(0), (void *)(unsigned long)ARG(1), ARG(2))); |
|
110 break; |
|
111 case SYS_WRITE: |
|
112 check_err(env, write(ARG(0), (void *)(unsigned long)ARG(1), ARG(2))); |
|
113 break; |
|
114 case SYS_OPEN: |
|
115 check_err(env, open((char *)(unsigned long)ARG(0), |
|
116 translate_openflags(ARG(1)), ARG(2))); |
|
117 break; |
|
118 case SYS_CLOSE: |
|
119 { |
|
120 /* Ignore attempts to close stdin/out/err. */ |
|
121 int fd = ARG(0); |
|
122 if (fd > 2) |
|
123 check_err(env, close(fd)); |
|
124 else |
|
125 check_err(env, 0); |
|
126 break; |
|
127 } |
|
128 case SYS_BRK: |
|
129 { |
|
130 int32_t ret; |
|
131 |
|
132 ret = do_brk((abi_ulong)ARG(0)); |
|
133 if (ret == -ENOMEM) |
|
134 ret = -1; |
|
135 check_err(env, ret); |
|
136 } |
|
137 break; |
|
138 case SYS_FSTAT: |
|
139 { |
|
140 struct stat s; |
|
141 int rc; |
|
142 struct m86k_sim_stat *p; |
|
143 rc = check_err(env, fstat(ARG(0), &s)); |
|
144 if (rc == 0) { |
|
145 p = (struct m86k_sim_stat *)(unsigned long)ARG(1); |
|
146 p->sim_st_dev = tswap16(s.st_dev); |
|
147 p->sim_st_ino = tswap16(s.st_ino); |
|
148 p->sim_st_mode = tswap32(s.st_mode); |
|
149 p->sim_st_nlink = tswap16(s.st_nlink); |
|
150 p->sim_st_uid = tswap16(s.st_uid); |
|
151 p->sim_st_gid = tswap16(s.st_gid); |
|
152 p->sim_st_rdev = tswap16(s.st_rdev); |
|
153 p->sim_st_size = tswap32(s.st_size); |
|
154 p->sim_st_atime = tswap32(s.st_atime); |
|
155 p->sim_st_mtime = tswap32(s.st_mtime); |
|
156 p->sim_st_ctime = tswap32(s.st_ctime); |
|
157 p->sim_st_blksize = tswap32(s.st_blksize); |
|
158 p->sim_st_blocks = tswap32(s.st_blocks); |
|
159 } |
|
160 } |
|
161 break; |
|
162 case SYS_ISATTY: |
|
163 check_err(env, isatty(ARG(0))); |
|
164 break; |
|
165 case SYS_LSEEK: |
|
166 check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2))); |
|
167 break; |
|
168 default: |
|
169 cpu_abort(env, "Unsupported m68k sim syscall %d\n", nr); |
|
170 } |
|
171 } |