1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2023 Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #ifndef _M68K_SEMIHOST_H_
37 #define _M68K_SEMIHOST_H_
38
39 #include <stdio.h>
40 #include <errno.h>
41 #include <endian.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45 #define HOSTED_EXIT 0
46 #define HOSTED_INIT_SIM 1
47 #define HOSTED_OPEN 2
48 #define HOSTED_CLOSE 3
49 #define HOSTED_READ 4
50 #define HOSTED_WRITE 5
51 #define HOSTED_LSEEK 6
52 #define HOSTED_RENAME 7
53 #define HOSTED_UNLINK 8
54 #define HOSTED_STAT 9
55 #define HOSTED_FSTAT 10
56 #define HOSTED_GETTIMEOFDAY 11
57 #define HOSTED_ISATTY 12
58 #define HOSTED_SYSTEM 13
59
60 #define GDB_O_RDONLY 0
61 #define GDB_O_WRONLY 1
62 #define GDB_O_RDWR 2
63 #define GDB_O_APPEND 8
64 #define GDB_O_CREAT 0x200
65 #define GDB_O_TRUNC 0x400
66 #define GDB_O_EXCL 0x800
67
68 typedef uint32_t my_mode_t;
69 typedef uint32_t my_time_t;
70
71 struct m68k_stat
72 {
73 uint32_t my_dev; /* device */
74 uint32_t my_ino; /* inode */
75 my_mode_t my_mode; /* protection */
76 uint32_t my_nlink; /* number of hard links */
77 uint32_t my_uid; /* user ID of owner */
78 uint32_t my_gid; /* group ID of owner */
79 uint32_t my_rdev; /* device type (if inode device) */
80 uint64_t my_size; /* total size, in bytes */
81 uint64_t my_blksize; /* blocksize for filesystem I/O */
82 uint64_t my_blocks; /* number of blocks allocated */
83 my_time_t my_atime; /* time of last access */
84 my_time_t my_mtime; /* time of last modification */
85 my_time_t my_ctime; /* time of last change */
86 };
87
88 static inline
copy_stat(struct stat * restrict statbuf,struct m68k_stat * m68k_stat)89 copy_stat(struct stat *restrict statbuf, struct m68k_stat *m68k_stat)
90 {
91 statbuf->st_dev = be32toh(m68k_stat->my_dev);
92 statbuf->st_ino = be32toh(m68k_stat->my_ino);
93 statbuf->st_mode = be32toh(m68k_stat->my_mode);
94 statbuf->st_nlink = be32toh(m68k_stat->my_nlink);
95 statbuf->st_uid = be32toh(m68k_stat->my_uid);
96 statbuf->st_gid = be32toh(m68k_stat->my_gid);
97 statbuf->st_rdev = be32toh(m68k_stat->my_rdev);
98 statbuf->st_size = be32toh(m68k_stat->my_size);
99 statbuf->st_blksize = be32toh(m68k_stat->my_blksize);
100 statbuf->st_blocks = be32toh(m68k_stat->my_blocks);
101 statbuf->st_atime = be32toh(m68k_stat->my_atime);
102 statbuf->st_mtime = be32toh(m68k_stat->my_mtime);
103 statbuf->st_ctime = be32toh(m68k_stat->my_ctime);
104 }
105
106 struct m68k_semihost {
107 uintptr_t args[4];
108 };
109
110 intptr_t
111 m68k_semihost(int func, struct m68k_semihost *args);
112
m68k_semihost1_immediate(int func,uintptr_t arg0)113 static inline intptr_t m68k_semihost1_immediate(int func, uintptr_t arg0) {
114 return m68k_semihost(func, (struct m68k_semihost *) arg0);
115 };
116
m68k_semihost1(int func,uintptr_t arg0)117 static inline intptr_t m68k_semihost1(int func, uintptr_t arg0) {
118 struct m68k_semihost args;
119 intptr_t ret;
120
121 args.args[0] = arg0;
122 m68k_semihost(func, &args);
123 ret = args.args[0];
124 if (ret < 0)
125 errno = args.args[1];
126 return ret;
127 };
128
m68k_semihost2(int func,uintptr_t arg0,uintptr_t arg1)129 static inline intptr_t m68k_semihost2(int func, uintptr_t arg0, uintptr_t arg1) {
130 struct m68k_semihost args;
131 intptr_t ret;
132
133 args.args[0] = arg0;
134 args.args[1] = arg1;
135 m68k_semihost(func, &args);
136 ret = args.args[0];
137 if (ret < 0)
138 errno = args.args[1];
139 return ret;
140 };
141
m68k_semihost3(int func,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2)142 static inline intptr_t m68k_semihost3(int func, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2) {
143 struct m68k_semihost args;
144 intptr_t ret;
145
146 args.args[0] = arg0;
147 args.args[1] = arg1;
148 args.args[2] = arg2;
149 m68k_semihost(func, &args);
150 ret = args.args[0];
151 if (ret < 0)
152 errno = args.args[1];
153 return ret;
154 };
155
m68k_semihost4_64(int func,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)156 static inline uint64_t m68k_semihost4_64(int func, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {
157 struct m68k_semihost args;
158 uint64_t ret;
159
160 args.args[0] = arg0;
161 args.args[1] = arg1;
162 args.args[2] = arg2;
163 args.args[3] = arg3;
164 m68k_semihost(func, &args);
165 ret = ((uint64_t) args.args[0] << 32) | args.args[1];
166 if ((int64_t) ret < 0)
167 errno = args.args[2];
168 return ret;
169 };
170
m68k_semihost4(int func,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)171 static inline intptr_t m68k_semihost4(int func, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {
172 struct m68k_semihost args;
173 intptr_t ret;
174
175 args.args[0] = arg0;
176 args.args[1] = arg1;
177 args.args[2] = arg2;
178 args.args[3] = arg3;
179 m68k_semihost(func, &args);
180 ret = args.args[0];
181 if (ret < 0)
182 errno = args.args[1];
183 return ret;
184 };
185
186 #endif /* _M68K_SEMIHOST_H_ */
187