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"
15 #include "exec/helper-proto.h"
17 #include "exec/softmmu-semi.h"
26 TARGET_SYS_fstat
= 10,
31 NEWLIB_O_RDONLY
= 0x0,
32 NEWLIB_O_WRONLY
= 0x1,
34 NEWLIB_O_APPEND
= 0x8,
35 NEWLIB_O_CREAT
= 0x200,
36 NEWLIB_O_TRUNC
= 0x400,
37 NEWLIB_O_EXCL
= 0x800,
40 static int translate_openflags(int flags
)
44 if (flags
& NEWLIB_O_WRONLY
) {
46 } else if (flags
& NEWLIB_O_RDWR
) {
52 if (flags
& NEWLIB_O_APPEND
) {
56 if (flags
& NEWLIB_O_CREAT
) {
60 if (flags
& NEWLIB_O_TRUNC
) {
64 if (flags
& NEWLIB_O_EXCL
) {
72 int16_t newlib_st_dev
; /* device */
73 uint16_t newlib_st_ino
; /* inode */
74 uint16_t newlib_st_mode
; /* protection */
75 uint16_t newlib_st_nlink
; /* number of hard links */
76 uint16_t newlib_st_uid
; /* user ID of owner */
77 uint16_t newlib_st_gid
; /* group ID of owner */
78 int16_t newlib_st_rdev
; /* device type (if inode device) */
79 int32_t newlib_st_size
; /* total size, in bytes */
80 int32_t newlib_st_atime
; /* time of last access */
81 uint32_t newlib_st_spare1
;
82 int32_t newlib_st_mtime
; /* time of last modification */
83 uint32_t newlib_st_spare2
;
84 int32_t newlib_st_ctime
; /* time of last change */
85 uint32_t newlib_st_spare3
;
88 static int translate_stat(CPULM32State
*env
, target_ulong addr
,
91 struct newlib_stat
*p
;
93 p
= lock_user(VERIFY_WRITE
, addr
, sizeof(struct newlib_stat
), 0);
97 p
->newlib_st_dev
= cpu_to_be16(s
->st_dev
);
98 p
->newlib_st_ino
= cpu_to_be16(s
->st_ino
);
99 p
->newlib_st_mode
= cpu_to_be16(s
->st_mode
);
100 p
->newlib_st_nlink
= cpu_to_be16(s
->st_nlink
);
101 p
->newlib_st_uid
= cpu_to_be16(s
->st_uid
);
102 p
->newlib_st_gid
= cpu_to_be16(s
->st_gid
);
103 p
->newlib_st_rdev
= cpu_to_be16(s
->st_rdev
);
104 p
->newlib_st_size
= cpu_to_be32(s
->st_size
);
105 p
->newlib_st_atime
= cpu_to_be32(s
->st_atime
);
106 p
->newlib_st_mtime
= cpu_to_be32(s
->st_mtime
);
107 p
->newlib_st_ctime
= cpu_to_be32(s
->st_ctime
);
108 unlock_user(p
, addr
, sizeof(struct newlib_stat
));
113 bool lm32_cpu_do_semihosting(CPUState
*cs
)
115 LM32CPU
*cpu
= LM32_CPU(cs
);
116 CPULM32State
*env
= &cpu
->env
;
119 target_ulong nr
, arg0
, arg1
, arg2
;
123 nr
= env
->regs
[R_R8
];
124 arg0
= env
->regs
[R_R1
];
125 arg1
= env
->regs
[R_R2
];
126 arg2
= env
->regs
[R_R3
];
129 case TARGET_SYS_exit
:
130 /* void _exit(int rc) */
133 case TARGET_SYS_open
:
134 /* int open(const char *pathname, int flags) */
135 p
= lock_user_string(arg0
);
139 ret
= open(p
, translate_openflags(arg2
));
140 unlock_user(p
, arg0
, 0);
144 case TARGET_SYS_read
:
145 /* ssize_t read(int fd, const void *buf, size_t count) */
146 p
= lock_user(VERIFY_WRITE
, arg1
, arg2
, 0);
150 ret
= read(arg0
, p
, arg2
);
151 unlock_user(p
, arg1
, arg2
);
155 case TARGET_SYS_write
:
156 /* ssize_t write(int fd, const void *buf, size_t count) */
157 p
= lock_user(VERIFY_READ
, arg1
, arg2
, 1);
161 ret
= write(arg0
, p
, arg2
);
162 unlock_user(p
, arg1
, 0);
166 case TARGET_SYS_close
:
167 /* int close(int fd) */
168 /* don't close stdin/stdout/stderr */
176 case TARGET_SYS_lseek
:
177 /* off_t lseek(int fd, off_t offset, int whence */
178 ret
= lseek(arg0
, arg1
, arg2
);
181 case TARGET_SYS_stat
:
182 /* int stat(const char *path, struct stat *buf) */
183 p
= lock_user_string(arg0
);
188 unlock_user(p
, arg0
, 0);
189 if (translate_stat(env
, arg1
, &s
) == 0) {
195 case TARGET_SYS_fstat
:
196 /* int stat(int fd, struct stat *buf) */
197 ret
= fstat(arg0
, &s
);
199 if (translate_stat(env
, arg1
, &s
) == 0) {
210 env
->regs
[R_R1
] = ret
;