ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp
(Generate patch)

Comparing SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp (file contents):
Revision 1.7 by gbeauche, 2003-10-12T05:44:15Z vs.
Revision 1.16 by gbeauche, 2003-11-10T15:11:44Z

# Line 28 | Line 28
28   #include "macos_util.h"
29   #include "block-alloc.hpp"
30   #include "sigsegv.h"
31 #include "spcflags.h"
31   #include "cpu/ppc/ppc-cpu.hpp"
32   #include "cpu/ppc/ppc-operations.hpp"
33  
# Line 36 | Line 35
35   #include "video.h"
36   #include "name_registry.h"
37   #include "serial.h"
38 + #include "ether.h"
39  
40   #include <stdio.h>
41  
# Line 44 | Line 44
44   #include "mon_disass.h"
45   #endif
46  
47 < #define DEBUG 1
47 > #define DEBUG 0
48   #include "debug.h"
49  
50 + // Emulation time statistics
51 + #define EMUL_TIME_STATS 1
52 +
53 + #if EMUL_TIME_STATS
54 + static clock_t emul_start_time;
55 + static uint32 interrupt_count = 0;
56 + static clock_t interrupt_time = 0;
57 + static uint32 exec68k_count = 0;
58 + static clock_t exec68k_time = 0;
59 + static uint32 native_exec_count = 0;
60 + static clock_t native_exec_time = 0;
61 + static uint32 macos_exec_count = 0;
62 + static clock_t macos_exec_time = 0;
63 + #endif
64 +
65   static void enter_mon(void)
66   {
67          // Start up mon in real-mode
# Line 57 | Line 72 | static void enter_mon(void)
72   }
73  
74   // Enable multicore (main/interrupts) cpu emulation?
75 < #define MULTICORE_CPU 0
75 > #define MULTICORE_CPU (ASYNC_IRQ ? 1 : 0)
76  
77   // Enable Execute68k() safety checks?
78   #define SAFE_EXEC_68K 1
# Line 79 | Line 94 | static KernelData * const kernel_data =
94   *              PowerPC emulator glue with special 'sheep' opcodes
95   **/
96  
82 struct sheepshaver_exec_return { };
83
97   class sheepshaver_cpu
98          : public powerpc_cpu
99   {
# Line 89 | Line 102 | class sheepshaver_cpu
102  
103   public:
104  
105 <        sheepshaver_cpu()
106 <                : powerpc_cpu()
94 <                { init_decoder(); }
105 >        // Constructor
106 >        sheepshaver_cpu();
107  
108          // Condition Register accessors
109          uint32 get_cr() const           { return cr().get(); }
110          void set_cr(uint32 v)           { cr().set(v); }
111  
112          // Execution loop
113 <        void execute(uint32 pc);
113 >        void execute(uint32 entry, bool enable_cache = false);
114  
115          // Execute 68k routine
116          void execute_68k(uint32 entry, M68kRegisters *r);
# Line 114 | Line 126 | public:
126  
127          // Handle MacOS interrupt
128          void interrupt(uint32 entry);
129 <
118 <        // spcflags for interrupts handling
119 <        static uint32 spcflags;
129 >        void handle_interrupt();
130  
131          // Lazy memory allocator (one item at a time)
132          void *operator new(size_t size)
# Line 128 | Line 138 | public:
138          void operator delete[](void *p);
139   };
140  
131 uint32 sheepshaver_cpu::spcflags = 0;
141   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
142  
143 + sheepshaver_cpu::sheepshaver_cpu()
144 +        : powerpc_cpu()
145 + {
146 +        init_decoder();
147 + }
148 +
149   void sheepshaver_cpu::init_decoder()
150   {
151   #ifndef PPC_NO_STATIC_II_INDEX_TABLE
# Line 142 | Line 157 | void sheepshaver_cpu::init_decoder()
157  
158          static const instr_info_t sheep_ii_table[] = {
159                  { "sheep",
160 <                  (execute_fn)&sheepshaver_cpu::execute_sheep,
160 >                  (execute_pmf)&sheepshaver_cpu::execute_sheep,
161                    NULL,
162                    D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP
163                  }
# Line 181 | Line 196 | void sheepshaver_cpu::execute_sheep(uint
196          case 0:         // EMUL_RETURN
197                  QuitEmulator();
198                  break;
199 <                
199 >
200          case 1:         // EXEC_RETURN
201 <                throw sheepshaver_exec_return();
201 >                spcflags().set(SPCFLAG_CPU_EXEC_RETURN);
202                  break;
203  
204          case 2:         // EXEC_NATIVE
# Line 216 | Line 231 | void sheepshaver_cpu::execute_sheep(uint
231          }
232   }
233  
219 // Checks for pending interrupts
220 struct execute_nothing {
221        static inline void execute(powerpc_cpu *) { }
222 };
223
224 struct execute_spcflags_check {
225        static inline void execute(powerpc_cpu *cpu) {
226 #if !ASYNC_IRQ
227                if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
228                        if (SPCFLAGS_TEST( SPCFLAG_ENTER_MON )) {
229                                SPCFLAGS_CLEAR( SPCFLAG_ENTER_MON );
230                                enter_mon();
231                        }
232                        if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
233                                SPCFLAGS_CLEAR( SPCFLAG_DOINT );
234                                HandleInterrupt();
235                        }
236                        if (SPCFLAGS_TEST( SPCFLAG_INT )) {
237                                SPCFLAGS_CLEAR( SPCFLAG_INT );
238                                SPCFLAGS_SET( SPCFLAG_DOINT );
239                        }
240                }
241 #endif
242        }
243 };
244
234   // Execution loop
235 < void sheepshaver_cpu::execute(uint32 entry)
235 > void sheepshaver_cpu::execute(uint32 entry, bool enable_cache)
236   {
237 <        try {
249 <                pc() = entry;
250 <                powerpc_cpu::do_execute<execute_nothing, execute_spcflags_check>();
251 <        }
252 <        catch (sheepshaver_exec_return const &) {
253 <                // Nothing, simply return
254 <        }
255 <        catch (...) {
256 <                printf("ERROR: execute() received an unknown exception!\n");
257 <                QuitEmulator();
258 <        }
237 >        powerpc_cpu::execute(entry, enable_cache);
238   }
239  
240   // Handle MacOS interrupt
241   void sheepshaver_cpu::interrupt(uint32 entry)
242   {
243 + #if EMUL_TIME_STATS
244 +        interrupt_count++;
245 +        const clock_t interrupt_start = clock();
246 + #endif
247 +
248   #if !MULTICORE_CPU
249          // Save program counters and branch registers
250          uint32 saved_pc = pc();
# Line 294 | Line 278 | void sheepshaver_cpu::interrupt(uint32 e
278          gpr(8)  = 0;
279          gpr(10) = (uint32)trampoline;
280          gpr(12) = (uint32)trampoline;
281 <        gpr(13) = cr().get();
281 >        gpr(13) = get_cr();
282  
283          // rlwimi. r7,r7,8,0,0
284          uint32 result = op_ppc_rlwimi::apply(gpr(7), 8, 0x80000000, gpr(7));
# Line 302 | Line 286 | void sheepshaver_cpu::interrupt(uint32 e
286          gpr(7) = result;
287  
288          gpr(11) = 0xf072; // MSR (SRR1)
289 <        cr().set((gpr(11) & 0x0fff0000) | (cr().get() & ~0x0fff0000));
289 >        cr().set((gpr(11) & 0x0fff0000) | (get_cr() & ~0x0fff0000));
290  
291          // Enter nanokernel
292          execute(entry);
# Line 314 | Line 298 | void sheepshaver_cpu::interrupt(uint32 e
298          ctr()= saved_ctr;
299          gpr(1) = saved_sp;
300   #endif
301 +
302 + #if EMUL_TIME_STATS
303 +        interrupt_time += (clock() - interrupt_start);
304 + #endif
305   }
306  
307   // Execute 68k routine
308   void sheepshaver_cpu::execute_68k(uint32 entry, M68kRegisters *r)
309   {
310 + #if EMUL_TIME_STATS
311 +        exec68k_count++;
312 +        const clock_t exec68k_start = clock();
313 + #endif
314 +
315   #if SAFE_EXEC_68K
316          if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP)
317                  printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
# Line 328 | Line 321 | void sheepshaver_cpu::execute_68k(uint32
321          uint32 saved_pc = pc();
322          uint32 saved_lr = lr();
323          uint32 saved_ctr= ctr();
324 +        uint32 saved_cr = get_cr();
325  
326          // Create MacOS stack frame
327          // FIXME: make sure MacOS doesn't expect PPC registers to live on top
# Line 399 | Line 393 | void sheepshaver_cpu::execute_68k(uint32
393          pc() = saved_pc;
394          lr() = saved_lr;
395          ctr()= saved_ctr;
396 +        set_cr(saved_cr);
397 +
398 + #if EMUL_TIME_STATS
399 +        exec68k_time += (clock() - exec68k_start);
400 + #endif
401   }
402  
403   // Call MacOS PPC code
404   uint32 sheepshaver_cpu::execute_macos_code(uint32 tvect, int nargs, uint32 const *args)
405   {
406 + #if EMUL_TIME_STATS
407 +        macos_exec_count++;
408 +        const clock_t macos_exec_start = clock();
409 + #endif
410 +
411          // Save program counters and branch registers
412          uint32 saved_pc = pc();
413          uint32 saved_lr = lr();
# Line 442 | Line 446 | uint32 sheepshaver_cpu::execute_macos_co
446          lr() = saved_lr;
447          ctr()= saved_ctr;
448  
449 + #if EMUL_TIME_STATS
450 +        macos_exec_time += (clock() - macos_exec_start);
451 + #endif
452 +
453          return retval;
454   }
455  
# Line 585 | Line 593 | void init_emul_ppc(void)
593          mon_add_command("regs", dump_registers, "regs                     Dump PowerPC registers\n");
594          mon_add_command("log", dump_log, "log                      Dump PowerPC emulation log\n");
595   #endif
596 +
597 + #if EMUL_TIME_STATS
598 +        emul_start_time = clock();
599 + #endif
600 + }
601 +
602 + /*
603 + *  Deinitialize emulation
604 + */
605 +
606 + void exit_emul_ppc(void)
607 + {
608 + #if EMUL_TIME_STATS
609 +        clock_t emul_end_time = clock();
610 +
611 +        printf("### Statistics for SheepShaver emulation parts\n");
612 +        const clock_t emul_time = emul_end_time - emul_start_time;
613 +        printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC));
614 +        printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count,
615 +                   (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time));
616 +
617 + #define PRINT_STATS(LABEL, VAR_PREFIX) do {                                                             \
618 +                printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count);             \
619 +                printf("Total " LABEL " time  : %.1f sec (%.1f%%)\n",                   \
620 +                           double(VAR_PREFIX##_time) / double(CLOCKS_PER_SEC),          \
621 +                           100.0 * double(VAR_PREFIX##_time) / double(emul_time));      \
622 +        } while (0)
623 +
624 +        PRINT_STATS("Execute68k[Trap] execution", exec68k);
625 +        PRINT_STATS("NativeOp execution", native_exec);
626 +        PRINT_STATS("MacOS routine execution", macos_exec);
627 +
628 + #undef PRINT_STATS
629 +        printf("\n");
630 + #endif
631 +
632 +        delete main_cpu;
633 + #if MULTICORE_CPU
634 +        delete interrupt_cpu;
635 + #endif
636   }
637  
638   /*
# Line 594 | Line 642 | void init_emul_ppc(void)
642   void emul_ppc(uint32 entry)
643   {
644          current_cpu = main_cpu;
645 + #if DEBUG
646          current_cpu->start_log();
647 <        current_cpu->execute(entry);
647 > #endif
648 >        // start emulation loop and enable code translation or caching
649 >        current_cpu->execute(entry, true);
650   }
651  
652   /*
653   *  Handle PowerPC interrupt
654   */
655  
656 < // Atomic operations
657 < extern int atomic_add(int *var, int v);
658 < extern int atomic_and(int *var, int v);
659 < extern int atomic_or(int *var, int v);
660 <
661 < #if !ASYNC_IRQ
656 > #if ASYNC_IRQ
657 > void HandleInterrupt(void)
658 > {
659 >        main_cpu->handle_interrupt();
660 > }
661 > #else
662   void TriggerInterrupt(void)
663   {
664   #if 0
665    WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
666   #else
667 <  SPCFLAGS_SET( SPCFLAG_INT );
667 >  // Trigger interrupt to main cpu only
668 >  if (main_cpu)
669 >          main_cpu->trigger_interrupt();
670   #endif
671   }
672   #endif
673  
674 < void HandleInterrupt(void)
674 > void sheepshaver_cpu::handle_interrupt(void)
675   {
676          // Do nothing if interrupts are disabled
677 <        if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
677 >        if (*(int32 *)XLM_IRQ_NEST > 0)
678                  return;
679  
680          // Do nothing if there is no interrupt pending
# Line 637 | Line 690 | void HandleInterrupt(void)
690                  // 68k emulator active, trigger 68k interrupt level 1
691                  assert(current_cpu == main_cpu);
692                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
693 <                main_cpu->set_cr(main_cpu->get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
693 >                set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
694                  break;
695      
696   #if INTERRUPTS_IN_NATIVE_MODE
697          case MODE_NATIVE:
698                  // 68k emulator inactive, in nanokernel?
699                  assert(current_cpu == main_cpu);
700 <                if (main_cpu->gpr(1) != KernelDataAddr) {
700 >                if (gpr(1) != KernelDataAddr) {
701                          // Prepare for 68k interrupt level 1
702                          WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
703                          WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc,
# Line 745 | Line 798 | static void r_get_resource(void);
798  
799   static void NativeOp(int selector)
800   {
801 + #if EMUL_TIME_STATS
802 +        native_exec_count++;
803 +        const clock_t native_exec_start = clock();
804 + #endif
805 +
806          switch (selector) {
807          case NATIVE_PATCH_NAME_REGISTRY:
808                  DoPatchNameRegistry();
# Line 759 | Line 817 | static void NativeOp(int selector)
817                  GPR(3) = (int32)(int16)VideoDoDriverIO((void *)GPR(3), (void *)GPR(4),
818                                                                                             (void *)GPR(5), GPR(6), GPR(7));
819                  break;
820 <        case NATIVE_GET_RESOURCE:
821 <                get_resource();
820 > #ifdef WORDS_BIGENDIAN
821 >        case NATIVE_ETHER_IRQ:
822 >                EtherIRQ();
823                  break;
824 <        case NATIVE_GET_1_RESOURCE:
825 <                get_1_resource();
824 >        case NATIVE_ETHER_INIT:
825 >                GPR(3) = InitStreamModule((void *)GPR(3));
826                  break;
827 <        case NATIVE_GET_IND_RESOURCE:
828 <                get_ind_resource();
827 >        case NATIVE_ETHER_TERM:
828 >                TerminateStreamModule();
829                  break;
830 <        case NATIVE_GET_1_IND_RESOURCE:
831 <                get_1_ind_resource();
830 >        case NATIVE_ETHER_OPEN:
831 >                GPR(3) = ether_open((queue_t *)GPR(3), (void *)GPR(4), GPR(5), GPR(6), (void*)GPR(7));
832 >                break;
833 >        case NATIVE_ETHER_CLOSE:
834 >                GPR(3) = ether_close((queue_t *)GPR(3), GPR(4), (void *)GPR(5));
835 >                break;
836 >        case NATIVE_ETHER_WPUT:
837 >                GPR(3) = ether_wput((queue_t *)GPR(3), (mblk_t *)GPR(4));
838                  break;
839 <        case NATIVE_R_GET_RESOURCE:
840 <                r_get_resource();
839 >        case NATIVE_ETHER_RSRV:
840 >                GPR(3) = ether_rsrv((queue_t *)GPR(3));
841 >                break;
842 > #else
843 >        case NATIVE_ETHER_INIT:
844 >                // FIXME: needs more complicated thunks
845 >                GPR(3) = false;
846                  break;
847 + #endif
848          case NATIVE_SERIAL_NOTHING:
849          case NATIVE_SERIAL_OPEN:
850          case NATIVE_SERIAL_PRIME_IN:
# Line 794 | Line 865 | static void NativeOp(int selector)
865                  GPR(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](GPR(3), GPR(4));
866                  break;
867          }
868 +        case NATIVE_GET_RESOURCE:
869 +        case NATIVE_GET_1_RESOURCE:
870 +        case NATIVE_GET_IND_RESOURCE:
871 +        case NATIVE_GET_1_IND_RESOURCE:
872 +        case NATIVE_R_GET_RESOURCE: {
873 +                typedef void (*GetResourceCallback)(void);
874 +                static const GetResourceCallback get_resource_callbacks[] = {
875 +                        get_resource,
876 +                        get_1_resource,
877 +                        get_ind_resource,
878 +                        get_1_ind_resource,
879 +                        r_get_resource
880 +                };
881 +                get_resource_callbacks[selector - NATIVE_GET_RESOURCE]();
882 +                break;
883 +        }
884          case NATIVE_DISABLE_INTERRUPT:
885                  DisableInterrupt();
886                  break;
# Line 808 | Line 895 | static void NativeOp(int selector)
895                  QuitEmulator();
896                  break;
897          }
898 +
899 + #if EMUL_TIME_STATS
900 +        native_exec_time += (clock() - native_exec_start);
901 + #endif
902   }
903  
904   /*
# Line 900 | Line 991 | uint32 call_macos7(uint32 tvect, uint32
991   }
992  
993   /*
903 *  Atomic operations
904 */
905
906 int atomic_add(int *var, int v)
907 {
908        int ret = *var;
909        *var += v;
910        return ret;
911 }
912
913 int atomic_and(int *var, int v)
914 {
915        int ret = *var;
916        *var &= v;
917        return ret;
918 }
919
920 int atomic_or(int *var, int v)
921 {
922        int ret = *var;
923        *var |= v;
924        return ret;
925 }
926
927 /*
994   *  Resource Manager thunks
995   */
996  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines