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.14 by cebix, 2000-07-14T21:29:13Z vs.
Revision 1.27 by cebix, 2000-11-30T16:20:52Z

# Line 30 | Line 30
30   # include <pthread.h>
31   #endif
32  
33 < #if defined(USE_MAPPED_MEMORY) || REAL_ADDRESSING
33 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
34   # include <sys/mman.h>
35   #endif
36  
# Line 108 | Line 108 | char *x_display_name = NULL;                                           // X11
108   Display *x_display = NULL;                                                      // X11 display handle
109  
110   static int zero_fd = -1;                                                        // FD of /dev/zero
111 static bool lm_area_mapped = false;                                     // Flag: Low Memory area mmap()ped
111   static uint8 last_xpram[256];                                           // Buffer for monitoring XPRAM changes
112  
113   #ifdef HAVE_PTHREADS
# Line 134 | Line 133 | static struct sigaction sigirq_sa;     // Vi
133   static struct sigaction sigill_sa;      // Illegal instruction
134   static void *sig_stack = NULL;          // Stack for signal handlers
135   uint16 EmulatedSR;                                      // Emulated bits of SR (supervisor bit and interrupt mask)
136 < uint32 ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
136 > #endif
137 >
138 > #if USE_SCRATCHMEM_SUBTERFUGE
139 > uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
140   #endif
141  
142   static struct sigaction timer_sa;       // sigaction used for timer
# Line 149 | Line 151 | static struct sigaction sigint_sa;     // si
151   static void sigint_handler(...);
152   #endif
153  
154 < #ifdef USE_MAPPED_MEMORY
155 < extern char *address_space, *good_address_map;
154 > #if REAL_ADDRESSING
155 > static bool lm_area_mapped = false;     // Flag: Low Memory area mmap()ped
156 > static bool memory_mapped_from_zero = false; // Flag: Could allocate RAM area from 0
157 > #endif
158 >
159 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
160 > static uint32 mapped_ram_rom_size;              // Total size of mmap()ed RAM/ROM area
161   #endif
162  
163  
# Line 257 | Line 264 | int main(int argc, char **argv)
264                  RAMSize = 1024*1024;
265          }
266  
267 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
268 +        const uint32 page_size = getpagesize();
269 +        const uint32 page_mask = page_size - 1;
270 +        const uint32 aligned_ram_size = (RAMSize + page_mask) & ~page_mask;
271 +        mapped_ram_rom_size = aligned_ram_size + 0x100000;
272 + #endif
273 +
274   #if REAL_ADDRESSING
275 +        // Try to allocate the complete address space from zero
276 +        // gb-- the Solaris manpage about mmap(2) states that using MAP_FIXED
277 +        // implies undefined behaviour for further use of sbrk(), malloc(), etc.
278 +        // cebix-- on NetBSD/m68k, this causes a segfault
279 + #if defined(OS_solaris) || defined(OS_netbsd)
280 +        // Anyway, it doesn't work...
281 +        if (0) {
282 + #else
283 +        if (mmap((caddr_t)0x0000, mapped_ram_rom_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) != MAP_FAILED) {
284 + #endif
285 +                D(bug("Could allocate RAM and ROM from 0x0000\n"));
286 +                memory_mapped_from_zero = true;
287 +        }
288          // Create Low Memory area (0x0000..0x2000)
289 <        if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
289 >        else if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) != MAP_FAILED) {
290 >                D(bug("Could allocate the Low Memory globals\n"));
291 >                lm_area_mapped = true;
292 >        }
293 >        // Exit on error
294 >        else {
295                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
296                  ErrorAlert(str);
297                  QuitEmulator();
298          }
267        lm_area_mapped = true;
299   #endif
300  
301 < #if !EMULATED_68K
301 > #if USE_SCRATCHMEM_SUBTERFUGE
302          // Allocate scratch memory
303 <        ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
303 >        ScratchMem = (uint8 *)malloc(SCRATCH_MEM_SIZE);
304          if (ScratchMem == NULL) {
305                  ErrorAlert(GetString(STR_NO_MEM_ERR));
306                  QuitEmulator();
# Line 278 | Line 309 | int main(int argc, char **argv)
309   #endif
310  
311          // Create areas for Mac RAM and ROM
312 < #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)
299 <        mmap(good_address_map + i + 0x00400000, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
312 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
313 >        // gb-- Overkill, needs to be cleaned up. Probably explode it for either
314 >        // real or direct addressing mode.
315 > #if REAL_ADDRESSING
316 >        if (memory_mapped_from_zero) {
317 >                RAMBaseHost = (uint8 *)0;
318 >                ROMBaseHost = RAMBaseHost + aligned_ram_size;
319 >        }
320 >        else
321 > #endif
322 >        {
323 >                RAMBaseHost = (uint8 *)mmap(0, mapped_ram_rom_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
324 >                if (RAMBaseHost == (uint8 *)MAP_FAILED) {
325 >                        ErrorAlert(GetString(STR_NO_MEM_ERR));
326 >                        QuitEmulator();
327 >                }
328 >                ROMBaseHost = RAMBaseHost + aligned_ram_size;
329 >        }
330   #else
331 <        RAMBaseHost = new uint8[RAMSize];
332 <        ROMBaseHost = new uint8[0x100000];
331 >        RAMBaseHost = (uint8 *)malloc(RAMSize);
332 >        ROMBaseHost = (uint8 *)malloc(0x100000);
333 >        if (RAMBaseHost == NULL || ROMBaseHost == NULL) {
334 >                ErrorAlert(GetString(STR_NO_MEM_ERR));
335 >                QuitEmulator();
336 >        }
337   #endif
338 < #if REAL_ADDRESSING && !EMULATED_68K
338 >
339 > #if DIRECT_ADDRESSING
340 >        // Initialize MEMBaseDiff now so that Host2MacAddr in the Video module
341 >        // will return correct results
342 >        RAMBaseMac = 0;
343 >        ROMBaseMac = RAMBaseMac + aligned_ram_size;
344 >        InitMEMBaseDiff(RAMBaseHost, RAMBaseMac);
345 > #endif
346 > #if REAL_ADDRESSING // && !EMULATED_68K
347          RAMBaseMac = (uint32)RAMBaseHost;
348          ROMBaseMac = (uint32)ROMBaseHost;
349   #endif
350          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
351          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
352 <
352 >        
353          // Get rom file path from preferences
354          const char *rom_path = PrefsFindString("rom");
355  
# Line 356 | Line 398 | int main(int argc, char **argv)
398                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
399                  CPUType = 2;
400          }
401 <        FPUType = 0;    //!!
401 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
402          TwentyFourBitAddressing = false;
403   #endif
404  
# Line 419 | Line 461 | int main(int argc, char **argv)
461   #ifdef ENABLE_MON
462          // Setup SIGINT handler to enter mon
463          sigemptyset(&sigint_sa.sa_mask);
464 <        sigint_sa.sa_handler = sigint_handler;
464 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
465          sigint_sa.sa_flags = 0;
466          sigaction(SIGINT, &sigint_sa, NULL);
467   #endif
# Line 428 | Line 470 | int main(int argc, char **argv)
470  
471          // POSIX.4 timers and real-time signals available, start 60Hz timer
472          sigemptyset(&timer_sa.sa_mask);
473 <        timer_sa.sa_sigaction = one_tick;
473 >        timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
474          timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
475          if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
476                  sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
# Line 557 | Line 599 | void QuitEmulator(void)
599          // Deinitialize everything
600          ExitAll();
601  
602 <        // Delete ROM area
603 <        delete[] ROMBaseHost;
604 <
605 <        // Delete RAM area
606 <        delete[] RAMBaseHost;
602 >        // Free ROM/RAM areas
603 > #if REAL_ADDRESSING
604 >        if (memory_mapped_from_zero)
605 >                munmap((caddr_t)0x0000, mapped_ram_rom_size);
606 >        else
607 > #endif
608 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
609 >        if (RAMBaseHost != (uint8 *)MAP_FAILED) {
610 >                munmap((caddr_t)RAMBaseHost, mapped_ram_rom_size);
611 >                RAMBaseHost = NULL;
612 >        }
613 > #else
614 >        if (ROMBaseHost) {
615 >                free(ROMBaseHost);
616 >                ROMBaseHost = NULL;
617 >        }
618 >        if (RAMBaseHost) {
619 >                free(RAMBaseHost);
620 >                RAMBaseHost = NULL;
621 >        }
622 > #endif
623  
624 < #if !EMULATED_68K
624 > #if USE_SCRATCHMEM_SUBTERFUGE
625          // Delete scratch memory area
626 <        if (ScratchMem)
626 >        if (ScratchMem) {
627                  free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
628 +                ScratchMem = NULL;
629 +        }
630   #endif
631  
632   #if REAL_ADDRESSING
# Line 618 | Line 678 | static void sigint_handler(...)
678          extern void m68k_dumpstate(uaecptr *nextpc);
679          m68k_dumpstate(&nextpc);
680   #else
681 <        char *arg[2] = {"rmon", NULL};
682 <        mon(1, arg);
681 >        char *arg[4] = {"mon", "-m", "-r", NULL};
682 >        mon(3, arg);
683          QuitEmulator();
684   #endif
685   }
# Line 665 | Line 725 | void TriggerInterrupt(void)
725          raise(SIG_IRQ);
726   #endif
727   }
728 +
729 + void TriggerNMI(void)
730 + {
731 +        // not yet supported
732 + }
733   #endif
734  
735  
# Line 684 | Line 749 | static void xpram_watchdog(void)
749   static void *xpram_func(void *arg)
750   {
751          while (!xpram_thread_cancel) {
752 <                for (int i=0; i<60 && !xpram_thread_cancel; i++) {
753 < #ifdef HAVE_NANOSLEEP
689 <                        struct timespec req = {1, 0};
690 <                        nanosleep(&req, NULL);
691 < #else
692 <                        usleep(1000000);
693 < #endif
694 <                }
752 >                for (int i=0; i<60 && !xpram_thread_cancel; i++)
753 >                        Delay_usec(999999);
754                  xpram_watchdog();
755          }
756          return NULL;
# Line 708 | Line 767 | static void one_second(void)
767          // Pseudo Mac 1Hz interrupt, update local time
768          WriteMacInt32(0x20c, TimerDateTime());
769  
770 <        SetInterruptFlag(INTFLAG_60HZ);
770 >        SetInterruptFlag(INTFLAG_1HZ);
771          TriggerInterrupt();
772  
773   #ifndef HAVE_PTHREADS
# Line 743 | Line 802 | static void one_tick(...)
802   #ifdef HAVE_PTHREADS
803   static void *tick_func(void *arg)
804   {
805 +        uint64 next = GetTicks_usec();
806          while (!tick_thread_cancel) {
747
748                // Wait
749 #ifdef HAVE_NANOSLEEP
750                struct timespec req = {0, 16625000};
751                nanosleep(&req, NULL);
752 #else
753                usleep(16625);
754 #endif
755
756                // Action
807                  one_tick();
808 +                next += 16625;
809 +                int64 delay = next - GetTicks_usec();
810 +                if (delay > 0)
811 +                        Delay_usec(delay);
812 +                else if (delay < -16625)
813 +                        next = GetTicks_usec();
814          }
815          return NULL;
816   }
817   #endif
818  
819  
820 + /*
821 + *  Get current value of microsecond timer
822 + */
823 +
824 + uint64 GetTicks_usec(void)
825 + {
826 + #ifdef HAVE_CLOCK_GETTIME
827 +        struct timespec t;
828 +        clock_gettime(CLOCK_REALTIME, &t);
829 +        return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000;
830 + #else
831 +        struct timeval t;
832 +        gettimeofday(&t, NULL);
833 +        return (uint64)t.tv_sec * 1000000 + t.tv_usec;
834 + #endif
835 + }
836 +
837 +
838 + /*
839 + *  Delay by specified number of microseconds (<1 second)
840 + *  (adapted from SDL_Delay() source; this function is designed to provide
841 + *  the highest accuracy possible)
842 + */
843 +
844 + #if defined(linux)
845 + // Linux select() changes its timeout parameter upon return to contain
846 + // the remaining time. Most other unixen leave it unchanged or undefined.
847 + #define SELECT_SETS_REMAINING
848 + #elif defined(__FreeBSD__) || defined(__sun__) || defined(sgi)
849 + #define USE_NANOSLEEP
850 + #endif
851 +
852 + void Delay_usec(uint32 usec)
853 + {
854 +        int was_error;
855 +
856 + #ifdef USE_NANOSLEEP
857 +        struct timespec elapsed, tv;
858 + #else
859 +        struct timeval tv;
860 + #ifndef SELECT_SETS_REMAINING
861 +        uint64 then, now, elapsed;
862 + #endif
863 + #endif
864 +
865 +        // Set the timeout interval - Linux only needs to do this once
866 + #ifdef SELECT_SETS_REMAINING
867 +    tv.tv_sec = 0;
868 +    tv.tv_usec = usec;
869 + #elif defined(USE_NANOSLEEP)
870 +    elapsed.tv_sec = 0;
871 +    elapsed.tv_nsec = usec * 1000;
872 + #else
873 +    then = GetTicks_usec();
874 + #endif
875 +
876 +        do {
877 +                errno = 0;
878 + #ifdef USE_NANOSLEEP
879 +                tv.tv_sec = elapsed.tv_sec;
880 +                tv.tv_nsec = elapsed.tv_nsec;
881 +                was_error = nanosleep(&tv, &elapsed);
882 + #else
883 + #ifndef SELECT_SETS_REMAINING
884 +                // Calculate the time interval left (in case of interrupt)
885 +                now = GetTicks_usec();
886 +                elapsed = now - then;
887 +                then = now;
888 +                if (elapsed >= usec)
889 +                        break;
890 +                usec -= elapsed;
891 +                tv.tv_sec = 0;
892 +                tv.tv_usec = usec;
893 + #endif
894 +                was_error = select(0, NULL, NULL, NULL, &tv);
895 + #endif
896 +        } while (was_error && (errno == EINTR));
897 + }
898 +
899 +
900   #if !EMULATED_68K
901   /*
902   *  Virtual 68k interrupt handler
# Line 811 | Line 947 | static void sigill_handler(int sig, int
947  
948   #define STORE_SR(v) \
949          scp->sc_ps = (v) & 0xff; \
950 <        EmulatedSR = (v) & 0x2700; \
950 >        EmulatedSR = (v) & 0xe700; \
951          if (((v) & 0x0700) == 0 && InterruptFlags) \
952                  TriggerInterrupt();
953  
# Line 874 | Line 1010 | static void sigill_handler(int sig, int
1010                  case 0x007c: {  // ori #xxxx,sr
1011                          uint16 sr = GET_SR | pc[1];
1012                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
1013 <                        EmulatedSR = sr & 0x2700;
1013 >                        EmulatedSR = sr & 0xe700;
1014                          INC_PC(4);
1015                          break;
1016                  }
# Line 951 | Line 1087 | static void sigill_handler(int sig, int
1087                  }
1088  
1089                  case 0xf327:    // fsave -(sp)
1090 <                        goto ill;       //!!
1090 >                        if (CPUIs68060) {
1091 >                                regs->a[7] -= 4;
1092 >                                WriteMacInt32(regs->a[7], 0x60000000);  // Idle frame
1093 >                                regs->a[7] -= 4;
1094 >                                WriteMacInt32(regs->a[7], 0);
1095 >                                regs->a[7] -= 4;
1096 >                                WriteMacInt32(regs->a[7], 0);
1097 >                        } else {
1098 >                                regs->a[7] -= 4;
1099 >                                WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1100 >                        }
1101 >                        scp->sc_sp = regs->a[7];
1102 >                        INC_PC(2);
1103 >                        break;
1104  
1105                  case 0xf35f:    // frestore (sp)+
1106 <                        goto ill;       //!!
1106 >                        if (CPUIs68060)
1107 >                                regs->a[7] += 12;
1108 >                        else
1109 >                                regs->a[7] += 4;
1110 >                        scp->sc_sp = regs->a[7];
1111 >                        INC_PC(2);
1112 >                        break;
1113  
1114 <                case 0x4e73: {  // rte (only handles format 0)
1114 >                case 0x4e73: {  // rte
1115                          uint32 a7 = regs->a[7];
1116                          uint16 sr = ReadMacInt16(a7);
1117                          a7 += 2;
1118                          scp->sc_ps = sr & 0xff;
1119 <                        EmulatedSR = sr & 0x2700;
1119 >                        EmulatedSR = sr & 0xe700;
1120                          scp->sc_pc = ReadMacInt32(a7);
1121 <                        a7 += 6;
1122 <                        scp->sc_sp = regs->a[7] = a7;
1121 >                        a7 += 4;
1122 >                        uint16 format = ReadMacInt16(a7) >> 12;
1123 >                        a7 += 2;
1124 >                        static const int frame_adj[16] = {
1125 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1126 >                        };
1127 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1128                          break;
1129                  }
1130  
1131                  case 0x4e7a:    // movec cr,x
1132                          switch (pc[1]) {
973                                case 0x8801:    // movec vbr,a0
974                                        regs->a[0] = 0;
975                                        break;
976                                case 0x9801:    // movec vbr,a1
977                                        regs->a[1] = 0;
978                                        break;
1133                                  case 0x0002:    // movec cacr,d0
1134                                          regs->d[0] = 0x3111;
1135                                          break;
# Line 983 | Line 1137 | static void sigill_handler(int sig, int
1137                                          regs->d[1] = 0x3111;
1138                                          break;
1139                                  case 0x0003:    // movec tc,d0
1140 +                                case 0x0004:    // movec itt0,d0
1141 +                                case 0x0005:    // movec itt1,d0
1142 +                                case 0x0006:    // movec dtt0,d0
1143 +                                case 0x0007:    // movec dtt1,d0
1144 +                                case 0x0806:    // movec urp,d0
1145 +                                case 0x0807:    // movec srp,d0
1146                                          regs->d[0] = 0;
1147                                          break;
1148 +                                case 0x1000:    // movec sfc,d1
1149 +                                case 0x1001:    // movec dfc,d1
1150                                  case 0x1003:    // movec tc,d1
1151 +                                case 0x1801:    // movec vbr,d1
1152                                          regs->d[1] = 0;
1153                                          break;
1154 +                                case 0x8801:    // movec vbr,a0
1155 +                                        regs->a[0] = 0;
1156 +                                        break;
1157 +                                case 0x9801:    // movec vbr,a1
1158 +                                        regs->a[1] = 0;
1159 +                                        break;
1160                                  default:
1161                                          goto ill;
1162                          }
# Line 996 | Line 1165 | static void sigill_handler(int sig, int
1165  
1166                  case 0x4e7b:    // movec x,cr
1167                          switch (pc[1]) {
1168 +                                case 0x1000:    // movec d1,sfc
1169 +                                case 0x1001:    // movec d1,dfc
1170                                  case 0x0801:    // movec d0,vbr
1171 +                                case 0x1801:    // movec d1,vbr
1172                                          break;
1173                                  case 0x0002:    // movec d0,cacr
1174                                  case 0x1002:    // movec d1,cacr
# Line 1031 | Line 1203 | ill:           printf("SIGILL num %d, code %d\n",
1203                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1204  
1205   #ifdef ENABLE_MON
1206 <                        char *arg[2] = {"rmon", NULL};
1207 <                        mon(1, arg);
1206 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1207 >                        mon(3, arg);
1208   #endif
1209                          QuitEmulator();
1210                          break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines