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"
16 #include "exec/softmmu-semi.h"
25 TARGET_SYS_fstat
= 10,
30 NEWLIB_O_RDONLY
= 0x0,
31 NEWLIB_O_WRONLY
= 0x1,
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
)
43 if (flags
& NEWLIB_O_WRONLY
) {
45 } else if (flags
& NEWLIB_O_RDWR
) {
51 if (flags
& NEWLIB_O_APPEND
) {
55 if (flags
& NEWLIB_O_CREAT
) {
59 if (flags
& NEWLIB_O_TRUNC
) {
63 if (flags
& NEWLIB_O_EXCL
) {
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
;
87 static int translate_stat(CPULM32State
*env
, target_ulong addr
,
90 struct newlib_stat
*p
;
92 p
= lock_user(VERIFY_WRITE
, addr
, sizeof(struct newlib_stat
), 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
));
112 bool lm32_cpu_do_semihosting(CPUState
*cs
)
114 LM32CPU
*cpu
= LM32_CPU(cs
);
115 CPULM32State
*env
= &cpu
->env
;
118 target_ulong nr
, arg0
, arg1
, arg2
;
122 nr
= env
->regs
[R_R8
];
123 arg0
= env
->regs
[R_R1
];
124 arg1
= env
->regs
[R_R2
];
125 arg2
= env
->regs
[R_R3
];
128 case TARGET_SYS_exit
:
129 /* void _exit(int rc) */
132 case TARGET_SYS_open
:
133 /* int open(const char *pathname, int flags) */
134 p
= lock_user_string(arg0
);
138 ret
= open(p
, translate_openflags(arg2
));
139 unlock_user(p
, arg0
, 0);
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);
149 ret
= read(arg0
, p
, arg2
);
150 unlock_user(p
, arg1
, arg2
);
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);
160 ret
= write(arg0
, p
, arg2
);
161 unlock_user(p
, arg1
, 0);
165 case TARGET_SYS_close
:
166 /* int close(int fd) */
167 /* don't close stdin/stdout/stderr */
175 case TARGET_SYS_lseek
:
176 /* off_t lseek(int fd, off_t offset, int whence */
177 ret
= lseek(arg0
, arg1
, arg2
);
180 case TARGET_SYS_stat
:
181 /* int stat(const char *path, struct stat *buf) */
182 p
= lock_user_string(arg0
);
187 unlock_user(p
, arg0
, 0);
188 if (translate_stat(env
, arg1
, &s
) == 0) {
194 case TARGET_SYS_fstat
:
195 /* int stat(int fd, struct stat *buf) */
196 ret
= fstat(arg0
, &s
);
198 if (translate_stat(env
, arg1
, &s
) == 0) {
209 env
->regs
[R_R1
] = ret
;