14e98e3e1Schristos /* emulos.c -- Small OS emulation 2*9b2a9e00Schristos Copyright 1999-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Written by Stephane Carrez (stcarrez@worldnet.fr) 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, GAS, and the GNU binutils. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 234e98e3e1Schristos #include "sim-main.h" 244e98e3e1Schristos #include <unistd.h> 25*9b2a9e00Schristos 26*9b2a9e00Schristos #include "m68hc11-sim.h" 274e98e3e1Schristos 284e98e3e1Schristos #ifndef WIN32 294b169a6bSchristos #include <errno.h> 304b169a6bSchristos #include <stdio.h> 314e98e3e1Schristos #include <sys/types.h> 324e98e3e1Schristos #include <sys/time.h> 334e98e3e1Schristos 344e98e3e1Schristos /* This file emulates some OS system calls. 354e98e3e1Schristos It's basically used to give access to the host OS facilities 364e98e3e1Schristos like: stdin, stdout, files, time of day. */ 374e98e3e1Schristos static int bench_mode = -1; 384e98e3e1Schristos static struct timeval bench_start; 394e98e3e1Schristos static struct timeval bench_stop; 404e98e3e1Schristos 41796c32c9Schristos static void 42796c32c9Schristos emul_bench (sim_cpu *cpu) 434e98e3e1Schristos { 444e98e3e1Schristos int op; 454e98e3e1Schristos 464e98e3e1Schristos op = cpu_get_d (cpu); 474e98e3e1Schristos switch (op) 484e98e3e1Schristos { 494e98e3e1Schristos case 0: 504e98e3e1Schristos bench_mode = 0; 514e98e3e1Schristos gettimeofday (&bench_start, 0); 524e98e3e1Schristos break; 534e98e3e1Schristos 544e98e3e1Schristos case 1: 554e98e3e1Schristos gettimeofday (&bench_stop, 0); 564e98e3e1Schristos if (bench_mode != 0) 574e98e3e1Schristos printf ("bench start not called...\n"); 584e98e3e1Schristos bench_mode = 1; 594e98e3e1Schristos break; 604e98e3e1Schristos 614e98e3e1Schristos case 2: 624e98e3e1Schristos { 634e98e3e1Schristos int sz = 0; 644e98e3e1Schristos int addr = cpu_get_x (cpu); 654e98e3e1Schristos double t_start, t_stop, t; 664e98e3e1Schristos char buf[1024]; 674e98e3e1Schristos 684e98e3e1Schristos op = cpu_get_y (cpu); 694e98e3e1Schristos t_start = (double) (bench_start.tv_sec) * 1.0e6; 704e98e3e1Schristos t_start += (double) (bench_start.tv_usec); 714e98e3e1Schristos t_stop = (double) (bench_stop.tv_sec) * 1.0e6; 724e98e3e1Schristos t_stop += (double) (bench_stop.tv_usec); 734e98e3e1Schristos 744e98e3e1Schristos while (sz < 1024) 754e98e3e1Schristos { 764e98e3e1Schristos buf[sz] = memory_read8 (cpu, addr); 774e98e3e1Schristos if (buf[sz] == 0) 784e98e3e1Schristos break; 794e98e3e1Schristos 804e98e3e1Schristos sz ++; 814e98e3e1Schristos addr++; 824e98e3e1Schristos } 834e98e3e1Schristos buf[1023] = 0; 844e98e3e1Schristos 854e98e3e1Schristos if (bench_mode != 1) 864e98e3e1Schristos printf ("bench_stop not called"); 874e98e3e1Schristos 884e98e3e1Schristos bench_mode = -1; 894e98e3e1Schristos t = t_stop - t_start; 904e98e3e1Schristos printf ("%-40.40s [%6d] %3.3f us\n", buf, 914e98e3e1Schristos op, t / (double) (op)); 924e98e3e1Schristos break; 934e98e3e1Schristos } 944e98e3e1Schristos } 954e98e3e1Schristos } 964e98e3e1Schristos #endif 974e98e3e1Schristos 98796c32c9Schristos static void 99796c32c9Schristos emul_write (sim_cpu *cpu) 1004e98e3e1Schristos { 101796c32c9Schristos int addr = cpu_get_x (cpu) & 0x0FFFF; 102796c32c9Schristos int size = cpu_get_d (cpu) & 0x0FFFF; 1034e98e3e1Schristos 1044e98e3e1Schristos if (addr + size > 0x0FFFF) { 1054e98e3e1Schristos size = 0x0FFFF - addr; 1064e98e3e1Schristos } 107*9b2a9e00Schristos M68HC11_SIM_CPU (cpu)->cpu_running = 0; 1084e98e3e1Schristos while (size) 1094e98e3e1Schristos { 1104b169a6bSchristos uint8_t val = memory_read8 (cpu, addr); 1114e98e3e1Schristos 1124b169a6bSchristos if (write (0, &val, 1) != 1) 1134b169a6bSchristos printf ("write failed: %s\n", strerror (errno)); 1144e98e3e1Schristos addr ++; 1154e98e3e1Schristos size--; 1164e98e3e1Schristos } 1174e98e3e1Schristos } 1184e98e3e1Schristos 1194e98e3e1Schristos /* emul_exit () is used by the default startup code of GCC to implement 1204e98e3e1Schristos the exit (). For a real target, this will create an ILLEGAL fault. 1214e98e3e1Schristos But doing an exit () on a real target is really a non-sense. 1224e98e3e1Schristos exit () is important for the validation of GCC. The exit status 1234e98e3e1Schristos is passed in 'D' register. */ 124796c32c9Schristos static void 1254e98e3e1Schristos emul_exit (sim_cpu *cpu) 1264e98e3e1Schristos { 1274e98e3e1Schristos sim_engine_halt (CPU_STATE (cpu), cpu, 1284e98e3e1Schristos NULL, NULL_CIA, sim_exited, 1294e98e3e1Schristos cpu_get_d (cpu)); 1304e98e3e1Schristos } 1314e98e3e1Schristos 1324e98e3e1Schristos void 133796c32c9Schristos emul_os (int code, sim_cpu *cpu) 1344e98e3e1Schristos { 135*9b2a9e00Schristos M68HC11_SIM_CPU (cpu)->cpu_current_cycle = 8; 1364e98e3e1Schristos switch (code) 1374e98e3e1Schristos { 1384e98e3e1Schristos case 0x0: 1394e98e3e1Schristos break; 1404e98e3e1Schristos 1414e98e3e1Schristos /* 0xCD 0x01 */ 1424e98e3e1Schristos case 0x01: 143796c32c9Schristos emul_write (cpu); 1444e98e3e1Schristos break; 1454e98e3e1Schristos 1464e98e3e1Schristos /* 0xCD 0x02 */ 1474e98e3e1Schristos case 0x02: 1484e98e3e1Schristos break; 1494e98e3e1Schristos 1504e98e3e1Schristos /* 0xCD 0x03 */ 1514e98e3e1Schristos case 0x03: 152796c32c9Schristos emul_exit (cpu); 1534e98e3e1Schristos break; 1544e98e3e1Schristos 1554e98e3e1Schristos /* 0xCD 0x04 */ 1564e98e3e1Schristos case 0x04: 1574e98e3e1Schristos #ifndef WIN32 158796c32c9Schristos emul_bench (cpu); 1594e98e3e1Schristos #endif 1604e98e3e1Schristos break; 1614e98e3e1Schristos 1624e98e3e1Schristos default: 1634e98e3e1Schristos break; 1644e98e3e1Schristos } 1654e98e3e1Schristos } 1664e98e3e1Schristos 167