ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/main_unix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/main_unix.cpp (file contents):
Revision 1.20 by gbeauche, 2000-09-22T17:14:28Z vs.
Revision 1.32 by cebix, 2001-04-01T12:11:44Z

# Line 1 | Line 1
1   /*
2   *  main_unix.cpp - Startup code for Unix
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2001 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 30 | Line 30
30   # include <pthread.h>
31   #endif
32  
33 < #if defined(USE_MAPPED_MEMORY) || REAL_ADDRESSING || DIRECT_ADDRESSING
33 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
34   # include <sys/mman.h>
35   #endif
36  
# Line 50 | Line 50 | struct sigstate {
50  
51   #ifdef ENABLE_GTK
52   # include <gtk/gtk.h>
53 + # include <gdk/gdk.h>
54   #endif
55  
56   #ifdef ENABLE_XF86_DGA
# Line 133 | Line 134 | static struct sigaction sigirq_sa;     // Vi
134   static struct sigaction sigill_sa;      // Illegal instruction
135   static void *sig_stack = NULL;          // Stack for signal handlers
136   uint16 EmulatedSR;                                      // Emulated bits of SR (supervisor bit and interrupt mask)
136 uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
137   #endif
138  
139   #if USE_SCRATCHMEM_SUBTERFUGE
140 < uint8 *ScratchMem = 0;                          // Scratch memory for Mac ROM writes
140 > uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
141   #endif
142  
143   static struct sigaction timer_sa;       // sigaction used for timer
# Line 157 | Line 157 | static bool lm_area_mapped = false;    // F
157   static bool memory_mapped_from_zero = false; // Flag: Could allocate RAM area from 0
158   #endif
159  
160 < #ifdef USE_MAPPED_MEMORY
161 < extern char *address_space, *good_address_map;
160 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
161 > static uint32 mapped_ram_rom_size;              // Total size of mmap()ed RAM/ROM area
162   #endif
163  
164  
# Line 195 | Line 195 | char *strdup(const char *s)
195   *  Main program
196   */
197  
198 + static void usage(const char *prg_name)
199 + {
200 +        printf("Usage: %s [OPTION...]\n", prg_name);
201 +        printf("\nUnix options:\n");
202 +        printf("  --display STRING\n    X display to use\n");
203 +        printf("  --break ADDRESS\n    set ROM breakpoint\n");
204 +        printf("  --rominfo\n    dump ROM information\n");
205 +        PrefsPrintUsage();
206 +        exit(0);
207 + }
208 +
209   int main(int argc, char **argv)
210   {
211          char str[256];
# Line 209 | Line 220 | int main(int argc, char **argv)
220          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
221          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
222  
223 <        // Parse arguments
223 > #ifdef ENABLE_GTK
224 >        // Init GTK
225 >        gtk_set_locale();
226 >        gtk_init(&argc, &argv);
227 >        x_display_name = gdk_get_display(); // gtk_init() handles and removes the "--display" argument
228 > #endif
229 >
230 >        // Read preferences
231 >        PrefsInit(argc, argv);
232 >
233 >        // Parse command line arguments
234          for (int i=1; i<argc; i++) {
235 <                if (strcmp(argv[i], "-display") == 0 && ++i < argc)
236 <                        x_display_name = argv[i];
237 <                else if (strcmp(argv[i], "-break") == 0 && ++i < argc)
238 <                        ROMBreakpoint = strtol(argv[i], NULL, 0);
239 <                else if (strcmp(argv[i], "-rominfo") == 0)
235 >                if (strcmp(argv[i], "--help") == 0) {
236 >                        usage(argv[0]);
237 >                } else if (strcmp(argv[i], "--display") == 0) {
238 >                        i++;
239 >                        if (i < argc)
240 >                                x_display_name = strdup(argv[i]);
241 >                } else if (strcmp(argv[i], "--break") == 0) {
242 >                        i++;
243 >                        if (i < argc)
244 >                                ROMBreakpoint = strtol(argv[i], NULL, 0);
245 >                } else if (strcmp(argv[i], "--rominfo") == 0) {
246                          PrintROMInfo = true;
247 +                } else if (argv[i][0] == '-') {
248 +                        fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
249 +                        usage(argv[0]);
250 +                }
251          }
252  
253          // Open display
# Line 233 | Line 264 | int main(int argc, char **argv)
264          XF86DGAForkApp(DefaultScreen(x_display));
265   #endif
266  
236 #ifdef ENABLE_GTK
237        // Init GTK
238        gtk_set_locale();
239        gtk_init(&argc, &argv);
240 #endif
241
242        // Read preferences
243        PrefsInit();
244
267          // Init system routines
268          SysInit();
269  
# Line 269 | Line 291 | int main(int argc, char **argv)
291          const uint32 page_size = getpagesize();
292          const uint32 page_mask = page_size - 1;
293          const uint32 aligned_ram_size = (RAMSize + page_mask) & ~page_mask;
294 <        const uint32 ram_rom_size = aligned_ram_size + 0x100000;
294 >        mapped_ram_rom_size = aligned_ram_size + 0x100000;
295   #endif
296  
297   #if REAL_ADDRESSING
298          // Try to allocate the complete address space from zero
299          // gb-- the Solaris manpage about mmap(2) states that using MAP_FIXED
300          // implies undefined behaviour for further use of sbrk(), malloc(), etc.
301 < #if defined(OS_solaris)
301 >        // cebix-- on NetBSD/m68k, this causes a segfault
302 > #if defined(OS_solaris) || defined(OS_netbsd)
303          // Anyway, it doesn't work...
304          if (0) {
305   #else
306 <        if (mmap((caddr_t)0x0000, ram_rom_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) != MAP_FAILED) {
306 >        if (mmap((caddr_t)0x0000, mapped_ram_rom_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) != MAP_FAILED) {
307   #endif
308                  D(bug("Could allocate RAM and ROM from 0x0000\n"));
309                  memory_mapped_from_zero = true;
# Line 298 | Line 321 | int main(int argc, char **argv)
321          }
322   #endif
323  
324 < #if !EMULATED_68K || USE_SCRATCHMEM_SUBTERFUGE
324 > #if USE_SCRATCHMEM_SUBTERFUGE
325          // Allocate scratch memory
326          ScratchMem = (uint8 *)malloc(SCRATCH_MEM_SIZE);
327          if (ScratchMem == NULL) {
# Line 309 | Line 332 | int main(int argc, char **argv)
332   #endif
333  
334          // Create areas for Mac RAM and ROM
335 < #if defined(USE_MAPPED_MEMORY)
313 <    good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
314 <    address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
315 <    if ((int)address_space < 0 || (int)good_address_map < 0) {
316 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
317 <                QuitEmulator();
318 <    }
319 <    RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
320 <    ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
321 <        char *nam = tmpnam(NULL);
322 <    int good_address_fd = open(nam, O_CREAT | O_RDWR, 0600);
323 <        char buffer[4096];
324 <    memset(buffer, 1, sizeof(buffer));
325 <    write(good_address_fd, buffer, sizeof(buffer));
326 <    unlink(nam);
327 <    for (int i=0; i<RAMSize; i+=4096)
328 <        mmap(good_address_map + i, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
329 <    for (int i=0; i<0x80000; i+=4096)
330 <        mmap(good_address_map + i + 0x00400000, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
331 < #elif REAL_ADDRESSING || DIRECT_ADDRESSING
335 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
336          // gb-- Overkill, needs to be cleaned up. Probably explode it for either
337          // real or direct addressing mode.
338   #if REAL_ADDRESSING
# Line 339 | Line 343 | int main(int argc, char **argv)
343          else
344   #endif
345          {
346 <                RAMBaseHost = (uint8 *)mmap(0, ram_rom_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
346 >                RAMBaseHost = (uint8 *)mmap(0, mapped_ram_rom_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
347                  if (RAMBaseHost == (uint8 *)MAP_FAILED) {
348                          ErrorAlert(GetString(STR_NO_MEM_ERR));
349                          QuitEmulator();
# Line 354 | Line 358 | int main(int argc, char **argv)
358                  QuitEmulator();
359          }
360   #endif
361 +
362   #if DIRECT_ADDRESSING
363          // Initialize MEMBaseDiff now so that Host2MacAddr in the Video module
364          // will return correct results
# Line 416 | Line 421 | int main(int argc, char **argv)
421                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
422                  CPUType = 2;
423          }
424 <        FPUType = 0;    //!!
424 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
425          TwentyFourBitAddressing = false;
426   #endif
427  
# Line 479 | Line 484 | int main(int argc, char **argv)
484   #ifdef ENABLE_MON
485          // Setup SIGINT handler to enter mon
486          sigemptyset(&sigint_sa.sa_mask);
487 <        sigint_sa.sa_handler = sigint_handler;
487 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
488          sigint_sa.sa_flags = 0;
489          sigaction(SIGINT, &sigint_sa, NULL);
490   #endif
# Line 617 | Line 622 | void QuitEmulator(void)
622          // Deinitialize everything
623          ExitAll();
624  
625 +        // Free ROM/RAM areas
626 + #if REAL_ADDRESSING
627 +        if (memory_mapped_from_zero)
628 +                munmap((caddr_t)0x0000, mapped_ram_rom_size);
629 +        else
630 + #endif
631   #if REAL_ADDRESSING || DIRECT_ADDRESSING
621        // Unmap ROM area
622        if (ROMBaseHost != (uint8 *)MAP_FAILED) {
623                munmap((caddr_t)ROMBaseHost, 0x100000);
624                ROMBaseHost = 0;
625        }
626        
627        //Unmap RAM area
632          if (RAMBaseHost != (uint8 *)MAP_FAILED) {
633 <                const uint32 page_size = getpagesize();
634 <                const uint32 page_mask = page_size - 1;
631 <                munmap((caddr_t)RAMBaseHost, ((RAMSize + page_mask) & ~page_mask));
633 >                munmap((caddr_t)RAMBaseHost, mapped_ram_rom_size);
634 >                RAMBaseHost = NULL;
635          }
636   #else
634        // Delete ROM area
637          if (ROMBaseHost) {
638                  free(ROMBaseHost);
639                  ROMBaseHost = NULL;
640          }
639
640        // Delete RAM area
641          if (RAMBaseHost) {
642                  free(RAMBaseHost);
643                  RAMBaseHost = NULL;
644          }
645   #endif
646  
647 < #if !EMULATED_68K || USE_SCRATMEM_SUBTERFUGE
647 > #if USE_SCRATCHMEM_SUBTERFUGE
648          // Delete scratch memory area
649          if (ScratchMem) {
650                  free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
# Line 701 | Line 701 | static void sigint_handler(...)
701          extern void m68k_dumpstate(uaecptr *nextpc);
702          m68k_dumpstate(&nextpc);
703   #else
704 <        char *arg[2] = {"rmon", NULL};
705 <        mon(1, arg);
704 >        char *arg[4] = {"mon", "-m", "-r", NULL};
705 >        mon(3, arg);
706          QuitEmulator();
707   #endif
708   }
# Line 748 | Line 748 | void TriggerInterrupt(void)
748          raise(SIG_IRQ);
749   #endif
750   }
751 +
752 + void TriggerNMI(void)
753 + {
754 +        // not yet supported
755 + }
756   #endif
757  
758  
# Line 768 | Line 773 | static void *xpram_func(void *arg)
773   {
774          while (!xpram_thread_cancel) {
775                  for (int i=0; i<60 && !xpram_thread_cancel; i++)
776 <                        Delay_usec(1000000);
776 >                        Delay_usec(999999);             // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
777                  xpram_watchdog();
778          }
779          return NULL;
# Line 855 | Line 860 | uint64 GetTicks_usec(void)
860  
861   /*
862   *  Delay by specified number of microseconds (<1 second)
863 < *  (adapted from SDL_Delay() source)
863 > *  (adapted from SDL_Delay() source; this function is designed to provide
864 > *  the highest accuracy possible)
865   */
866  
867 + #if defined(linux)
868 + // Linux select() changes its timeout parameter upon return to contain
869 + // the remaining time. Most other unixen leave it unchanged or undefined.
870 + #define SELECT_SETS_REMAINING
871 + #elif defined(__FreeBSD__) || defined(__sun__)
872 + #define USE_NANOSLEEP
873 + #elif defined(HAVE_PTHREADS) && defined(sgi)
874 + // SGI pthreads has a bug when using pthreads+signals+nanosleep,
875 + // so instead of using nanosleep, wait on a CV which is never signalled.
876 + #define USE_COND_TIMEDWAIT
877 + #endif
878 +
879   void Delay_usec(uint32 usec)
880   {
881          int was_error;
882 < #ifndef __linux__       // Non-Linux implementations need to calculate time left
882 >
883 > #if defined(USE_NANOSLEEP)
884 >        struct timespec elapsed, tv;
885 > #elif defined(USE_COND_TIMEDWAIT)
886 >        // Use a local mutex and cv, so threads remain independent
887 >        pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER;
888 >        pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER;
889 >        struct timespec elapsed;
890 >        uint64 future;
891 > #else
892 >        struct timeval tv;
893 > #ifndef SELECT_SETS_REMAINING
894          uint64 then, now, elapsed;
895   #endif
896 <        struct timeval tv;
896 > #endif
897  
898          // Set the timeout interval - Linux only needs to do this once
899 < #ifdef __linux__
900 <        tv.tv_sec = 0;
901 <        tv.tv_usec = usec;
899 > #if defined(SELECT_SETS_REMAINING)
900 >    tv.tv_sec = 0;
901 >    tv.tv_usec = usec;
902 > #elif defined(USE_NANOSLEEP)
903 >    elapsed.tv_sec = 0;
904 >    elapsed.tv_nsec = usec * 1000;
905 > #elif defined(USE_COND_TIMEDWAIT)
906 >        future = GetTicks_usec() + usec;
907 >        elapsed.tv_sec = future / 1000000;
908 >        elapsed.tv_nsec = (future % 1000000) * 1000;
909   #else
910 <        then = GetTicks_usec();
910 >    then = GetTicks_usec();
911   #endif
912 +
913          do {
914                  errno = 0;
915 < #ifndef __linux__
916 <                /* Calculate the time interval left (in case of interrupt) */
915 > #if defined(USE_NANOSLEEP)
916 >                tv.tv_sec = elapsed.tv_sec;
917 >                tv.tv_nsec = elapsed.tv_nsec;
918 >                was_error = nanosleep(&tv, &elapsed);
919 > #elif defined(USE_COND_TIMEDWAIT)
920 >                was_error = pthread_mutex_lock(&delay_mutex);
921 >                was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed);
922 >                was_error = pthread_mutex_unlock(&delay_mutex);
923 > #else
924 > #ifndef SELECT_SETS_REMAINING
925 >                // Calculate the time interval left (in case of interrupt)
926                  now = GetTicks_usec();
927                  elapsed = now - then;
928                  then = now;
# Line 887 | Line 933 | void Delay_usec(uint32 usec)
933                  tv.tv_usec = usec;
934   #endif
935                  was_error = select(0, NULL, NULL, NULL, &tv);
936 + #endif
937          } while (was_error && (errno == EINTR));
938   }
939  
# Line 941 | Line 988 | static void sigill_handler(int sig, int
988  
989   #define STORE_SR(v) \
990          scp->sc_ps = (v) & 0xff; \
991 <        EmulatedSR = (v) & 0x2700; \
991 >        EmulatedSR = (v) & 0xe700; \
992          if (((v) & 0x0700) == 0 && InterruptFlags) \
993                  TriggerInterrupt();
994  
# Line 1004 | Line 1051 | static void sigill_handler(int sig, int
1051                  case 0x007c: {  // ori #xxxx,sr
1052                          uint16 sr = GET_SR | pc[1];
1053                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
1054 <                        EmulatedSR = sr & 0x2700;
1054 >                        EmulatedSR = sr & 0xe700;
1055                          INC_PC(4);
1056                          break;
1057                  }
# Line 1081 | Line 1128 | static void sigill_handler(int sig, int
1128                  }
1129  
1130                  case 0xf327:    // fsave -(sp)
1131 <                        goto ill;       //!!
1131 >                        if (CPUIs68060) {
1132 >                                regs->a[7] -= 4;
1133 >                                WriteMacInt32(regs->a[7], 0x60000000);  // Idle frame
1134 >                                regs->a[7] -= 4;
1135 >                                WriteMacInt32(regs->a[7], 0);
1136 >                                regs->a[7] -= 4;
1137 >                                WriteMacInt32(regs->a[7], 0);
1138 >                        } else {
1139 >                                regs->a[7] -= 4;
1140 >                                WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1141 >                        }
1142 >                        scp->sc_sp = regs->a[7];
1143 >                        INC_PC(2);
1144 >                        break;
1145  
1146                  case 0xf35f:    // frestore (sp)+
1147 <                        goto ill;       //!!
1147 >                        if (CPUIs68060)
1148 >                                regs->a[7] += 12;
1149 >                        else
1150 >                                regs->a[7] += 4;
1151 >                        scp->sc_sp = regs->a[7];
1152 >                        INC_PC(2);
1153 >                        break;
1154  
1155 <                case 0x4e73: {  // rte (only handles format 0)
1155 >                case 0x4e73: {  // rte
1156                          uint32 a7 = regs->a[7];
1157                          uint16 sr = ReadMacInt16(a7);
1158                          a7 += 2;
1159                          scp->sc_ps = sr & 0xff;
1160 <                        EmulatedSR = sr & 0x2700;
1160 >                        EmulatedSR = sr & 0xe700;
1161                          scp->sc_pc = ReadMacInt32(a7);
1162 <                        a7 += 6;
1163 <                        scp->sc_sp = regs->a[7] = a7;
1162 >                        a7 += 4;
1163 >                        uint16 format = ReadMacInt16(a7) >> 12;
1164 >                        a7 += 2;
1165 >                        static const int frame_adj[16] = {
1166 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1167 >                        };
1168 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1169                          break;
1170                  }
1171  
1172                  case 0x4e7a:    // movec cr,x
1173                          switch (pc[1]) {
1103                                case 0x8801:    // movec vbr,a0
1104                                        regs->a[0] = 0;
1105                                        break;
1106                                case 0x9801:    // movec vbr,a1
1107                                        regs->a[1] = 0;
1108                                        break;
1174                                  case 0x0002:    // movec cacr,d0
1175                                          regs->d[0] = 0x3111;
1176                                          break;
# Line 1113 | Line 1178 | static void sigill_handler(int sig, int
1178                                          regs->d[1] = 0x3111;
1179                                          break;
1180                                  case 0x0003:    // movec tc,d0
1181 +                                case 0x0004:    // movec itt0,d0
1182 +                                case 0x0005:    // movec itt1,d0
1183 +                                case 0x0006:    // movec dtt0,d0
1184 +                                case 0x0007:    // movec dtt1,d0
1185 +                                case 0x0806:    // movec urp,d0
1186 +                                case 0x0807:    // movec srp,d0
1187                                          regs->d[0] = 0;
1188                                          break;
1189 +                                case 0x1000:    // movec sfc,d1
1190 +                                case 0x1001:    // movec dfc,d1
1191                                  case 0x1003:    // movec tc,d1
1192 +                                case 0x1801:    // movec vbr,d1
1193                                          regs->d[1] = 0;
1194                                          break;
1195 +                                case 0x8801:    // movec vbr,a0
1196 +                                        regs->a[0] = 0;
1197 +                                        break;
1198 +                                case 0x9801:    // movec vbr,a1
1199 +                                        regs->a[1] = 0;
1200 +                                        break;
1201                                  default:
1202                                          goto ill;
1203                          }
# Line 1126 | Line 1206 | static void sigill_handler(int sig, int
1206  
1207                  case 0x4e7b:    // movec x,cr
1208                          switch (pc[1]) {
1209 +                                case 0x1000:    // movec d1,sfc
1210 +                                case 0x1001:    // movec d1,dfc
1211                                  case 0x0801:    // movec d0,vbr
1212 +                                case 0x1801:    // movec d1,vbr
1213                                          break;
1214                                  case 0x0002:    // movec d0,cacr
1215                                  case 0x1002:    // movec d1,cacr
# Line 1161 | Line 1244 | ill:           printf("SIGILL num %d, code %d\n",
1244                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1245  
1246   #ifdef ENABLE_MON
1247 <                        char *arg[2] = {"rmon", NULL};
1248 <                        mon(1, arg);
1247 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1248 >                        mon(3, arg);
1249   #endif
1250                          QuitEmulator();
1251                          break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines