version 0.2.39: fix of arith insts and start of re-structure
[fw/sdcc] / sim / ucsim / s51.src / sim51.cc
1 /*
2  * Simulator of microcontrollers (sim51.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <errno.h>
34 #include "i_string.h"
35
36 #include "globals.h"
37 #include "utils.h"
38 #include "cmdutil.h"
39 #ifdef SOCKET_AVAIL
40 #include <sys/socket.h>
41 #endif
42
43 #include "sim51cl.h"
44 //#include "cmd51cl.h"
45 #include "uc51cl.h"
46 #include "uc52cl.h"
47 #include "uc51rcl.h"
48 #include "uc89c51rcl.h"
49 #include "uc251cl.h"
50 #include "glob.h"
51
52
53 cl_sim51::cl_sim51(int iargc, char *iargv[]):
54   cl_sim("t:s:S:hHk:", iargc, iargv)
55 {}
56
57 static void
58 print_help(char *name)
59 {
60   printf("%s: %s\n", name, VERSIONSTR);
61   printf("Usage: %s [-hHVvP] [-p prompt] [-t CPU] [-X freq[k|M]]\n"
62          "       [-c file] [-s file] [-S optionlist]"
63 #ifdef SOCKET_AVAIL
64          " [-Z portnum] [-k portnum]"
65 #endif
66          "\n"
67          "       [files...]\n", name);
68   printf
69     (
70      "Options:\n"
71      "  -t CPU       Type of CPU: 51, C52, 251, etc.\n"
72      "  -X freq[k|M] XTAL frequency\n"
73      "  -c file      Open command console on `file'\n"
74 #ifdef SOCKET_AVAIL
75      "  -Z portnum   Use localhost:portnumber for command console\n"
76      "  -k portnum   Use localhost:portnum for serial I/O\n"
77 #endif
78      "  -s file      Connect serial interface to `file'\n"
79      "  -S options   `options' is a comma separated list of options\n"
80      "               according to serial interface. Know options are:\n"
81      "                  in=file   serial input will be read from file named `file'\n"
82      "                  out=file  serial output will be written to `file'\n"
83      "  -p prompt    Specify string for prompt\n"
84      "  -P           Prompt is a null ('\\0') character\n"
85      "  -V           Verbose mode\n"
86      "  -v           Print out version number\n"
87      "  -H           Print out types of known CPUs\n"
88      "  -h           Print out this help\n"
89      );
90 }
91
92 enum {
93   SOPT_IN= 0,
94   SOPT_OUT
95 };
96
97 static const char *S_opts[]= {
98   /*[SOPT_IN]=*/ "in",
99   /*[SOPT_OUT]=*/ "out",
100   NULL
101 };
102
103 int
104 cl_sim51::proc_arg(char optopt, char *optarg)
105 {
106   char *cpu_type= NULL, *cp;
107   int i;
108   char *subopts, *value;
109
110   switch (optopt)
111     {
112
113     case 't':
114
115       if (cpu_type)
116         free(cpu_type);
117       cpu_type= strdup(optarg);
118       for (cp= cpu_type; *cp; *cp= toupper(*cp), cp++);
119       arguments->add(new cl_prg_arg('t', 0, cpu_type));
120       break;
121
122     case 's':
123       {
124         FILE *Ser_in, *Ser_out;
125         if (arg_avail('s'))
126           {
127             fprintf(stderr, "-s option can not be used more than once.\n");
128             break;
129           }
130         arguments->add(new cl_prg_arg('s', 0, (long)1));
131         if ((Ser_in= fopen(optarg, "r")) == NULL)
132           {
133             fprintf(stderr,
134                     "Can't open `%s': %s\n", optarg, strerror(errno));
135             return(4);
136           }
137         arguments->add(new cl_prg_arg(0, "Ser_in", Ser_in));
138         if ((Ser_out= fopen(optarg, "w")) == NULL)
139           {
140             fprintf(stderr,
141                     "Can't open `%s': %s\n", optarg, strerror(errno));
142             return(4);
143           }
144         arguments->add(new cl_prg_arg(0, "Ser_out", Ser_out));
145         break;
146       }
147
148 #ifdef SOCKET_AVAIL
149       // socket serial I/O by Alexandre Frey <Alexandre.Frey@trusted-logic.fr>
150     case 'k':
151       {
152         FILE *Ser_in, *Ser_out;
153         int  sock;
154         unsigned short serverport;
155         int client_sock;
156
157         if (arg_avail("Ser_in")) {
158           fprintf(stderr, "Serial input specified more than once.\n");
159         }
160         if (arg_avail("Ser_out")) {
161           fprintf(stderr, "Serial output specified more than once.\n");
162         }
163
164         serverport = atoi(optarg);
165         sock = make_server_socket(serverport);
166         if (listen(sock, 1) < 0) {
167           fprintf(stderr, "Listen on port %d: %s\n", serverport,
168                   strerror(errno));
169           return (4);
170         }
171         fprintf(stderr, "Listening on port %d for a serial connection.\n",
172                 serverport);
173         if ((client_sock = accept(sock, NULL, NULL)) < 0) {
174           fprintf(stderr, "accept: %s\n", strerror(errno));
175         }
176         fprintf(stderr, "Serial connection established.\n");
177
178         if ((Ser_in = fdopen(client_sock, "r")) == NULL) {
179           fprintf(stderr, "Can't create input stream: %s\n", strerror(errno));
180           return (4);
181         }
182         arguments->add(new cl_prg_arg(0, "Ser_in", Ser_in));
183         if ((Ser_out = fdopen(client_sock, "w")) == NULL) {
184           fprintf(stderr, "Can't create output stream: %s\n", strerror(errno));
185           return (4);
186         }
187         arguments->add(new cl_prg_arg(0, "Ser_out", Ser_out));
188         break;
189       }
190 #endif
191       
192     case 'S':
193
194       subopts= optarg;
195       while (*subopts != '\0')
196         switch (get_sub_opt(&subopts, S_opts, &value))
197           {
198             FILE *Ser_in, *Ser_out;
199           case SOPT_IN:
200             if (value == NULL) {
201               fprintf(stderr, "No value for -S in\n");
202               exit(1);
203             }
204             if (arg_avail("Ser_in"))
205               {
206                 fprintf(stderr, "Serial input specified more than once.\n");
207                 break;
208               }
209             if ((Ser_in= fopen(value, "r")) == NULL)
210               {
211                 fprintf(stderr,
212                         "Can't open `%s': %s\n", value, strerror(errno));
213                 exit(4);
214               }
215             arguments->add(new cl_prg_arg(0, "Ser_in", Ser_in));
216             break;
217           case SOPT_OUT:
218             if (value == NULL) {
219               fprintf(stderr, "No value for -S out\n");
220               exit(1);
221             }
222             if (arg_avail("Ser_out"))
223               {
224                 fprintf(stderr, "Serial output specified more than once.\n");
225                 break;
226               }
227             if ((Ser_out= fopen(value, "w")) == NULL)
228               {
229                 fprintf(stderr,
230                         "Can't open `%s': %s\n", value, strerror(errno));
231                 exit(4);
232               }
233             arguments->add(new cl_prg_arg(0, "Ser_out", Ser_out));
234             break;
235           default:
236             /* Unknown suboption. */
237             fprintf(stderr, "Unknown suboption `%s' for -S\n", value);
238             exit(1);
239             break;
240           }
241       break;
242
243     case 'h':
244
245       print_help("s51");
246       exit(0);
247       break;
248       
249     case 'H':
250       i= 0;
251       while (cpus_51[i].type_str != NULL)
252         {
253           printf("%s\n", cpus_51[i].type_str);
254           i++;
255         }
256       exit(0);
257       break;
258       
259     case '?':
260
261       if (isprint(optopt))
262         fprintf(stderr, "Unknown option `-%c'.\n", optopt);
263       else
264         fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
265       return(1);
266       break;
267       
268     default:
269       // should never happen...
270       abort();
271     }
272   return(0);
273 }
274
275
276 class cl_uc *
277 cl_sim51::mk_controller(void)
278 {
279   int i;
280
281   i= 0;
282   if (get_sarg('t', 0) == NULL)
283     arguments->add(new cl_prg_arg('t', 0, "C51"));
284   while ((cpus_51[i].type_str != NULL) &&
285          (strcmp(get_sarg('t', 0), cpus_51[i].type_str) != 0))
286     i++;
287   if (cpus_51[i].type_str == NULL)
288     {
289       fprintf(stderr, "Unknown processor type. "
290               "Use -H option to see known types.\n");
291       return(NULL);
292     }
293   switch (cpus_51[i].type)
294     {
295     case CPU_51: case CPU_31:
296       return(new t_uc51(cpus_51[i].type, cpus_51[i].technology, this));
297     case CPU_52: case CPU_32:
298       return(new t_uc52(cpus_51[i].type, cpus_51[i].technology, this));
299     case CPU_51R:
300       return(new t_uc51r(cpus_51[i].type, cpus_51[i].technology, this));
301     case CPU_89C51R:
302       return(new t_uc89c51r(cpus_51[i].type, cpus_51[i].technology, this));
303     case CPU_251:
304       return(new t_uc251(cpus_51[i].type, cpus_51[i].technology, this));
305     }
306   return(NULL);
307 }
308
309
310 /* End of s51.src/sim51.cc */