[AArch64] MTE corefile support
[binutils-gdb.git] / sim / m68hc11 / emulos.c
1 /* emulos.c -- Small OS emulation
2 Copyright 1999-2022 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* This must come before any other includes. */
21 #include "defs.h"
22
23 #include "sim-main.h"
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #ifndef WIN32
29 #include <errno.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/time.h>
33
34 /* This file emulates some OS system calls.
35 It's basically used to give access to the host OS facilities
36 like: stdin, stdout, files, time of day. */
37 static int bench_mode = -1;
38 static struct timeval bench_start;
39 static struct timeval bench_stop;
40
41 static void
42 emul_bench (sim_cpu *cpu)
43 {
44 int op;
45
46 op = cpu_get_d (cpu);
47 switch (op)
48 {
49 case 0:
50 bench_mode = 0;
51 gettimeofday (&bench_start, 0);
52 break;
53
54 case 1:
55 gettimeofday (&bench_stop, 0);
56 if (bench_mode != 0)
57 printf ("bench start not called...\n");
58 bench_mode = 1;
59 break;
60
61 case 2:
62 {
63 int sz = 0;
64 int addr = cpu_get_x (cpu);
65 double t_start, t_stop, t;
66 char buf[1024];
67
68 op = cpu_get_y (cpu);
69 t_start = (double) (bench_start.tv_sec) * 1.0e6;
70 t_start += (double) (bench_start.tv_usec);
71 t_stop = (double) (bench_stop.tv_sec) * 1.0e6;
72 t_stop += (double) (bench_stop.tv_usec);
73
74 while (sz < 1024)
75 {
76 buf[sz] = memory_read8 (cpu, addr);
77 if (buf[sz] == 0)
78 break;
79
80 sz ++;
81 addr++;
82 }
83 buf[1023] = 0;
84
85 if (bench_mode != 1)
86 printf ("bench_stop not called");
87
88 bench_mode = -1;
89 t = t_stop - t_start;
90 printf ("%-40.40s [%6d] %3.3f us\n", buf,
91 op, t / (double) (op));
92 break;
93 }
94 }
95 }
96 #endif
97
98 static void
99 emul_write (sim_cpu *cpu)
100 {
101 int addr = cpu_get_x (cpu) & 0x0FFFF;
102 int size = cpu_get_d (cpu) & 0x0FFFF;
103
104 if (addr + size > 0x0FFFF) {
105 size = 0x0FFFF - addr;
106 }
107 cpu->cpu_running = 0;
108 while (size)
109 {
110 uint8_t val = memory_read8 (cpu, addr);
111
112 if (write (0, &val, 1) != 1)
113 printf ("write failed: %s\n", strerror (errno));
114 addr ++;
115 size--;
116 }
117 }
118
119 /* emul_exit () is used by the default startup code of GCC to implement
120 the exit (). For a real target, this will create an ILLEGAL fault.
121 But doing an exit () on a real target is really a non-sense.
122 exit () is important for the validation of GCC. The exit status
123 is passed in 'D' register. */
124 static void
125 emul_exit (sim_cpu *cpu)
126 {
127 sim_engine_halt (CPU_STATE (cpu), cpu,
128 NULL, NULL_CIA, sim_exited,
129 cpu_get_d (cpu));
130 }
131
132 void
133 emul_os (int code, sim_cpu *cpu)
134 {
135 cpu->cpu_current_cycle = 8;
136 switch (code)
137 {
138 case 0x0:
139 break;
140
141 /* 0xCD 0x01 */
142 case 0x01:
143 emul_write (cpu);
144 break;
145
146 /* 0xCD 0x02 */
147 case 0x02:
148 break;
149
150 /* 0xCD 0x03 */
151 case 0x03:
152 emul_exit (cpu);
153 break;
154
155 /* 0xCD 0x04 */
156 case 0x04:
157 #ifndef WIN32
158 emul_bench (cpu);
159 #endif
160 break;
161
162 default:
163 break;
164 }
165 }
166