1 /* emulos.c -- Small OS emulation 2 Copyright 1999-2024 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 #include <unistd.h> 25 26 #include "m68hc11-sim.h" 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 M68HC11_SIM_CPU (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 M68HC11_SIM_CPU (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 167