xref: /qemu/target/mips/tcg/sysemu/mips-semi.c (revision ad520a97)
1*ad520a97SPhilippe Mathieu-Daudé /*
2*ad520a97SPhilippe Mathieu-Daudé  * Unified Hosting Interface syscalls.
3*ad520a97SPhilippe Mathieu-Daudé  *
4*ad520a97SPhilippe Mathieu-Daudé  * Copyright (c) 2015 Imagination Technologies
5*ad520a97SPhilippe Mathieu-Daudé  *
6*ad520a97SPhilippe Mathieu-Daudé  * This library is free software; you can redistribute it and/or
7*ad520a97SPhilippe Mathieu-Daudé  * modify it under the terms of the GNU Lesser General Public
8*ad520a97SPhilippe Mathieu-Daudé  * License as published by the Free Software Foundation; either
9*ad520a97SPhilippe Mathieu-Daudé  * version 2.1 of the License, or (at your option) any later version.
10*ad520a97SPhilippe Mathieu-Daudé  *
11*ad520a97SPhilippe Mathieu-Daudé  * This library is distributed in the hope that it will be useful,
12*ad520a97SPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*ad520a97SPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*ad520a97SPhilippe Mathieu-Daudé  * Lesser General Public License for more details.
15*ad520a97SPhilippe Mathieu-Daudé  *
16*ad520a97SPhilippe Mathieu-Daudé  * You should have received a copy of the GNU Lesser General Public
17*ad520a97SPhilippe Mathieu-Daudé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18*ad520a97SPhilippe Mathieu-Daudé  */
19*ad520a97SPhilippe Mathieu-Daudé 
20*ad520a97SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
21*ad520a97SPhilippe Mathieu-Daudé #include "cpu.h"
22*ad520a97SPhilippe Mathieu-Daudé #include "qemu/log.h"
23*ad520a97SPhilippe Mathieu-Daudé #include "exec/helper-proto.h"
24*ad520a97SPhilippe Mathieu-Daudé #include "exec/softmmu-semi.h"
25*ad520a97SPhilippe Mathieu-Daudé #include "semihosting/semihost.h"
26*ad520a97SPhilippe Mathieu-Daudé #include "semihosting/console.h"
27*ad520a97SPhilippe Mathieu-Daudé 
28*ad520a97SPhilippe Mathieu-Daudé typedef enum UHIOp {
29*ad520a97SPhilippe Mathieu-Daudé     UHI_exit = 1,
30*ad520a97SPhilippe Mathieu-Daudé     UHI_open = 2,
31*ad520a97SPhilippe Mathieu-Daudé     UHI_close = 3,
32*ad520a97SPhilippe Mathieu-Daudé     UHI_read = 4,
33*ad520a97SPhilippe Mathieu-Daudé     UHI_write = 5,
34*ad520a97SPhilippe Mathieu-Daudé     UHI_lseek = 6,
35*ad520a97SPhilippe Mathieu-Daudé     UHI_unlink = 7,
36*ad520a97SPhilippe Mathieu-Daudé     UHI_fstat = 8,
37*ad520a97SPhilippe Mathieu-Daudé     UHI_argc = 9,
38*ad520a97SPhilippe Mathieu-Daudé     UHI_argnlen = 10,
39*ad520a97SPhilippe Mathieu-Daudé     UHI_argn = 11,
40*ad520a97SPhilippe Mathieu-Daudé     UHI_plog = 13,
41*ad520a97SPhilippe Mathieu-Daudé     UHI_assert = 14,
42*ad520a97SPhilippe Mathieu-Daudé     UHI_pread = 19,
43*ad520a97SPhilippe Mathieu-Daudé     UHI_pwrite = 20,
44*ad520a97SPhilippe Mathieu-Daudé     UHI_link = 22
45*ad520a97SPhilippe Mathieu-Daudé } UHIOp;
46*ad520a97SPhilippe Mathieu-Daudé 
47*ad520a97SPhilippe Mathieu-Daudé typedef struct UHIStat {
48*ad520a97SPhilippe Mathieu-Daudé     int16_t uhi_st_dev;
49*ad520a97SPhilippe Mathieu-Daudé     uint16_t uhi_st_ino;
50*ad520a97SPhilippe Mathieu-Daudé     uint32_t uhi_st_mode;
51*ad520a97SPhilippe Mathieu-Daudé     uint16_t uhi_st_nlink;
52*ad520a97SPhilippe Mathieu-Daudé     uint16_t uhi_st_uid;
53*ad520a97SPhilippe Mathieu-Daudé     uint16_t uhi_st_gid;
54*ad520a97SPhilippe Mathieu-Daudé     int16_t uhi_st_rdev;
55*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_size;
56*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_atime;
57*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_spare1;
58*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_mtime;
59*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_spare2;
60*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_ctime;
61*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_spare3;
62*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_blksize;
63*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_blocks;
64*ad520a97SPhilippe Mathieu-Daudé     uint64_t uhi_st_spare4[2];
65*ad520a97SPhilippe Mathieu-Daudé } UHIStat;
66*ad520a97SPhilippe Mathieu-Daudé 
67*ad520a97SPhilippe Mathieu-Daudé enum UHIOpenFlags {
68*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_RDONLY = 0x0,
69*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_WRONLY = 0x1,
70*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_RDWR   = 0x2,
71*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_APPEND = 0x8,
72*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_CREAT  = 0x200,
73*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_TRUNC  = 0x400,
74*ad520a97SPhilippe Mathieu-Daudé     UHIOpen_EXCL   = 0x800
75*ad520a97SPhilippe Mathieu-Daudé };
76*ad520a97SPhilippe Mathieu-Daudé 
77*ad520a97SPhilippe Mathieu-Daudé /* Errno values taken from asm-mips/errno.h */
78*ad520a97SPhilippe Mathieu-Daudé static uint16_t host_to_mips_errno[] = {
79*ad520a97SPhilippe Mathieu-Daudé     [ENAMETOOLONG] = 78,
80*ad520a97SPhilippe Mathieu-Daudé #ifdef EOVERFLOW
81*ad520a97SPhilippe Mathieu-Daudé     [EOVERFLOW]    = 79,
82*ad520a97SPhilippe Mathieu-Daudé #endif
83*ad520a97SPhilippe Mathieu-Daudé #ifdef ELOOP
84*ad520a97SPhilippe Mathieu-Daudé     [ELOOP]        = 90,
85*ad520a97SPhilippe Mathieu-Daudé #endif
86*ad520a97SPhilippe Mathieu-Daudé };
87*ad520a97SPhilippe Mathieu-Daudé 
88*ad520a97SPhilippe Mathieu-Daudé static int errno_mips(int err)
89*ad520a97SPhilippe Mathieu-Daudé {
90*ad520a97SPhilippe Mathieu-Daudé     if (err < 0 || err >= ARRAY_SIZE(host_to_mips_errno)) {
91*ad520a97SPhilippe Mathieu-Daudé         return EINVAL;
92*ad520a97SPhilippe Mathieu-Daudé     } else if (host_to_mips_errno[err]) {
93*ad520a97SPhilippe Mathieu-Daudé         return host_to_mips_errno[err];
94*ad520a97SPhilippe Mathieu-Daudé     } else {
95*ad520a97SPhilippe Mathieu-Daudé         return err;
96*ad520a97SPhilippe Mathieu-Daudé     }
97*ad520a97SPhilippe Mathieu-Daudé }
98*ad520a97SPhilippe Mathieu-Daudé 
99*ad520a97SPhilippe Mathieu-Daudé static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src,
100*ad520a97SPhilippe Mathieu-Daudé                                target_ulong vaddr)
101*ad520a97SPhilippe Mathieu-Daudé {
102*ad520a97SPhilippe Mathieu-Daudé     hwaddr len = sizeof(struct UHIStat);
103*ad520a97SPhilippe Mathieu-Daudé     UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
104*ad520a97SPhilippe Mathieu-Daudé     if (!dst) {
105*ad520a97SPhilippe Mathieu-Daudé         errno = EFAULT;
106*ad520a97SPhilippe Mathieu-Daudé         return -1;
107*ad520a97SPhilippe Mathieu-Daudé     }
108*ad520a97SPhilippe Mathieu-Daudé 
109*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_dev = tswap16(src->st_dev);
110*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_ino = tswap16(src->st_ino);
111*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_mode = tswap32(src->st_mode);
112*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_nlink = tswap16(src->st_nlink);
113*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_uid = tswap16(src->st_uid);
114*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_gid = tswap16(src->st_gid);
115*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_rdev = tswap16(src->st_rdev);
116*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_size = tswap64(src->st_size);
117*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_atime = tswap64(src->st_atime);
118*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_mtime = tswap64(src->st_mtime);
119*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_ctime = tswap64(src->st_ctime);
120*ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32
121*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_blksize = 0;
122*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_blocks = 0;
123*ad520a97SPhilippe Mathieu-Daudé #else
124*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_blksize = tswap64(src->st_blksize);
125*ad520a97SPhilippe Mathieu-Daudé     dst->uhi_st_blocks = tswap64(src->st_blocks);
126*ad520a97SPhilippe Mathieu-Daudé #endif
127*ad520a97SPhilippe Mathieu-Daudé     unlock_user(dst, vaddr, len);
128*ad520a97SPhilippe Mathieu-Daudé     return 0;
129*ad520a97SPhilippe Mathieu-Daudé }
130*ad520a97SPhilippe Mathieu-Daudé 
131*ad520a97SPhilippe Mathieu-Daudé static int get_open_flags(target_ulong target_flags)
132*ad520a97SPhilippe Mathieu-Daudé {
133*ad520a97SPhilippe Mathieu-Daudé     int open_flags = 0;
134*ad520a97SPhilippe Mathieu-Daudé 
135*ad520a97SPhilippe Mathieu-Daudé     if (target_flags & UHIOpen_RDWR) {
136*ad520a97SPhilippe Mathieu-Daudé         open_flags |= O_RDWR;
137*ad520a97SPhilippe Mathieu-Daudé     } else if (target_flags & UHIOpen_WRONLY) {
138*ad520a97SPhilippe Mathieu-Daudé         open_flags |= O_WRONLY;
139*ad520a97SPhilippe Mathieu-Daudé     } else {
140*ad520a97SPhilippe Mathieu-Daudé         open_flags |= O_RDONLY;
141*ad520a97SPhilippe Mathieu-Daudé     }
142*ad520a97SPhilippe Mathieu-Daudé 
143*ad520a97SPhilippe Mathieu-Daudé     open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0;
144*ad520a97SPhilippe Mathieu-Daudé     open_flags |= (target_flags & UHIOpen_CREAT)  ? O_CREAT  : 0;
145*ad520a97SPhilippe Mathieu-Daudé     open_flags |= (target_flags & UHIOpen_TRUNC)  ? O_TRUNC  : 0;
146*ad520a97SPhilippe Mathieu-Daudé     open_flags |= (target_flags & UHIOpen_EXCL)   ? O_EXCL   : 0;
147*ad520a97SPhilippe Mathieu-Daudé 
148*ad520a97SPhilippe Mathieu-Daudé     return open_flags;
149*ad520a97SPhilippe Mathieu-Daudé }
150*ad520a97SPhilippe Mathieu-Daudé 
151*ad520a97SPhilippe Mathieu-Daudé static int write_to_file(CPUMIPSState *env, target_ulong fd, target_ulong vaddr,
152*ad520a97SPhilippe Mathieu-Daudé                          target_ulong len, target_ulong offset)
153*ad520a97SPhilippe Mathieu-Daudé {
154*ad520a97SPhilippe Mathieu-Daudé     int num_of_bytes;
155*ad520a97SPhilippe Mathieu-Daudé     void *dst = lock_user(VERIFY_READ, vaddr, len, 1);
156*ad520a97SPhilippe Mathieu-Daudé     if (!dst) {
157*ad520a97SPhilippe Mathieu-Daudé         errno = EFAULT;
158*ad520a97SPhilippe Mathieu-Daudé         return -1;
159*ad520a97SPhilippe Mathieu-Daudé     }
160*ad520a97SPhilippe Mathieu-Daudé 
161*ad520a97SPhilippe Mathieu-Daudé     if (offset) {
162*ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32
163*ad520a97SPhilippe Mathieu-Daudé         num_of_bytes = 0;
164*ad520a97SPhilippe Mathieu-Daudé #else
165*ad520a97SPhilippe Mathieu-Daudé         num_of_bytes = pwrite(fd, dst, len, offset);
166*ad520a97SPhilippe Mathieu-Daudé #endif
167*ad520a97SPhilippe Mathieu-Daudé     } else {
168*ad520a97SPhilippe Mathieu-Daudé         num_of_bytes = write(fd, dst, len);
169*ad520a97SPhilippe Mathieu-Daudé     }
170*ad520a97SPhilippe Mathieu-Daudé 
171*ad520a97SPhilippe Mathieu-Daudé     unlock_user(dst, vaddr, 0);
172*ad520a97SPhilippe Mathieu-Daudé     return num_of_bytes;
173*ad520a97SPhilippe Mathieu-Daudé }
174*ad520a97SPhilippe Mathieu-Daudé 
175*ad520a97SPhilippe Mathieu-Daudé static int read_from_file(CPUMIPSState *env, target_ulong fd,
176*ad520a97SPhilippe Mathieu-Daudé                           target_ulong vaddr, target_ulong len,
177*ad520a97SPhilippe Mathieu-Daudé                           target_ulong offset)
178*ad520a97SPhilippe Mathieu-Daudé {
179*ad520a97SPhilippe Mathieu-Daudé     int num_of_bytes;
180*ad520a97SPhilippe Mathieu-Daudé     void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
181*ad520a97SPhilippe Mathieu-Daudé     if (!dst) {
182*ad520a97SPhilippe Mathieu-Daudé         errno = EFAULT;
183*ad520a97SPhilippe Mathieu-Daudé         return -1;
184*ad520a97SPhilippe Mathieu-Daudé     }
185*ad520a97SPhilippe Mathieu-Daudé 
186*ad520a97SPhilippe Mathieu-Daudé     if (offset) {
187*ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32
188*ad520a97SPhilippe Mathieu-Daudé         num_of_bytes = 0;
189*ad520a97SPhilippe Mathieu-Daudé #else
190*ad520a97SPhilippe Mathieu-Daudé         num_of_bytes = pread(fd, dst, len, offset);
191*ad520a97SPhilippe Mathieu-Daudé #endif
192*ad520a97SPhilippe Mathieu-Daudé     } else {
193*ad520a97SPhilippe Mathieu-Daudé         num_of_bytes = read(fd, dst, len);
194*ad520a97SPhilippe Mathieu-Daudé     }
195*ad520a97SPhilippe Mathieu-Daudé 
196*ad520a97SPhilippe Mathieu-Daudé     unlock_user(dst, vaddr, len);
197*ad520a97SPhilippe Mathieu-Daudé     return num_of_bytes;
198*ad520a97SPhilippe Mathieu-Daudé }
199*ad520a97SPhilippe Mathieu-Daudé 
200*ad520a97SPhilippe Mathieu-Daudé static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
201*ad520a97SPhilippe Mathieu-Daudé                                target_ulong vaddr)
202*ad520a97SPhilippe Mathieu-Daudé {
203*ad520a97SPhilippe Mathieu-Daudé     int strsize = strlen(semihosting_get_arg(arg_num)) + 1;
204*ad520a97SPhilippe Mathieu-Daudé     char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0);
205*ad520a97SPhilippe Mathieu-Daudé     if (!dst) {
206*ad520a97SPhilippe Mathieu-Daudé         return -1;
207*ad520a97SPhilippe Mathieu-Daudé     }
208*ad520a97SPhilippe Mathieu-Daudé 
209*ad520a97SPhilippe Mathieu-Daudé     strcpy(dst, semihosting_get_arg(arg_num));
210*ad520a97SPhilippe Mathieu-Daudé 
211*ad520a97SPhilippe Mathieu-Daudé     unlock_user(dst, vaddr, strsize);
212*ad520a97SPhilippe Mathieu-Daudé     return 0;
213*ad520a97SPhilippe Mathieu-Daudé }
214*ad520a97SPhilippe Mathieu-Daudé 
215*ad520a97SPhilippe Mathieu-Daudé #define GET_TARGET_STRING(p, addr)              \
216*ad520a97SPhilippe Mathieu-Daudé     do {                                        \
217*ad520a97SPhilippe Mathieu-Daudé         p = lock_user_string(addr);             \
218*ad520a97SPhilippe Mathieu-Daudé         if (!p) {                               \
219*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = -1;                        \
220*ad520a97SPhilippe Mathieu-Daudé             gpr[3] = EFAULT;                    \
221*ad520a97SPhilippe Mathieu-Daudé             return;                             \
222*ad520a97SPhilippe Mathieu-Daudé         }                                       \
223*ad520a97SPhilippe Mathieu-Daudé     } while (0)
224*ad520a97SPhilippe Mathieu-Daudé 
225*ad520a97SPhilippe Mathieu-Daudé #define GET_TARGET_STRINGS_2(p, addr, p2, addr2)        \
226*ad520a97SPhilippe Mathieu-Daudé     do {                                                \
227*ad520a97SPhilippe Mathieu-Daudé         p = lock_user_string(addr);                     \
228*ad520a97SPhilippe Mathieu-Daudé         if (!p) {                                       \
229*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = -1;                                \
230*ad520a97SPhilippe Mathieu-Daudé             gpr[3] = EFAULT;                            \
231*ad520a97SPhilippe Mathieu-Daudé             return;                                     \
232*ad520a97SPhilippe Mathieu-Daudé         }                                               \
233*ad520a97SPhilippe Mathieu-Daudé         p2 = lock_user_string(addr2);                   \
234*ad520a97SPhilippe Mathieu-Daudé         if (!p2) {                                      \
235*ad520a97SPhilippe Mathieu-Daudé             unlock_user(p, addr, 0);                    \
236*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = -1;                                \
237*ad520a97SPhilippe Mathieu-Daudé             gpr[3] = EFAULT;                            \
238*ad520a97SPhilippe Mathieu-Daudé             return;                                     \
239*ad520a97SPhilippe Mathieu-Daudé         }                                               \
240*ad520a97SPhilippe Mathieu-Daudé     } while (0)
241*ad520a97SPhilippe Mathieu-Daudé 
242*ad520a97SPhilippe Mathieu-Daudé #define FREE_TARGET_STRING(p, gpr)              \
243*ad520a97SPhilippe Mathieu-Daudé     do {                                        \
244*ad520a97SPhilippe Mathieu-Daudé         unlock_user(p, gpr, 0);                 \
245*ad520a97SPhilippe Mathieu-Daudé     } while (0)
246*ad520a97SPhilippe Mathieu-Daudé 
247*ad520a97SPhilippe Mathieu-Daudé void helper_do_semihosting(CPUMIPSState *env)
248*ad520a97SPhilippe Mathieu-Daudé {
249*ad520a97SPhilippe Mathieu-Daudé     target_ulong *gpr = env->active_tc.gpr;
250*ad520a97SPhilippe Mathieu-Daudé     const UHIOp op = gpr[25];
251*ad520a97SPhilippe Mathieu-Daudé     char *p, *p2;
252*ad520a97SPhilippe Mathieu-Daudé 
253*ad520a97SPhilippe Mathieu-Daudé     switch (op) {
254*ad520a97SPhilippe Mathieu-Daudé     case UHI_exit:
255*ad520a97SPhilippe Mathieu-Daudé         qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]);
256*ad520a97SPhilippe Mathieu-Daudé         exit(gpr[4]);
257*ad520a97SPhilippe Mathieu-Daudé     case UHI_open:
258*ad520a97SPhilippe Mathieu-Daudé         GET_TARGET_STRING(p, gpr[4]);
259*ad520a97SPhilippe Mathieu-Daudé         if (!strcmp("/dev/stdin", p)) {
260*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = 0;
261*ad520a97SPhilippe Mathieu-Daudé         } else if (!strcmp("/dev/stdout", p)) {
262*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = 1;
263*ad520a97SPhilippe Mathieu-Daudé         } else if (!strcmp("/dev/stderr", p)) {
264*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = 2;
265*ad520a97SPhilippe Mathieu-Daudé         } else {
266*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]);
267*ad520a97SPhilippe Mathieu-Daudé             gpr[3] = errno_mips(errno);
268*ad520a97SPhilippe Mathieu-Daudé         }
269*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p, gpr[4]);
270*ad520a97SPhilippe Mathieu-Daudé         break;
271*ad520a97SPhilippe Mathieu-Daudé     case UHI_close:
272*ad520a97SPhilippe Mathieu-Daudé         if (gpr[4] < 3) {
273*ad520a97SPhilippe Mathieu-Daudé             /* ignore closing stdin/stdout/stderr */
274*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = 0;
275*ad520a97SPhilippe Mathieu-Daudé             return;
276*ad520a97SPhilippe Mathieu-Daudé         }
277*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = close(gpr[4]);
278*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
279*ad520a97SPhilippe Mathieu-Daudé         break;
280*ad520a97SPhilippe Mathieu-Daudé     case UHI_read:
281*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0);
282*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
283*ad520a97SPhilippe Mathieu-Daudé         break;
284*ad520a97SPhilippe Mathieu-Daudé     case UHI_write:
285*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0);
286*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
287*ad520a97SPhilippe Mathieu-Daudé         break;
288*ad520a97SPhilippe Mathieu-Daudé     case UHI_lseek:
289*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = lseek(gpr[4], gpr[5], gpr[6]);
290*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
291*ad520a97SPhilippe Mathieu-Daudé         break;
292*ad520a97SPhilippe Mathieu-Daudé     case UHI_unlink:
293*ad520a97SPhilippe Mathieu-Daudé         GET_TARGET_STRING(p, gpr[4]);
294*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = remove(p);
295*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
296*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p, gpr[4]);
297*ad520a97SPhilippe Mathieu-Daudé         break;
298*ad520a97SPhilippe Mathieu-Daudé     case UHI_fstat:
299*ad520a97SPhilippe Mathieu-Daudé         {
300*ad520a97SPhilippe Mathieu-Daudé             struct stat sbuf;
301*ad520a97SPhilippe Mathieu-Daudé             memset(&sbuf, 0, sizeof(sbuf));
302*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = fstat(gpr[4], &sbuf);
303*ad520a97SPhilippe Mathieu-Daudé             gpr[3] = errno_mips(errno);
304*ad520a97SPhilippe Mathieu-Daudé             if (gpr[2]) {
305*ad520a97SPhilippe Mathieu-Daudé                 return;
306*ad520a97SPhilippe Mathieu-Daudé             }
307*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
308*ad520a97SPhilippe Mathieu-Daudé             gpr[3] = errno_mips(errno);
309*ad520a97SPhilippe Mathieu-Daudé         }
310*ad520a97SPhilippe Mathieu-Daudé         break;
311*ad520a97SPhilippe Mathieu-Daudé     case UHI_argc:
312*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = semihosting_get_argc();
313*ad520a97SPhilippe Mathieu-Daudé         break;
314*ad520a97SPhilippe Mathieu-Daudé     case UHI_argnlen:
315*ad520a97SPhilippe Mathieu-Daudé         if (gpr[4] >= semihosting_get_argc()) {
316*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = -1;
317*ad520a97SPhilippe Mathieu-Daudé             return;
318*ad520a97SPhilippe Mathieu-Daudé         }
319*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = strlen(semihosting_get_arg(gpr[4]));
320*ad520a97SPhilippe Mathieu-Daudé         break;
321*ad520a97SPhilippe Mathieu-Daudé     case UHI_argn:
322*ad520a97SPhilippe Mathieu-Daudé         if (gpr[4] >= semihosting_get_argc()) {
323*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = -1;
324*ad520a97SPhilippe Mathieu-Daudé             return;
325*ad520a97SPhilippe Mathieu-Daudé         }
326*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
327*ad520a97SPhilippe Mathieu-Daudé         break;
328*ad520a97SPhilippe Mathieu-Daudé     case UHI_plog:
329*ad520a97SPhilippe Mathieu-Daudé         GET_TARGET_STRING(p, gpr[4]);
330*ad520a97SPhilippe Mathieu-Daudé         p2 = strstr(p, "%d");
331*ad520a97SPhilippe Mathieu-Daudé         if (p2) {
332*ad520a97SPhilippe Mathieu-Daudé             int char_num = p2 - p;
333*ad520a97SPhilippe Mathieu-Daudé             GString *s = g_string_new_len(p, char_num);
334*ad520a97SPhilippe Mathieu-Daudé             g_string_append_printf(s, "%d%s", (int)gpr[5], p2 + 2);
335*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = qemu_semihosting_log_out(s->str, s->len);
336*ad520a97SPhilippe Mathieu-Daudé             g_string_free(s, true);
337*ad520a97SPhilippe Mathieu-Daudé         } else {
338*ad520a97SPhilippe Mathieu-Daudé             gpr[2] = qemu_semihosting_log_out(p, strlen(p));
339*ad520a97SPhilippe Mathieu-Daudé         }
340*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p, gpr[4]);
341*ad520a97SPhilippe Mathieu-Daudé         break;
342*ad520a97SPhilippe Mathieu-Daudé     case UHI_assert:
343*ad520a97SPhilippe Mathieu-Daudé         GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]);
344*ad520a97SPhilippe Mathieu-Daudé         printf("assertion '");
345*ad520a97SPhilippe Mathieu-Daudé         printf("\"%s\"", p);
346*ad520a97SPhilippe Mathieu-Daudé         printf("': file \"%s\", line %d\n", p2, (int)gpr[6]);
347*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p2, gpr[5]);
348*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p, gpr[4]);
349*ad520a97SPhilippe Mathieu-Daudé         abort();
350*ad520a97SPhilippe Mathieu-Daudé         break;
351*ad520a97SPhilippe Mathieu-Daudé     case UHI_pread:
352*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
353*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
354*ad520a97SPhilippe Mathieu-Daudé         break;
355*ad520a97SPhilippe Mathieu-Daudé     case UHI_pwrite:
356*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
357*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
358*ad520a97SPhilippe Mathieu-Daudé         break;
359*ad520a97SPhilippe Mathieu-Daudé #ifndef _WIN32
360*ad520a97SPhilippe Mathieu-Daudé     case UHI_link:
361*ad520a97SPhilippe Mathieu-Daudé         GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]);
362*ad520a97SPhilippe Mathieu-Daudé         gpr[2] = link(p, p2);
363*ad520a97SPhilippe Mathieu-Daudé         gpr[3] = errno_mips(errno);
364*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p2, gpr[5]);
365*ad520a97SPhilippe Mathieu-Daudé         FREE_TARGET_STRING(p, gpr[4]);
366*ad520a97SPhilippe Mathieu-Daudé         break;
367*ad520a97SPhilippe Mathieu-Daudé #endif
368*ad520a97SPhilippe Mathieu-Daudé     default:
369*ad520a97SPhilippe Mathieu-Daudé         fprintf(stderr, "Unknown UHI operation %d\n", op);
370*ad520a97SPhilippe Mathieu-Daudé         abort();
371*ad520a97SPhilippe Mathieu-Daudé     }
372*ad520a97SPhilippe Mathieu-Daudé     return;
373*ad520a97SPhilippe Mathieu-Daudé }
374