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.
18 #include "exec/helper-proto.h"
20 #include "exec/softmmu-semi.h"
29 TARGET_SYS_fstat
= 10,
34 NEWLIB_O_RDONLY
= 0x0,
35 NEWLIB_O_WRONLY
= 0x1,
37 NEWLIB_O_APPEND
= 0x8,
38 NEWLIB_O_CREAT
= 0x200,
39 NEWLIB_O_TRUNC
= 0x400,
40 NEWLIB_O_EXCL
= 0x800,
43 static int translate_openflags(int flags
)
47 if (flags
& NEWLIB_O_WRONLY
) {
49 } else if (flags
& NEWLIB_O_RDWR
) {
55 if (flags
& NEWLIB_O_APPEND
) {
59 if (flags
& NEWLIB_O_CREAT
) {
63 if (flags
& NEWLIB_O_TRUNC
) {
67 if (flags
& NEWLIB_O_EXCL
) {
75 int16_t newlib_st_dev
; /* device */
76 uint16_t newlib_st_ino
; /* inode */
77 uint16_t newlib_st_mode
; /* protection */
78 uint16_t newlib_st_nlink
; /* number of hard links */
79 uint16_t newlib_st_uid
; /* user ID of owner */
80 uint16_t newlib_st_gid
; /* group ID of owner */
81 int16_t newlib_st_rdev
; /* device type (if inode device) */
82 int32_t newlib_st_size
; /* total size, in bytes */
83 int32_t newlib_st_atime
; /* time of last access */
84 uint32_t newlib_st_spare1
;
85 int32_t newlib_st_mtime
; /* time of last modification */
86 uint32_t newlib_st_spare2
;
87 int32_t newlib_st_ctime
; /* time of last change */
88 uint32_t newlib_st_spare3
;
91 static int translate_stat(CPULM32State
*env
, target_ulong addr
,
94 struct newlib_stat
*p
;
96 p
= lock_user(VERIFY_WRITE
, addr
, sizeof(struct newlib_stat
), 0);
100 p
->newlib_st_dev
= cpu_to_be16(s
->st_dev
);
101 p
->newlib_st_ino
= cpu_to_be16(s
->st_ino
);
102 p
->newlib_st_mode
= cpu_to_be16(s
->st_mode
);
103 p
->newlib_st_nlink
= cpu_to_be16(s
->st_nlink
);
104 p
->newlib_st_uid
= cpu_to_be16(s
->st_uid
);
105 p
->newlib_st_gid
= cpu_to_be16(s
->st_gid
);
106 p
->newlib_st_rdev
= cpu_to_be16(s
->st_rdev
);
107 p
->newlib_st_size
= cpu_to_be32(s
->st_size
);
108 p
->newlib_st_atime
= cpu_to_be32(s
->st_atime
);
109 p
->newlib_st_mtime
= cpu_to_be32(s
->st_mtime
);
110 p
->newlib_st_ctime
= cpu_to_be32(s
->st_ctime
);
111 unlock_user(p
, addr
, sizeof(struct newlib_stat
));
116 bool lm32_cpu_do_semihosting(CPUState
*cs
)
118 LM32CPU
*cpu
= LM32_CPU(cs
);
119 CPULM32State
*env
= &cpu
->env
;
122 target_ulong nr
, arg0
, arg1
, arg2
;
126 nr
= env
->regs
[R_R8
];
127 arg0
= env
->regs
[R_R1
];
128 arg1
= env
->regs
[R_R2
];
129 arg2
= env
->regs
[R_R3
];
132 case TARGET_SYS_exit
:
133 /* void _exit(int rc) */
136 case TARGET_SYS_open
:
137 /* int open(const char *pathname, int flags) */
138 p
= lock_user_string(arg0
);
142 ret
= open(p
, translate_openflags(arg2
));
143 unlock_user(p
, arg0
, 0);
147 case TARGET_SYS_read
:
148 /* ssize_t read(int fd, const void *buf, size_t count) */
149 p
= lock_user(VERIFY_WRITE
, arg1
, arg2
, 0);
153 ret
= read(arg0
, p
, arg2
);
154 unlock_user(p
, arg1
, arg2
);
158 case TARGET_SYS_write
:
159 /* ssize_t write(int fd, const void *buf, size_t count) */
160 p
= lock_user(VERIFY_READ
, arg1
, arg2
, 1);
164 ret
= write(arg0
, p
, arg2
);
165 unlock_user(p
, arg1
, 0);
169 case TARGET_SYS_close
:
170 /* int close(int fd) */
171 /* don't close stdin/stdout/stderr */
179 case TARGET_SYS_lseek
:
180 /* off_t lseek(int fd, off_t offset, int whence */
181 ret
= lseek(arg0
, arg1
, arg2
);
184 case TARGET_SYS_stat
:
185 /* int stat(const char *path, struct stat *buf) */
186 p
= lock_user_string(arg0
);
191 unlock_user(p
, arg0
, 0);
192 if (translate_stat(env
, arg1
, &s
) == 0) {
198 case TARGET_SYS_fstat
:
199 /* int stat(int fd, struct stat *buf) */
200 ret
= fstat(arg0
, &s
);
202 if (translate_stat(env
, arg1
, &s
) == 0) {
213 env
->regs
[R_R1
] = ret
;