merge from gcc
[external/binutils.git] / sim / m68hc11 / emulos.c
1 /* emulos.c -- Small OS emulation
2    Copyright 1999, 2000, 2007, 2008, 2009, 2010 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 <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.  */
32 static int bench_mode = -1;
33 static struct timeval bench_start;
34 static struct timeval bench_stop;
35
36 void
37 emul_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
93 void
94 emul_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.  */
118 void
119 emul_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
126 void
127 emul_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