]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/emulos.c
sim: m68hc11: warn when emul_write fails
[thirdparty/binutils-gdb.git] / sim / m68hc11 / emulos.c
1 /* emulos.c -- Small OS emulation
2 Copyright 1999-2021 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 #include "sim-main.h"
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24
25 #ifndef WIN32
26 #include <errno.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30
31 /* This file emulates some OS system calls.
32 It's basically used to give access to the host OS facilities
33 like: stdin, stdout, files, time of day. */
34 static int bench_mode = -1;
35 static struct timeval bench_start;
36 static struct timeval bench_stop;
37
38 static void
39 emul_bench (sim_cpu *cpu)
40 {
41 int op;
42
43 op = cpu_get_d (cpu);
44 switch (op)
45 {
46 case 0:
47 bench_mode = 0;
48 gettimeofday (&bench_start, 0);
49 break;
50
51 case 1:
52 gettimeofday (&bench_stop, 0);
53 if (bench_mode != 0)
54 printf ("bench start not called...\n");
55 bench_mode = 1;
56 break;
57
58 case 2:
59 {
60 int sz = 0;
61 int addr = cpu_get_x (cpu);
62 double t_start, t_stop, t;
63 char buf[1024];
64
65 op = cpu_get_y (cpu);
66 t_start = (double) (bench_start.tv_sec) * 1.0e6;
67 t_start += (double) (bench_start.tv_usec);
68 t_stop = (double) (bench_stop.tv_sec) * 1.0e6;
69 t_stop += (double) (bench_stop.tv_usec);
70
71 while (sz < 1024)
72 {
73 buf[sz] = memory_read8 (cpu, addr);
74 if (buf[sz] == 0)
75 break;
76
77 sz ++;
78 addr++;
79 }
80 buf[1023] = 0;
81
82 if (bench_mode != 1)
83 printf ("bench_stop not called");
84
85 bench_mode = -1;
86 t = t_stop - t_start;
87 printf ("%-40.40s [%6d] %3.3f us\n", buf,
88 op, t / (double) (op));
89 break;
90 }
91 }
92 }
93 #endif
94
95 static void
96 emul_write (sim_cpu *cpu)
97 {
98 int addr = cpu_get_x (cpu) & 0x0FFFF;
99 int size = cpu_get_d (cpu) & 0x0FFFF;
100
101 if (addr + size > 0x0FFFF) {
102 size = 0x0FFFF - addr;
103 }
104 cpu->cpu_running = 0;
105 while (size)
106 {
107 uint8 val = memory_read8 (cpu, addr);
108
109 if (write (0, &val, 1) != 1)
110 printf ("write failed: %s\n", strerror (errno));
111 addr ++;
112 size--;
113 }
114 }
115
116 /* emul_exit () is used by the default startup code of GCC to implement
117 the exit (). For a real target, this will create an ILLEGAL fault.
118 But doing an exit () on a real target is really a non-sense.
119 exit () is important for the validation of GCC. The exit status
120 is passed in 'D' register. */
121 static void
122 emul_exit (sim_cpu *cpu)
123 {
124 sim_engine_halt (CPU_STATE (cpu), cpu,
125 NULL, NULL_CIA, sim_exited,
126 cpu_get_d (cpu));
127 }
128
129 void
130 emul_os (int code, sim_cpu *cpu)
131 {
132 cpu->cpu_current_cycle = 8;
133 switch (code)
134 {
135 case 0x0:
136 break;
137
138 /* 0xCD 0x01 */
139 case 0x01:
140 emul_write (cpu);
141 break;
142
143 /* 0xCD 0x02 */
144 case 0x02:
145 break;
146
147 /* 0xCD 0x03 */
148 case 0x03:
149 emul_exit (cpu);
150 break;
151
152 /* 0xCD 0x04 */
153 case 0x04:
154 #ifndef WIN32
155 emul_bench (cpu);
156 #endif
157 break;
158
159 default:
160 break;
161 }
162 }
163