fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 340 lines 7.2 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/sim405/main.c * 7 * Created: 2004-06-01 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2004-2022 Hampa Hug <hampa@hampa.ch> * 9 * Copyright: (C) 2004-2006 Lukas Ruf <ruf@lpr.ch> * 10 *****************************************************************************/ 11 12/***************************************************************************** 13 * This program is free software. You can redistribute it and / or modify it * 14 * under the terms of the GNU General Public License version 2 as published * 15 * by the Free Software Foundation. * 16 * * 17 * This program is distributed in the hope that it will be useful, but * 18 * WITHOUT ANY WARRANTY, without even the implied warranty of * 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 20 * Public License for more details. * 21 *****************************************************************************/ 22 23/***************************************************************************** 24 * This software was developed at the Computer Engineering and Networks * 25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. * 26 *****************************************************************************/ 27 28 29#include "main.h" 30 31#include <stdio.h> 32#include <stdlib.h> 33#include <stdarg.h> 34#include <signal.h> 35 36#include "cmd_ppc.h" 37#include "msg.h" 38#include "sim405.h" 39 40#include <lib/cfg.h> 41#include <lib/cmd.h> 42#include <lib/console.h> 43#include <lib/getopt.h> 44#include <lib/log.h> 45#include <lib/monitor.h> 46#include <lib/path.h> 47#include <lib/sysdep.h> 48 49#include <libini/libini.h> 50 51 52static pce_option_t opts[] = { 53 { '?', 0, "help", NULL, "Print usage information" }, 54 { 'c', 1, "config", "string", "Set the config file name [none]" }, 55 { 'd', 1, "path", "string", "Add a directory to the search path" }, 56 { 'i', 1, "ini-prefix", "string", "Add an ini string before the config file" }, 57 { 'I', 1, "ini-append", "string", "Add an ini string after the config file" }, 58 { 'l', 1, "log", "string", "Set the log file name [none]" }, 59 { 'p', 1, "cpu", "string", "Set the CPU model" }, 60 { 'q', 0, "quiet", NULL, "Set the log level to error [no]" }, 61 { 'r', 0, "run", NULL, "Start running immediately [no]" }, 62 { 'v', 0, "verbose", NULL, "Set the log level to debug [no]" }, 63 { 'V', 0, "version", NULL, "Print version information" }, 64 { -1, 0, NULL, NULL, NULL } 65}; 66 67 68char *par_cpu = NULL; 69 70unsigned par_xlat = P405_XLAT_CPU; 71 72sim405_t *par_sim = NULL; 73 74unsigned par_sig_int = 0; 75 76ini_sct_t *par_cfg = NULL; 77 78static ini_strings_t par_ini_str; 79 80 81static 82void print_help (void) 83{ 84 pce_getopt_help ( 85 "pce-sim405: PowerPC 405 emulator", 86 "usage: pce-sim405 [options]", 87 opts 88 ); 89 90 fflush (stdout); 91} 92 93static 94void print_version (void) 95{ 96 fputs ( 97 "pce-sim405 version " PCE_VERSION_STR 98 "\n\n" 99 "Copyright (C) 2004-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n", 100 stdout 101 ); 102 103 fflush (stdout); 104} 105 106static 107void s405_log_banner (void) 108{ 109 pce_log_inf ( 110 "pce-sim405 version " PCE_VERSION_STR "\n" 111 "Copyright (C) 2004-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n" 112 ); 113} 114 115static 116void sig_int (int s) 117{ 118 signal (SIGINT, sig_int); 119 120 par_sig_int = 1; 121} 122 123static 124void sig_terminate (int s) 125{ 126 fprintf (stderr, "pce-sim405: signal %d\n", s); 127 128 if ((par_sim != NULL) && (par_sim->ppc != NULL)) { 129 fprintf (stderr, " PC=%08lX\n", 130 (unsigned long) p405_get_pc (par_sim->ppc) 131 ); 132 } 133 134 fflush (stderr); 135 136 pce_set_fd_interactive (0, 1); 137 138 exit (1); 139} 140 141static 142int cmd_get_sym (sim405_t *sim, const char *sym, unsigned long *val) 143{ 144 if (p405_get_reg (sim->ppc, sym, val) == 0) { 145 return (0); 146 } 147 148 return (1); 149} 150 151static 152int cmd_set_sym (sim405_t *sim, const char *sym, unsigned long val) 153{ 154 if (p405_set_reg (sim->ppc, sym, val) == 0) { 155 return (0); 156 } 157 158 return (1); 159} 160 161static 162unsigned char s405_get_mem8 (sim405_t *sim, unsigned long addr) 163{ 164 unsigned char val; 165 166 if (p405_get_xlat8 (sim->ppc, addr, par_xlat, &val)) { 167 val = 0xff; 168 } 169 170 return (val); 171} 172 173static 174void s405_set_mem8 (sim405_t *sim, unsigned long addr, unsigned char val) 175{ 176 if (p405_set_xlat8 (sim->ppc, addr, par_xlat, val)) { 177 ; /* TLB miss */ 178 } 179} 180 181int main (int argc, char *argv[]) 182{ 183 int r; 184 char **optarg; 185 int run; 186 char *cfg; 187 ini_sct_t *sct; 188 monitor_t mon; 189 190 cfg = NULL; 191 run = 0; 192 193 pce_log_init(); 194 pce_log_add_fp (stderr, 0, MSG_INF); 195 196 par_cfg = ini_sct_new (NULL); 197 198 if (par_cfg == NULL) { 199 return (1); 200 } 201 202 ini_str_init (&par_ini_str); 203 204 while (1) { 205 r = pce_getopt (argc, argv, &optarg, opts); 206 207 if (r == GETOPT_DONE) { 208 break; 209 } 210 211 if (r < 0) { 212 return (1); 213 } 214 215 switch (r) { 216 case '?': 217 print_help(); 218 return (0); 219 220 case 'V': 221 print_version(); 222 return (0); 223 224 case 'c': 225 cfg = optarg[0]; 226 break; 227 228 case 'd': 229 pce_path_set (optarg[0]); 230 break; 231 232 case 'i': 233 if (ini_read_str (par_cfg, optarg[0])) { 234 fprintf (stderr, 235 "%s: error parsing ini string (%s)\n", 236 argv[0], optarg[0] 237 ); 238 return (1); 239 } 240 break; 241 242 case 'I': 243 ini_str_add (&par_ini_str, optarg[0], "\n", NULL); 244 break; 245 246 case 'l': 247 pce_log_add_fname (optarg[0], MSG_DEB); 248 break; 249 250 case 'p': 251 ini_str_add (&par_ini_str, "cpu.model = \"", 252 optarg[0], "\"\n" 253 ); 254 break; 255 256 case 'q': 257 pce_log_set_level (stderr, MSG_ERR); 258 break; 259 260 case 'r': 261 run = 1; 262 break; 263 264 case 'v': 265 pce_log_set_level (stderr, MSG_DEB); 266 break; 267 268 case 0: 269 fprintf (stderr, "%s: unknown option (%s)\n", 270 argv[0], optarg[0] 271 ); 272 return (1); 273 274 default: 275 return (1); 276 } 277 } 278 279 s405_log_banner(); 280 281 if (pce_load_config (par_cfg, cfg)) { 282 return (1); 283 } 284 285 sct = ini_next_sct (par_cfg, NULL, "sim405"); 286 287 if (sct == NULL) { 288 sct = par_cfg; 289 } 290 291 if (ini_str_eval (&par_ini_str, sct, 1)) { 292 return (1); 293 } 294 295 pce_path_ini (sct); 296 297 par_sim = s405_new (sct); 298 299 signal (SIGINT, sig_int); 300 signal (SIGTERM, sig_terminate); 301 signal (SIGSEGV, sig_terminate); 302 303#ifdef SIGPIPE 304 signal (SIGPIPE, SIG_IGN); 305#endif 306 307 pce_console_init (stdin, stdout); 308 309 mon_init (&mon); 310 mon_set_cmd_fct (&mon, ppc_do_cmd, par_sim); 311 mon_set_msg_fct (&mon, s405_set_msg, par_sim); 312 mon_set_get_mem_fct (&mon, par_sim, s405_get_mem8); 313 mon_set_set_mem_fct (&mon, par_sim, s405_set_mem8); 314 mon_set_memory_mode (&mon, 0); 315 316 cmd_init (par_sim, cmd_get_sym, cmd_set_sym); 317 ppc_cmd_init (par_sim, &mon); 318 319 s405_reset (par_sim); 320 321 if (run) { 322 ppc_run (par_sim); 323 if (par_sim->brk != PCE_BRK_ABORT) { 324 fputs ("\n", stdout); 325 } 326 } 327 else { 328 pce_puts ("type 'h' for help\n"); 329 } 330 331 mon_run (&mon); 332 333 s405_del (par_sim); 334 335 mon_free (&mon); 336 pce_console_done(); 337 pce_log_done(); 338 339 return (0); 340}