1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
3fcf5ef2aSThomas Huth * All rights reserved.
4fcf5ef2aSThomas Huth *
5fcf5ef2aSThomas Huth * Redistribution and use in source and binary forms, with or without
6fcf5ef2aSThomas Huth * modification, are permitted provided that the following conditions are met:
7fcf5ef2aSThomas Huth * * Redistributions of source code must retain the above copyright
8fcf5ef2aSThomas Huth * notice, this list of conditions and the following disclaimer.
9fcf5ef2aSThomas Huth * * Redistributions in binary form must reproduce the above copyright
10fcf5ef2aSThomas Huth * notice, this list of conditions and the following disclaimer in the
11fcf5ef2aSThomas Huth * documentation and/or other materials provided with the distribution.
12fcf5ef2aSThomas Huth * * Neither the name of the Open Source and Linux Lab nor the
13fcf5ef2aSThomas Huth * names of its contributors may be used to endorse or promote products
14fcf5ef2aSThomas Huth * derived from this software without specific prior written permission.
15fcf5ef2aSThomas Huth *
16fcf5ef2aSThomas Huth * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17fcf5ef2aSThomas Huth * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18fcf5ef2aSThomas Huth * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19fcf5ef2aSThomas Huth * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20fcf5ef2aSThomas Huth * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21fcf5ef2aSThomas Huth * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22fcf5ef2aSThomas Huth * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23fcf5ef2aSThomas Huth * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24fcf5ef2aSThomas Huth * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25fcf5ef2aSThomas Huth * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26fcf5ef2aSThomas Huth */
27fcf5ef2aSThomas Huth
28fcf5ef2aSThomas Huth #include "qemu/osdep.h"
29fcf5ef2aSThomas Huth #include "cpu.h"
308128b3e0SMax Filippov #include "chardev/char-fe.h"
31fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
326b5fe137SPhilippe Mathieu-Daudé #include "semihosting/semihost.h"
338128b3e0SMax Filippov #include "qapi/error.h"
34fcf5ef2aSThomas Huth #include "qemu/log.h"
358128b3e0SMax Filippov
36fcf5ef2aSThomas Huth enum {
37fcf5ef2aSThomas Huth TARGET_SYS_exit = 1,
38fcf5ef2aSThomas Huth TARGET_SYS_read = 3,
39fcf5ef2aSThomas Huth TARGET_SYS_write = 4,
40fcf5ef2aSThomas Huth TARGET_SYS_open = 5,
41fcf5ef2aSThomas Huth TARGET_SYS_close = 6,
42fcf5ef2aSThomas Huth TARGET_SYS_lseek = 19,
43fcf5ef2aSThomas Huth TARGET_SYS_select_one = 29,
44fcf5ef2aSThomas Huth
45fcf5ef2aSThomas Huth TARGET_SYS_argc = 1000,
46fcf5ef2aSThomas Huth TARGET_SYS_argv_sz = 1001,
47fcf5ef2aSThomas Huth TARGET_SYS_argv = 1002,
48fcf5ef2aSThomas Huth TARGET_SYS_memset = 1004,
49fcf5ef2aSThomas Huth };
50fcf5ef2aSThomas Huth
51fcf5ef2aSThomas Huth enum {
52fcf5ef2aSThomas Huth SELECT_ONE_READ = 1,
53fcf5ef2aSThomas Huth SELECT_ONE_WRITE = 2,
54fcf5ef2aSThomas Huth SELECT_ONE_EXCEPT = 3,
55fcf5ef2aSThomas Huth };
56fcf5ef2aSThomas Huth
57fcf5ef2aSThomas Huth enum {
58fcf5ef2aSThomas Huth TARGET_EPERM = 1,
59fcf5ef2aSThomas Huth TARGET_ENOENT = 2,
60fcf5ef2aSThomas Huth TARGET_ESRCH = 3,
61fcf5ef2aSThomas Huth TARGET_EINTR = 4,
62fcf5ef2aSThomas Huth TARGET_EIO = 5,
63fcf5ef2aSThomas Huth TARGET_ENXIO = 6,
64fcf5ef2aSThomas Huth TARGET_E2BIG = 7,
65fcf5ef2aSThomas Huth TARGET_ENOEXEC = 8,
66fcf5ef2aSThomas Huth TARGET_EBADF = 9,
67fcf5ef2aSThomas Huth TARGET_ECHILD = 10,
68fcf5ef2aSThomas Huth TARGET_EAGAIN = 11,
69fcf5ef2aSThomas Huth TARGET_ENOMEM = 12,
70fcf5ef2aSThomas Huth TARGET_EACCES = 13,
71fcf5ef2aSThomas Huth TARGET_EFAULT = 14,
72fcf5ef2aSThomas Huth TARGET_ENOTBLK = 15,
73fcf5ef2aSThomas Huth TARGET_EBUSY = 16,
74fcf5ef2aSThomas Huth TARGET_EEXIST = 17,
75fcf5ef2aSThomas Huth TARGET_EXDEV = 18,
76fcf5ef2aSThomas Huth TARGET_ENODEV = 19,
77fcf5ef2aSThomas Huth TARGET_ENOTDIR = 20,
78fcf5ef2aSThomas Huth TARGET_EISDIR = 21,
79fcf5ef2aSThomas Huth TARGET_EINVAL = 22,
80fcf5ef2aSThomas Huth TARGET_ENFILE = 23,
81fcf5ef2aSThomas Huth TARGET_EMFILE = 24,
82fcf5ef2aSThomas Huth TARGET_ENOTTY = 25,
83fcf5ef2aSThomas Huth TARGET_ETXTBSY = 26,
84fcf5ef2aSThomas Huth TARGET_EFBIG = 27,
85fcf5ef2aSThomas Huth TARGET_ENOSPC = 28,
86fcf5ef2aSThomas Huth TARGET_ESPIPE = 29,
87fcf5ef2aSThomas Huth TARGET_EROFS = 30,
88fcf5ef2aSThomas Huth TARGET_EMLINK = 31,
89fcf5ef2aSThomas Huth TARGET_EPIPE = 32,
90fcf5ef2aSThomas Huth TARGET_EDOM = 33,
91fcf5ef2aSThomas Huth TARGET_ERANGE = 34,
92fcf5ef2aSThomas Huth TARGET_ENOSYS = 88,
93fcf5ef2aSThomas Huth TARGET_ELOOP = 92,
94fcf5ef2aSThomas Huth };
95fcf5ef2aSThomas Huth
errno_h2g(int host_errno)96fcf5ef2aSThomas Huth static uint32_t errno_h2g(int host_errno)
97fcf5ef2aSThomas Huth {
98*3b51b506SThomas Huth switch (host_errno) {
99*3b51b506SThomas Huth case 0: return 0;
100*3b51b506SThomas Huth case EPERM: return TARGET_EPERM;
101*3b51b506SThomas Huth case ENOENT: return TARGET_ENOENT;
102*3b51b506SThomas Huth case ESRCH: return TARGET_ESRCH;
103*3b51b506SThomas Huth case EINTR: return TARGET_EINTR;
104*3b51b506SThomas Huth case EIO: return TARGET_EIO;
105*3b51b506SThomas Huth case ENXIO: return TARGET_ENXIO;
106*3b51b506SThomas Huth case E2BIG: return TARGET_E2BIG;
107*3b51b506SThomas Huth case ENOEXEC: return TARGET_ENOEXEC;
108*3b51b506SThomas Huth case EBADF: return TARGET_EBADF;
109*3b51b506SThomas Huth case ECHILD: return TARGET_ECHILD;
110*3b51b506SThomas Huth case EAGAIN: return TARGET_EAGAIN;
111*3b51b506SThomas Huth case ENOMEM: return TARGET_ENOMEM;
112*3b51b506SThomas Huth case EACCES: return TARGET_EACCES;
113*3b51b506SThomas Huth case EFAULT: return TARGET_EFAULT;
114fcf5ef2aSThomas Huth #ifdef ENOTBLK
115*3b51b506SThomas Huth case ENOTBLK: return TARGET_ENOTBLK;
116fcf5ef2aSThomas Huth #endif
117*3b51b506SThomas Huth case EBUSY: return TARGET_EBUSY;
118*3b51b506SThomas Huth case EEXIST: return TARGET_EEXIST;
119*3b51b506SThomas Huth case EXDEV: return TARGET_EXDEV;
120*3b51b506SThomas Huth case ENODEV: return TARGET_ENODEV;
121*3b51b506SThomas Huth case ENOTDIR: return TARGET_ENOTDIR;
122*3b51b506SThomas Huth case EISDIR: return TARGET_EISDIR;
123*3b51b506SThomas Huth case EINVAL: return TARGET_EINVAL;
124*3b51b506SThomas Huth case ENFILE: return TARGET_ENFILE;
125*3b51b506SThomas Huth case EMFILE: return TARGET_EMFILE;
126*3b51b506SThomas Huth case ENOTTY: return TARGET_ENOTTY;
127fcf5ef2aSThomas Huth #ifdef ETXTBSY
128*3b51b506SThomas Huth case ETXTBSY: return TARGET_ETXTBSY;
129fcf5ef2aSThomas Huth #endif
130*3b51b506SThomas Huth case EFBIG: return TARGET_EFBIG;
131*3b51b506SThomas Huth case ENOSPC: return TARGET_ENOSPC;
132*3b51b506SThomas Huth case ESPIPE: return TARGET_ESPIPE;
133*3b51b506SThomas Huth case EROFS: return TARGET_EROFS;
134*3b51b506SThomas Huth case EMLINK: return TARGET_EMLINK;
135*3b51b506SThomas Huth case EPIPE: return TARGET_EPIPE;
136*3b51b506SThomas Huth case EDOM: return TARGET_EDOM;
137*3b51b506SThomas Huth case ERANGE: return TARGET_ERANGE;
138*3b51b506SThomas Huth case ENOSYS: return TARGET_ENOSYS;
139fcf5ef2aSThomas Huth #ifdef ELOOP
140*3b51b506SThomas Huth case ELOOP: return TARGET_ELOOP;
141fcf5ef2aSThomas Huth #endif
142fcf5ef2aSThomas Huth };
143fcf5ef2aSThomas Huth
144fcf5ef2aSThomas Huth return TARGET_EINVAL;
145fcf5ef2aSThomas Huth }
146fcf5ef2aSThomas Huth
1475aa37f48SMax Filippov typedef struct XtensaSimConsole {
1485aa37f48SMax Filippov CharBackend be;
1495aa37f48SMax Filippov struct {
1505aa37f48SMax Filippov char buffer[16];
1515aa37f48SMax Filippov size_t offset;
1525aa37f48SMax Filippov } input;
1535aa37f48SMax Filippov } XtensaSimConsole;
1545aa37f48SMax Filippov
1555aa37f48SMax Filippov static XtensaSimConsole *sim_console;
1565aa37f48SMax Filippov
1575aa37f48SMax Filippov static IOCanReadHandler sim_console_can_read;
sim_console_can_read(void * opaque)1585aa37f48SMax Filippov static int sim_console_can_read(void *opaque)
1595aa37f48SMax Filippov {
1605aa37f48SMax Filippov XtensaSimConsole *p = opaque;
1615aa37f48SMax Filippov
1625aa37f48SMax Filippov return sizeof(p->input.buffer) - p->input.offset;
1635aa37f48SMax Filippov }
1645aa37f48SMax Filippov
1655aa37f48SMax Filippov static IOReadHandler sim_console_read;
sim_console_read(void * opaque,const uint8_t * buf,int size)1665aa37f48SMax Filippov static void sim_console_read(void *opaque, const uint8_t *buf, int size)
1675aa37f48SMax Filippov {
1685aa37f48SMax Filippov XtensaSimConsole *p = opaque;
1695aa37f48SMax Filippov size_t copy = sizeof(p->input.buffer) - p->input.offset;
1705aa37f48SMax Filippov
1715aa37f48SMax Filippov if (size < copy) {
1725aa37f48SMax Filippov copy = size;
1735aa37f48SMax Filippov }
1745aa37f48SMax Filippov memcpy(p->input.buffer + p->input.offset, buf, copy);
1755aa37f48SMax Filippov p->input.offset += copy;
1765aa37f48SMax Filippov }
1775aa37f48SMax Filippov
xtensa_sim_open_console(Chardev * chr)1788128b3e0SMax Filippov void xtensa_sim_open_console(Chardev *chr)
1798128b3e0SMax Filippov {
1805aa37f48SMax Filippov static XtensaSimConsole console;
1818128b3e0SMax Filippov
1825aa37f48SMax Filippov qemu_chr_fe_init(&console.be, chr, &error_abort);
1835aa37f48SMax Filippov qemu_chr_fe_set_handlers(&console.be,
1845aa37f48SMax Filippov sim_console_can_read,
1855aa37f48SMax Filippov sim_console_read,
1865aa37f48SMax Filippov NULL, NULL, &console,
1875aa37f48SMax Filippov NULL, true);
1885aa37f48SMax Filippov sim_console = &console;
1898128b3e0SMax Filippov }
1908128b3e0SMax Filippov
HELPER(simcall)191fcf5ef2aSThomas Huth void HELPER(simcall)(CPUXtensaState *env)
192fcf5ef2aSThomas Huth {
19392fddfbdSRichard Henderson CPUState *cs = env_cpu(env);
194fcf5ef2aSThomas Huth uint32_t *regs = env->regs;
195fcf5ef2aSThomas Huth
196fcf5ef2aSThomas Huth switch (regs[2]) {
197fcf5ef2aSThomas Huth case TARGET_SYS_exit:
198fcf5ef2aSThomas Huth exit(regs[3]);
199fcf5ef2aSThomas Huth break;
200fcf5ef2aSThomas Huth
201fcf5ef2aSThomas Huth case TARGET_SYS_read:
202fcf5ef2aSThomas Huth case TARGET_SYS_write:
203fcf5ef2aSThomas Huth {
204fcf5ef2aSThomas Huth bool is_write = regs[2] == TARGET_SYS_write;
205fcf5ef2aSThomas Huth uint32_t fd = regs[3];
206fcf5ef2aSThomas Huth uint32_t vaddr = regs[4];
207fcf5ef2aSThomas Huth uint32_t len = regs[5];
208347ec030SMax Filippov uint32_t len_done = 0;
209fcf5ef2aSThomas Huth
210fcf5ef2aSThomas Huth while (len > 0) {
211fcf5ef2aSThomas Huth hwaddr paddr = cpu_get_phys_page_debug(cs, vaddr);
212fcf5ef2aSThomas Huth uint32_t page_left =
213fcf5ef2aSThomas Huth TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
214fcf5ef2aSThomas Huth uint32_t io_sz = page_left < len ? page_left : len;
215fcf5ef2aSThomas Huth hwaddr sz = io_sz;
21630c2afd1SMax Filippov void *buf = cpu_physical_memory_map(paddr, &sz, !is_write);
217347ec030SMax Filippov uint32_t io_done;
218347ec030SMax Filippov bool error = false;
219fcf5ef2aSThomas Huth
220fcf5ef2aSThomas Huth if (buf) {
221fcf5ef2aSThomas Huth vaddr += io_sz;
222fcf5ef2aSThomas Huth len -= io_sz;
2235aa37f48SMax Filippov if (fd < 3 && sim_console) {
2248128b3e0SMax Filippov if (is_write && (fd == 1 || fd == 2)) {
2255aa37f48SMax Filippov io_done = qemu_chr_fe_write_all(&sim_console->be,
2268128b3e0SMax Filippov buf, io_sz);
2278128b3e0SMax Filippov regs[3] = errno_h2g(errno);
2285aa37f48SMax Filippov } else if (!is_write && fd == 0) {
2295aa37f48SMax Filippov if (sim_console->input.offset) {
2305aa37f48SMax Filippov io_done = sim_console->input.offset;
2315aa37f48SMax Filippov if (io_sz < io_done) {
2325aa37f48SMax Filippov io_done = io_sz;
2335aa37f48SMax Filippov }
2345aa37f48SMax Filippov memcpy(buf, sim_console->input.buffer, io_done);
2355aa37f48SMax Filippov memmove(sim_console->input.buffer,
2365aa37f48SMax Filippov sim_console->input.buffer + io_done,
2375aa37f48SMax Filippov sim_console->input.offset - io_done);
2385aa37f48SMax Filippov sim_console->input.offset -= io_done;
2395aa37f48SMax Filippov qemu_chr_fe_accept_input(&sim_console->be);
2405aa37f48SMax Filippov } else {
2415aa37f48SMax Filippov io_done = -1;
2425aa37f48SMax Filippov regs[3] = TARGET_EAGAIN;
2435aa37f48SMax Filippov }
2448128b3e0SMax Filippov } else {
2458128b3e0SMax Filippov qemu_log_mask(LOG_GUEST_ERROR,
2468128b3e0SMax Filippov "%s fd %d is not supported with chardev console\n",
2478128b3e0SMax Filippov is_write ?
2488128b3e0SMax Filippov "writing to" : "reading from", fd);
2498128b3e0SMax Filippov io_done = -1;
2508128b3e0SMax Filippov regs[3] = TARGET_EBADF;
2518128b3e0SMax Filippov }
2528128b3e0SMax Filippov } else {
253347ec030SMax Filippov io_done = is_write ?
254fcf5ef2aSThomas Huth write(fd, buf, io_sz) :
255fcf5ef2aSThomas Huth read(fd, buf, io_sz);
256fcf5ef2aSThomas Huth regs[3] = errno_h2g(errno);
2578128b3e0SMax Filippov }
258347ec030SMax Filippov if (io_done == -1) {
259347ec030SMax Filippov error = true;
260347ec030SMax Filippov io_done = 0;
261fcf5ef2aSThomas Huth }
262347ec030SMax Filippov cpu_physical_memory_unmap(buf, sz, !is_write, io_done);
263fcf5ef2aSThomas Huth } else {
264347ec030SMax Filippov error = true;
265fcf5ef2aSThomas Huth regs[3] = TARGET_EINVAL;
266fcf5ef2aSThomas Huth break;
267fcf5ef2aSThomas Huth }
268347ec030SMax Filippov if (error) {
269347ec030SMax Filippov if (!len_done) {
270347ec030SMax Filippov len_done = -1;
271fcf5ef2aSThomas Huth }
272347ec030SMax Filippov break;
273347ec030SMax Filippov }
274347ec030SMax Filippov len_done += io_done;
275347ec030SMax Filippov if (io_done < io_sz) {
276347ec030SMax Filippov break;
277347ec030SMax Filippov }
278347ec030SMax Filippov }
279347ec030SMax Filippov regs[2] = len_done;
280fcf5ef2aSThomas Huth }
281fcf5ef2aSThomas Huth break;
282fcf5ef2aSThomas Huth
283fcf5ef2aSThomas Huth case TARGET_SYS_open:
284fcf5ef2aSThomas Huth {
285fcf5ef2aSThomas Huth char name[1024];
286fcf5ef2aSThomas Huth int rc;
287fcf5ef2aSThomas Huth int i;
288fcf5ef2aSThomas Huth
289fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(name); ++i) {
290fcf5ef2aSThomas Huth rc = cpu_memory_rw_debug(cs, regs[3] + i,
291fcf5ef2aSThomas Huth (uint8_t *)name + i, 1, 0);
292fcf5ef2aSThomas Huth if (rc != 0 || name[i] == 0) {
293fcf5ef2aSThomas Huth break;
294fcf5ef2aSThomas Huth }
295fcf5ef2aSThomas Huth }
296fcf5ef2aSThomas Huth
297fcf5ef2aSThomas Huth if (rc == 0 && i < ARRAY_SIZE(name)) {
298fcf5ef2aSThomas Huth regs[2] = open(name, regs[4], regs[5]);
299fcf5ef2aSThomas Huth regs[3] = errno_h2g(errno);
300fcf5ef2aSThomas Huth } else {
301fcf5ef2aSThomas Huth regs[2] = -1;
302fcf5ef2aSThomas Huth regs[3] = TARGET_EINVAL;
303fcf5ef2aSThomas Huth }
304fcf5ef2aSThomas Huth }
305fcf5ef2aSThomas Huth break;
306fcf5ef2aSThomas Huth
307fcf5ef2aSThomas Huth case TARGET_SYS_close:
308fcf5ef2aSThomas Huth if (regs[3] < 3) {
309fcf5ef2aSThomas Huth regs[2] = regs[3] = 0;
310fcf5ef2aSThomas Huth } else {
311fcf5ef2aSThomas Huth regs[2] = close(regs[3]);
312fcf5ef2aSThomas Huth regs[3] = errno_h2g(errno);
313fcf5ef2aSThomas Huth }
314fcf5ef2aSThomas Huth break;
315fcf5ef2aSThomas Huth
316fcf5ef2aSThomas Huth case TARGET_SYS_lseek:
317fcf5ef2aSThomas Huth regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
318fcf5ef2aSThomas Huth regs[3] = errno_h2g(errno);
319fcf5ef2aSThomas Huth break;
320fcf5ef2aSThomas Huth
321fcf5ef2aSThomas Huth case TARGET_SYS_select_one:
322fcf5ef2aSThomas Huth {
323fcf5ef2aSThomas Huth uint32_t fd = regs[3];
324fcf5ef2aSThomas Huth uint32_t rq = regs[4];
325fcf5ef2aSThomas Huth uint32_t target_tv = regs[5];
326fcf5ef2aSThomas Huth uint32_t target_tvv[2];
327fcf5ef2aSThomas Huth
328fcf5ef2aSThomas Huth struct timeval tv = {0};
329fcf5ef2aSThomas Huth
330fcf5ef2aSThomas Huth if (target_tv) {
331fcf5ef2aSThomas Huth cpu_memory_rw_debug(cs, target_tv,
332fcf5ef2aSThomas Huth (uint8_t *)target_tvv, sizeof(target_tvv), 0);
333fcf5ef2aSThomas Huth tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
334fcf5ef2aSThomas Huth tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
335fcf5ef2aSThomas Huth }
3365aa37f48SMax Filippov if (fd < 3 && sim_console) {
3378128b3e0SMax Filippov if ((fd == 1 || fd == 2) && rq == SELECT_ONE_WRITE) {
3388128b3e0SMax Filippov regs[2] = 1;
3395aa37f48SMax Filippov } else if (fd == 0 && rq == SELECT_ONE_READ) {
3405aa37f48SMax Filippov regs[2] = sim_console->input.offset > 0;
3418128b3e0SMax Filippov } else {
3428128b3e0SMax Filippov regs[2] = 0;
3438128b3e0SMax Filippov }
3448128b3e0SMax Filippov regs[3] = 0;
3458128b3e0SMax Filippov } else {
3468128b3e0SMax Filippov fd_set fdset;
3478128b3e0SMax Filippov
3488128b3e0SMax Filippov FD_ZERO(&fdset);
3498128b3e0SMax Filippov FD_SET(fd, &fdset);
350fcf5ef2aSThomas Huth regs[2] = select(fd + 1,
351fcf5ef2aSThomas Huth rq == SELECT_ONE_READ ? &fdset : NULL,
352fcf5ef2aSThomas Huth rq == SELECT_ONE_WRITE ? &fdset : NULL,
353fcf5ef2aSThomas Huth rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
354fcf5ef2aSThomas Huth target_tv ? &tv : NULL);
355fcf5ef2aSThomas Huth regs[3] = errno_h2g(errno);
356fcf5ef2aSThomas Huth }
3578128b3e0SMax Filippov }
358fcf5ef2aSThomas Huth break;
359fcf5ef2aSThomas Huth
360fcf5ef2aSThomas Huth case TARGET_SYS_argc:
361f289bb09SMax Filippov regs[2] = semihosting_get_argc();
362fcf5ef2aSThomas Huth regs[3] = 0;
363fcf5ef2aSThomas Huth break;
364fcf5ef2aSThomas Huth
365fcf5ef2aSThomas Huth case TARGET_SYS_argv_sz:
366f289bb09SMax Filippov {
367f289bb09SMax Filippov int argc = semihosting_get_argc();
368f289bb09SMax Filippov int sz = (argc + 1) * sizeof(uint32_t);
369f289bb09SMax Filippov int i;
370f289bb09SMax Filippov
371f289bb09SMax Filippov for (i = 0; i < argc; ++i) {
372f289bb09SMax Filippov sz += 1 + strlen(semihosting_get_arg(i));
373f289bb09SMax Filippov }
374f289bb09SMax Filippov regs[2] = sz;
375fcf5ef2aSThomas Huth regs[3] = 0;
376f289bb09SMax Filippov }
377fcf5ef2aSThomas Huth break;
378fcf5ef2aSThomas Huth
379fcf5ef2aSThomas Huth case TARGET_SYS_argv:
380fcf5ef2aSThomas Huth {
381f289bb09SMax Filippov int argc = semihosting_get_argc();
382f289bb09SMax Filippov int str_offset = (argc + 1) * sizeof(uint32_t);
383f289bb09SMax Filippov int i;
384f289bb09SMax Filippov uint32_t argptr;
385fcf5ef2aSThomas Huth
386f289bb09SMax Filippov for (i = 0; i < argc; ++i) {
387f289bb09SMax Filippov const char *str = semihosting_get_arg(i);
388f289bb09SMax Filippov int str_size = strlen(str) + 1;
389f289bb09SMax Filippov
390f289bb09SMax Filippov argptr = tswap32(regs[3] + str_offset);
391f289bb09SMax Filippov
392fcf5ef2aSThomas Huth cpu_memory_rw_debug(cs,
393f289bb09SMax Filippov regs[3] + i * sizeof(uint32_t),
394f289bb09SMax Filippov (uint8_t *)&argptr, sizeof(argptr), 1);
395f289bb09SMax Filippov cpu_memory_rw_debug(cs,
396f289bb09SMax Filippov regs[3] + str_offset,
397f289bb09SMax Filippov (uint8_t *)str, str_size, 1);
398f289bb09SMax Filippov str_offset += str_size;
399f289bb09SMax Filippov }
400f289bb09SMax Filippov argptr = 0;
401f289bb09SMax Filippov cpu_memory_rw_debug(cs,
402f289bb09SMax Filippov regs[3] + i * sizeof(uint32_t),
403f289bb09SMax Filippov (uint8_t *)&argptr, sizeof(argptr), 1);
404f289bb09SMax Filippov regs[3] = 0;
405fcf5ef2aSThomas Huth }
406fcf5ef2aSThomas Huth break;
407fcf5ef2aSThomas Huth
408fcf5ef2aSThomas Huth case TARGET_SYS_memset:
409fcf5ef2aSThomas Huth {
410fcf5ef2aSThomas Huth uint32_t base = regs[3];
411fcf5ef2aSThomas Huth uint32_t sz = regs[5];
412fcf5ef2aSThomas Huth
413fcf5ef2aSThomas Huth while (sz) {
414fcf5ef2aSThomas Huth hwaddr len = sz;
415fcf5ef2aSThomas Huth void *buf = cpu_physical_memory_map(base, &len, 1);
416fcf5ef2aSThomas Huth
417fcf5ef2aSThomas Huth if (buf && len) {
418fcf5ef2aSThomas Huth memset(buf, regs[4], len);
419fcf5ef2aSThomas Huth cpu_physical_memory_unmap(buf, len, 1, len);
420fcf5ef2aSThomas Huth } else {
421fcf5ef2aSThomas Huth len = 1;
422fcf5ef2aSThomas Huth }
423fcf5ef2aSThomas Huth base += len;
424fcf5ef2aSThomas Huth sz -= len;
425fcf5ef2aSThomas Huth }
426fcf5ef2aSThomas Huth regs[2] = regs[3];
427fcf5ef2aSThomas Huth regs[3] = 0;
428fcf5ef2aSThomas Huth }
429fcf5ef2aSThomas Huth break;
430fcf5ef2aSThomas Huth
431fcf5ef2aSThomas Huth default:
432fcf5ef2aSThomas Huth qemu_log_mask(LOG_GUEST_ERROR, "%s(%d): not implemented\n", __func__, regs[2]);
433fcf5ef2aSThomas Huth regs[2] = -1;
434fcf5ef2aSThomas Huth regs[3] = TARGET_ENOSYS;
435fcf5ef2aSThomas Huth break;
436fcf5ef2aSThomas Huth }
437fcf5ef2aSThomas Huth }
438