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