1 //============================================================================
2 //
3 //   SSSS    tt          lll  lll
4 //  SS  SS   tt           ll   ll
5 //  SS     tttttt  eeee   ll   ll   aaaa
6 //   SSSS    tt   ee  ee  ll   ll      aa
7 //      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
8 //  SS  SS   tt   ee      ll   ll  aa  aa
9 //   SSSS     ttt  eeeee llll llll  aaaaa
10 //
11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //============================================================================
17 
18 //============================================================================
19 // This class provides Thumb emulation code ("Thumbulator")
20 //    by David Welch (dwelch@dwelch.com)
21 // Modified by Fred Quimby
22 // Code is public domain and used with the author's consent
23 //============================================================================
24 
25 #include "bspf.hxx"
26 #include "Base.hxx"
27 #include "Cart.hxx"
28 #include "Thumbulator.hxx"
29 using Common::Base;
30 
31 // Uncomment the following to enable specific functionality
32 // WARNING!!! This slows the runtime to a crawl
33 // #define THUMB_DISS
34 // #define THUMB_DBUG
35 
36 #if defined(THUMB_DISS)
37   #define DO_DISS(statement) statement
38 #else
39   #define DO_DISS(statement)
40 #endif
41 #if defined(THUMB_DBUG)
42   #define DO_DBUG(statement) statement
43 #else
44   #define DO_DBUG(statement)
45 #endif
46 
47 #ifdef __BIG_ENDIAN__
48   #define CONV_DATA(d)   (((d & 0xFFFF)>>8) | ((d & 0xffff)<<8)) & 0xffff
49   #define CONV_RAMROM(d) ((d>>8) | (d<<8)) & 0xffff
50 #else
51   #define CONV_DATA(d)   (d & 0xFFFF)
52   #define CONV_RAMROM(d) (d)
53 #endif
54 
55 #ifdef THUMB_CYCLE_COUNT
56   #define MERGE_I_S
57   #define INC_S_CYCLES(addr, accessType) \
58     if(_countCycles)                     \
59       incSCycles(addr, accessType)
60   #define INC_N_CYCLES(addr, accessType) \
61     if(_countCycles)                     \
62       incNCycles(addr, accessType)
63   #define INC_I_CYCLES                   \
64     if(_countCycles)                     \
65       incICycles()
66   #define INC_I_CYCLES_M(m)              \
67     if(_countCycles)                     \
68       incICycles(m)
69 
70   #define INC_SHIFT_CYCLES               \
71     INC_I_CYCLES                         \
72     //FETCH_TYPE(CycleType::S, AccessType::data)
73 
74   #define INC_LDR_CYCLES                 \
75     INC_N_CYCLES(rb, AccessType::data);  \
76     INC_I_CYCLES                         \
77     /*FETCH_TYPE(CycleType::N, AccessType::data); \
78       FETCH_TYPE_N;*/
79   #define INC_LDRB_CYCLES                       \
80     INC_N_CYCLES(rb & (~1U), AccessType::data); \
81     INC_I_CYCLES                                \
82     /*FETCH_TYPE(CycleType::N, AccessType::data); \
83       FETCH_TYPE_N;*/
84 
85   #define INC_STR_CYCLES                 \
86     INC_N_CYCLES(rb, AccessType::data);  \
87     FETCH_TYPE_N                         \
88     //INC_N_CYCLES(rb, AccessType::data);
89   #define INC_STRB_CYCLES                       \
90     INC_N_CYCLES(rb & (~1U), AccessType::data); \
91     FETCH_TYPE_N                                \
92     //INC_N_CYCLES(rb & (~1U), AccessType::data);
93 
94 #if 0 // unused for now
95   #define FETCH_TYPE(cycleType, accessType) \
96     _prefetchCycleType[_pipeIdx] = cycleType; \
97     _prefetchAccessType[_pipeIdx] = accessType
98 #endif
99   #define FETCH_TYPE_N                          \
100     _prefetchCycleType[_pipeIdx] = CycleType::N
101 
102   // ARM cycles
103   #define INC_ARM_CYCLES(m) \
104     _totalCycles += m
105 #else
106   #define INC_S_CYCLES(addr, accessType)
107   #define INC_N_CYCLES(addr, accessType)
108   #define INC_I_CYCLES
109   #define INC_I_CYCLES_M(m)
110 
111   #define INC_SHIFT_CYCLES
112 
113   #define INC_LDR_CYCLES
114   #define INC_LDRB_CYCLES
115 
116   #define INC_STR_CYCLES
117   #define INC_STRB_CYCLES
118 
119   #define FETCH_TYPE(cycleType, accessType)
120   #define FETCH_TYPE_N
121 
122   // ARM cycles
123   #define INC_ARM_CYCLES(m)
124 #endif
125 
126 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Thumbulator(const uInt16 * rom_ptr,uInt16 * ram_ptr,uInt32 rom_size,const uInt32 c_base,const uInt32 c_start,const uInt32 c_stack,bool traponfatal,double cyclefactor,Thumbulator::ConfigureFor configurefor,Cartridge * cartridge)127 Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
128                          const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,
129                          bool traponfatal, double cyclefactor,
130                          Thumbulator::ConfigureFor configurefor,
131                          Cartridge* cartridge)
132   : rom{rom_ptr},
133     romSize{rom_size},
134     cBase{c_base},
135     cStart{c_start},
136     cStack{c_stack},
137     decodedRom{make_unique<Op[]>(romSize / 2)},  // NOLINT
138     ram{ram_ptr},
139     configuration{configurefor},
140     myCartridge{cartridge}
141 {
142   for(uInt32 i = 0; i < romSize / 2; ++i)
143     decodedRom[i] = decodeInstructionWord(CONV_RAMROM(rom[i]));
144 
145   setConsoleTiming(ConsoleTiming::ntsc);
146 #ifndef UNSAFE_OPTIMIZATIONS
147   trapFatalErrors(traponfatal);
148 #endif
149 #ifdef DEBUGGER_SUPPORT
150   cycleFactor(cyclefactor);
151 #endif
152   reset();
153 }
154 
155 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
doRun(uInt32 & cycles,bool irqDrivenAudio)156 string Thumbulator::doRun(uInt32& cycles, bool irqDrivenAudio)
157 {
158   _irqDrivenAudio = irqDrivenAudio;
159   reset();
160   for(;;)
161   {
162     if(execute()) break;
163 #ifndef UNSAFE_OPTIMIZATIONS
164     if(_stats.instructions > 500000) // way more than would otherwise be possible
165       throw runtime_error("instructions > 500000");
166 #endif
167   }
168 #ifdef THUMB_CYCLE_COUNT
169   _totalCycles *= _armCyclesFactor;
170 
171   // assuming 10% per scanline is spend for audio updates
172   // (equals 5 cycles 6507 code + ~130-155 cycles ARM code)
173   if(_irqDrivenAudio)
174     _totalCycles *= 1.10;
175 
176   //_totalCycles = 127148; // VB during Turbo start sequence
177   cycles = _totalCycles / timing_factor;
178 #else
179   cycles = 0;
180 #endif
181 #if defined(THUMB_DISS) || defined(THUMB_DBUG)
182   dump_counters();
183   cout << statusMsg.str() << endl;
184   return statusMsg.str();
185 #else
186   return "";
187 #endif
188 }
189 
190 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setConsoleTiming(ConsoleTiming timing)191 void Thumbulator::setConsoleTiming(ConsoleTiming timing)
192 {
193   // this sets how many ticks of the Harmony/Melody clock
194   // will occur per tick of the 6507 clock
195   constexpr double NTSC   = 1.19318166666667;  // NTSC  6507 clock rate
196   constexpr double PAL    = 1.182298;          // PAL   6507 clock rate
197   constexpr double SECAM  = 1.187500;          // SECAM 6507 clock rate
198 
199   _consoleTiming = timing;
200   switch(timing)
201   {
202     case ConsoleTiming::ntsc:   timing_factor = _MHz / NTSC;   break;
203     case ConsoleTiming::pal:    timing_factor = _MHz / PAL;    break;
204     case ConsoleTiming::secam:  timing_factor = _MHz / SECAM;  break;
205     default:  break;  // satisfy compiler
206   }
207 }
208 
209 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
updateTimer(uInt32 cycles)210 void Thumbulator::updateTimer(uInt32 cycles)
211 {
212 #ifdef TIMER_0
213   if(T0TCR & 1) // bit 0 controls timer on/off
214   {
215     T0TC += static_cast<uInt32>(cycles * timing_factor);
216     tim0Total = 0;
217   }
218 #endif
219   if(T1TCR & 1) // bit 0 controls timer on/off
220   {
221     T1TC += static_cast<uInt32>(cycles * timing_factor);
222     tim1Total = 0;
223   }
224 }
225 
226 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
run(uInt32 & cycles,bool irqDrivenAudio)227 string Thumbulator::run(uInt32& cycles, bool irqDrivenAudio)
228 {
229   updateTimer(cycles);
230   return doRun(cycles, irqDrivenAudio);
231 }
232 
233 #ifndef UNSAFE_OPTIMIZATIONS
234 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fatalError(const char * opcode,uInt32 v1,const char * msg)235 inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, const char* msg)
236 {
237   statusMsg << "Thumb ARM emulation fatal error: " << endl
238             << opcode << "(" << Base::HEX8 << v1 << "), " << msg << endl;
239   dump_regs();
240   if(trapOnFatal)
241     throw runtime_error(statusMsg.str());
242   return 0;
243 }
244 
245 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fatalError(const char * opcode,uInt32 v1,uInt32 v2,const char * msg)246 inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, uInt32 v2,
247                                    const char* msg)
248 {
249   statusMsg << "Thumb ARM emulation fatal error: " << endl
250             << opcode << "(" << Base::HEX8 << v1 << "," << v2 << "), " << msg << endl;
251   dump_regs();
252   if(trapOnFatal)
253     throw runtime_error(statusMsg.str());
254   return 0;
255 }
256 
257 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dump_counters()258 void Thumbulator::dump_counters()
259 {
260   cout << endl << endl
261        << "instructions " << _stats.instructions << endl;
262 #ifdef THUMB_STATS
263   cout << "reads        " << _stats.reads << endl
264        << "writes       " << _stats.writes << endl
265        << "memcycles    " << (_stats.instructions + _stats.reads + _stats.writes) << endl;
266 #endif
267 }
268 
269 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dump_regs()270 void Thumbulator::dump_regs()
271 {
272   for (int cnt = 0; cnt <= 12; cnt++)
273   {
274     statusMsg << "R" << std::dec << std::setfill(' ') << std::setw(2) << std::left << cnt
275       << "= " << Base::HEX8 << reg_norm[cnt];
276     if((cnt + 1) % 4 == 0)
277       statusMsg << endl;
278     else
279       statusMsg << "  ";
280   }
281   statusMsg << endl
282             << "SP = " << Base::HEX8 << reg_norm[13] << "  "
283             << "LR = " << Base::HEX8 << reg_norm[14] << "  "
284             << "PC = " << Base::HEX8 << reg_norm[15] << endl;
285 }
286 #endif
287 
288 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fetch16(uInt32 addr)289 uInt32 Thumbulator::fetch16(uInt32 addr)
290 {
291 #ifndef UNSAFE_OPTIMIZATIONS
292   uInt32 data;
293 
294 #ifdef THUMB_CYCLE_COUNT
295   _pipeIdx = (_pipeIdx+1) % 3;
296 
297 #ifdef MERGE_I_S
298   if(_lastCycleType[2] == CycleType::I)
299   //if(_lastCycleType[_pipeIdx] == CycleType::I)
300     --_totalCycles;
301 #endif
302 
303   if(_prefetchCycleType[_pipeIdx] == CycleType::S)
304   {
305   //#ifdef MERGE_I_S
306   //  //if(_lastCycleType[2] == CycleType::I)
307   //  if(_lastCycleType[_pipeIdx] == CycleType::I)
308   //  {
309   //    --_totalCycles;
310   //    INC_S_CYCLES(addr, AccessType::prefetch); // N?
311   //  }
312   //  else
313   //#endif
314       INC_S_CYCLES(addr, AccessType::prefetch);
315       //INC_S_CYCLES(addr, _prefetchAccessType[_pipeIdx]);
316   }
317   else
318   {
319     INC_N_CYCLES(addr, AccessType::prefetch); // or ::data ?
320     //INC_N_CYCLES(addr, _prefetchAccessType[_pipeIdx]);
321   }
322   _prefetchCycleType[_pipeIdx] = CycleType::S; // default
323   //_prefetchAccessType[_pipeIdx] = AccessType::prefetch; // default
324 #endif
325 
326   switch(addr & 0xF0000000)
327   {
328     case 0x00000000: //ROM
329       addr &= ROMADDMASK;
330       if(addr < 0x50)
331         fatalError("fetch16", addr, "abort");
332       addr >>= 1;
333       data = CONV_RAMROM(rom[addr]);
334       DO_DBUG(statusMsg << "fetch16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
335       return data;
336 
337     case 0x40000000: //RAM
338       addr &= RAMADDMASK;
339       addr >>= 1;
340       data = CONV_RAMROM(ram[addr]);
341       DO_DBUG(statusMsg << "fetch16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
342       return data;
343   }
344   return fatalError("fetch16", addr, "abort");
345 #else
346   addr &= ROMADDMASK;
347   addr >>= 1;
348   return CONV_RAMROM(rom[addr]);
349 #endif
350 }
351 
352 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
write16(uInt32 addr,uInt32 data)353 void Thumbulator::write16(uInt32 addr, uInt32 data)
354 {
355 #ifndef UNSAFE_OPTIMIZATIONS
356   if((addr > 0x40007fff) && (addr < 0x50000000))
357     fatalError("write16", addr, "abort - out of range");
358 
359   if (isProtected(addr)) fatalError("write16", addr, "to driver area");
360 
361   if(addr & 1)
362     fatalError("write16", addr, "abort - misaligned");
363 #endif
364 #ifdef THUMB_STATS
365   ++_stats.writes;
366 #endif
367 
368   DO_DBUG(statusMsg << "write16(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl);
369 
370   switch(addr & 0xF0000000)
371   {
372     case 0x40000000: //RAM
373       addr &= RAMADDMASK;
374       addr >>= 1;
375       ram[addr] = CONV_DATA(data);
376       return;
377 
378 #ifndef UNSAFE_OPTIMIZATIONS
379     case 0xE0000000: //MAMCR
380 #else
381     default:
382 #endif
383       if(addr == 0xE01FC000)
384       {
385         DO_DBUG(statusMsg << "write16(" << Base::HEX8 << "MAMCR" << "," << Base::HEX8 << data << ") *" << endl);
386         if(!_lockMamcr)
387           mamcr = static_cast<MamModeType>(data);
388         return;
389       }
390   }
391 #ifndef UNSAFE_OPTIMIZATIONS
392   fatalError("write16", addr, data, "abort");
393 #endif
394 }
395 
396 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
write32(uInt32 addr,uInt32 data)397 void Thumbulator::write32(uInt32 addr, uInt32 data)
398 {
399 #ifndef UNSAFE_OPTIMIZATIONS
400   if(addr & 3)
401     fatalError("write32", addr, "abort - misaligned");
402 
403   if (isProtected(addr)) fatalError("write32", addr, "to driver area");
404 #endif
405   DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl);
406 
407   switch(addr & 0xF0000000)
408   {
409 #ifndef UNSAFE_OPTIMIZATIONS
410     case 0xF0000000: //halt
411       dump_counters();
412       throw runtime_error("HALT");
413 #endif
414 
415     case 0xE0000000: //periph
416       switch(addr)
417       {
418 #ifndef UNSAFE_OPTIMIZATIONS
419         case 0xE0000000:
420           DO_DISS(statusMsg << "uart: [" << char(data&0xFF) << "]" << endl);
421           break;
422 #endif
423 #ifdef TIMER_0
424         case 0xE0004004:  // T0TCR - Timer 0 Control Register
425         #ifdef THUMB_CYCLE_COUNT
426           if((T0TCR ^ data) & 1)
427           {
428             // timer changed counter state
429             if(data & 1)
430               // timer switched to counting
431               tim0Start = _totalCycles;
432             else
433               // timer switched to disabled
434               tim0Total += _totalCycles - tim0Start;
435           }
436         #endif
437           T0TCR = data;
438           break;
439 
440         case 0xE0004008:  // T0TC - Timer 0 Counter
441         #ifdef THUMB_CYCLE_COUNT
442           tim0Start = _totalCycles;
443           tim0Total = data / _armCyclesFactor;
444         #endif
445           T0TC = data;
446           break;
447 #endif
448         case 0xE0008004:  // T1TCR - Timer 1 Control Register
449         #ifdef THUMB_CYCLE_COUNT
450           if((T1TCR ^ data) & 1)
451           {
452             // timer changed counter state
453             if(data & 1)
454               // timer switched to counting
455               tim1Start = _totalCycles;
456             else
457               // timer switched to disabled
458               tim1Total += _totalCycles - tim1Start;
459           }
460         #endif
461           T1TCR = data;
462           break;
463 
464         case 0xE0008008:  // T1TC - Timer 1 Counter
465         #ifdef THUMB_CYCLE_COUNT
466           tim1Start = _totalCycles;
467           tim1Total = data / _armCyclesFactor;
468         #endif
469           T1TC = data;
470           break;
471 
472         case 0xE000E010:
473         {
474           uInt32 old = systick_ctrl;
475           systick_ctrl = data & 0x00010007;
476           if(((old & 1) == 0) && (systick_ctrl & 1))
477           {
478             // timer started, load count
479             systick_count = systick_reload;
480           }
481           break;
482         }
483 
484         case 0xE000E014:
485           systick_reload = data & 0x00FFFFFF;
486           break;
487 
488         case 0xE000E018:
489           systick_count = data & 0x00FFFFFF;
490           break;
491 
492         case 0xE000E01C:
493           systick_calibrate = data & 0x00FFFFFF;
494           break;
495 
496       #ifdef THUMB_CYCLE_COUNT
497         case 0xE01FC000: //MAMCR
498           DO_DBUG(statusMsg << "write32(" << Base::HEX8 << "MAMCR" << ","
499                   << Base::HEX8 << data << ") *" << endl);
500           if(!_lockMamcr)
501             mamcr = static_cast<MamModeType>(data);
502           break;
503       #endif
504 
505         default:
506           break;
507       }
508       return;
509 
510     case 0xD0000000: //debug
511 #ifndef UNSAFE_OPTIMIZATIONS
512       switch(addr & 0xFF)
513       {
514         case 0x00:
515           statusMsg << "[" << Base::HEX8 << read_register(14) << "]["
516                     << addr << "] " << data << endl;
517           return;
518 
519         case 0x10:
520           statusMsg << Base::HEX8 << data << endl;
521           return;
522 
523         case 0x20:
524           statusMsg << Base::HEX8 << data << endl;
525           return;
526 
527         default:
528           break;
529       }
530 #endif
531       return;
532 
533 #ifndef UNSAFE_OPTIMIZATIONS
534     case 0x40000000: //RAM
535 #else
536     default:
537 #endif
538       write16(addr+0, (data >>  0) & 0xFFFF);
539       write16(addr+2, (data >> 16) & 0xFFFF);
540       return;
541   }
542 #ifndef UNSAFE_OPTIMIZATIONS
543   fatalError("write32", addr, data, "abort");
544 #endif
545 }
546 
547 #ifndef UNSAFE_OPTIMIZATIONS
548 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
isProtected(uInt32 addr)549 bool Thumbulator::isProtected(uInt32 addr)
550 {
551   if (addr < 0x40000000) return false;
552   addr -= 0x40000000;
553 
554   switch (configuration) {
555     case ConfigureFor::DPCplus:
556       return (addr < 0x0c00) && (addr > 0x0028);
557 
558     case ConfigureFor::CDF:
559       return  (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x06e0) && (addr < (0x0e60 + 284)));
560 
561     case ConfigureFor::CDF1:
562       return  (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x00a0) && (addr < (0x00a0 + 284)));
563 
564     case ConfigureFor::CDFJ:
565     case ConfigureFor::CDFJplus:
566       return  (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292)));
567 
568     case ConfigureFor::BUS:
569       return  (addr < 0x06d8) && (addr > 0x0028);
570   }
571 
572   return false;
573 }
574 #endif
575 
576 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
read16(uInt32 addr)577 uInt32 Thumbulator::read16(uInt32 addr)
578 {
579   uInt32 data;
580 #ifndef UNSAFE_OPTIMIZATIONS
581   if((addr > 0x40007fff) && (addr < 0x50000000))
582     fatalError("read16", addr, "abort - out of range");
583   else if((addr > 0x0007ffff) && (addr < 0x10000000))
584     fatalError("read16", addr, "abort - out of range");
585   if(addr & 1)
586     fatalError("read16", addr, "abort - misaligned");
587 #endif
588 #ifdef THUMB_STATS
589   ++_stats.reads;
590 #endif
591 
592   switch(addr & 0xF0000000)
593   {
594     case 0x00000000: //ROM
595       addr &= ROMADDMASK;
596       addr >>= 1;
597       data = CONV_RAMROM(rom[addr]);
598       DO_DBUG(statusMsg << "read16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
599       return data;
600 
601     case 0x40000000: //RAM
602       addr &= RAMADDMASK;
603       addr >>= 1;
604       data = CONV_RAMROM(ram[addr]);
605       DO_DBUG(statusMsg << "read16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
606       return data;
607 
608     case 0xe0000000: //peripherals
609     #ifdef THUMB_CYCLE_COUNT
610       if(addr == 0xE01FC000) //MAMCR
611     #else
612     default:
613     #endif
614       {
615         DO_DBUG(statusMsg << "read32(" << "MAMCR" << addr << ")=" << mamcr << " *");
616         data = static_cast<uInt32>(mamcr);
617         return data;
618       }
619   }
620 #ifndef UNSAFE_OPTIMIZATIONS
621   return fatalError("read16", addr, "abort");
622 #endif
623 }
624 
625 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
read32(uInt32 addr)626 uInt32 Thumbulator::read32(uInt32 addr)
627 {
628 #ifndef UNSAFE_OPTIMIZATIONS
629   if(addr & 3)
630     fatalError("read32", addr, "abort - misaligned");
631 #endif
632 
633   uInt32 data;
634   switch(addr & 0xF0000000)
635   {
636     case 0x00000000: //ROM
637     case 0x40000000: //RAM
638       data = read16(addr+0);
639       data |= (uInt32(read16(addr+2))) << 16;
640       DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl);
641       return data;
642 
643 #ifndef UNSAFE_OPTIMIZATIONS
644     case 0xE0000000:
645 #else
646     default:
647 #endif
648     {
649       switch(addr)
650       {
651       #ifdef THUMB_CYCLE_COUNT
652         case 0xE01FC000: //MAMCR
653           DO_DBUG(statusMsg << "read32(" << "MAMCR" << addr << ")=" << mamcr << " *");
654           data = static_cast<uInt32>(mamcr);
655           return data;
656       #endif
657 
658       #ifdef TIMER_0
659         case 0xE0004004:  // T0TCR - Timer 0 Control Register
660           data = T0TCR;
661           return data;
662 
663         case 0xE0004008:  // T0TC - Timer 0 Counter
664         #ifdef THUMB_CYCLE_COUNT
665           if(T0TCR & 1)
666             // timer is counting
667             data = T0TC + (tim0Total + (_totalCycles - tim0Start)) * _armCyclesFactor;
668           else
669             // timer is disabled
670             data = T0TC + tim0Total * _armCyclesFactor;
671         #else
672           data = T0TC;
673         #endif
674           break;
675       #endif
676         case 0xE0008004:  // T1TCR - Timer 1 Control Register
677           data = T1TCR;
678           return data;
679 
680         case 0xE0008008:  // T1TC - Timer 1 Counter
681         #ifdef THUMB_CYCLE_COUNT
682           if(T1TCR & 1)
683             // timer is counting
684             data = T1TC + (tim1Total + (_totalCycles - tim1Start)) * _armCyclesFactor;
685           else
686             // timer is disabled
687             data = T1TC + tim1Total * _armCyclesFactor;
688         #else
689           data = T1TC;
690         #endif
691           return data;
692 
693         case 0xE000E010:
694           data = systick_ctrl;
695           systick_ctrl &= (~0x00010000);
696           return data;
697 
698         case 0xE000E014:
699           data = systick_reload;
700           return data;
701 
702         case 0xE000E018:
703           data = systick_count;
704           return data;
705 
706 #ifndef UNSAFE_OPTIMIZATIONS
707         case 0xE000E01C:
708 #else
709         default:
710 #endif
711           data = systick_calibrate;
712           return data;
713       }
714     }
715   }
716 #ifndef UNSAFE_OPTIMIZATIONS
717   return fatalError("read32", addr, "abort");
718 #endif
719 }
720 
721 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
read_register(uInt32 reg)722 uInt32 Thumbulator::read_register(uInt32 reg)
723 {
724   reg &= 0xF;
725 
726   uInt32 data = reg_norm[reg];
727   DO_DBUG(statusMsg << "read_register(" << dec << reg << ")=" << Base::HEX8 << data << endl);
728 #ifndef UNSAFE_OPTIMIZATIONS
729   if(reg == 15)
730   {
731     if(data & 1)
732     {
733       DO_DBUG(statusMsg << "pc has lsbit set 0x" << Base::HEX8 << data << endl);
734     }
735     data &= ~1;
736   }
737 #endif
738   return data;
739 }
740 
741 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
write_register(uInt32 reg,uInt32 data,bool isFlowBreak)742 void Thumbulator::write_register(uInt32 reg, uInt32 data, bool isFlowBreak)
743 {
744   reg &= 0xF;
745 
746   DO_DBUG(statusMsg << "write_register(" << dec << reg << "," << Base::HEX8 << data << ")" << endl);
747 //#ifndef UNSAFE_OPTIMIZATIONS // this fails when combined with read_register UNSAFE_OPTIMIZATIONS
748   if(reg == 15)
749   {
750     data &= ~1;
751     if(isFlowBreak)
752     {
753     #ifdef THUMB_STATS
754       ++_stats.taken;
755     #endif
756       // dummy fetch + fill the pipeline
757       //INC_N_CYCLES(reg_norm[15] - 2, AccessType::prefetch);
758       //INC_S_CYCLES(data - 2, AccessType::branch);
759       INC_N_CYCLES(reg_norm[15] + 4, AccessType::prefetch);
760       INC_S_CYCLES(data, AccessType::branch);
761     }
762   }
763 //#endif
764   reg_norm[reg] = data;
765 }
766 
767 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
do_zflag(uInt32 x)768 void Thumbulator::do_zflag(uInt32 x)
769 {
770   if(x == 0) cpsr |= CPSR_Z;  else cpsr &= ~CPSR_Z;
771 }
772 
773 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
do_nflag(uInt32 x)774 void Thumbulator::do_nflag(uInt32 x)
775 {
776   if(x & 0x80000000) cpsr |= CPSR_N;  else cpsr &= ~CPSR_N;
777 }
778 
779 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
do_cflag(uInt32 a,uInt32 b,uInt32 c)780 void Thumbulator::do_cflag(uInt32 a, uInt32 b, uInt32 c)
781 {
782   uInt32 rc;
783 
784   rc = (a & 0x7FFFFFFF) + (b & 0x7FFFFFFF) + c; //carry in
785   rc = (rc >> 31) + (a >> 31) + (b >> 31);      //carry out
786   if(rc & 2)
787     cpsr |= CPSR_C;
788   else
789     cpsr &= ~CPSR_C;
790 }
791 
792 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
do_vflag(uInt32 a,uInt32 b,uInt32 c)793 void Thumbulator::do_vflag(uInt32 a, uInt32 b, uInt32 c)
794 {
795   uInt32 rc, rd;
796 
797   rc = (a & 0x7FFFFFFF) + (b & 0x7FFFFFFF) + c; //carry in
798   rc >>= 31; //carry in in lsbit
799   rd = (rc & 1) + ((a >> 31) & 1) + ((b >> 31) & 1); //carry out
800   rd >>= 1; //carry out in lsbit
801   rc = (rc^rd) & 1; //if carry in != carry out then signed overflow
802   if(rc)
803     cpsr |= CPSR_V;
804   else
805     cpsr &= ~CPSR_V;
806 }
807 
808 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
do_cflag_bit(uInt32 x)809 void Thumbulator::do_cflag_bit(uInt32 x)
810 {
811   if(x) cpsr |= CPSR_C;  else cpsr &= ~CPSR_C;
812 }
813 
814 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
do_vflag_bit(uInt32 x)815 void Thumbulator::do_vflag_bit(uInt32 x)
816 {
817   if(x) cpsr |= CPSR_V;  else cpsr &= ~CPSR_V;
818 }
819 
820 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
decodeInstructionWord(uint16_t inst)821 Thumbulator::Op Thumbulator::decodeInstructionWord(uint16_t inst) {
822   //ADC add with carry
823   if((inst & 0xFFC0) == 0x4140) return Op::adc;
824 
825   //ADD(1) small immediate two registers
826   if((inst & 0xFE00) == 0x1C00 && (inst >> 6) & 0x7) return Op::add1;
827 
828   //ADD(2) big immediate one register
829   if((inst & 0xF800) == 0x3000) return Op::add2;
830 
831   //ADD(3) three registers
832   if((inst & 0xFE00) == 0x1800) return Op::add3;
833 
834   //ADD(4) two registers one or both high no flags
835   if((inst & 0xFF00) == 0x4400) return Op::add4;
836 
837   //ADD(5) rd = pc plus immediate
838   if((inst & 0xF800) == 0xA000) return Op::add5;
839 
840   //ADD(6) rd = sp plus immediate
841   if((inst & 0xF800) == 0xA800) return Op::add6;
842 
843   //ADD(7) sp plus immediate
844   if((inst & 0xFF80) == 0xB000) return Op::add7;
845 
846   //AND
847   if((inst & 0xFFC0) == 0x4000) return Op::and_;
848 
849   //ASR(1) two register immediate
850   if((inst & 0xF800) == 0x1000) return Op::asr1;
851 
852   //ASR(2) two register
853   if((inst & 0xFFC0) == 0x4100) return Op::asr2;
854 
855   //B(1) conditional branch
856   if((inst & 0xF000) == 0xD000) return Op::b1;
857 
858   //B(2) unconditional branch
859   if((inst & 0xF800) == 0xE000) return Op::b2;
860 
861   //BIC
862   if((inst & 0xFFC0) == 0x4380) return Op::bic;
863 
864   //BKPT
865   if((inst & 0xFF00) == 0xBE00) return Op::bkpt;
866 
867   //BL/BLX(1)
868   if((inst & 0xE000) == 0xE000) return Op::blx1;
869 
870   //BLX(2)
871   if((inst & 0xFF87) == 0x4780) return Op::blx2;
872 
873   //BX
874   if((inst & 0xFF87) == 0x4700) return Op::bx;
875 
876   //CMN
877   if((inst & 0xFFC0) == 0x42C0) return Op::cmn;
878 
879   //CMP(1) compare immediate
880   if((inst & 0xF800) == 0x2800) return Op::cmp1;
881 
882   //CMP(2) compare register
883   if((inst & 0xFFC0) == 0x4280) return Op::cmp2;
884 
885   //CMP(3) compare high register
886   if((inst & 0xFF00) == 0x4500) return Op::cmp3;
887 
888   //CPS
889   if((inst & 0xFFE8) == 0xB660) return Op::cps;
890 
891   //CPY copy high register
892   if((inst & 0xFFC0) == 0x4600) return Op::cpy;
893 
894   //EOR
895   if((inst & 0xFFC0) == 0x4040) return Op::eor;
896 
897   //LDMIA
898   if((inst & 0xF800) == 0xC800) return Op::ldmia;
899 
900   //LDR(1) two register immediate
901   if((inst & 0xF800) == 0x6800) return Op::ldr1;
902 
903   //LDR(2) three register
904   if((inst & 0xFE00) == 0x5800) return Op::ldr2;
905 
906   //LDR(3)
907   if((inst & 0xF800) == 0x4800) return Op::ldr3;
908 
909   //LDR(4)
910   if((inst & 0xF800) == 0x9800) return Op::ldr4;
911 
912   //LDRB(1)
913   if((inst & 0xF800) == 0x7800) return Op::ldrb1;
914 
915   //LDRB(2)
916   if((inst & 0xFE00) == 0x5C00) return Op::ldrb2;
917 
918   //LDRH(1)
919   if((inst & 0xF800) == 0x8800) return Op::ldrh1;
920 
921   //LDRH(2)
922   if((inst & 0xFE00) == 0x5A00) return Op::ldrh2;
923 
924   //LDRSB
925   if((inst & 0xFE00) == 0x5600) return Op::ldrsb;
926 
927   //LDRSH
928   if((inst & 0xFE00) == 0x5E00) return Op::ldrsh;
929 
930   //LSL(1)
931   if((inst & 0xF800) == 0x0000) return Op::lsl1;
932 
933   //LSL(2) two register
934   if((inst & 0xFFC0) == 0x4080) return Op::lsl2;
935 
936   //LSR(1) two register immediate
937   if((inst & 0xF800) == 0x0800) return Op::lsr1;
938 
939   //LSR(2) two register
940   if((inst & 0xFFC0) == 0x40C0) return Op::lsr2;
941 
942   //MOV(1) immediate
943   if((inst & 0xF800) == 0x2000) return Op::mov1;
944 
945   //MOV(2) two low registers
946   if((inst & 0xFFC0) == 0x1C00) return Op::mov2;
947 
948   //MOV(3)
949   if((inst & 0xFF00) == 0x4600) return Op::mov3;
950 
951   //MUL
952   if((inst & 0xFFC0) == 0x4340) return Op::mul;
953 
954   //MVN
955   if((inst & 0xFFC0) == 0x43C0) return Op::mvn;
956 
957   //NEG
958   if((inst & 0xFFC0) == 0x4240) return Op::neg;
959 
960   //ORR
961   if((inst & 0xFFC0) == 0x4300) return Op::orr;
962 
963   //POP
964   if((inst & 0xFE00) == 0xBC00) return Op::pop;
965 
966   //PUSH
967   if((inst & 0xFE00) == 0xB400) return Op::push;
968 
969   //REV
970   if((inst & 0xFFC0) == 0xBA00) return Op::rev;
971 
972   //REV16
973   if((inst & 0xFFC0) == 0xBA40) return Op::rev16;
974 
975   //REVSH
976   if((inst & 0xFFC0) == 0xBAC0) return Op::revsh;
977 
978   //ROR
979   if((inst & 0xFFC0) == 0x41C0) return Op::ror;
980 
981   //SBC
982   if((inst & 0xFFC0) == 0x4180) return Op::sbc;
983 
984   //SETEND
985   if((inst & 0xFFF7) == 0xB650) return Op::setend;
986 
987   //STMIA
988   if((inst & 0xF800) == 0xC000) return Op::stmia;
989 
990   //STR(1)
991   if((inst & 0xF800) == 0x6000) return Op::str1;
992 
993   //STR(2)
994   if((inst & 0xFE00) == 0x5000) return Op::str2;
995 
996   //STR(3)
997   if((inst & 0xF800) == 0x9000) return Op::str3;
998 
999   //STRB(1)
1000   if((inst & 0xF800) == 0x7000) return Op::strb1;
1001 
1002   //STRB(2)
1003   if((inst & 0xFE00) == 0x5400) return Op::strb2;
1004 
1005   //STRH(1)
1006   if((inst & 0xF800) == 0x8000) return Op::strh1;
1007 
1008   //STRH(2)
1009   if((inst & 0xFE00) == 0x5200) return Op::strh2;
1010 
1011   //SUB(1)
1012   if((inst & 0xFE00) == 0x1E00) return Op::sub1;
1013 
1014   //SUB(2)
1015   if((inst & 0xF800) == 0x3800) return Op::sub2;
1016 
1017   //SUB(3)
1018   if((inst & 0xFE00) == 0x1A00) return Op::sub3;
1019 
1020   //SUB(4)
1021   if((inst & 0xFF80) == 0xB080) return Op::sub4;
1022 
1023   //SWI SoftWare Interupt
1024   if((inst & 0xFF00) == 0xDF00) return Op::swi;
1025 
1026   //SXTB
1027   if((inst & 0xFFC0) == 0xB240) return Op::sxtb;
1028 
1029   //SXTH
1030   if((inst & 0xFFC0) == 0xB200) return Op::sxth;
1031 
1032   //TST
1033   if((inst & 0xFFC0) == 0x4200) return Op::tst;
1034 
1035   //UXTB
1036   if((inst & 0xFFC0) == 0xB2C0) return Op::uxtb;
1037 
1038   //UXTH Zero extend Halfword
1039   if((inst & 0xFFC0) == 0xB280) return Op::uxth;
1040 
1041   return Op::invalid;
1042 }
1043 
1044 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
execute()1045 int Thumbulator::execute()
1046 {
1047   uInt32 pc, sp, inst, ra, rb, rc, rm, rd, rn, rs, op;
1048 
1049   pc = read_register(15);
1050 
1051   uInt32 instructionPtr = pc - 2;
1052   inst = fetch16(instructionPtr);
1053 
1054   pc += 2;
1055   write_register(15, pc, false);
1056   DO_DISS(statusMsg << Base::HEX8 << (pc-5) << ": " << Base::HEX4 << inst << " ");
1057 
1058 #ifndef UNSAFE_OPTIMIZATIONS
1059   ++_stats.instructions;
1060 #endif
1061 
1062   Op decodedOp;
1063 #ifndef UNSAFE_OPTIMIZATIONS
1064   if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize)
1065     decodedOp = decodedRom[instructionPtr >> 1];
1066   else
1067     decodedOp = decodeInstructionWord(inst);
1068 #else
1069   decodedOp = decodedRom[(instructionPtr & ROMADDMASK) >> 1];
1070 #endif
1071 
1072 #ifdef COUNT_OPS
1073   ++opCount[int(decodedOp)];
1074 #endif
1075   switch (decodedOp) {
1076     //ADC
1077     case Op::adc: {
1078       rd = (inst >> 0) & 0x07;
1079       rm = (inst >> 3) & 0x07;
1080       DO_DISS(statusMsg << "adc r" << dec << rd << ",r" << dec << rm << endl);
1081       ra = read_register(rd);
1082       rb = read_register(rm);
1083       rc = ra + rb;
1084       if(cpsr & CPSR_C)
1085         ++rc;
1086       write_register(rd, rc);
1087       do_nflag(rc);
1088       do_zflag(rc);
1089       if(cpsr & CPSR_C) { do_cflag(ra, rb, 1); do_vflag(ra, rb, 1); }
1090       else              { do_cflag(ra, rb, 0); do_vflag(ra, rb, 0); }
1091       return 0;
1092     }
1093 
1094     //ADD(1) small immediate two registers
1095     case Op::add1: {
1096       rd = (inst >> 0) & 0x7;
1097       rn = (inst >> 3) & 0x7;
1098       rb = (inst >> 6) & 0x7;
1099       if(rb)
1100       {
1101         DO_DISS(statusMsg << "adds r" << dec << rd << ",r" << dec << rn << ","
1102                           << "#0x" << Base::HEX2 << rb << endl);
1103         ra = read_register(rn);
1104         rc = ra + rb;
1105         //fprintf(stderr,"0x%08X = 0x%08X + 0x%08X\n",rc,ra,rb);
1106         write_register(rd, rc);
1107         do_nflag(rc);
1108         do_zflag(rc);
1109         do_cflag(ra, rb, 0);
1110         do_vflag(ra, rb, 0);
1111         return 0;
1112       }
1113       else
1114       {
1115         //this is a mov
1116       }
1117       break;
1118     }
1119 
1120     //ADD(2) big immediate one register
1121     case Op::add2: {
1122       rb = (inst >> 0) & 0xFF;
1123       rd = (inst >> 8) & 0x7;
1124       DO_DISS(statusMsg << "adds r" << dec << rd << ",#0x" << Base::HEX2 << rb << endl);
1125       ra = read_register(rd);
1126       rc = ra + rb;
1127       write_register(rd, rc);
1128       do_nflag(rc);
1129       do_zflag(rc);
1130       do_cflag(ra, rb, 0);
1131       do_vflag(ra, rb, 0);
1132       return 0;
1133     }
1134 
1135     //ADD(3) three registers
1136     case Op::add3: {
1137       rd = (inst >> 0) & 0x7;
1138       rn = (inst >> 3) & 0x7;
1139       rm = (inst >> 6) & 0x7;
1140       DO_DISS(statusMsg << "adds r" << dec << rd << ",r" << dec << rn << ",r" << rm << endl);
1141       ra = read_register(rn);
1142       rb = read_register(rm);
1143       rc = ra + rb;
1144       write_register(rd, rc);
1145       do_nflag(rc);
1146       do_zflag(rc);
1147       do_cflag(ra, rb, 0);
1148       do_vflag(ra, rb, 0);
1149       return 0;
1150     }
1151 
1152     //ADD(4) two registers one or both high no flags
1153     case Op::add4: {
1154       if((inst >> 6) & 3)
1155       {
1156         //UNPREDICTABLE
1157       }
1158       rd  = (inst >> 0) & 0x7;
1159       rd |= (inst >> 4) & 0x8;
1160       rm  = (inst >> 3) & 0xF;
1161       DO_DISS(statusMsg << "add r" << dec << rd << ",r" << dec << rm << endl);
1162       ra = read_register(rd);
1163       rb = read_register(rm);
1164       rc = ra + rb;
1165       if(rd == 15)
1166       {
1167 #ifndef UNSAFE_OPTIMIZATIONS
1168         if((rc & 1) == 0)
1169           fatalError("add pc", pc, rc, " produced an arm address");
1170 #endif
1171         //rc &= ~1; //write_register may do this as well
1172         rc += 2;  //The program counter is special
1173       }
1174       //fprintf(stderr,"0x%08X = 0x%08X + 0x%08X\n",rc,ra,rb);
1175       write_register(rd, rc);
1176       return 0;
1177     }
1178 
1179     //ADD(5) rd = pc plus immediate
1180     case Op::add5: {
1181       rb = (inst >> 0) & 0xFF;
1182       rd = (inst >> 8) & 0x7;
1183       rb <<= 2;
1184       DO_DISS(statusMsg << "add r" << dec << rd << ",PC,#0x" << Base::HEX2 << rb << endl);
1185       ra = read_register(15);
1186       rc = (ra & (~3U)) + rb;
1187       write_register(rd, rc);
1188       return 0;
1189     }
1190 
1191     //ADD(6) rd = sp plus immediate
1192     case Op::add6: {
1193       rb = (inst >> 0) & 0xFF;
1194       rd = (inst >> 8) & 0x7;
1195       rb <<= 2;
1196       DO_DISS(statusMsg << "add r" << dec << rd << ",SP,#0x" << Base::HEX2 << rb << endl);
1197       ra = read_register(13);
1198       rc = ra + rb;
1199       write_register(rd, rc);
1200       return 0;
1201     }
1202 
1203     //ADD(7) sp plus immediate
1204     case Op::add7: {
1205       rb = (inst >> 0) & 0x7F;
1206       rb <<= 2;
1207       DO_DISS(statusMsg << "add SP,#0x" << Base::HEX2 << rb << endl);
1208       ra = read_register(13);
1209       rc = ra + rb;
1210       write_register(13, rc);
1211       return 0;
1212     }
1213 
1214     //AND
1215     case Op::and_: {
1216       rd = (inst >> 0) & 0x7;
1217       rm = (inst >> 3) & 0x7;
1218       DO_DISS(statusMsg << "ands r" << dec << rd << ",r" << dec << rm << endl);
1219       ra = read_register(rd);
1220       rb = read_register(rm);
1221       rc = ra & rb;
1222       write_register(rd, rc);
1223       do_nflag(rc);
1224       do_zflag(rc);
1225       return 0;
1226     }
1227 
1228     //ASR(1) two register immediate
1229     case Op::asr1: {
1230       rd = (inst >> 0) & 0x07;
1231       rm = (inst >> 3) & 0x07;
1232       rb = (inst >> 6) & 0x1F;
1233       DO_DISS(statusMsg << "asrs r" << dec << rd << ",r" << dec << rm << ",#0x" << Base::HEX2 << rb << endl);
1234       rc = read_register(rm);
1235       if(rb == 0)
1236       {
1237         if(rc & 0x80000000)
1238         {
1239           do_cflag_bit(1);
1240           rc = ~0U;
1241         }
1242         else
1243         {
1244           do_cflag_bit(0);
1245           rc = 0;
1246         }
1247       }
1248       else
1249       {
1250         do_cflag_bit(rc & (1 << (rb-1)));
1251         ra = rc & 0x80000000;
1252         rc >>= rb;
1253         if(ra) //asr, sign is shifted in
1254           rc |= (~0U) << (32-rb);
1255       }
1256       write_register(rd, rc);
1257       do_nflag(rc);
1258       do_zflag(rc);
1259       INC_SHIFT_CYCLES;
1260       return 0;
1261     }
1262 
1263     //ASR(2) two register
1264     case Op::asr2: {
1265       rd = (inst >> 0) & 0x07;
1266       rs = (inst >> 3) & 0x07;
1267       DO_DISS(statusMsg << "asrs r" << dec << rd << ",r" << dec << rs << endl);
1268       rc = read_register(rd);
1269       rb = read_register(rs);
1270       rb &= 0xFF;
1271       if(rb == 0)
1272       {
1273       }
1274       else if(rb < 32)
1275       {
1276         do_cflag_bit(rc & (1 << (rb-1)));
1277         ra = rc & 0x80000000;
1278         rc >>= rb;
1279         if(ra) //asr, sign is shifted in
1280         {
1281           rc |= (~0U) << (32-rb);
1282         }
1283       }
1284       else
1285       {
1286         if(rc & 0x80000000)
1287         {
1288           do_cflag_bit(1);
1289           rc = (~0U);
1290         }
1291         else
1292         {
1293           do_cflag_bit(0);
1294           rc = 0;
1295         }
1296       }
1297       write_register(rd, rc);
1298       do_nflag(rc);
1299       do_zflag(rc);
1300       INC_SHIFT_CYCLES;
1301       return 0;
1302     }
1303 
1304     //B(1) conditional branch
1305     case Op::b1: {
1306     #ifdef THUMB_STATS
1307       ++_stats.branches;
1308     #endif
1309       rb = inst & 0xFF;
1310       if(rb & 0x80)
1311         rb |= (~0U) << 8;
1312       rb <<= 1;
1313       rb += pc;
1314       rb += 2;
1315 
1316       op = (inst >> 8) & 0xF;
1317       switch(op)
1318       {
1319         case 0x0: //b eq  z set
1320           DO_DISS(statusMsg << "beq 0x" << Base::HEX8 << (rb-3) << endl);
1321           if(cpsr & CPSR_Z)
1322             write_register(15, rb);
1323           return 0;
1324 
1325         case 0x1: //b ne  z clear
1326           DO_DISS(statusMsg << "bne 0x" << Base::HEX8 << (rb-3) << endl);
1327           if(!(cpsr & CPSR_Z))
1328             write_register(15, rb);
1329           return 0;
1330 
1331         case 0x2: //b cs c set
1332           DO_DISS(statusMsg << "bcs 0x" << Base::HEX8 << (rb-3) << endl);
1333           if(cpsr & CPSR_C)
1334             write_register(15, rb);
1335           return 0;
1336 
1337         case 0x3: //b cc c clear
1338           DO_DISS(statusMsg << "bcc 0x" << Base::HEX8 << (rb-3) << endl);
1339           if(!(cpsr & CPSR_C))
1340             write_register(15, rb);
1341           return 0;
1342 
1343         case 0x4: //b mi n set
1344           DO_DISS(statusMsg << "bmi 0x" << Base::HEX8 << (rb-3) << endl);
1345           if(cpsr & CPSR_N)
1346             write_register(15, rb);
1347           return 0;
1348 
1349         case 0x5: //b pl n clear
1350           DO_DISS(statusMsg << "bpl 0x" << Base::HEX8 << (rb-3) << endl);
1351           if(!(cpsr & CPSR_N))
1352             write_register(15, rb);
1353           return 0;
1354 
1355         case 0x6: //b vs v set
1356           DO_DISS(statusMsg << "bvs 0x" << Base::HEX8 << (rb-3) << endl);
1357           if(cpsr & CPSR_V)
1358             write_register(15, rb);
1359           return 0;
1360 
1361         case 0x7: //b vc v clear
1362           DO_DISS(statusMsg << "bvc 0x" << Base::HEX8 << (rb-3) << endl);
1363           if(!(cpsr & CPSR_V))
1364             write_register(15, rb);
1365           return 0;
1366 
1367         case 0x8: //b hi c set z clear
1368           DO_DISS(statusMsg << "bhi 0x" << Base::HEX8 << (rb-3) << endl);
1369           if((cpsr & CPSR_C) && (!(cpsr & CPSR_Z)))
1370             write_register(15, rb);
1371           return 0;
1372 
1373         case 0x9: //b ls c clear or z set
1374           DO_DISS(statusMsg << "bls 0x" << Base::HEX8 << (rb-3) << endl);
1375           if((cpsr & CPSR_Z) || (!(cpsr & CPSR_C)))
1376             write_register(15, rb);
1377           return 0;
1378 
1379         case 0xA: //b ge N == V
1380           DO_DISS(statusMsg << "bge 0x" << Base::HEX8 << (rb-3) << endl);
1381           if(((cpsr & CPSR_N) && (cpsr & CPSR_V)) ||
1382              ((!(cpsr & CPSR_N)) && (!(cpsr & CPSR_V))))
1383             write_register(15, rb);
1384           return 0;
1385 
1386         case 0xB: //b lt N != V
1387           DO_DISS(statusMsg << "blt 0x" << Base::HEX8 << (rb-3) << endl);
1388           if((!(cpsr & CPSR_N) && (cpsr & CPSR_V)) ||
1389             (((cpsr & CPSR_N)) && !(cpsr & CPSR_V)))
1390             write_register(15, rb);
1391           return 0;
1392 
1393         case 0xC: //b gt Z==0 and N == V
1394           DO_DISS(statusMsg << "bgt 0x" << Base::HEX8 << (rb-3) << endl);
1395           if(!(cpsr & CPSR_Z))
1396           {
1397             if(((cpsr & CPSR_N) && (cpsr & CPSR_V)) ||
1398                ((!(cpsr & CPSR_N)) && (!(cpsr & CPSR_V))))
1399               write_register(15, rb);
1400           }
1401           return 0;
1402 
1403         case 0xD: //b le Z==1 or N != V
1404           DO_DISS(statusMsg << "ble 0x" << Base::HEX8 << (rb-3) << endl);
1405           if((cpsr & CPSR_Z) ||
1406             (!(cpsr & CPSR_N) && (cpsr & CPSR_V)) ||
1407             (((cpsr & CPSR_N)) && !(cpsr & CPSR_V)))
1408             write_register(15, rb);
1409           return 0;
1410 
1411         case 0xE:
1412           //undefined instruction
1413           break;
1414 
1415         case 0xF:
1416           //swi
1417           break;
1418 
1419         default:
1420           break;
1421       }
1422       break;
1423     }
1424 
1425     //B(2) unconditional branch
1426     case Op::b2: {
1427     #ifdef THUMB_STATS
1428       ++_stats.branches;
1429     #endif
1430       rb = (inst >> 0) & 0x7FF;
1431       if(rb & (1 << 10))
1432         rb |= (~0U) << 11;
1433       rb <<= 1;
1434       rb += pc;
1435       rb += 2;
1436       DO_DISS(statusMsg << "B 0x" << Base::HEX8 << (rb-3) << endl);
1437       write_register(15, rb);
1438       return 0;
1439     }
1440 
1441     //BIC
1442     case Op::bic: {
1443       rd = (inst >> 0) & 0x7;
1444       rm = (inst >> 3) & 0x7;
1445       DO_DISS(statusMsg << "bics r" << dec << rd << ",r" << dec << rm << endl);
1446       ra = read_register(rd);
1447       rb = read_register(rm);
1448       rc = ra & (~rb);
1449       write_register(rd, rc);
1450       do_nflag(rc);
1451       do_zflag(rc);
1452       return 0;
1453     }
1454 
1455 #ifndef UNSAFE_OPTIMIZATIONS
1456     //BKPT
1457     case Op::bkpt: {
1458       rb = (inst >> 0) & 0xFF;
1459       statusMsg << "bkpt 0x" << Base::HEX2 << rb << endl;
1460       return 1;
1461     }
1462 #endif
1463 
1464     //BL/BLX(1)
1465     case Op::blx1: {
1466       if((inst & 0x1800) == 0x1000) //H=b10
1467       {
1468         DO_DISS(statusMsg << endl);
1469         rb = inst & ((1 << 11) - 1);
1470         if(rb & 1<<10) rb |= (~((1 << 11) - 1)); //sign extend
1471         rb <<= 12;
1472         rb += pc;
1473         write_register(14, rb);
1474         return 0;
1475       }
1476       else if((inst & 0x1800) == 0x1800) //H=b11
1477       {
1478         //branch to thumb
1479         rb = read_register(14);
1480         rb += (inst & ((1 << 11) - 1)) << 1;
1481         rb += 2;
1482         DO_DISS(statusMsg << "bl 0x" << Base::HEX8 << (rb-3) << endl);
1483         write_register(14, (pc-2) | 1);
1484         write_register(15, rb);
1485         return 0;
1486       }
1487       else if((inst & 0x1800) == 0x0800) //H=b01
1488       {
1489         //fprintf(stderr,"cannot branch to arm 0x%08X 0x%04X\n",pc,inst);
1490         // fxq: this should exit the code without having to detect it
1491         // TJ: seems to be not used
1492         rb = read_register(14);
1493         rb += (inst & ((1 << 11) - 1)) << 1;
1494         rb &= 0xFFFFFFFC;
1495         rb += 2;
1496         DO_DISS(statusMsg << "bl 0x" << Base::HEX8 << (rb-3) << endl);
1497         write_register(14, (pc-2) | 1);
1498         write_register(15, rb);
1499         return 0;
1500       }
1501       break;
1502     }
1503 
1504     //BLX(2)
1505     case Op::blx2: {
1506       rm = (inst >> 3) & 0xF;
1507       DO_DISS(statusMsg << "blx r" << dec << rm << endl);
1508       rc = read_register(rm);
1509       //fprintf(stderr,"blx r%u 0x%X 0x%X\n",rm,rc,pc);
1510       rc += 2;
1511       if(rc & 1)
1512       {
1513         write_register(14, (pc-2) | 1);
1514         //rc &= ~1;
1515         write_register(15, rc);
1516         return 0;
1517       }
1518       else
1519       {
1520         //fprintf(stderr,"cannot branch to arm 0x%08X 0x%04X\n",pc,inst);
1521         // fxq: this could serve as exit code
1522         return 1;
1523       }
1524     }
1525 
1526     //BX
1527     case Op::bx: {
1528       rm = (inst >> 3) & 0xF;
1529       DO_DISS(statusMsg << "bx r" << dec << rm << endl);
1530       rc = read_register(rm);
1531       rc += 2;
1532       //fprintf(stderr,"bx r%u 0x%X 0x%X\n",rm,rc,pc);
1533       if(rc & 1)
1534       {
1535         // branch to odd address denotes 16 bit ARM code
1536         //rc &= ~1;
1537         write_register(15, rc);
1538         return 0;
1539       }
1540       else
1541       {
1542         // branch to even address denotes 32 bit ARM code, which the Thumbulator
1543         // class does not support. So capture relevant information and hand it
1544         // off to the Cartridge class for it to handle.
1545 
1546         bool handled = false;
1547 
1548         switch(configuration)
1549         {
1550           case ConfigureFor::BUS:
1551             // this subroutine interface is used in the BUS driver,
1552             // it starts at address 0x000006d8
1553             // _SetNote:
1554             //   ldr     r4, =NoteStore
1555             //   bx      r4   // bx instruction at 0x000006da
1556             // _ResetWave:
1557             //   ldr     r4, =ResetWaveStore
1558             //   bx      r4   // bx instruction at 0x000006de
1559             // _GetWavePtr:
1560             //   ldr     r4, =WavePtrFetch
1561             //   bx      r4   // bx instruction at 0x000006e2
1562             // _SetWaveSize:
1563             //   ldr     r4, =WaveSizeStore
1564             //   bx      r4   // bx instruction at 0x000006e6
1565 
1566             // address to test for is + 4 due to pipelining
1567 
1568   #define BUS_SetNote     (0x000006da + 4)
1569   #define BUS_ResetWave   (0x000006de + 4)
1570   #define BUS_GetWavePtr  (0x000006e2 + 4)
1571   #define BUS_SetWaveSize (0x000006e6 + 4)
1572 
1573             if      (pc == BUS_SetNote)
1574             {
1575               myCartridge->thumbCallback(0, read_register(2), read_register(3));
1576               handled = true;
1577             }
1578             else if (pc == BUS_ResetWave)
1579             {
1580               myCartridge->thumbCallback(1, read_register(2), 0);
1581               handled = true;
1582             }
1583             else if (pc == BUS_GetWavePtr)
1584             {
1585               write_register(2, myCartridge->thumbCallback(2, read_register(2), 0));
1586               handled = true;
1587             }
1588             else if (pc == BUS_SetWaveSize)
1589             {
1590               myCartridge->thumbCallback(3, read_register(2), read_register(3));
1591               handled = true;
1592             }
1593             else if (pc == 0x0000083a)
1594             {
1595               // exiting Custom ARM code, returning to BUS Driver control
1596             }
1597             else
1598             {
1599   #if 0  // uncomment this for testing
1600               uInt32 r0 = read_register(0);
1601               uInt32 r1 = read_register(1);
1602               uInt32 r2 = read_register(2);
1603               uInt32 r3 = read_register(3);
1604               uInt32 r4 = read_register(4);
1605   #endif
1606               myCartridge->thumbCallback(255, 0, 0);
1607             }
1608 
1609             break;
1610 
1611           case ConfigureFor::CDF:
1612             // this subroutine interface is used in the CDF driver,
1613             // it starts at address 0x000006e0
1614             // _SetNote:
1615             //   ldr     r4, =NoteStore
1616             //   bx      r4   // bx instruction at 0x000006e2
1617             // _ResetWave:
1618             //   ldr     r4, =ResetWaveStore
1619             //   bx      r4   // bx instruction at 0x000006e6
1620             // _GetWavePtr:
1621             //   ldr     r4, =WavePtrFetch
1622             //   bx      r4   // bx instruction at 0x000006ea
1623             // _SetWaveSize:
1624             //   ldr     r4, =WaveSizeStore
1625             //   bx      r4   // bx instruction at 0x000006ee
1626 
1627             // address to test for is + 4 due to pipelining
1628 
1629           #define CDF_SetNote     (0x000006e2 + 4)
1630           #define CDF_ResetWave   (0x000006e6 + 4)
1631           #define CDF_GetWavePtr  (0x000006ea + 4)
1632           #define CDF_SetWaveSize (0x000006ee + 4)
1633 
1634             if      (pc == CDF_SetNote)
1635             {
1636               myCartridge->thumbCallback(0, read_register(2), read_register(3));
1637               handled = true;
1638             }
1639             else if (pc == CDF_ResetWave)
1640             {
1641               myCartridge->thumbCallback(1, read_register(2), 0);
1642               handled = true;
1643             }
1644             else if (pc == CDF_GetWavePtr)
1645             {
1646               write_register(2, myCartridge->thumbCallback(2, read_register(2), 0));
1647               handled = true;
1648             }
1649             else if (pc == CDF_SetWaveSize)
1650             {
1651               myCartridge->thumbCallback(3, read_register(2), read_register(3));
1652               handled = true;
1653             }
1654             else if (pc == 0x0000083a)
1655             {
1656               // exiting Custom ARM code, returning to CDF Driver control
1657             }
1658             else
1659             {
1660             #if 0  // uncomment this for testing
1661               uInt32 r0 = read_register(0);
1662               uInt32 r1 = read_register(1);
1663               uInt32 r2 = read_register(2);
1664               uInt32 r3 = read_register(3);
1665               uInt32 r4 = read_register(4);
1666             #endif
1667               myCartridge->thumbCallback(255, 0, 0);
1668             }
1669 
1670             break;
1671 
1672           case ConfigureFor::CDF1:
1673           case ConfigureFor::CDFJ:
1674           case ConfigureFor::CDFJplus:
1675             // this subroutine interface is used in the CDF driver,
1676             // it starts at address 0x00000750
1677             // _SetNote:
1678             //   ldr     r4, =NoteStore
1679             //   bx      r4   // bx instruction at 0x000006e2
1680             // _ResetWave:
1681             //   ldr     r4, =ResetWaveStore
1682             //   bx      r4   // bx instruction at 0x000006e6
1683             // _GetWavePtr:
1684             //   ldr     r4, =WavePtrFetch
1685             //   bx      r4   // bx instruction at 0x000006ea
1686             // _SetWaveSize:
1687             //   ldr     r4, =WaveSizeStore
1688             //   bx      r4   // bx instruction at 0x000006ee
1689 
1690             // address to test for is + 4 due to pipelining
1691 
1692   #define CDF1_SetNote     (0x00000752 + 4)
1693   #define CDF1_ResetWave   (0x00000756 + 4)
1694   #define CDF1_GetWavePtr  (0x0000075a + 4)
1695   #define CDF1_SetWaveSize (0x0000075e + 4)
1696 
1697             if      (pc == CDF1_SetNote)
1698             {
1699               myCartridge->thumbCallback(0, read_register(2), read_register(3));
1700               // approximated cycles
1701               INC_ARM_CYCLES(_flashCycles + 1);     // this instruction
1702               INC_ARM_CYCLES(6);                    // ARM code NoteStore
1703               INC_ARM_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
1704               handled = true;
1705             }
1706             else if (pc == CDF1_ResetWave)
1707             {
1708               myCartridge->thumbCallback(1, read_register(2), 0);
1709               // approximated cycles
1710               INC_ARM_CYCLES(_flashCycles + 1);     // this instruction
1711               INC_ARM_CYCLES(6 + _flashCycles + 2); // ARM code ResetWaveStore
1712               INC_ARM_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
1713               handled = true;
1714             }
1715             else if (pc == CDF1_GetWavePtr)
1716             {
1717               write_register(2, myCartridge->thumbCallback(2, read_register(2), 0));
1718               // approximated cycles
1719               INC_ARM_CYCLES(_flashCycles + 1);     // this instruction
1720               INC_ARM_CYCLES(6 + _flashCycles + 2); // ARM code WavePtrFetch
1721               INC_ARM_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
1722               handled = true;
1723             }
1724             else if (pc == CDF1_SetWaveSize)
1725             {
1726               myCartridge->thumbCallback(3, read_register(2), read_register(3));
1727               // approximated cycles
1728               INC_ARM_CYCLES(_flashCycles + 1);           // this instruction
1729               INC_ARM_CYCLES(18 + _flashCycles * 3 + 2);  // ARM code WaveSizeStore
1730               INC_ARM_CYCLES(2 + _flashCycles + 2);       // ARM code ReturnC
1731               handled = true;
1732             }
1733             else if (pc == 0x0000083a)
1734             {
1735               // exiting Custom ARM code, returning to CDFJ Driver control
1736             }
1737             else
1738             {
1739   #if 0  // uncomment this for testing
1740               uInt32 r0 = read_register(0);
1741               uInt32 r1 = read_register(1);
1742               uInt32 r2 = read_register(2);
1743               uInt32 r3 = read_register(3);
1744               uInt32 r4 = read_register(4);
1745   #endif
1746               myCartridge->thumbCallback(255, 0, 0);
1747             }
1748 
1749             break;
1750 
1751           case ConfigureFor::DPCplus:
1752             // no 32-bit subroutines in DPC+
1753             break;
1754         }
1755 
1756         if (handled)
1757         {
1758           rc = read_register(14); // lr
1759           rc += 2;
1760           //rc &= ~1;
1761           write_register(15, rc);
1762           //_totalCycles += 100; // just a wild guess
1763           return 0;
1764         }
1765         return 1;
1766       }
1767     }
1768 
1769     //CMN
1770     case Op::cmn: {
1771       rn = (inst >> 0) & 0x7;
1772       rm = (inst >> 3) & 0x7;
1773       DO_DISS(statusMsg << "cmns r" << dec << rn << ",r" << dec << rm << endl);
1774       ra = read_register(rn);
1775       rb = read_register(rm);
1776       rc = ra + rb;
1777       do_nflag(rc);
1778       do_zflag(rc);
1779       do_cflag(ra, rb, 0);
1780       do_vflag(ra, rb, 0);
1781       return 0;
1782     }
1783 
1784     //CMP(1) compare immediate
1785     case Op::cmp1: {
1786       rb = (inst >> 0) & 0xFF;
1787       rn = (inst >> 8) & 0x07;
1788       DO_DISS(statusMsg << "cmp r" << dec << rn << ",#0x" << Base::HEX2 << rb << endl);
1789       ra = read_register(rn);
1790       rc = ra - rb;
1791       //fprintf(stderr,"0x%08X 0x%08X\n",ra,rb);
1792       do_nflag(rc);
1793       do_zflag(rc);
1794       do_cflag(ra, ~rb, 1);
1795       do_vflag(ra, ~rb, 1);
1796       return 0;
1797     }
1798 
1799     //CMP(2) compare register
1800     case Op::cmp2: {
1801       rn = (inst >> 0) & 0x7;
1802       rm = (inst >> 3) & 0x7;
1803       DO_DISS(statusMsg << "cmps r" << dec << rn << ",r" << dec << rm << endl);
1804       ra = read_register(rn);
1805       rb = read_register(rm);
1806       rc = ra - rb;
1807       //fprintf(stderr,"0x%08X 0x%08X\n",ra,rb);
1808       do_nflag(rc);
1809       do_zflag(rc);
1810       do_cflag(ra, ~rb, 1);
1811       do_vflag(ra, ~rb, 1);
1812       return 0;
1813     }
1814 
1815     //CMP(3) compare high register
1816     case Op::cmp3: {
1817       if(((inst >> 6) & 3) == 0x0)
1818       {
1819         //UNPREDICTABLE
1820       }
1821       rn = (inst >> 0) & 0x7;
1822       rn |= (inst >> 4) & 0x8;
1823       if(rn == 0xF)
1824       {
1825         //UNPREDICTABLE
1826       }
1827       rm = (inst >> 3) & 0xF;
1828       DO_DISS(statusMsg << "cmps r" << dec << rn << ",r" << dec << rm << endl);
1829       ra = read_register(rn);
1830       rb = read_register(rm);
1831       rc = ra - rb;
1832       do_nflag(rc);
1833       do_zflag(rc);
1834       do_cflag(ra, ~rb, 1);
1835       do_vflag(ra, ~rb, 1);
1836       return 0;
1837     }
1838 
1839 #ifndef UNSAFE_OPTIMIZATIONS
1840     //CPS
1841     case Op::cps: {
1842       DO_DISS(statusMsg << "cps TODO" << endl);
1843       return 1;
1844     }
1845 #endif
1846 
1847     //CPY copy high register
1848     case Op::cpy: {
1849       //same as mov except you can use both low registers
1850       //going to let mov handle high registers
1851       rd = (inst >> 0) & 0x7;
1852       rm = (inst >> 3) & 0x7;
1853       DO_DISS(statusMsg << "cpy r" << dec << rd << ",r" << dec << rm << endl);
1854       rc = read_register(rm);
1855       write_register(rd, rc);
1856       return 0;
1857     }
1858 
1859     //EOR
1860     case Op::eor: {
1861       rd = (inst >> 0) & 0x7;
1862       rm = (inst >> 3) & 0x7;
1863       DO_DISS(statusMsg << "eors r" << dec << rd << ",r" << dec << rm << endl);
1864       ra = read_register(rd);
1865       rb = read_register(rm);
1866       rc = ra ^ rb;
1867       write_register(rd, rc);
1868       do_nflag(rc);
1869       do_zflag(rc);
1870       return 0;
1871     }
1872 
1873     //LDMIA
1874     case Op::ldmia: {
1875       rn = (inst >> 8) & 0x7;
1876     #if defined(THUMB_DISS)
1877       statusMsg << "ldmia r" << dec << rn << "!,{";
1878       for(ra=0,rb=0x01,rc=0;rb;rb=(rb<<1)&0xFF,++ra)
1879       {
1880         if(inst&rb)
1881         {
1882           if(rc) statusMsg << ",";
1883           statusMsg << "r" << dec << ra;
1884           rc++;
1885         }
1886       }
1887       statusMsg << "}" << endl;
1888     #endif
1889       bool first = true;
1890 
1891       sp = read_register(rn);
1892       for(ra = 0, rb = 0x01; rb; rb = (rb << 1) & 0xFF, ++ra)
1893       {
1894         if(inst & rb)
1895         {
1896           write_register(ra, read32(sp));
1897           if(first)
1898           {
1899             INC_N_CYCLES(sp, AccessType::data);
1900             first = false;
1901           }
1902           else
1903           {
1904             INC_S_CYCLES(sp, AccessType::data);
1905           }
1906           sp += 4;
1907         }
1908       }
1909       INC_I_CYCLES; // Note: destination PC not possible, see pop instead
1910       //there is a write back exception.
1911       if((inst & (1 << rn)) == 0)
1912         write_register(rn, sp);
1913       return 0;
1914     }
1915 
1916     //LDR(1) two register immediate
1917     case Op::ldr1: {
1918       rd = (inst >> 0) & 0x07;
1919       rn = (inst >> 3) & 0x07;
1920       rb = (inst >> 6) & 0x1F;
1921       rb <<= 2;
1922       DO_DISS(statusMsg << "ldr r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl);
1923       rb = read_register(rn) + rb;
1924       rc = read32(rb);
1925       write_register(rd, rc);
1926       INC_LDR_CYCLES;
1927       return 0;
1928     }
1929 
1930     //LDR(2) three register
1931     case Op::ldr2: {
1932       rd = (inst >> 0) & 0x7;
1933       rn = (inst >> 3) & 0x7;
1934       rm = (inst >> 6) & 0x7;
1935       DO_DISS(statusMsg << "ldr r" << dec << rd << ",[r" << dec << rn << ",r" << dec << "]" << endl);
1936       rb = read_register(rn) + read_register(rm);
1937       rc = read32(rb);
1938       write_register(rd, rc);
1939       INC_LDR_CYCLES;
1940       return 0;
1941     }
1942 
1943     //LDR(3)
1944     case Op::ldr3: {
1945       rb = (inst >> 0) & 0xFF;
1946       rd = (inst >> 8) & 0x07;
1947       rb <<= 2;
1948       DO_DISS(statusMsg << "ldr r" << dec << rd << ",[PC+#0x" << Base::HEX2 << rb << "] ");
1949       ra = read_register(15);
1950       ra &= ~3;
1951       rb += ra;
1952       DO_DISS(statusMsg << ";@ 0x" << Base::HEX2 << rb << endl);
1953       rc = read32(rb);
1954       write_register(rd, rc);
1955       INC_LDR_CYCLES;
1956       return 0;
1957     }
1958 
1959     //LDR(4)
1960     case Op::ldr4: {
1961       rb = (inst >> 0) & 0xFF;
1962       rd = (inst >> 8) & 0x07;
1963       rb <<= 2;
1964       DO_DISS(statusMsg << "ldr r" << dec << rd << ",[SP+#0x" << Base::HEX2 << rb << "]" << endl);
1965       ra = read_register(13);
1966       //ra&=~3;
1967       rb += ra;
1968       rc = read32(rb);
1969       write_register(rd, rc);
1970       INC_LDR_CYCLES;
1971       return 0;
1972     }
1973 
1974     //LDRB(1)
1975     case Op::ldrb1: {
1976       rd = (inst >> 0) & 0x07;
1977       rn = (inst >> 3) & 0x07;
1978       rb = (inst >> 6) & 0x1F;
1979       DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl);
1980       rb = read_register(rn) + rb;
1981 #ifndef UNSAFE_OPTIMIZATIONS
1982       rc = read16(rb & (~1U));
1983 #else
1984       rc = read16(rb);
1985 #endif
1986       if(rb & 1)
1987       {
1988         rc >>= 8;
1989       }
1990       else
1991       {
1992       }
1993       write_register(rd, rc & 0xFF);
1994       INC_LDRB_CYCLES;
1995       return 0;
1996     }
1997 
1998     //LDRB(2)
1999     case Op::ldrb2: {
2000       rd = (inst >> 0) & 0x7;
2001       rn = (inst >> 3) & 0x7;
2002       rm = (inst >> 6) & 0x7;
2003       DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl);
2004       rb = read_register(rn) + read_register(rm);
2005 #ifndef UNSAFE_OPTIMIZATIONS
2006       rc = read16(rb & (~1U));
2007 #else
2008       rc = read16(rb);
2009 #endif
2010       if(rb & 1)
2011       {
2012         rc >>= 8;
2013       }
2014       write_register(rd, rc & 0xFF);
2015       INC_LDRB_CYCLES;
2016       return 0;
2017     }
2018 
2019     //LDRH(1)
2020     case Op::ldrh1: {
2021       rd = (inst >> 0) & 0x07;
2022       rn = (inst >> 3) & 0x07;
2023       rb = (inst >> 6) & 0x1F;
2024       rb <<= 1;
2025       DO_DISS(statusMsg << "ldrh r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl);
2026       rb = read_register(rn) + rb;
2027       rc = read16(rb);
2028       write_register(rd, rc & 0xFFFF);
2029       INC_LDR_CYCLES;
2030       return 0;
2031     }
2032 
2033     //LDRH(2)
2034     case Op::ldrh2: {
2035       rd = (inst >> 0) & 0x7;
2036       rn = (inst >> 3) & 0x7;
2037       rm = (inst >> 6) & 0x7;
2038       DO_DISS(statusMsg << "ldrh r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl);
2039       rb = read_register(rn) + read_register(rm);
2040       rc = read16(rb);
2041       write_register(rd, rc & 0xFFFF);
2042       INC_LDR_CYCLES;
2043       return 0;
2044     }
2045 
2046     //LDRSB
2047     case Op::ldrsb: {
2048       rd = (inst >> 0) & 0x7;
2049       rn = (inst >> 3) & 0x7;
2050       rm = (inst >> 6) & 0x7;
2051       DO_DISS(statusMsg << "ldrsb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl);
2052       rb = read_register(rn) + read_register(rm);
2053 #ifndef UNSAFE_OPTIMIZATIONS
2054       rc = read16(rb & (~1U));
2055 #else
2056       rc = read16(rb);
2057 #endif
2058       if(rb & 1)
2059       {
2060         rc >>= 8;
2061       }
2062       rc &= 0xFF;
2063       if(rc & 0x80)
2064         rc |= ((~0U) << 8);
2065       write_register(rd, rc);
2066       INC_LDRB_CYCLES;
2067       return 0;
2068     }
2069 
2070     //LDRSH
2071     case Op::ldrsh: {
2072       rd = (inst >> 0) & 0x7;
2073       rn = (inst >> 3) & 0x7;
2074       rm = (inst >> 6) & 0x7;
2075       DO_DISS(statusMsg << "ldrsh r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl);
2076       rb = read_register(rn) + read_register(rm);
2077       rc = read16(rb);
2078       rc &= 0xFFFF;
2079       if(rc & 0x8000)
2080         rc |= ((~0U) << 16);
2081       write_register(rd, rc);
2082       INC_LDR_CYCLES;
2083       return 0;
2084     }
2085 
2086     //LSL(1)
2087     case Op::lsl1: {
2088       rd = (inst >> 0) & 0x07;
2089       rm = (inst >> 3) & 0x07;
2090       rb = (inst >> 6) & 0x1F;
2091       DO_DISS(statusMsg << "lsls r" << dec << rd << ",r" << dec << rm << ",#0x" << Base::HEX2 << rb << endl);
2092       rc = read_register(rm);
2093       if(rb == 0)
2094       {
2095         //if immed_5 == 0
2096         //C unaffected
2097         //result not shifted
2098       }
2099       else
2100       {
2101         //else immed_5 > 0
2102         do_cflag_bit(rc & (1 << (32-rb)));
2103         rc <<= rb;
2104       }
2105       write_register(rd, rc);
2106       do_nflag(rc);
2107       do_zflag(rc);
2108       INC_SHIFT_CYCLES;
2109       return 0;
2110     }
2111 
2112     //LSL(2) two register
2113     case Op::lsl2: {
2114       rd = (inst >> 0) & 0x07;
2115       rs = (inst >> 3) & 0x07;
2116       DO_DISS(statusMsg << "lsls r" << dec << rd << ",r" << dec << rs << endl);
2117       rc = read_register(rd);
2118       rb = read_register(rs);
2119       rb &= 0xFF;
2120       if(rb == 0)
2121       {
2122       }
2123       else if(rb < 32)
2124       {
2125         do_cflag_bit(rc & (1 << (32-rb)));
2126         rc <<= rb;
2127       }
2128       else if(rb == 32)
2129       {
2130         do_cflag_bit(rc & 1);
2131         rc = 0;
2132       }
2133       else
2134       {
2135         do_cflag_bit(0);
2136         rc = 0;
2137       }
2138       write_register(rd, rc);
2139       do_nflag(rc);
2140       do_zflag(rc);
2141       INC_SHIFT_CYCLES;
2142       return 0;
2143     }
2144 
2145     //LSR(1) two register immediate
2146     case Op::lsr1: {
2147       rd = (inst >> 0) & 0x07;
2148       rm = (inst >> 3) & 0x07;
2149       rb = (inst >> 6) & 0x1F;
2150       DO_DISS(statusMsg << "lsrs r" << dec << rd << ",r" << dec << rm << ",#0x" << Base::HEX2 << rb << endl);
2151       rc = read_register(rm);
2152       if(rb == 0)
2153       {
2154         do_cflag_bit(rc & 0x80000000);
2155         rc = 0;
2156       }
2157       else
2158       {
2159         do_cflag_bit(rc & (1 << (rb-1)));
2160         rc >>= rb;
2161       }
2162       write_register(rd, rc);
2163       do_nflag(rc);
2164       do_zflag(rc);
2165       INC_SHIFT_CYCLES;
2166       return 0;
2167     }
2168 
2169     //LSR(2) two register
2170     case Op::lsr2: {
2171       rd = (inst >> 0) & 0x07;
2172       rs = (inst >> 3) & 0x07;
2173       DO_DISS(statusMsg << "lsrs r" << dec << rd << ",r" << dec << rs << endl);
2174       rc = read_register(rd);
2175       rb = read_register(rs);
2176       rb &= 0xFF;
2177       if(rb == 0)
2178       {
2179       }
2180       else if(rb < 32)
2181       {
2182         do_cflag_bit(rc & (1 << (rb-1)));
2183         rc >>= rb;
2184       }
2185       else if(rb == 32)
2186       {
2187         do_cflag_bit(rc & 0x80000000);
2188         rc = 0;
2189       }
2190       else
2191       {
2192         do_cflag_bit(0);
2193         rc = 0;
2194       }
2195       write_register(rd, rc);
2196       do_nflag(rc);
2197       do_zflag(rc);
2198       INC_SHIFT_CYCLES;
2199       return 0;
2200     }
2201 
2202     //MOV(1) immediate
2203     case Op::mov1: {
2204       rb = (inst >> 0) & 0xFF;
2205       rd = (inst >> 8) & 0x07;
2206       DO_DISS(statusMsg << "movs r" << dec << rd << ",#0x" << Base::HEX2 << rb << endl);
2207       write_register(rd, rb);
2208       do_nflag(rb);
2209       do_zflag(rb);
2210       return 0;
2211     }
2212 
2213     //MOV(2) two low registers
2214     case Op::mov2: {
2215       rd = (inst >> 0) & 7;
2216       rn = (inst >> 3) & 7;
2217       DO_DISS(statusMsg << "movs r" << dec << rd << ",r" << dec << rn << endl);
2218       rc = read_register(rn);
2219       //fprintf(stderr,"0x%08X\n",rc);
2220       write_register(rd, rc);
2221       do_nflag(rc);
2222       do_zflag(rc);
2223       do_cflag_bit(0);
2224       do_vflag_bit(0);
2225       return 0;
2226     }
2227 
2228     //MOV(3)
2229     case Op::mov3: {
2230       rd  = (inst >> 0) & 0x7;
2231       rd |= (inst >> 4) & 0x8;
2232       rm  = (inst >> 3) & 0xF;
2233       DO_DISS(statusMsg << "mov r" << dec << rd << ",r" << dec << rm << endl);
2234       rc = read_register(rm);
2235       if((rd == 14) && (rm == 15))
2236       {
2237         //printf("mov lr,pc warning 0x%08X\n",pc-2);
2238         //rc|=1;
2239       }
2240       if(rd == 15)
2241       {
2242         //rc &= ~1; //write_register may do this as well
2243         rc += 2;  //The program counter is special
2244       }
2245       write_register(rd, rc);
2246       return 0;
2247     }
2248 
2249     //MUL
2250     case Op::mul: {
2251       rd = (inst >> 0) & 0x7;
2252       rm = (inst >> 3) & 0x7;
2253       DO_DISS(statusMsg << "muls r" << dec << rd << ",r" << dec << rm << endl);
2254       ra = read_register(rd);
2255       rb = read_register(rm);
2256     #ifdef DEBUGGER_SUPPORT
2257       if((rb & 0xffffff00) == 0 || (rb & 0xffffff00) == 0xffffff00)       // -2^8 <= rb < 2^8
2258       {
2259         INC_I_CYCLES;
2260       }
2261       else if((rb & 0xffff0000) == 0 || (rb & 0xffff0000) == 0xffff0000)  // -2^16 <= rb < 2^16
2262       {
2263         INC_I_CYCLES_M(2);
2264       }
2265       else if((rb & 0xff000000) == 0 || (rb & 0xff000000) == 0xff000000)  // -2^24 <= rb < 2^24
2266       {
2267         INC_I_CYCLES_M(3);
2268       }
2269       else
2270       {
2271         INC_I_CYCLES_M(4);
2272       }
2273     #endif
2274       rc = ra * rb;
2275       write_register(rd, rc);
2276       do_nflag(rc);
2277       do_zflag(rc);
2278       return 0;
2279     }
2280 
2281     //MVN
2282     case Op::mvn: {
2283       rd = (inst >> 0) & 0x7;
2284       rm = (inst >> 3) & 0x7;
2285       DO_DISS(statusMsg << "mvns r" << dec << rd << ",r" << dec << rm << endl);
2286       ra = read_register(rm);
2287       rc = (~ra);
2288       write_register(rd, rc);
2289       do_nflag(rc);
2290       do_zflag(rc);
2291       return 0;
2292     }
2293 
2294     //NEG
2295     case Op::neg: {
2296       rd = (inst >> 0) & 0x7;
2297       rm = (inst >> 3) & 0x7;
2298       DO_DISS(statusMsg << "negs r" << dec << rd << ",r" << dec << rm << endl);
2299       ra = read_register(rm);
2300       rc = 0 - ra;
2301       write_register(rd, rc);
2302       do_nflag(rc);
2303       do_zflag(rc);
2304       do_cflag(0, ~ra, 1);
2305       do_vflag(0, ~ra, 1);
2306       return 0;
2307     }
2308 
2309     //ORR
2310     case Op::orr: {
2311       rd = (inst >> 0) & 0x7;
2312       rm = (inst >> 3) & 0x7;
2313       DO_DISS(statusMsg << "orrs r" << dec << rd << ",r" << dec << rm << endl);
2314       ra = read_register(rd);
2315       rb = read_register(rm);
2316       rc = ra | rb;
2317       write_register(rd, rc);
2318       do_nflag(rc);
2319       do_zflag(rc);
2320       return 0;
2321     }
2322 
2323     //POP
2324     case Op::pop: {
2325     #if defined(THUMB_DISS)
2326       statusMsg << "pop {";
2327       for(ra=0,rb=0x01,rc=0;rb;rb=(rb<<1)&0xFF,++ra)
2328       {
2329         if(inst&rb)
2330         {
2331           if(rc) statusMsg << ",";
2332           statusMsg << "r" << dec << ra;
2333           rc++;
2334         }
2335       }
2336       if(inst&0x100)
2337       {
2338         if(rc) statusMsg << ",";
2339         statusMsg << "pc";
2340       }
2341       statusMsg << "}" << endl;
2342     #endif
2343       bool first = true;
2344 
2345       sp = read_register(13);
2346       for(ra = 0, rb = 0x01; rb; rb = (rb << 1) & 0xFF, ++ra)
2347       {
2348         if(inst & rb)
2349         {
2350           write_register(ra, read32(sp));
2351           if(first)
2352           {
2353             INC_N_CYCLES(sp, AccessType::data);
2354             first = false;
2355           }
2356           else
2357           {
2358             INC_S_CYCLES(sp, AccessType::data);
2359           }
2360           sp += 4;
2361         }
2362       }
2363       INC_I_CYCLES; // ??? (copied from ldmia)
2364       if(inst & 0x100)
2365       {
2366         rc = read32(sp);
2367         if(first)
2368         {
2369           INC_N_CYCLES(sp, AccessType::data);
2370         }
2371         else
2372         {
2373           INC_S_CYCLES(sp, AccessType::data);
2374         }
2375         rc += 2;
2376         write_register(15, rc);
2377         sp += 4;
2378       }
2379       write_register(13, sp);
2380       return 0;
2381     }
2382 
2383     //PUSH
2384     case Op::push: {
2385     #if defined(THUMB_DISS)
2386       statusMsg << "push {";
2387       for(ra=0,rb=0x01,rc=0;rb;rb=(rb<<1)&0xFF,++ra)
2388       {
2389         if(inst&rb)
2390         {
2391           if(rc) statusMsg << ",";
2392           statusMsg << "r" << dec << ra;
2393           rc++;
2394         }
2395       }
2396       if(inst&0x100)
2397       {
2398         if(rc) statusMsg << ",";
2399         statusMsg << "lr";
2400       }
2401       statusMsg << "}" << endl;
2402     #endif
2403 
2404       sp = read_register(13);
2405       //fprintf(stderr,"sp 0x%08X\n",sp);
2406       for(ra = 0, rb = 0x01, rc = 0; rb; rb = (rb << 1) & 0xFF, ++ra)
2407       {
2408         if(inst & rb)
2409         {
2410           ++rc;
2411         }
2412       }
2413       if(inst & 0x100) ++rc;
2414       rc <<= 2;
2415       sp -= rc;
2416       bool first = true;
2417 
2418       rd = sp;
2419       for(ra = 0, rb = 0x01; rb; rb = (rb << 1) & 0xFF, ++ra)
2420       {
2421         if(inst & rb)
2422         {
2423           write32(rd, read_register(ra));
2424           if(first)
2425           {
2426             INC_N_CYCLES(rd, AccessType::data);
2427             first = false;
2428           }
2429           else
2430           {
2431             INC_S_CYCLES(rd, AccessType::data);
2432           }
2433           rd += 4;
2434         }
2435       }
2436       if(inst & 0x100)
2437       {
2438         rc = read_register(14);
2439         write32(rd, rc);
2440         if(first)
2441         {
2442           INC_N_CYCLES(rd, AccessType::data);
2443         }
2444         else
2445         {
2446           INC_S_CYCLES(rd, AccessType::data);
2447         }
2448         if((rc & 1) == 0)
2449         {
2450           // FIXME fprintf(stderr,"push {lr} with an ARM address pc 0x%08X popped 0x%08X\n",pc,rc);
2451         }
2452       }
2453       write_register(13, sp);
2454       FETCH_TYPE_N; // ??? (copied from stmia)
2455       return 0;
2456     }
2457 
2458     //REV
2459     case Op::rev: {
2460       rd = (inst >> 0) & 0x7;
2461       rn = (inst >> 3) & 0x7;
2462       DO_DISS(statusMsg << "rev r" << dec << rd << ",r" << dec << rn << endl);
2463       ra = read_register(rn);
2464       rc  = ((ra >>  0) & 0xFF) << 24;
2465       rc |= ((ra >>  8) & 0xFF) << 16;
2466       rc |= ((ra >> 16) & 0xFF) <<  8;
2467       rc |= ((ra >> 24) & 0xFF) <<  0;
2468       write_register(rd, rc);
2469       return 0;
2470     }
2471 
2472     //REV16
2473     case Op::rev16: {
2474       rd = (inst >> 0) & 0x7;
2475       rn = (inst >> 3) & 0x7;
2476       DO_DISS(statusMsg << "rev16 r" << dec << rd << ",r" << dec << rn << endl);
2477       ra = read_register(rn);
2478       rc  = ((ra >>  0) & 0xFF) <<  8;
2479       rc |= ((ra >>  8) & 0xFF) <<  0;
2480       rc |= ((ra >> 16) & 0xFF) << 24;
2481       rc |= ((ra >> 24) & 0xFF) << 16;
2482       write_register(rd, rc);
2483       return 0;
2484     }
2485 
2486     //REVSH
2487     case Op::revsh: {
2488       rd = (inst >> 0) & 0x7;
2489       rn = (inst >> 3) & 0x7;
2490       DO_DISS(statusMsg << "revsh r" << dec << rd << ",r" << dec << rn << endl);
2491       ra = read_register(rn);
2492       rc  = ((ra >> 0) & 0xFF) << 8;
2493       rc |= ((ra >> 8) & 0xFF) << 0;
2494       if(rc & 0x8000) rc |= 0xFFFF0000;
2495       else            rc &= 0x0000FFFF;
2496       write_register(rd, rc);
2497       return 0;
2498     }
2499 
2500     //ROR
2501     case Op::ror: {
2502       rd = (inst >> 0) & 0x7;
2503       rs = (inst >> 3) & 0x7;
2504       DO_DISS(statusMsg << "rors r" << dec << rd << ",r" << dec << rs << endl);
2505       rc = read_register(rd);
2506       ra = read_register(rs);
2507       ra &= 0xFF;
2508       if(ra == 0)
2509       {
2510       }
2511       else
2512       {
2513         ra &= 0x1F;
2514         if(ra == 0)
2515         {
2516           do_cflag_bit(rc & 0x80000000);
2517         }
2518         else
2519         {
2520           do_cflag_bit(rc & (1 << (ra-1)));
2521           rb = rc << (32-ra);
2522           rc >>= ra;
2523           rc |= rb;
2524         }
2525       }
2526       write_register(rd, rc);
2527       do_nflag(rc);
2528       do_zflag(rc);
2529       INC_SHIFT_CYCLES;
2530       return 0;
2531     }
2532 
2533     //SBC
2534     case Op::sbc: {
2535       rd = (inst >> 0) & 0x7;
2536       rm = (inst >> 3) & 0x7;
2537       DO_DISS(statusMsg << "sbc r" << dec << rd << ",r" << dec << rm << endl);
2538       ra = read_register(rd);
2539       rb = read_register(rm);
2540       rc = ra - rb;
2541       if(!(cpsr & CPSR_C)) --rc;
2542       write_register(rd, rc);
2543       do_nflag(rc);
2544       do_zflag(rc);
2545       if(cpsr & CPSR_C)
2546       {
2547         do_cflag(ra, ~rb, 1);
2548         do_vflag(ra, ~rb, 1);
2549       }
2550       else
2551       {
2552         do_cflag(ra, ~rb, 0);
2553         do_vflag(ra, ~rb, 0);
2554       }
2555       return 0;
2556     }
2557 
2558 #ifndef UNSAFE_OPTIMIZATIONS
2559     //SETEND
2560     case Op::setend: {
2561       statusMsg << "setend not implemented" << endl;
2562       return 1;
2563     }
2564 #endif
2565 
2566     //STMIA
2567     case Op::stmia: {
2568       rn = (inst >> 8) & 0x7;
2569     #if defined(THUMB_DISS)
2570       statusMsg << "stmia r" << dec << rn << "!,{";
2571       for(ra=0,rb=0x01,rc=0;rb;rb=(rb<<1)&0xFF,++ra)
2572       {
2573         if(inst & rb)
2574         {
2575           if(rc) statusMsg << ",";
2576           statusMsg << "r" << dec << ra;
2577           rc++;
2578         }
2579       }
2580       statusMsg << "}" << endl;
2581     #endif
2582       bool first = true;
2583 
2584       sp = read_register(rn);
2585       for(ra = 0, rb = 0x01; rb; rb = (rb << 1) & 0xFF, ++ra)
2586       {
2587         if(inst & rb)
2588         {
2589           write32(sp, read_register(ra));
2590           if(first)
2591           {
2592             INC_N_CYCLES(sp, AccessType::data);
2593             first = false;
2594           }
2595           else
2596           {
2597             INC_S_CYCLES(sp, AccessType::data);
2598           }
2599           sp += 4;
2600         }
2601       }
2602       write_register(rn, sp);
2603       FETCH_TYPE_N;
2604       return 0;
2605     }
2606 
2607     //STR(1)
2608     case Op::str1: {
2609       rd = (inst >> 0) & 0x07;
2610       rn = (inst >> 3) & 0x07;
2611       rb = (inst >> 6) & 0x1F;
2612       rb <<= 2;
2613       DO_DISS(statusMsg << "str r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl);
2614       rb = read_register(rn) + rb;
2615       rc = read_register(rd);
2616       write32(rb, rc);
2617       INC_STR_CYCLES;
2618       return 0;
2619     }
2620 
2621     //STR(2)
2622     case Op::str2: {
2623       rd = (inst >> 0) & 0x7;
2624       rn = (inst >> 3) & 0x7;
2625       rm = (inst >> 6) & 0x7;
2626       DO_DISS(statusMsg << "str r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl);
2627       rb = read_register(rn) + read_register(rm);
2628       rc = read_register(rd);
2629       write32(rb, rc);
2630       INC_STR_CYCLES;
2631       return 0;
2632     }
2633 
2634     //STR(3)
2635     case Op::str3: {
2636       rb = (inst >> 0) & 0xFF;
2637       rd = (inst >> 8) & 0x07;
2638       rb <<= 2;
2639       DO_DISS(statusMsg << "str r" << dec << rd << ",[SP,#0x" << Base::HEX2 << rb << "]" << endl);
2640       rb = read_register(13) + rb;
2641       //fprintf(stderr,"0x%08X\n",rb);
2642       rc = read_register(rd);
2643       write32(rb, rc);
2644       INC_STR_CYCLES;
2645       return 0;
2646     }
2647 
2648     //STRB(1)
2649     case Op::strb1: {
2650       rd = (inst >> 0) & 0x07;
2651       rn = (inst >> 3) & 0x07;
2652       rb = (inst >> 6) & 0x1F;
2653       DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX8 << rb << "]" << endl);
2654       rb = read_register(rn) + rb;
2655       rc = read_register(rd);
2656 #ifndef UNSAFE_OPTIMIZATIONS
2657       ra = read16(rb & (~1U));
2658 #else
2659       ra = read16(rb);
2660 #endif
2661       if(rb & 1)
2662       {
2663         ra &= 0x00FF;
2664         ra |= rc << 8;
2665       }
2666       else
2667       {
2668         ra &= 0xFF00;
2669         ra |= rc & 0x00FF;
2670       }
2671       write16(rb & (~1U), ra & 0xFFFF);
2672       INC_STRB_CYCLES;
2673       return 0;
2674     }
2675 
2676     //STRB(2)
2677     case Op::strb2: {
2678       rd = (inst >> 0) & 0x7;
2679       rn = (inst >> 3) & 0x7;
2680       rm = (inst >> 6) & 0x7;
2681       DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",r" << rm << "]" << endl);
2682       rb = read_register(rn) + read_register(rm);
2683       rc = read_register(rd);
2684 #ifndef UNSAFE_OPTIMIZATIONS
2685       ra = read16(rb & (~1U));
2686 #else
2687       ra = read16(rb);
2688 #endif
2689       if(rb & 1)
2690       {
2691         ra &= 0x00FF;
2692         ra |= rc << 8;
2693       }
2694       else
2695       {
2696         ra &= 0xFF00;
2697         ra |= rc & 0x00FF;
2698       }
2699       write16(rb & (~1U), ra & 0xFFFF);
2700       INC_STRB_CYCLES;
2701       return 0;
2702     }
2703 
2704     //STRH(1)
2705     case Op::strh1: {
2706       rd = (inst >> 0) & 0x07;
2707       rn = (inst >> 3) & 0x07;
2708       rb = (inst >> 6) & 0x1F;
2709       rb <<= 1;
2710       DO_DISS(statusMsg << "strh r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl);
2711       rb = read_register(rn) + rb;
2712       rc=  read_register(rd);
2713       write16(rb, rc & 0xFFFF);
2714       INC_STR_CYCLES;
2715       return 0;
2716     }
2717 
2718     //STRH(2)
2719     case Op::strh2: {
2720       rd = (inst >> 0) & 0x7;
2721       rn = (inst >> 3) & 0x7;
2722       rm = (inst >> 6) & 0x7;
2723       DO_DISS(statusMsg << "strh r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl);
2724       rb = read_register(rn) + read_register(rm);
2725       rc = read_register(rd);
2726       write16(rb, rc & 0xFFFF);
2727       INC_STR_CYCLES;
2728       return 0;
2729     }
2730 
2731     //SUB(1)
2732     case Op::sub1: {
2733       rd = (inst >> 0) & 0x7;
2734       rn = (inst >> 3) & 0x7;
2735       rb = (inst >> 6) & 0x7;
2736       DO_DISS(statusMsg << "subs r" << dec << rd << ",r" << dec << rn << ",#0x" << Base::HEX2 << rb << endl);
2737       ra = read_register(rn);
2738       rc = ra - rb;
2739       write_register(rd, rc);
2740       do_nflag(rc);
2741       do_zflag(rc);
2742       do_cflag(ra, ~rb, 1);
2743       do_vflag(ra, ~rb, 1);
2744       return 0;
2745     }
2746 
2747     //SUB(2)
2748     case Op::sub2: {
2749       rb = (inst >> 0) & 0xFF;
2750       rd = (inst >> 8) & 0x07;
2751       DO_DISS(statusMsg << "subs r" << dec << rd << ",#0x" << Base::HEX2 << rb << endl);
2752       ra = read_register(rd);
2753       rc = ra - rb;
2754       write_register(rd, rc);
2755       do_nflag(rc);
2756       do_zflag(rc);
2757       do_cflag(ra, ~rb, 1);
2758       do_vflag(ra, ~rb, 1);
2759       return 0;
2760     }
2761 
2762     //SUB(3)
2763     case Op::sub3: {
2764       rd = (inst >> 0) & 0x7;
2765       rn = (inst >> 3) & 0x7;
2766       rm = (inst >> 6) & 0x7;
2767       DO_DISS(statusMsg << "subs r" << dec << rd << ",r" << dec << rn << ",r" << dec << rm << endl);
2768       ra = read_register(rn);
2769       rb = read_register(rm);
2770       rc = ra - rb;
2771       write_register(rd, rc);
2772       do_nflag(rc);
2773       do_zflag(rc);
2774       do_cflag(ra, ~rb, 1);
2775       do_vflag(ra, ~rb, 1);
2776       return 0;
2777     }
2778 
2779     //SUB(4)
2780     case Op::sub4: {
2781       rb = inst & 0x7F;
2782       rb <<= 2;
2783       DO_DISS(statusMsg << "sub SP,#0x" << Base::HEX2 << rb << endl);
2784       ra = read_register(13);
2785       ra -= rb;
2786       write_register(13, ra);
2787       return 0;
2788     }
2789 
2790     //SWI
2791     case Op::swi: {
2792       rb = inst & 0xFF;
2793       DO_DISS(statusMsg << "swi 0x" << Base::HEX2 << rb << endl);
2794 
2795       if(rb == 0xCC)
2796       {
2797         write_register(0, cpsr);
2798         return 0;
2799       }
2800       else
2801       {
2802 #if defined(THUMB_DISS)
2803         statusMsg << endl << endl << "swi 0x" << Base::HEX2 << rb << endl;
2804 #endif
2805         return 1;
2806       }
2807     }
2808 
2809     //SXTB
2810     case Op::sxtb: {
2811       rd = (inst >> 0) & 0x7;
2812       rm = (inst >> 3) & 0x7;
2813       DO_DISS(statusMsg << "sxtb r" << dec << rd << ",r" << dec << rm << endl);
2814       ra = read_register(rm);
2815       rc = ra & 0xFF;
2816       if(rc & 0x80)
2817         rc |= (~0U) << 8;
2818       write_register(rd, rc);
2819       return 0;
2820     }
2821 
2822     //SXTH
2823     case Op::sxth: {
2824       rd = (inst >> 0) & 0x7;
2825       rm = (inst >> 3) & 0x7;
2826       DO_DISS(statusMsg << "sxth r" << dec << rd << ",r" << dec << rm << endl);
2827       ra = read_register(rm);
2828       rc = ra & 0xFFFF;
2829       if(rc & 0x8000)
2830         rc |= (~0U) << 16;
2831       write_register(rd, rc);
2832       return 0;
2833     }
2834 
2835     //TST
2836     case Op::tst: {
2837       rn = (inst >> 0) & 0x7;
2838       rm = (inst >> 3) & 0x7;
2839       DO_DISS(statusMsg << "tst r" << dec << rn << ",r" << dec << rm << endl);
2840       ra = read_register(rn);
2841       rb = read_register(rm);
2842       rc = ra & rb;
2843       do_nflag(rc);
2844       do_zflag(rc);
2845       return 0;
2846     }
2847 
2848     //UXTB
2849     case Op::uxtb: {
2850       rd = (inst >> 0) & 0x7;
2851       rm = (inst >> 3) & 0x7;
2852       DO_DISS(statusMsg << "uxtb r" << dec << rd << ",r" << dec << rm << endl);
2853       ra = read_register(rm);
2854       rc = ra & 0xFF;
2855       write_register(rd, rc);
2856       return 0;
2857     }
2858 
2859     //UXTH
2860     case Op::uxth: {
2861       rd = (inst >> 0) & 0x7;
2862       rm = (inst >> 3) & 0x7;
2863       DO_DISS(statusMsg << "uxth r" << dec << rd << ",r" << dec << rm << endl);
2864       ra = read_register(rm);
2865       rc = ra & 0xFFFF;
2866       write_register(rd, rc);
2867       return 0;
2868     }
2869 
2870     // Silence compiler
2871     case Op::numOps:
2872       break;
2873 
2874 #ifndef UNSAFE_OPTIMIZATIONS
2875     case Op::invalid:
2876       break;
2877 #else
2878     default:
2879       break;
2880 #endif
2881   }
2882 
2883 #ifndef UNSAFE_OPTIMIZATIONS
2884   statusMsg << "invalid instruction " << Base::HEX8 << pc << " " << Base::HEX4 << inst << endl;
2885 #endif
2886   return 1;
2887 }
2888 
2889 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
reset()2890 int Thumbulator::reset()
2891 {
2892   reg_norm.fill(0);
2893 
2894   reg_norm[13] = cStack;              // SP
2895   reg_norm[14] = cBase;               // LR
2896   reg_norm[15] = (cStart + 2) | 1;    // PC (+2 for pipeline, lower bit for THUMB)
2897 
2898   cpsr = 0;
2899   handler_mode = false;
2900 
2901   systick_ctrl = 0x00000004;
2902   systick_reload = 0x00000000;
2903   systick_count = 0x00000000;
2904   systick_calibrate = 0x00ABCDEF;
2905 
2906   // fxq: don't care about below so much (maybe to guess timing???)
2907 #ifndef UNSAFE_OPTIMIZATIONS
2908   _stats.instructions = 0;
2909   statusMsg.str("");
2910 #endif
2911 #ifdef THUMB_STATS
2912   _stats.reads = _stats.writes
2913     = _stats.nCylces = _stats.sCylces = _stats.iCylces
2914     = _stats.branches = _stats.taken
2915     = _stats.mamPrefetchHits = _stats.mamPrefetchMisses
2916     = _stats.mamBranchHits = _stats.mamBranchMisses
2917     = _stats.mamDataHits = _stats.mamDataMisses = 0;
2918 #endif
2919 #ifdef THUMB_CYCLE_COUNT
2920   _totalCycles = 0;
2921  #ifdef EMULATE_PIPELINE
2922   _fetchPipeline = _memory0Pipeline = _memory1Pipeline = 0;
2923  #endif
2924 #endif
2925 #ifdef COUNT_OPS
2926   //memset(opCount, 0, sizeof(opCount));
2927 #endif
2928   return 0;
2929 }
2930 
2931 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setChipType(ChipType type)2932 Thumbulator::ChipPropsType Thumbulator::setChipType(ChipType type)
2933 {
2934   ChipPropsType props = ChipProps[static_cast<uInt32>(type)];
2935 
2936   _chipType = type;
2937   _MHz = props.MHz;
2938 #ifdef THUMB_CYCLE_COUNT
2939   _flashCycles = props.flashCycles;
2940   _flashBanks = props.flashBanks;
2941 #endif
2942 
2943   setConsoleTiming(_consoleTiming);
2944 
2945   return props;
2946 }
2947 
2948 #ifdef THUMB_CYCLE_COUNT
2949 // Notes:
2950 // For exact cylce counting we have to
2951 // - emulate the LPC21xx prefetch, branch and data buffers
2952 // - differentiate between S and N cycles
2953 // - simulation the pipeline (including stalls)
2954 
2955 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2956 /*
2957   This simulates the MAM of the LPC2101_02_03. It has three 128-bits buffers:
2958   - prefetch buffer
2959   - branch trail buffer
2960   - data buffer
2961 
2962   Instruction prefetches are checking the prefetch and the branch trail buffer.
2963   - If a prefetch cannot be found in the two buffers a new line of 128 bits is read from memory
2964     and put into the prefetch buffer. This causes wait states.
2965   - If a branch target cannot be found in the two buffers a new line of 128 bits is read from
2966     memory and put into the branch trail buffer. This causes wait states.
2967 
2968   Data access is only checking and updating the data buffer.
2969 
2970   The function returns true in case of a buffer hit.
2971 */
isMamBuffered(uInt32 addr,AccessType accessType)2972 bool Thumbulator::isMamBuffered(uInt32 addr, AccessType accessType)
2973 {
2974   if(_flashBanks == 1) // e.g. LPC2101_02_03
2975   {
2976     // single Flash bank
2977     addr &= ~0x7F; // 128-bit address line
2978 
2979     switch(accessType)
2980     {
2981       case AccessType::prefetch:
2982         if(addr != _prefetchBufferAddr[0] && addr != _branchBufferAddr[0])
2983         {
2984         #ifdef THUMB_STATS
2985           ++_stats.mamPrefetchMisses;
2986         #endif
2987           _prefetchBufferAddr[0] = addr;
2988           return false;
2989         }
2990       #ifdef THUMB_STATS
2991         ++_stats.mamPrefetchHits;
2992       #endif
2993         break;
2994 
2995       case AccessType::branch:
2996         if(addr != _prefetchBufferAddr[0] && addr != _branchBufferAddr[0])
2997         {
2998         #ifdef THUMB_STATS
2999           ++_stats.mamBranchMisses;
3000         #endif
3001           _branchBufferAddr[0] = addr;
3002           return false;
3003         }
3004       #ifdef THUMB_STATS
3005         ++_stats.mamBranchHits;
3006       #endif
3007 
3008         break;
3009 
3010       default: // AccessType::data
3011         if(addr != _dataBufferAddr)
3012         {
3013         #ifdef THUMB_STATS
3014           ++_stats.mamDataMisses;
3015         #endif
3016           _dataBufferAddr = addr;
3017           return false;
3018         }
3019       #ifdef THUMB_STATS
3020         ++_stats.mamDataHits;
3021       #endif
3022         break;
3023     }
3024   }
3025   else // e.g. LPC2104_05_06
3026   {
3027     // dual Flash bank
3028     uInt32 bank = (addr & 0x80) ? 1 : 0;
3029 
3030     addr &= ~0x7F; // 128-bit address line
3031 
3032     switch(accessType)
3033     {
3034       case AccessType::prefetch:
3035         // speculative load, executed after last instrucution has been executed
3036         _prefetchBufferAddr[bank ^ 1] = addr + 0x80;
3037         if(addr != _prefetchBufferAddr[bank] && addr != _branchBufferAddr[bank])
3038         {
3039         #ifdef THUMB_STATS
3040           ++_stats.mamPrefetchMisses;
3041         #endif
3042           _prefetchBufferAddr[bank] = addr;
3043           return false;
3044         }
3045       #ifdef THUMB_STATS
3046         ++_stats.mamPrefetchHits;
3047       #endif
3048         break;
3049 
3050       case AccessType::branch:
3051         if(addr != _prefetchBufferAddr[bank] && addr != _branchBufferAddr[bank])
3052         {
3053         #ifdef THUMB_STATS
3054           ++_stats.mamBranchMisses;
3055         #endif
3056           // load both branch trail buffers at once
3057           _branchBufferAddr[bank] = addr;
3058           _branchBufferAddr[bank ^ 1] = addr + 0x80;
3059           return false;
3060         }
3061       #ifdef THUMB_STATS
3062         ++_stats.mamBranchHits;
3063       #endif
3064         break;
3065 
3066       default: // AccessType::data
3067         if(addr != _dataBufferAddr)
3068         {
3069         #ifdef THUMB_STATS
3070           ++_stats.mamDataMisses;
3071         #endif
3072           _dataBufferAddr = addr;
3073           return false;
3074         }
3075       #ifdef THUMB_STATS
3076         ++_stats.mamDataHits;
3077       #endif
3078         break;
3079     }
3080   }
3081   return true;
3082 }
3083 
3084 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
incCycles(AccessType accessType,uInt32 cycles)3085 void Thumbulator::incCycles(AccessType accessType, uInt32 cycles)
3086 {
3087 #ifdef EMULATE_PIPELINE
3088   // simulate the pipeline effects
3089   //if(_memory0Pipeline)
3090   //{
3091   //  --_memory0Pipeline; // == 0
3092   //  ++_fetchPipeline;
3093   //}
3094   if(_memory1Pipeline)
3095   {
3096     --_memory1Pipeline;
3097     ++_memory0Pipeline; // == 1
3098   }
3099 
3100   switch(accessType)
3101   {
3102     case AccessType::branch:
3103       _fetchPipeline = _memory0Pipeline = _memory1Pipeline = 0; // flush pipeline
3104       break;
3105 
3106     case AccessType::data:
3107       if(cycles == 1) // no Flash access
3108         ++_fetchPipeline;
3109       else
3110         _memory1Pipeline += cycles;
3111       break;
3112 
3113     default: // AccessType::prefetch
3114     {
3115       // Reduce cycles by pipelined cycles
3116       // Cart (Turbo start sequence): 1F0AC
3117       // None:      1FF2E @ 90% (22989 @ 100%)
3118     #if 1
3119       // Version 1: 1ECFC @ 90% (223C3 @ 100%)
3120       if(cycles == _flashCycles)
3121       {
3122         if(!_memory1Pipeline) // there must be no pending memory access
3123         {
3124           uInt32 newCycles = std::max(1, Int32(cycles - _fetchPipeline));
3125 
3126           _fetchPipeline -= (cycles - newCycles);
3127           cycles = newCycles;
3128         }
3129       }
3130     #endif
3131     #if 0
3132       // Version 2: 1ED23 @ 90% (223EF @ 100%)
3133       //   considers that partial fetches are not allowed
3134       if(cycles == _flashCycles)
3135       {
3136         //_memory0Pipeline = _memory1Pipeline = 0;
3137         if(!_memory1Pipeline && _fetchPipeline >= _flashCycles)
3138         {
3139           _fetchPipeline -= (_flashCycles - 1);
3140           cycles = 1;
3141         }
3142         //else
3143         // _fetchPipeline = 0; // Flash prefetch abort (makes 0 difference!)
3144       }
3145     #endif
3146       break;
3147     }
3148   };
3149 #endif
3150 
3151 //#ifdef MERGE_I_S
3152 //   TODO
3153 //  if(accessType == AccessType::branch)
3154 //    _lastCycleType[2] = _lastCycleType[1] = _lastCycleType[0] = CycleType::S;
3155 //#endif
3156 
3157   _totalCycles += cycles;
3158 }
3159 
3160 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
incSCycles(uInt32 addr,AccessType accessType)3161 void Thumbulator::incSCycles(uInt32 addr, AccessType accessType)
3162 {
3163 #ifdef THUMB_STATS
3164   ++_stats.sCylces;
3165 #endif
3166 
3167   uInt32 cycles;
3168 
3169 
3170   if(addr & 0xC0000000) // RAM, peripherals
3171     cycles = 1;
3172   else // Flash
3173   {
3174     if(mamcr == MamModeType::mode0 ||
3175        (mamcr == MamModeType::mode1 && accessType == AccessType::data))
3176     {
3177       cycles = _flashCycles; // 3|4
3178     }
3179     else
3180     {
3181       if(isMamBuffered(addr, accessType) || mamcr == MamModeType::modeX)
3182         cycles = 1;
3183       else
3184         cycles = _flashCycles;
3185     }
3186   }
3187 
3188 #ifdef MERGE_I_S
3189   //if(accessType != AccessType::prefetch)
3190   //{
3191   //  if(_lastCycleType[0] == CycleType::I)
3192   //  {
3193   //    _lastCycleType[0] = CycleType::S; // merge cannot be used twice!
3194   //    --cycles;
3195   //  }
3196   //}
3197   //else if(_lastCycleType[2] == CycleType::I)
3198   //  --cycles;
3199 
3200   //if(accessType == AccessType::prefetch &&
3201   //  _lastCycleType[_pipeIdx] == CycleType::I)
3202   //  --cycles;
3203 
3204 
3205   _lastCycleType[2] = _lastCycleType[1];
3206   _lastCycleType[1] = _lastCycleType[0];
3207   _lastCycleType[0] = CycleType::S;
3208   //_lastCycleType[_pipeIdx] = CycleType::S;
3209 #endif
3210   incCycles(accessType, cycles);
3211 
3212 
3213 #ifdef MERGE_I_S
3214   if(accessType == AccessType::branch)
3215   {
3216     if(_lastCycleType[1] == CycleType::I || _lastCycleType[2] == CycleType::I)
3217     _lastCycleType[1] = _lastCycleType[2] = CycleType::S;
3218     //if(_lastCycleType[_pipeIdx ^ 1] == CycleType::I || _lastCycleType[_pipeIdx ^ 2] == CycleType::I)
3219     //  _lastCycleType[_pipeIdx ^ 1] = _lastCycleType[_pipeIdx ^ 2] = CycleType::S;
3220   }
3221 #endif // MERGE_I_S
3222 }
3223 
3224 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
incNCycles(uInt32 addr,AccessType accessType)3225 void Thumbulator::incNCycles(uInt32 addr, AccessType accessType)
3226 {
3227 #ifdef THUMB_STATS
3228   ++_stats.nCylces;
3229 #endif
3230 
3231   uInt32 cycles;
3232 
3233   if(addr & 0xC0000000) // RAM, peripherals
3234     cycles = 1;
3235   else // Flash
3236   {
3237     if(mamcr < MamModeType::mode2)
3238       cycles = _flashCycles; // 3|4
3239     else
3240       if(isMamBuffered(addr, accessType) || mamcr == MamModeType::modeX)
3241         cycles = 1;
3242       else
3243         cycles = _flashCycles;
3244   }
3245 #ifdef MERGE_I_S
3246   _lastCycleType[2] = _lastCycleType[1];
3247   _lastCycleType[1] = _lastCycleType[0];
3248   _lastCycleType[0] = CycleType::N;
3249   //_lastCycleType[_pipeIdx] = CycleType::N;
3250 #endif
3251   incCycles(accessType, cycles);
3252 }
3253 
3254 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
incICycles(uInt32 m)3255 void Thumbulator::incICycles(uInt32 m)
3256 {
3257 #ifdef THUMB_STATS
3258   ++_stats.iCylces;
3259 #endif
3260 
3261  #ifdef EMULATE_PIPELINE
3262   _fetchPipeline += m;
3263   //if(_memory0Pipeline)
3264   //{
3265   //  --_memory0Pipeline; // == 0
3266   //  ++_fetchPipeline;
3267   //}
3268 
3269   // TODO: m!
3270   if(_memory1Pipeline)
3271   {
3272     --_memory1Pipeline;
3273     ++_memory0Pipeline; // == 1
3274   }
3275  #endif
3276 #ifdef MERGE_I_S
3277   _lastCycleType[2] = _lastCycleType[1];
3278   _lastCycleType[1] = _lastCycleType[0];
3279   _lastCycleType[0] = CycleType::I;
3280   //_lastCycleType[_pipeIdx] = CycleType::I;
3281 #endif
3282   _totalCycles += m;
3283 }
3284 
3285 #endif // THUMB_CYCLE_COUNT
3286