Statistics
| Branch: | Revision:

root / arm-semi.c @ 51b2772f

History | View | Annotate | Download (11.9 kB)

1 a4f81979 bellard
/*
2 a4f81979 bellard
 *  Arm "Angel" semihosting syscalls
3 a4f81979 bellard
 * 
4 8e71621f pbrook
 *  Copyright (c) 2005, 2007 CodeSourcery.
5 8e71621f pbrook
 *  Written by Paul Brook.
6 a4f81979 bellard
 *
7 a4f81979 bellard
 *  This program is free software; you can redistribute it and/or modify
8 a4f81979 bellard
 *  it under the terms of the GNU General Public License as published by
9 a4f81979 bellard
 *  the Free Software Foundation; either version 2 of the License, or
10 a4f81979 bellard
 *  (at your option) any later version.
11 a4f81979 bellard
 *
12 a4f81979 bellard
 *  This program is distributed in the hope that it will be useful,
13 a4f81979 bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 a4f81979 bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 a4f81979 bellard
 *  GNU General Public License for more details.
16 a4f81979 bellard
 *
17 a4f81979 bellard
 *  You should have received a copy of the GNU General Public License
18 a4f81979 bellard
 *  along with this program; if not, write to the Free Software
19 a4f81979 bellard
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 a4f81979 bellard
 */
21 a4f81979 bellard
22 a4f81979 bellard
#include <sys/types.h>
23 a4f81979 bellard
#include <sys/stat.h>
24 a4f81979 bellard
#include <fcntl.h>
25 a4f81979 bellard
#include <unistd.h>
26 a4f81979 bellard
#include <stdlib.h>
27 a4f81979 bellard
#include <stdio.h>
28 a4f81979 bellard
#include <time.h>
29 a4f81979 bellard
30 8e71621f pbrook
#include "cpu.h"
31 8e71621f pbrook
#ifdef CONFIG_USER_ONLY
32 a4f81979 bellard
#include "qemu.h"
33 a4f81979 bellard
34 a4f81979 bellard
#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
35 8e71621f pbrook
#else
36 8e71621f pbrook
#include "vl.h"
37 8e71621f pbrook
#endif
38 a4f81979 bellard
39 a4f81979 bellard
#define SYS_OPEN        0x01
40 a4f81979 bellard
#define SYS_CLOSE       0x02
41 a4f81979 bellard
#define SYS_WRITEC      0x03
42 a4f81979 bellard
#define SYS_WRITE0      0x04
43 a4f81979 bellard
#define SYS_WRITE       0x05
44 a4f81979 bellard
#define SYS_READ        0x06
45 a4f81979 bellard
#define SYS_READC       0x07
46 a4f81979 bellard
#define SYS_ISTTY       0x09
47 a4f81979 bellard
#define SYS_SEEK        0x0a
48 a4f81979 bellard
#define SYS_FLEN        0x0c
49 a4f81979 bellard
#define SYS_TMPNAM      0x0d
50 a4f81979 bellard
#define SYS_REMOVE      0x0e
51 a4f81979 bellard
#define SYS_RENAME      0x0f
52 a4f81979 bellard
#define SYS_CLOCK       0x10
53 a4f81979 bellard
#define SYS_TIME        0x11
54 a4f81979 bellard
#define SYS_SYSTEM      0x12
55 a4f81979 bellard
#define SYS_ERRNO       0x13
56 a4f81979 bellard
#define SYS_GET_CMDLINE 0x15
57 a4f81979 bellard
#define SYS_HEAPINFO    0x16
58 a4f81979 bellard
#define SYS_EXIT        0x18
59 a4f81979 bellard
60 a4f81979 bellard
#ifndef O_BINARY
61 a4f81979 bellard
#define O_BINARY 0
62 a4f81979 bellard
#endif
63 a4f81979 bellard
64 a2d1ebaf pbrook
#define GDB_O_RDONLY  0x000
65 a2d1ebaf pbrook
#define GDB_O_WRONLY  0x001
66 a2d1ebaf pbrook
#define GDB_O_RDWR    0x002
67 a2d1ebaf pbrook
#define GDB_O_APPEND  0x008
68 a2d1ebaf pbrook
#define GDB_O_CREAT   0x200
69 a2d1ebaf pbrook
#define GDB_O_TRUNC   0x400
70 a2d1ebaf pbrook
#define GDB_O_BINARY  0
71 a2d1ebaf pbrook
72 a2d1ebaf pbrook
static int gdb_open_modeflags[12] = {
73 a2d1ebaf pbrook
    GDB_O_RDONLY,
74 a2d1ebaf pbrook
    GDB_O_RDONLY | GDB_O_BINARY,
75 a2d1ebaf pbrook
    GDB_O_RDWR,
76 a2d1ebaf pbrook
    GDB_O_RDWR | GDB_O_BINARY,
77 a2d1ebaf pbrook
    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
78 a2d1ebaf pbrook
    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
79 a2d1ebaf pbrook
    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
80 a2d1ebaf pbrook
    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
81 a2d1ebaf pbrook
    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
82 a2d1ebaf pbrook
    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
83 a2d1ebaf pbrook
    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
84 a2d1ebaf pbrook
    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
85 a2d1ebaf pbrook
};
86 a2d1ebaf pbrook
87 a2d1ebaf pbrook
static int open_modeflags[12] = {
88 a4f81979 bellard
    O_RDONLY,
89 a4f81979 bellard
    O_RDONLY | O_BINARY,
90 a4f81979 bellard
    O_RDWR,
91 a4f81979 bellard
    O_RDWR | O_BINARY,
92 a4f81979 bellard
    O_WRONLY | O_CREAT | O_TRUNC,
93 a4f81979 bellard
    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
94 a4f81979 bellard
    O_RDWR | O_CREAT | O_TRUNC,
95 a4f81979 bellard
    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
96 a4f81979 bellard
    O_WRONLY | O_CREAT | O_APPEND,
97 a4f81979 bellard
    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
98 a4f81979 bellard
    O_RDWR | O_CREAT | O_APPEND,
99 a4f81979 bellard
    O_RDWR | O_CREAT | O_APPEND | O_BINARY
100 a4f81979 bellard
};
101 a4f81979 bellard
102 8e71621f pbrook
#ifdef CONFIG_USER_ONLY
103 a4f81979 bellard
static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
104 a4f81979 bellard
{
105 8e71621f pbrook
    if (code == (uint32_t)-1)
106 8e71621f pbrook
        ts->swi_errno = errno;
107 8e71621f pbrook
    return code;
108 8e71621f pbrook
}
109 8e71621f pbrook
#else
110 8e71621f pbrook
static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
111 8e71621f pbrook
{
112 8e71621f pbrook
    return code;
113 8e71621f pbrook
}
114 8e71621f pbrook
115 a87295e8 pbrook
#include "softmmu-semi.h"
116 8e71621f pbrook
#endif
117 a4f81979 bellard
118 a2d1ebaf pbrook
static target_ulong arm_semi_syscall_len;
119 a2d1ebaf pbrook
120 a2d1ebaf pbrook
static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
121 a2d1ebaf pbrook
{
122 a2d1ebaf pbrook
#ifdef CONFIG_USER_ONLY
123 a2d1ebaf pbrook
    TaskState *ts = env->opaque;
124 a2d1ebaf pbrook
#endif
125 a2d1ebaf pbrook
    if (ret == (target_ulong)-1) {
126 a2d1ebaf pbrook
#ifdef CONFIG_USER_ONLY
127 a2d1ebaf pbrook
        ts->swi_errno = err;
128 a2d1ebaf pbrook
#endif
129 a2d1ebaf pbrook
        env->regs[0] = ret;
130 a2d1ebaf pbrook
    } else {
131 a2d1ebaf pbrook
        /* Fixup syscalls that use nonstardard return conventions.  */
132 a2d1ebaf pbrook
        switch (env->regs[0]) {
133 a2d1ebaf pbrook
        case SYS_WRITE:
134 a2d1ebaf pbrook
        case SYS_READ:
135 a2d1ebaf pbrook
            env->regs[0] = arm_semi_syscall_len - ret;
136 a2d1ebaf pbrook
            break;
137 a2d1ebaf pbrook
        case SYS_SEEK:
138 a2d1ebaf pbrook
            env->regs[0] = 0;
139 a2d1ebaf pbrook
            break;
140 a2d1ebaf pbrook
        default:
141 a2d1ebaf pbrook
            env->regs[0] = ret;
142 a2d1ebaf pbrook
            break;
143 a2d1ebaf pbrook
        }
144 a2d1ebaf pbrook
    }
145 a2d1ebaf pbrook
}
146 a2d1ebaf pbrook
147 38d0662a pbrook
#define ARG(n) tget32(args + (n) * 4)
148 38d0662a pbrook
#define SET_ARG(n, val) tput32(args + (n) * 4,val)
149 a4f81979 bellard
uint32_t do_arm_semihosting(CPUState *env)
150 a4f81979 bellard
{
151 53a5960a pbrook
    target_ulong args;
152 a4f81979 bellard
    char * s;
153 a4f81979 bellard
    int nr;
154 a4f81979 bellard
    uint32_t ret;
155 8e71621f pbrook
    uint32_t len;
156 8e71621f pbrook
#ifdef CONFIG_USER_ONLY
157 a4f81979 bellard
    TaskState *ts = env->opaque;
158 8e71621f pbrook
#else
159 8e71621f pbrook
    CPUState *ts = env;
160 8e71621f pbrook
#endif
161 a4f81979 bellard
162 a4f81979 bellard
    nr = env->regs[0];
163 53a5960a pbrook
    args = env->regs[1];
164 a4f81979 bellard
    switch (nr) {
165 a4f81979 bellard
    case SYS_OPEN:
166 8e71621f pbrook
        s = lock_user_string(ARG(0));
167 a4f81979 bellard
        if (ARG(1) >= 12)
168 a4f81979 bellard
          return (uint32_t)-1;
169 a4f81979 bellard
        if (strcmp(s, ":tt") == 0) {
170 a4f81979 bellard
            if (ARG(1) < 4)
171 a4f81979 bellard
                return STDIN_FILENO;
172 a4f81979 bellard
            else
173 a4f81979 bellard
                return STDOUT_FILENO;
174 a4f81979 bellard
        }
175 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
176 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2),
177 a2d1ebaf pbrook
                           gdb_open_modeflags[ARG(1)]);
178 a2d1ebaf pbrook
            return env->regs[0];
179 a2d1ebaf pbrook
        } else {
180 a2d1ebaf pbrook
            ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
181 a2d1ebaf pbrook
        }
182 8e71621f pbrook
        unlock_user(s, ARG(0), 0);
183 8e71621f pbrook
        return ret;
184 a4f81979 bellard
    case SYS_CLOSE:
185 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
186 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
187 a2d1ebaf pbrook
            return env->regs[0];
188 a2d1ebaf pbrook
        } else {
189 a2d1ebaf pbrook
            return set_swi_errno(ts, close(ARG(0)));
190 a2d1ebaf pbrook
        }
191 a4f81979 bellard
    case SYS_WRITEC:
192 53a5960a pbrook
        {
193 53a5960a pbrook
          char c = tget8(args);
194 53a5960a pbrook
          /* Write to debug console.  stderr is near enough.  */
195 a2d1ebaf pbrook
          if (use_gdb_syscalls()) {
196 a2d1ebaf pbrook
                gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
197 a2d1ebaf pbrook
                return env->regs[0];
198 a2d1ebaf pbrook
          } else {
199 a2d1ebaf pbrook
                return write(STDERR_FILENO, &c, 1);
200 a2d1ebaf pbrook
          }
201 53a5960a pbrook
        }
202 a4f81979 bellard
    case SYS_WRITE0:
203 53a5960a pbrook
        s = lock_user_string(args);
204 a2d1ebaf pbrook
        len = strlen(s);
205 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
206 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
207 a2d1ebaf pbrook
            ret = env->regs[0];
208 a2d1ebaf pbrook
        } else {
209 a2d1ebaf pbrook
            ret = write(STDERR_FILENO, s, len);
210 a2d1ebaf pbrook
        }
211 53a5960a pbrook
        unlock_user(s, args, 0);
212 53a5960a pbrook
        return ret;
213 a4f81979 bellard
    case SYS_WRITE:
214 8e71621f pbrook
        len = ARG(2);
215 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
216 a2d1ebaf pbrook
            arm_semi_syscall_len = len;
217 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
218 a2d1ebaf pbrook
            return env->regs[0];
219 a2d1ebaf pbrook
        } else {
220 a2d1ebaf pbrook
            s = lock_user(ARG(1), len, 1);
221 a2d1ebaf pbrook
            ret = set_swi_errno(ts, write(ARG(0), s, len));
222 a2d1ebaf pbrook
            unlock_user(s, ARG(1), 0);
223 a2d1ebaf pbrook
            if (ret == (uint32_t)-1)
224 a2d1ebaf pbrook
                return -1;
225 a2d1ebaf pbrook
            return len - ret;
226 a2d1ebaf pbrook
        }
227 a4f81979 bellard
    case SYS_READ:
228 8e71621f pbrook
        len = ARG(2);
229 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
230 a2d1ebaf pbrook
            arm_semi_syscall_len = len;
231 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
232 a2d1ebaf pbrook
            return env->regs[0];
233 a2d1ebaf pbrook
        } else {
234 a2d1ebaf pbrook
            s = lock_user(ARG(1), len, 0);
235 a2d1ebaf pbrook
            do
236 a2d1ebaf pbrook
              ret = set_swi_errno(ts, read(ARG(0), s, len));
237 a2d1ebaf pbrook
            while (ret == -1 && errno == EINTR);
238 a2d1ebaf pbrook
            unlock_user(s, ARG(1), len);
239 a2d1ebaf pbrook
            if (ret == (uint32_t)-1)
240 a2d1ebaf pbrook
                return -1;
241 a2d1ebaf pbrook
            return len - ret;
242 a2d1ebaf pbrook
        }
243 a4f81979 bellard
    case SYS_READC:
244 a4f81979 bellard
       /* XXX: Read from debug cosole. Not implemented.  */
245 a4f81979 bellard
        return 0;
246 a4f81979 bellard
    case SYS_ISTTY:
247 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
248 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
249 a2d1ebaf pbrook
            return env->regs[0];
250 a2d1ebaf pbrook
        } else {
251 a2d1ebaf pbrook
            return isatty(ARG(0));
252 a2d1ebaf pbrook
        }
253 a4f81979 bellard
    case SYS_SEEK:
254 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
255 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1));
256 a2d1ebaf pbrook
            return env->regs[0];
257 a2d1ebaf pbrook
        } else {
258 a2d1ebaf pbrook
            ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
259 a2d1ebaf pbrook
            if (ret == (uint32_t)-1)
260 a2d1ebaf pbrook
              return -1;
261 a2d1ebaf pbrook
            return 0;
262 a2d1ebaf pbrook
        }
263 a4f81979 bellard
    case SYS_FLEN:
264 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
265 a2d1ebaf pbrook
            /* TODO: Use stat syscall.  */
266 a2d1ebaf pbrook
            return -1;
267 a2d1ebaf pbrook
        } else {
268 a4f81979 bellard
            struct stat buf;
269 a4f81979 bellard
            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
270 a4f81979 bellard
            if (ret == (uint32_t)-1)
271 a4f81979 bellard
                return -1;
272 a4f81979 bellard
            return buf.st_size;
273 a4f81979 bellard
        }
274 a4f81979 bellard
    case SYS_TMPNAM:
275 a4f81979 bellard
        /* XXX: Not implemented.  */
276 a4f81979 bellard
        return -1;
277 a4f81979 bellard
    case SYS_REMOVE:
278 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
279 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1));
280 a2d1ebaf pbrook
            ret = env->regs[0];
281 a2d1ebaf pbrook
        } else {
282 a2d1ebaf pbrook
            s = lock_user_string(ARG(0));
283 a2d1ebaf pbrook
            ret =  set_swi_errno(ts, remove(s));
284 a2d1ebaf pbrook
            unlock_user(s, ARG(0), 0);
285 a2d1ebaf pbrook
        }
286 8e71621f pbrook
        return ret;
287 a4f81979 bellard
    case SYS_RENAME:
288 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
289 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
290 a2d1ebaf pbrook
                           ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
291 a2d1ebaf pbrook
            return env->regs[0];
292 a2d1ebaf pbrook
        } else {
293 8e71621f pbrook
            char *s2;
294 8e71621f pbrook
            s = lock_user_string(ARG(0));
295 8e71621f pbrook
            s2 = lock_user_string(ARG(2));
296 8e71621f pbrook
            ret = set_swi_errno(ts, rename(s, s2));
297 8e71621f pbrook
            unlock_user(s2, ARG(2), 0);
298 8e71621f pbrook
            unlock_user(s, ARG(0), 0);
299 8e71621f pbrook
            return ret;
300 8e71621f pbrook
        }
301 a4f81979 bellard
    case SYS_CLOCK:
302 a4f81979 bellard
        return clock() / (CLOCKS_PER_SEC / 100);
303 a4f81979 bellard
    case SYS_TIME:
304 a4f81979 bellard
        return set_swi_errno(ts, time(NULL));
305 a4f81979 bellard
    case SYS_SYSTEM:
306 a2d1ebaf pbrook
        if (use_gdb_syscalls()) {
307 a2d1ebaf pbrook
            gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1));
308 a2d1ebaf pbrook
            return env->regs[0];
309 a2d1ebaf pbrook
        } else {
310 a2d1ebaf pbrook
            s = lock_user_string(ARG(0));
311 a2d1ebaf pbrook
            ret = set_swi_errno(ts, system(s));
312 a2d1ebaf pbrook
            unlock_user(s, ARG(0), 0);
313 a2d1ebaf pbrook
        }
314 a4f81979 bellard
    case SYS_ERRNO:
315 8e71621f pbrook
#ifdef CONFIG_USER_ONLY
316 a4f81979 bellard
        return ts->swi_errno;
317 8e71621f pbrook
#else
318 8e71621f pbrook
        return 0;
319 8e71621f pbrook
#endif
320 a4f81979 bellard
    case SYS_GET_CMDLINE:
321 8e71621f pbrook
#ifdef CONFIG_USER_ONLY
322 38d0662a pbrook
        /* Build a commandline from the original argv.  */
323 38d0662a pbrook
        {
324 38d0662a pbrook
            char **arg = ts->info->host_argv;
325 38d0662a pbrook
            int len = ARG(1);
326 38d0662a pbrook
            /* lock the buffer on the ARM side */
327 38d0662a pbrook
            char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
328 38d0662a pbrook
329 38d0662a pbrook
            s = cmdline_buffer;
330 38d0662a pbrook
            while (*arg && len > 2) {
331 38d0662a pbrook
                int n = strlen(*arg);
332 38d0662a pbrook
333 38d0662a pbrook
                if (s != cmdline_buffer) {
334 38d0662a pbrook
                    *(s++) = ' ';
335 38d0662a pbrook
                    len--;
336 38d0662a pbrook
                }
337 38d0662a pbrook
                if (n >= len)
338 38d0662a pbrook
                    n = len - 1;
339 38d0662a pbrook
                memcpy(s, *arg, n);
340 38d0662a pbrook
                s += n;
341 38d0662a pbrook
                len -= n;
342 38d0662a pbrook
                arg++;
343 38d0662a pbrook
            }
344 38d0662a pbrook
            /* Null terminate the string.  */
345 38d0662a pbrook
            *s = 0;
346 38d0662a pbrook
            len = s - cmdline_buffer;
347 38d0662a pbrook
348 38d0662a pbrook
            /* Unlock the buffer on the ARM side.  */
349 38d0662a pbrook
            unlock_user(cmdline_buffer, ARG(0), len);
350 38d0662a pbrook
351 38d0662a pbrook
            /* Adjust the commandline length argument.  */
352 38d0662a pbrook
            SET_ARG(1, len);
353 38d0662a pbrook
354 38d0662a pbrook
            /* Return success if commandline fit into buffer.  */
355 38d0662a pbrook
            return *arg ? -1 : 0;
356 38d0662a pbrook
        }
357 8e71621f pbrook
#else
358 8e71621f pbrook
      return -1;
359 8e71621f pbrook
#endif
360 a4f81979 bellard
    case SYS_HEAPINFO:
361 a4f81979 bellard
        {
362 a4f81979 bellard
            uint32_t *ptr;
363 a4f81979 bellard
            uint32_t limit;
364 a4f81979 bellard
365 8e71621f pbrook
#ifdef CONFIG_USER_ONLY
366 8e71621f pbrook
            /* Some C libraries assume the heap immediately follows .bss, so
367 a4f81979 bellard
               allocate it using sbrk.  */
368 a4f81979 bellard
            if (!ts->heap_limit) {
369 a4f81979 bellard
                long ret;
370 a4f81979 bellard
371 53a5960a pbrook
                ts->heap_base = do_brk(0);
372 a4f81979 bellard
                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
373 a4f81979 bellard
                /* Try a big heap, and reduce the size if that fails.  */
374 a4f81979 bellard
                for (;;) {
375 53a5960a pbrook
                    ret = do_brk(limit);
376 a4f81979 bellard
                    if (ret != -1)
377 a4f81979 bellard
                        break;
378 a4f81979 bellard
                    limit = (ts->heap_base >> 1) + (limit >> 1);
379 a4f81979 bellard
                }
380 a4f81979 bellard
                ts->heap_limit = limit;
381 a4f81979 bellard
            }
382 a4f81979 bellard
              
383 8e71621f pbrook
            ptr = lock_user(ARG(0), 16, 0);
384 a4f81979 bellard
            ptr[0] = tswap32(ts->heap_base);
385 a4f81979 bellard
            ptr[1] = tswap32(ts->heap_limit);
386 a4f81979 bellard
            ptr[2] = tswap32(ts->stack_base);
387 a4f81979 bellard
            ptr[3] = tswap32(0); /* Stack limit.  */
388 8e71621f pbrook
            unlock_user(ptr, ARG(0), 16);
389 8e71621f pbrook
#else
390 8e71621f pbrook
            limit = ram_size;
391 8e71621f pbrook
            ptr = lock_user(ARG(0), 16, 0);
392 8e71621f pbrook
            /* TODO: Make this use the limit of the loaded application.  */
393 8e71621f pbrook
            ptr[0] = tswap32(limit / 2);
394 8e71621f pbrook
            ptr[1] = tswap32(limit);
395 8e71621f pbrook
            ptr[2] = tswap32(limit); /* Stack base */
396 8e71621f pbrook
            ptr[3] = tswap32(0); /* Stack limit.  */
397 8e71621f pbrook
            unlock_user(ptr, ARG(0), 16);
398 8e71621f pbrook
#endif
399 a4f81979 bellard
            return 0;
400 a4f81979 bellard
        }
401 a4f81979 bellard
    case SYS_EXIT:
402 a4f81979 bellard
        exit(0);
403 a4f81979 bellard
    default:
404 a4f81979 bellard
        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
405 a4f81979 bellard
        cpu_dump_state(env, stderr, fprintf, 0);
406 a4f81979 bellard
        abort();
407 a4f81979 bellard
    }
408 a4f81979 bellard
}