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

Comparing SheepShaver/src/Unix/main_unix.cpp (file contents):
Revision 1.3 by gbeauche, 2002-04-21T15:07:08Z vs.
Revision 1.13 by gbeauche, 2003-11-03T21:28:25Z

# Line 107 | Line 107
107   #include "macos_util.h"
108   #include "rom_patches.h"
109   #include "user_strings.h"
110 + #include "vm_alloc.h"
111 + #include "sigsegv.h"
112  
113   #define DEBUG 0
114   #include "debug.h"
# Line 143 | Line 145
145   const char ROM_FILE_NAME[] = "ROM";
146   const char ROM_FILE_NAME2[] = "Mac OS ROM";
147  
148 < const uint32 ROM_AREA_SIZE = 0x500000;          // Size of ROM area
147 < const uint32 ROM_END = ROM_BASE + ROM_SIZE;     // End of ROM
148 <
149 < const uint32 KERNEL_DATA_BASE = 0x68ffe000;     // Address of Kernel Data
150 < const uint32 KERNEL_DATA2_BASE = 0x5fffe000;    // Alternate address of Kernel Data
151 < const uint32 KERNEL_AREA_SIZE = 0x2000;         // Size of Kernel Data area
152 <
148 > const uint32 RAM_BASE = 0x20000000;                     // Base address of RAM
149   const uint32 SIG_STACK_SIZE = 0x10000;          // Size of signal stack
150  
151  
156 // 68k Emulator Data
157 struct EmulatorData {
158        uint32  v[0x400];      
159 };
160
161
162 // Kernel Data
163 struct KernelData {
164        uint32  v[0x400];
165        EmulatorData ed;
166 };
167
168
152   #if !EMULATED_PPC
153   // Structure in which registers are saved in a signal handler;
154   // sigcontext->regs points to it
# Line 189 | Line 172 | void *TOC;                             // Small data pointer (r13
172   #endif
173   uint32 RAMBase;                 // Base address of Mac RAM
174   uint32 RAMSize;                 // Size of Mac RAM
175 + uint32 SheepStack1Base; // SheepShaver first alternate stack base
176 + uint32 SheepStack2Base; // SheepShaver second alternate stack base
177 + uint32 SheepThunksBase; // SheepShaver thunks base
178   uint32 KernelDataAddr;  // Address of Kernel Data
179   uint32 BootGlobsAddr;   // Address of BootGlobs structure at top of Mac RAM
180   uint32 PVR;                             // Theoretical PVR
# Line 197 | Line 183 | int64 BusClockSpeed;   // Bus clock speed
183  
184  
185   // Global variables
186 < static char *x_display_name = NULL;                     // X11 display name
186 > char *x_display_name = NULL;                            // X11 display name
187   Display *x_display = NULL;                                      // X11 display handle
188  
189   static int zero_fd = 0;                                         // FD of /dev/zero
190 + static bool sheep_area_mapped = false;          // Flag: SheepShaver data area mmap()ed
191   static bool lm_area_mapped = false;                     // Flag: Low Memory area mmap()ped
192   static int kernel_area = -1;                            // SHM ID of Kernel Data area
193   static bool rom_area_mapped = false;            // Flag: Mac ROM mmap()ped
194   static bool ram_area_mapped = false;            // Flag: Mac RAM mmap()ped
208 static void *mmap_RAMBase = NULL;                       // Base address of mmap()ed RAM area
195   static KernelData *kernel_data;                         // Pointer to Kernel Data
196   static EmulatorData *emulator_data;
197  
# Line 220 | Line 206 | static pthread_t emul_thread;                          // MacO
206   static bool ready_for_signals = false;          // Handler installed, signals can be sent
207   static int64 num_segv = 0;                                      // Number of handled SEGV signals
208  
223 #if !EMULATED_PPC
209   static struct sigaction sigusr2_action;         // Interrupt signal (of emulator thread)
210 + #if !EMULATED_PPC
211   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
212   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
213   static void *sig_stack = NULL;                          // Stack for signal handlers
# Line 236 | Line 222 | static void Quit(void);
222   static void *emul_func(void *arg);
223   static void *nvram_func(void *arg);
224   static void *tick_func(void *arg);
225 < #if !EMULATED_PPC
225 > #if EMULATED_PPC
226 > static void sigusr2_handler(int sig);
227 > extern void emul_ppc(uint32 start);
228 > extern void init_emul_ppc(void);
229 > extern void exit_emul_ppc(void);
230 > #else
231   static void sigusr2_handler(int sig, sigcontext_struct *sc);
232   static void sigsegv_handler(int sig, sigcontext_struct *sc);
233   static void sigill_handler(int sig, sigcontext_struct *sc);
# Line 244 | Line 235 | static void sigill_handler(int sig, sigc
235  
236  
237   // From asm_linux.S
238 < #if EMULATED_PPC
248 < extern int atomic_add(int *var, int v);
249 < extern int atomic_and(int *var, int v);
250 < extern int atomic_or(int *var, int v);
251 < #else
238 > #if !EMULATED_PPC
239   extern "C" void *get_toc(void);
240   extern "C" void *get_sp(void);
241   extern "C" void flush_icache_range(void *start, void *end);
# Line 263 | Line 250 | extern void paranoia_check(void);
250   #endif
251  
252  
253 + #if EMULATED_PPC
254 + /*
255 + *  Atomic operations
256 + */
257 +
258 + #if HAVE_SPINLOCKS
259 + static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED;
260 + #else
261 + #define spin_lock(LOCK)
262 + #define spin_unlock(LOCK)
263 + #endif
264 +
265 + int atomic_add(int *var, int v)
266 + {
267 +        spin_lock(&atomic_ops_lock);
268 +        int ret = *var;
269 +        *var += v;
270 +        spin_unlock(&atomic_ops_lock);
271 +        return ret;
272 + }
273 +
274 + int atomic_and(int *var, int v)
275 + {
276 +        spin_lock(&atomic_ops_lock);
277 +        int ret = *var;
278 +        *var &= v;
279 +        spin_unlock(&atomic_ops_lock);
280 +        return ret;
281 + }
282 +
283 + int atomic_or(int *var, int v)
284 + {
285 +        spin_lock(&atomic_ops_lock);
286 +        int ret = *var;
287 +        *var |= v;
288 +        spin_unlock(&atomic_ops_lock);
289 +        return ret;
290 + }
291 + #endif
292 +
293 +
294   /*
295   *  Main program
296   */
# Line 281 | Line 309 | int main(int argc, char **argv)
309          char str[256];
310          uint32 *boot_globs;
311          int16 i16;
284        int drive, driver;
312          int rom_fd;
313          FILE *proc_file;
314          const char *rom_path;
# Line 291 | Line 318 | int main(int argc, char **argv)
318  
319          // Initialize variables
320          RAMBase = 0;
294        mmap_RAMBase = NULL;
321          tzset();
322  
323          // Print some info
# Line 420 | Line 446 | int main(int argc, char **argv)
446          }
447  
448          // Create Low Memory area (0x0000..0x3000)
449 <        if (mmap((char *)0x0000, 0x3000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
449 >        if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
450                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
451                  ErrorAlert(str);
452                  goto quit;
# Line 449 | Line 475 | int main(int argc, char **argv)
475          KernelDataAddr = (uint32)kernel_data;
476          D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
477  
478 +        // Create area for SheepShaver data
479 +        if (vm_acquire_fixed((char *)SHEEP_BASE, SHEEP_SIZE) < 0) {
480 +                sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
481 +                ErrorAlert(str);
482 +                goto quit;
483 +        }
484 +        SheepStack1Base = SHEEP_BASE + 0x10000;
485 +        SheepStack2Base = SheepStack1Base + 0x10000;
486 +        SheepThunksBase = SheepStack2Base + 0x1000;
487 +        sheep_area_mapped = true;
488 +
489          // Create area for Mac ROM
490 <        if (mmap((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
490 >        if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
491                  sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
492                  ErrorAlert(str);
493                  goto quit;
494          }
495 + #if !EMULATED_PPC || defined(__powerpc__)
496 +        if (vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
497 +                sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
498 +                ErrorAlert(str);
499 +                goto quit;
500 +        }
501 + #endif
502          rom_area_mapped = true;
503          D(bug("ROM area at %08x\n", ROM_BASE));
504  
# Line 465 | Line 509 | int main(int argc, char **argv)
509                  RAMSize = 8*1024*1024;
510          }
511  
512 <        mmap_RAMBase = mmap((void *)0x20000000, RAMSize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0);
469 <        if (mmap_RAMBase == (void *)-1) {
512 >        if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) {
513                  sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
514                  ErrorAlert(str);
515                  goto quit;
516          }
517 <        RAMBase = (uint32)mmap_RAMBase;
517 > #if !EMULATED_PPC
518 >        if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
519 >                sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
520 >                ErrorAlert(str);
521 >                goto quit;
522 >        }
523 > #endif
524 >        RAMBase = RAM_BASE;
525          ram_area_mapped = true;
526          D(bug("RAM area at %08x\n", RAMBase));
527  
# Line 513 | Line 563 | int main(int argc, char **argv)
563          XPRAMInit();
564  
565          // Set boot volume
566 <        drive = PrefsFindInt32("bootdrive");
566 >        i16 = PrefsFindInt32("bootdrive");
567          XPRAM[0x1378] = i16 >> 8;
568          XPRAM[0x1379] = i16 & 0xff;
569 <        driver = PrefsFindInt32("bootdriver");
569 >        i16 = PrefsFindInt32("bootdriver");
570          XPRAM[0x137a] = i16 >> 8;
571          XPRAM[0x137b] = i16 & 0xff;
572  
# Line 567 | Line 617 | int main(int argc, char **argv)
617   #if !EMULATED_PPC
618          MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE);
619   #endif
620 <        mprotect((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ);
620 >        vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
621  
622          // Initialize Kernel Data
623          memset(kernel_data, 0, sizeof(KernelData));
# Line 621 | Line 671 | int main(int argc, char **argv)
671          WriteMacInt32(XLM_PVR, PVR);                                                                    // Theoretical PVR
672          WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed);                                    // For DriverServicesLib patch
673          WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN);                // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
674 < #if !EMULATED_PPC
674 > #if EMULATED_PPC
675 >        WriteMacInt32(XLM_ETHER_INIT, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_INIT));
676 >        WriteMacInt32(XLM_ETHER_TERM, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_TERM));
677 >        WriteMacInt32(XLM_ETHER_OPEN, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_OPEN));
678 >        WriteMacInt32(XLM_ETHER_CLOSE, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_CLOSE));
679 >        WriteMacInt32(XLM_ETHER_WPUT, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_WPUT));
680 >        WriteMacInt32(XLM_ETHER_RSRV, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_RSRV));
681 >        WriteMacInt32(XLM_VIDEO_DOIO, POWERPC_NATIVE_OP_FUNC(NATIVE_VIDEO_DO_DRIVER_IO));
682 > #else
683          WriteMacInt32(XLM_TOC, (uint32)TOC);                                                    // TOC pointer of emulator
684          WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule);                // DLPI ethernet driver functions
685          WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule);
# Line 691 | Line 749 | int main(int argc, char **argv)
749                  ErrorAlert(str);
750                  goto quit;
751          }
752 + #endif
753  
754          // Install interrupt signal handler
755          sigemptyset(&sigusr2_action.sa_mask);
756          sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
757 +        sigusr2_action.sa_flags = 0;
758 + #if !EMULATED_PPC
759          sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
760 + #endif
761          sigusr2_action.sa_restorer = NULL;
762          if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
763                  sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
764                  ErrorAlert(str);
765                  goto quit;
766          }
705 #endif
767  
768          // Get my thread ID and execute MacOS thread function
769          emul_thread = pthread_self();
# Line 721 | Line 782 | quit:
782  
783   static void Quit(void)
784   {
785 + #if EMULATED_PPC
786 +        // Exit PowerPC emulation
787 +        exit_emul_ppc();
788 + #endif
789 +
790          // Stop 60Hz thread
791          if (tick_thread_active) {
792                  pthread_cancel(tick_thread);
# Line 779 | Line 845 | static void Quit(void)
845  
846          // Delete RAM area
847          if (ram_area_mapped)
848 <                munmap(mmap_RAMBase, RAMSize);
848 >                vm_release((char *)RAM_BASE, RAMSize);
849  
850          // Delete ROM area
851          if (rom_area_mapped)
852 <                munmap((char *)ROM_BASE, ROM_AREA_SIZE);
852 >                vm_release((char *)ROM_BASE, ROM_AREA_SIZE);
853  
854          // Delete Kernel Data area
855          if (kernel_area >= 0) {
# Line 824 | Line 890 | static void Quit(void)
890   */
891  
892   #if EMULATED_PPC
827 extern void emul_ppc(uint32 start);
828 extern void init_emul_ppc(void);
893   void jump_to_rom(uint32 entry)
894   {
895          init_emul_ppc();
# Line 890 | Line 954 | void Execute68kTrap(uint16 trap, M68kReg
954          uint16 proc[2] = {trap, M68K_RTS};
955          Execute68k((uint32)proc, r);
956   }
893 #endif
957  
958  
959   /*
# Line 904 | Line 967 | void ExecutePPC(void (*func)())
967          M68kRegisters r;
968          Execute68k((uint32)&desc, &r);
969   }
970 + #endif
971  
972  
973   /*
# Line 965 | Line 1029 | void Dump68kRegs(M68kRegisters *r)
1029  
1030   void MakeExecutable(int dummy, void *start, uint32 length)
1031   {
1032 < #if !EMULATED_PPC
969 <        if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE)))
1032 >        if (((uintptr)start >= ROM_BASE) && ((uintptr)start < (ROM_BASE + ROM_SIZE)))
1033                  return;
1034 <        flush_icache_range(start, (void *)((uint32)start + length));
1034 > #if EMULATED_PPC
1035 >        FlushCodeCache((uintptr)start, (uintptr)start + length);
1036 > #else
1037 >        flush_icache_range(start, (void *)((uintptr)start + length));
1038   #endif
1039   }
1040  
# Line 979 | Line 1045 | void MakeExecutable(int dummy, void *sta
1045  
1046   void PatchAfterStartup(void)
1047   {
1048 + #if EMULATED_PPC
1049 +        ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL);
1050 + #else
1051          ExecutePPC(VideoInstallAccel);
1052 + #endif
1053          InstallExtFS();
1054   }
1055  
# Line 1090 | Line 1160 | void Set_pthread_attr(pthread_attr_t *at
1160   *  Mutexes
1161   */
1162  
1163 + #ifdef HAVE_PTHREADS
1164 +
1165 + struct B2_mutex {
1166 +        B2_mutex() {
1167 +            pthread_mutexattr_t attr;
1168 +            pthread_mutexattr_init(&attr);
1169 +            // Initialize the mutex for priority inheritance --
1170 +            // required for accurate timing.
1171 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
1172 +            pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1173 + #endif
1174 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
1175 +            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
1176 + #endif
1177 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
1178 +            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
1179 + #endif
1180 +            pthread_mutex_init(&m, &attr);
1181 +            pthread_mutexattr_destroy(&attr);
1182 +        }
1183 +        ~B2_mutex() {
1184 +            pthread_mutex_trylock(&m); // Make sure it's locked before
1185 +            pthread_mutex_unlock(&m);  // unlocking it.
1186 +            pthread_mutex_destroy(&m);
1187 +        }
1188 +        pthread_mutex_t m;
1189 + };
1190 +
1191 + B2_mutex *B2_create_mutex(void)
1192 + {
1193 +        return new B2_mutex;
1194 + }
1195 +
1196 + void B2_lock_mutex(B2_mutex *mutex)
1197 + {
1198 +        pthread_mutex_lock(&mutex->m);
1199 + }
1200 +
1201 + void B2_unlock_mutex(B2_mutex *mutex)
1202 + {
1203 +        pthread_mutex_unlock(&mutex->m);
1204 + }
1205 +
1206 + void B2_delete_mutex(B2_mutex *mutex)
1207 + {
1208 +        delete mutex;
1209 + }
1210 +
1211 + #else
1212 +
1213   struct B2_mutex {
1214          int dummy;
1215   };
# Line 1112 | Line 1232 | void B2_delete_mutex(B2_mutex *mutex)
1232          delete mutex;
1233   }
1234  
1235 + #endif
1236 +
1237  
1238   /*
1239   *  Trigger signal USR2 from another thread
1240   */
1241  
1242 + #if !EMULATED_PPC || ASYNC_IRQ
1243   void TriggerInterrupt(void)
1244   {
1122 #if EMULATED_PPC
1123        WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1124 #else
1125 #if 0
1126        WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1127 #else
1245          if (ready_for_signals)
1246                  pthread_kill(emul_thread, SIGUSR2);
1130 #endif
1131 #endif
1247   }
1248 + #endif
1249  
1250  
1251   /*
# Line 1169 | Line 1285 | void EnableInterrupt(void)
1285   }
1286  
1287  
1172 #if !EMULATED_PPC
1288   /*
1289   *  USR2 handler
1290   */
1291  
1292 + #if EMULATED_PPC
1293 + static void sigusr2_handler(int sig)
1294 + {
1295 + #if ASYNC_IRQ
1296 +        extern void HandleInterrupt(void);
1297 +        HandleInterrupt();
1298 + #endif
1299 + }
1300 + #else
1301   static void sigusr2_handler(int sig, sigcontext_struct *sc)
1302   {
1303          pt_regs *r = sc->regs;
# Line 1255 | Line 1379 | static void sigusr2_handler(int sig, sig
1379                          }
1380                          break;
1381   #endif
1258
1382          }
1383   }
1384 + #endif
1385  
1386  
1387   /*
1388   *  SIGSEGV handler
1389   */
1390  
1391 + #if !EMULATED_PPC
1392   static void sigsegv_handler(int sig, sigcontext_struct *sc)
1393   {
1394          pt_regs *r = sc->regs;
1395 +
1396 +        // Get effective address
1397 +        uint32 addr = r->dar;
1398 +        
1399 + #if ENABLE_VOSF
1400 +        // Handle screen fault.
1401 +        extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
1402 +        if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->nip))
1403 +                return;
1404 + #endif
1405 +
1406          num_segv++;
1407  
1408          // Fault in Mac ROM or RAM?
1409          bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
1410          if (mac_fault) {
1411  
1276                // Get opcode and divide into fields
1277                uint32 opcode = *((uint32 *)r->nip);
1278                uint32 primop = opcode >> 26;
1279                uint32 exop = (opcode >> 1) & 0x3ff;
1280                uint32 ra = (opcode >> 16) & 0x1f;
1281                uint32 rb = (opcode >> 11) & 0x1f;
1282                uint32 rd = (opcode >> 21) & 0x1f;
1283                int32 imm = (int16)(opcode & 0xffff);
1284
1412                  // "VM settings" during MacOS 8 installation
1413                  if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) {
1414                          r->nip += 4;
# Line 1309 | Line 1436 | static void sigsegv_handler(int sig, sig
1436                          return;
1437                  }
1438  
1439 +                // Get opcode and divide into fields
1440 +                uint32 opcode = *((uint32 *)r->nip);
1441 +                uint32 primop = opcode >> 26;
1442 +                uint32 exop = (opcode >> 1) & 0x3ff;
1443 +                uint32 ra = (opcode >> 16) & 0x1f;
1444 +                uint32 rb = (opcode >> 11) & 0x1f;
1445 +                uint32 rd = (opcode >> 21) & 0x1f;
1446 +                int32 imm = (int16)(opcode & 0xffff);
1447 +
1448                  // Analyze opcode
1449                  enum {
1450                          TYPE_UNKNOWN,
# Line 1392 | Line 1528 | static void sigsegv_handler(int sig, sig
1528                                  transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1529                  }
1530          
1395                // Calculate effective address
1396                uint32 addr = 0;
1397                switch (addr_mode) {
1398                        case MODE_X:
1399                        case MODE_UX:
1400                                if (ra == 0)
1401                                        addr = r->gpr[rb];
1402                                else
1403                                        addr = r->gpr[ra] + r->gpr[rb];
1404                                break;
1405                        case MODE_NORM:
1406                        case MODE_U:
1407                                if (ra == 0)
1408                                        addr = (int32)(int16)imm;
1409                                else
1410                                        addr = r->gpr[ra] + (int32)(int16)imm;
1411                                break;
1412                        default:
1413                                break;
1414                }
1415
1531                  // Ignore ROM writes
1532                  if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
1533   //                      D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->nip));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines