hw: Do not include qemu/log.h if it is not necessary
[qemu/ar7.git] / target / lm32 / lm32-semi.c
blob661a77024906f0ec06e0669ffb1f8e953a0cc866
1 /*
2 * Lattice Mico32 semihosting syscall interface
4 * Copyright (c) 2014 Michael Walle <michael@walle.cc>
6 * Based on target/m68k/m68k-semi.c, which is
7 * Copyright (c) 2005-2007 CodeSourcery.
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "cpu.h"
15 #include "exec/helper-proto.h"
16 #include "exec/softmmu-semi.h"
18 enum {
19 TARGET_SYS_exit = 1,
20 TARGET_SYS_open = 2,
21 TARGET_SYS_close = 3,
22 TARGET_SYS_read = 4,
23 TARGET_SYS_write = 5,
24 TARGET_SYS_lseek = 6,
25 TARGET_SYS_fstat = 10,
26 TARGET_SYS_stat = 15,
29 enum {
30 NEWLIB_O_RDONLY = 0x0,
31 NEWLIB_O_WRONLY = 0x1,
32 NEWLIB_O_RDWR = 0x2,
33 NEWLIB_O_APPEND = 0x8,
34 NEWLIB_O_CREAT = 0x200,
35 NEWLIB_O_TRUNC = 0x400,
36 NEWLIB_O_EXCL = 0x800,
39 static int translate_openflags(int flags)
41 int hf;
43 if (flags & NEWLIB_O_WRONLY) {
44 hf = O_WRONLY;
45 } else if (flags & NEWLIB_O_RDWR) {
46 hf = O_RDWR;
47 } else {
48 hf = O_RDONLY;
51 if (flags & NEWLIB_O_APPEND) {
52 hf |= O_APPEND;
55 if (flags & NEWLIB_O_CREAT) {
56 hf |= O_CREAT;
59 if (flags & NEWLIB_O_TRUNC) {
60 hf |= O_TRUNC;
63 if (flags & NEWLIB_O_EXCL) {
64 hf |= O_EXCL;
67 return hf;
70 struct newlib_stat {
71 int16_t newlib_st_dev; /* device */
72 uint16_t newlib_st_ino; /* inode */
73 uint16_t newlib_st_mode; /* protection */
74 uint16_t newlib_st_nlink; /* number of hard links */
75 uint16_t newlib_st_uid; /* user ID of owner */
76 uint16_t newlib_st_gid; /* group ID of owner */
77 int16_t newlib_st_rdev; /* device type (if inode device) */
78 int32_t newlib_st_size; /* total size, in bytes */
79 int32_t newlib_st_atime; /* time of last access */
80 uint32_t newlib_st_spare1;
81 int32_t newlib_st_mtime; /* time of last modification */
82 uint32_t newlib_st_spare2;
83 int32_t newlib_st_ctime; /* time of last change */
84 uint32_t newlib_st_spare3;
85 } QEMU_PACKED;
87 static int translate_stat(CPULM32State *env, target_ulong addr,
88 struct stat *s)
90 struct newlib_stat *p;
92 p = lock_user(VERIFY_WRITE, addr, sizeof(struct newlib_stat), 0);
93 if (!p) {
94 return 0;
96 p->newlib_st_dev = cpu_to_be16(s->st_dev);
97 p->newlib_st_ino = cpu_to_be16(s->st_ino);
98 p->newlib_st_mode = cpu_to_be16(s->st_mode);
99 p->newlib_st_nlink = cpu_to_be16(s->st_nlink);
100 p->newlib_st_uid = cpu_to_be16(s->st_uid);
101 p->newlib_st_gid = cpu_to_be16(s->st_gid);
102 p->newlib_st_rdev = cpu_to_be16(s->st_rdev);
103 p->newlib_st_size = cpu_to_be32(s->st_size);
104 p->newlib_st_atime = cpu_to_be32(s->st_atime);
105 p->newlib_st_mtime = cpu_to_be32(s->st_mtime);
106 p->newlib_st_ctime = cpu_to_be32(s->st_ctime);
107 unlock_user(p, addr, sizeof(struct newlib_stat));
109 return 1;
112 bool lm32_cpu_do_semihosting(CPUState *cs)
114 LM32CPU *cpu = LM32_CPU(cs);
115 CPULM32State *env = &cpu->env;
117 int ret = -1;
118 target_ulong nr, arg0, arg1, arg2;
119 void *p;
120 struct stat s;
122 nr = env->regs[R_R8];
123 arg0 = env->regs[R_R1];
124 arg1 = env->regs[R_R2];
125 arg2 = env->regs[R_R3];
127 switch (nr) {
128 case TARGET_SYS_exit:
129 /* void _exit(int rc) */
130 exit(arg0);
132 case TARGET_SYS_open:
133 /* int open(const char *pathname, int flags) */
134 p = lock_user_string(arg0);
135 if (!p) {
136 ret = -1;
137 } else {
138 ret = open(p, translate_openflags(arg2));
139 unlock_user(p, arg0, 0);
141 break;
143 case TARGET_SYS_read:
144 /* ssize_t read(int fd, const void *buf, size_t count) */
145 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
146 if (!p) {
147 ret = -1;
148 } else {
149 ret = read(arg0, p, arg2);
150 unlock_user(p, arg1, arg2);
152 break;
154 case TARGET_SYS_write:
155 /* ssize_t write(int fd, const void *buf, size_t count) */
156 p = lock_user(VERIFY_READ, arg1, arg2, 1);
157 if (!p) {
158 ret = -1;
159 } else {
160 ret = write(arg0, p, arg2);
161 unlock_user(p, arg1, 0);
163 break;
165 case TARGET_SYS_close:
166 /* int close(int fd) */
167 /* don't close stdin/stdout/stderr */
168 if (arg0 > 2) {
169 ret = close(arg0);
170 } else {
171 ret = 0;
173 break;
175 case TARGET_SYS_lseek:
176 /* off_t lseek(int fd, off_t offset, int whence */
177 ret = lseek(arg0, arg1, arg2);
178 break;
180 case TARGET_SYS_stat:
181 /* int stat(const char *path, struct stat *buf) */
182 p = lock_user_string(arg0);
183 if (!p) {
184 ret = -1;
185 } else {
186 ret = stat(p, &s);
187 unlock_user(p, arg0, 0);
188 if (translate_stat(env, arg1, &s) == 0) {
189 ret = -1;
192 break;
194 case TARGET_SYS_fstat:
195 /* int stat(int fd, struct stat *buf) */
196 ret = fstat(arg0, &s);
197 if (ret == 0) {
198 if (translate_stat(env, arg1, &s) == 0) {
199 ret = -1;
202 break;
204 default:
205 /* unhandled */
206 return false;
209 env->regs[R_R1] = ret;
210 return true;