OSDN Git Service

[VM][STATE] Apply new framework to some VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / tms9995.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME TMS99xx Core
5         Author : Takeda.Toshiya
6         Date   : 2007.07.14 -
7
8         [ TMS9995 ]
9 */
10
11 #include "tms9995.h"
12 #ifdef USE_DEBUGGER
13 #include "debugger.h"
14 #endif
15
16 #define ST_LGT  0x8000
17 #define ST_AGT  0x4000
18 #define ST_EQ   0x2000
19 #define ST_C    0x1000
20 #define ST_OV   0x0800
21 #define ST_OP   0x0400
22 #define ST_X    0x0200
23 #define ST_OVIE 0x0020
24 #define ST_IM   0x000f
25
26 #define R0      0
27 #define R1      2
28 #define R2      4
29 #define R3      6
30 #define R4      8
31 #define R5      10
32 #define R6      12
33 #define R7      14
34 #define R8      16
35 #define R9      18
36 #define R10     20
37 #define R11     22
38 #define R12     24
39 #define R13     26
40 #define R14     28
41 #define R15     30
42
43 #define MEM_WAIT_BYTE   4
44 #define MEM_WAIT_WORD   12
45
46 #ifdef __BIG_ENDIAN__
47 #define BYTE_XOR_BE(a)  (a)
48 #else
49 #define BYTE_XOR_BE(a)  ((a) ^ 1)
50 #endif
51
52 #define CRU_MASK_R      ((1 << 12) - 1)
53 #define CRU_MASK_W      ((1 << 15) - 1)
54
55 static const uint16_t right_shift_mask_table[17] = {
56         0xffff,
57         0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff, 0x00ff,
58         0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001, 0x0000
59 };
60 static const uint16_t inverted_right_shift_mask_table[17] = {
61         0x0000,
62         0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
63         0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff
64 };
65
66 // memory
67 uint16_t TMS9995::RM16(uint16_t addr)
68 #ifdef USE_DEBUGGER
69 {
70         return d_mem_tmp->read_data16(addr);
71 }
72 uint32_t TMS9995::read_data16(uint32_t addr)
73 #endif
74 {
75         if(addr < 0xf000) {
76                 period += MEM_WAIT_WORD;
77                 uint16_t tmp = d_mem->read_data8(addr);
78                 return (tmp << 8) | d_mem->read_data8(addr + 1);
79         } else if(addr < 0xf0fc) {
80                 return *(uint16_t *)(&RAM[addr & 0xff]);
81         } else if(addr < 0xfffa) {
82                 period += MEM_WAIT_WORD;
83                 uint16_t tmp = d_mem->read_data8(addr);
84                 return (tmp << 8) | d_mem->read_data8(addr + 1);
85         } else if(addr < 0xfffc) {
86                 if(dec_enabled && !(mode & 1)) {
87                         return (dec_timer >> 4) & 0xffff;
88                 } else {
89                         return dec_count;
90                 }
91         } else {
92                 return *(uint16_t *)(&RAM[addr & 0xff]);
93         }
94 }
95
96 void TMS9995::WM16(uint16_t addr, uint16_t val)
97 #ifdef USE_DEBUGGER
98 {
99         d_mem_tmp->write_data16(addr, val);
100 }
101 void TMS9995::write_data16(uint32_t addr, uint32_t val)
102 #endif
103 {
104         if(addr < 0xf000) {
105                 period += MEM_WAIT_WORD;
106                 d_mem->write_data8(addr, val >> 8);
107                 d_mem->write_data8(addr + 1, val & 0xff);
108         } else if(addr < 0xf0fc) {
109                 *(uint16_t *)(&RAM[addr & 0xff]) = val;
110         } else if(addr < 0xfffa) {
111                 period += MEM_WAIT_WORD;
112                 d_mem->write_data8(addr, val >> 8);
113                 d_mem->write_data8(addr + 1, val & 0xff);
114         } else if(addr < 0xfffc) {
115                 dec_interval = val;
116                 update_dec();
117         } else {
118                 *(uint16_t *)(&RAM[addr & 0xff]) = val;
119         }
120 }
121
122 uint8_t TMS9995::RM8(uint16_t addr)
123 #ifdef USE_DEBUGGER
124 {
125         return d_mem_tmp->read_data8(addr);
126 }
127 uint32_t TMS9995::read_data8(uint32_t addr)
128 #endif
129 {
130         if((addr < 0xf000)) {
131                 period += MEM_WAIT_BYTE;
132                 return d_mem->read_data8(addr);
133         } else if(addr < 0xf0fc) {
134                 return RAM[BYTE_XOR_BE(addr & 0xff)];
135         } else if(addr < 0xfffa) {
136                 period += MEM_WAIT_BYTE;
137                 return d_mem->read_data8(addr);
138         } else if(addr < 0xfffc) {
139                 uint16_t tmp;
140                 if(dec_enabled && !(mode & 1)) {
141                         tmp = (dec_timer >> 4) & 0xffff;
142                 } else {
143                         tmp = dec_count;
144                 }
145                 return (addr & 1) ? (tmp & 0xff) : (tmp >> 8);
146         } else {
147                 return RAM[BYTE_XOR_BE(addr & 0xff)];
148         }
149 }
150
151 void TMS9995::WM8(uint32_t addr, uint8_t val)
152 #ifdef USE_DEBUGGER
153 {
154         d_mem_tmp->write_data8(addr, val);
155 }
156 void TMS9995::write_data8(uint32_t addr, uint32_t val)
157 #endif
158 {
159         if((addr < 0xf000)) {
160                 period += MEM_WAIT_BYTE;
161                 d_mem->write_data8(addr, val);
162         } else if(addr < 0xf0fc) {
163                 RAM[BYTE_XOR_BE(addr & 0xff)] = val;
164         } else if(addr < 0xfffa) {
165                 period += MEM_WAIT_BYTE;
166                 d_mem->write_data8(addr, val);
167         } else if(addr < 0xfffc) {
168                 dec_interval = (val << 8) | val;
169                 update_dec();
170         } else {
171                 RAM[BYTE_XOR_BE(addr & 0xff)] = val;
172         }
173 }
174
175 inline uint16_t TMS9995::FETCH16()
176 {
177         uint16_t tmp = RM16(PC);
178         PC += 2;
179         return tmp;
180 }
181
182 #define RREG(reg)       RM16((WP + (reg)) & 0xffff)
183 #define WREG(reg, val)  WM16((WP + (reg)) & 0xffff, (val))
184
185 // i/o
186 uint16_t TMS9995::IN8(int addr)
187 #ifdef USE_DEBUGGER
188 {
189         return d_io_tmp->read_io8(addr);
190 }
191 uint32_t TMS9995::read_io8(uint32_t addr)
192 #endif
193 {
194         switch(addr) {
195         case 0x1ee:
196                 return mode & 0xff;
197         case 0x1ef:
198                 return (mode >> 8) & 0xff;
199         case 0x1fd:
200                 if(mid) {
201                         return d_io->read_io8(addr) | 0x10;
202                 } else {
203                         return d_io->read_io8(addr) & ~ 0x10;
204                 }
205         }
206         return d_io->read_io8(addr);
207 }
208
209 void TMS9995::OUT8(uint16_t addr, uint16_t val)
210 #ifdef USE_DEBUGGER
211 {
212         d_io_tmp->write_io8(addr, val);
213 }
214 void TMS9995::write_io8(uint32_t addr, uint32_t val)
215 #endif
216 {
217         switch(addr) {
218         case 0xf70:
219                 if(val & 1) {
220                         mode |= 1;
221                 } else {
222                         mode &= ~1;
223                 }
224                 update_dec();
225                 break;
226         case 0xf71:
227                 if(val & 1) {
228                         mode |= 2;
229                 } else {
230                         mode &= ~2;
231                 }
232                 update_dec();
233                 break;
234         case 0xf72:
235         case 0xf73:
236         case 0xf74:
237                 break;
238         case 0xf75:
239         case 0xf76:
240         case 0xf77:
241         case 0xf78:
242         case 0xf79:
243         case 0xf7a:
244         case 0xf7b:
245         case 0xf7c:
246         case 0xf7d:
247         case 0xf7e:
248         case 0xf7f:
249                 if(val & 1) {
250                         mode |= (1 << (addr - 0xf70));
251                 } else {
252                         mode &= ~(1 << (addr - 0xf70));
253                 }
254                 break;
255         case 0xfed:
256                 mid = ((val & 1) != 0);
257                 break;
258         }
259         d_io->write_io8(addr, val & 1);
260 }
261
262 inline void TMS9995::EXTOUT8(uint16_t addr)
263 {
264 #ifdef USE_DEBUGGER
265         d_io_tmp->write_io8(addr << 15, 0);     // or is it 1 ???
266 #else
267         d_io->write_io8(addr << 15, 0); // or is it 1 ???
268 #endif
269 }
270
271 uint16_t TMS9995::RCRU(uint16_t addr, int bits)
272 {
273         static const uint16_t bitmask[] = {
274                 0,
275                 0x0001,0x0003,0x0007,0x000f,0x001f,0x003f,0x007f,0x00ff,
276                 0x01ff,0x03ff,0x07ff,0x0fff,0x1fff,0x3fff,0x7fff,0xffff
277         };
278         uint16_t loc = (uint16_t)((addr >> 3) & CRU_MASK_R);
279         uint16_t ofs = addr & 7;
280         uint16_t val = IN8(loc);
281         
282         if((ofs + bits) > 8) {
283                 loc = (uint16_t)((loc + 1) & CRU_MASK_R);
284                 val |= IN8(loc) << 8;
285                 if((ofs + bits) > 16) {
286                         loc = (uint16_t)((loc + 1) & CRU_MASK_R);
287                         val |= IN8(loc) << 16;
288                 }
289         }
290         val >>= ofs;
291         return val & bitmask[bits];
292 }
293
294 void TMS9995::WCRU(uint16_t addr, int bits, uint16_t val)
295 {
296         addr &= CRU_MASK_W;
297         for(int i = 0; i < bits; i++) {
298                 OUT8(addr, val);
299                 val >>= 1;
300                 addr = (uint16_t)((addr + 1) & CRU_MASK_W);
301         }
302 }
303
304 void TMS9995::initialize()
305 {
306         DEVICE::initialize();
307 #ifdef USE_DEBUGGER
308         d_mem_tmp = d_io_tmp = this;
309         d_debugger->set_context_mem(this);
310         d_debugger->set_context_io(this);
311 #endif
312 }
313
314 void TMS9995::reset()
315 {
316         ST = 0;
317         getstat();
318         mid = idle = false;
319         
320         mode &= ~3;
321         update_dec();
322         int_latch = 0;
323         mode &= 0xffe3;
324         update_int();
325         contextswitch(0x0000);
326 //      period += 56;
327         count = 0;
328 }
329
330 int TMS9995::run(int clock)
331 {
332         // run cpu
333         if(clock == -1) {
334                 // run only one opcode
335                 count = 0;
336                 run_one_opecode();
337                 return -count;
338         } else {
339                 // run cpu while given clocks
340                 count += clock;
341                 int first_count = count;
342                 
343                 while(count > 0) {
344                         run_one_opecode();
345                 }
346                 return first_count - count;
347         }
348 }
349
350 void TMS9995::run_one_opecode()
351 #ifdef USE_DEBUGGER
352 {
353         bool now_debugging = d_debugger->now_debugging;
354         if(now_debugging) {
355                 d_debugger->check_break_points(PC);
356                 if(d_debugger->now_suspended) {
357                         emu->mute_sound();
358                         d_debugger->now_waiting = true;
359                         while(d_debugger->now_debugging && d_debugger->now_suspended) {
360                                 emu->sleep(10);
361                         }
362                         d_debugger->now_waiting = false;
363                 }
364                 if(d_debugger->now_debugging) {
365                         d_mem_tmp = d_io_tmp = d_debugger;
366                 } else {
367                         now_debugging = false;
368                 }
369                 
370                 int first_count = count;
371                 run_one_opecode_tmp();
372                 total_count += first_count - count;
373                 
374                 if(now_debugging) {
375                         if(!d_debugger->now_going) {
376                                 d_debugger->now_suspended = true;
377                         }
378                         d_mem_tmp = d_io_tmp = this;
379                 }
380         } else {
381                 int first_count = count;
382                 run_one_opecode_tmp();
383                 total_count += first_count - count;
384         }
385 }
386 void TMS9995::run_one_opecode_tmp()
387 #endif
388 {
389         period = 0;
390         
391         // update interrupt
392         if(int_pending && int_enabled) {
393                 int level = irq_level;
394                 if(nmi) {
395                         contextswitch(0xfffc);
396                         ST &= ~ST_IM;
397                         idle = false;
398                         period += 56;
399                 } else if(level <= (ST & ST_IM)) {
400                         contextswitch(level*4);
401                         if(level) {
402                                 ST = (ST & ~ST_IM) | (level -1);
403                                 int_pending = false;
404                         } else {
405                                 ST &= ~ST_IM;
406                         }
407                         ST &= 0xfe00;
408                         idle = false;
409                         
410                         if(level != 2) {
411                                 int int_mask = 1 << level;
412                                 int mode_mask = (level == 1) ? 4 : int_mask;
413                                 int_latch &= ~int_mask;
414                                 mode &= ~mode_mask;
415                         }
416                         period += 56;
417                 } else {
418                         int_pending = false;
419                 }
420         }
421         
422         // execute opecode
423         if(idle) {
424                 EXTOUT8(2);
425                 period += 8;
426         } else {
427                 int_enabled = true;
428 #ifdef USE_DEBUGGER
429                 d_debugger->add_cpu_trace(PC);
430 #endif
431                 prevPC = PC;
432                 uint16_t op = FETCH16();
433                 execute(op);
434                 if((ST & ST_OVIE) && (ST & ST_OV) && (irq_level > 2)) {
435                         irq_level = 2;
436                 }
437         }
438         count -= period;
439         
440         // update timer
441         if(dec_enabled && !(mode & 1)) {
442                 dec_timer -= period;
443                 if(dec_timer <= 0) {
444                         int_latch |= 8;
445                         mode |= 8;
446                         update_int();
447                         
448                         // restart ???
449                         dec_timer += dec_interval << 4;
450                 }
451         }
452 }
453
454 void TMS9995::write_signal(int id, uint32_t data, uint32_t mask)
455 {
456         if(id == SIG_TMS9995_NMI) {
457                 nmi = ((data & mask) != 0);
458                 update_int();
459         } else if(id == SIG_TMS9995_INT1) {
460                 set_irq_line(0, ((data & mask) != 0));
461         } else if(id == SIG_TMS9995_INT4) {
462                 set_irq_line(1, ((data & mask) != 0));
463         }
464 }
465
466 void TMS9995::set_irq_line(int irqline, bool state)
467 {
468         int int_mask = (irqline == 0) ? 2 : 0x10;
469         int mode_mask = (irqline == 0) ? 4 : 0x10;
470         bool prev_state = ((int_state & int_mask) != 0);
471         
472         if(prev_state != state) {
473                 if(state) {
474                         int_state |= int_mask;
475                         if((irqline == 1) && (mode & 1)) {
476                                 if(dec_enabled) {
477                                         if((--dec_count) == 0) {
478                                                 int_latch |= 8;
479                                                 mode |= 8;
480                                                 update_int();
481                                                 dec_count = dec_interval;
482                                         }
483                                 }
484                         } else {
485                                 int_latch |= int_mask;
486                                 mode |= mode_mask;
487                         }
488                 } else {
489                         int_state &= ~int_mask;
490                 }
491                 update_int();
492         }
493 }
494
495 void TMS9995::update_int()
496 {
497         if(nmi) {
498                 int_pending = true;
499         } else {
500                 int cur_int, level;
501                 if(mode & 1) {
502                         cur_int = (int_state & ~0x10) | int_latch;
503                 } else {
504                         cur_int = int_state | int_latch;
505                 }
506                 if(cur_int) {
507                         for (level = 0; !(cur_int & 1); cur_int >>= 1, level++) {
508                                 ;
509                         }
510                 } else {
511                         level = 16;
512                 }
513                 irq_level = level;
514                 int_pending = (level <= (ST & ST_IM));
515         }
516 }
517
518 void TMS9995::update_dec()
519 {
520         dec_count = dec_interval;
521         dec_enabled = ((mode & 2) && dec_interval);
522         dec_timer = dec_interval << 4;
523 }
524
525 void TMS9995::contextswitch(uint16_t addr)
526 {
527         uint16_t oldWP = WP;
528         uint16_t oldPC = PC;
529         
530         WP = RM16(addr) & ~1;
531         PC = RM16(addr+2) & ~1;
532         WREG(R13, oldWP);
533         WREG(R14, oldPC);
534         setstat();
535         WREG(R15, ST);
536 }
537
538 void TMS9995::execute(uint16_t op)
539 {
540         switch(op >> 8) {
541         case 0x00:
542                 h0040(op);
543                 break;
544         case 0x01:
545                 h0100(op);
546                 break;
547         case 0x02: case 0x03:
548                 h0200(op);
549                 break;
550         case 0x04: case 0x05: case 0x06: case 0x07:
551                 h0400(op);
552                 break;
553         case 0x08: case 0x09: case 0x0a: case 0x0b:
554                 h0800(op);
555                 break;
556         case 0x0c: case 0x0d: case 0x0e: case 0x0f:
557                 illegal(op);
558                 break;
559         case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
560         case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
561                 h1000(op);
562                 break;
563         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
564         case 0x28: case 0x29: case 0x2a: case 0x2b:
565         case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
566                 h2000(op);
567                 break;
568         case 0x2c: case 0x2d: case 0x2e: case 0x2f:
569                 xop(op);
570                 break;
571         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
572                 ldcr_stcr(op);
573                 break;
574         case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
575         case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
576         case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
577         case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
578         case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
579         case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
580         case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
581         case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
582         case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
583         case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
584         case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
585         case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
586                 h4000w(op);
587                 break;
588         case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
589         case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
590         case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
591         case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
592         case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
593         case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
594         case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
595         case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
596         case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
597         case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
598         case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
599         case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
600                 h4000b(op);
601                 break;
602         }
603 }
604
605 void TMS9995::h0040(uint16_t op)
606 {
607         uint16_t addr = (((op & 0xf) << 1) + WP) & ~1;
608         
609         switch((op & 0xf0) >> 4) {
610         case 8: // LST
611                 ST = RM16(addr);
612                 getstat();
613                 break;
614         case 9: // LWP
615                 WP = RM16(addr) & ~1;
616                 break;
617         default:
618                 illegal(op);
619                 break;
620         }
621 }
622
623 void TMS9995::h0100(uint16_t op)
624 {
625         uint16_t src = decipheraddr(op) & ~1;
626         int16_t d;
627         int32_t p, q;
628         
629         switch((op & 0xc0) >> 6) {
630         case 2: // DIVS
631                 d = (int16_t)RM16(src);
632                 p = (int32_t)((RREG(R0) << 16) | RREG(R1));
633                 q = d ? (p / d) : 0;
634                 if((d == 0) || (q < -32768L) || (q > 32767L)) {
635                         ST |= ST_OV;
636                         period += 40;
637                 } else {
638                         ST &= ~ST_OV;
639                         setst_lae(q);
640                         WREG(R0, q);
641                         WREG(R1, p % d);
642                         period += 132;
643                 }
644                 break;
645         case 3: // MPYS
646                 p = ((int32_t)(int16_t)RM16(src)) * ((int32_t)(int16_t)RREG(R0));
647                 ST &= ~(ST_LGT | ST_AGT | ST_EQ);
648                 if(p > 0) {
649                         ST |= (ST_LGT | ST_AGT);
650                 } else if(p < 0) {
651                         ST |= ST_LGT;
652                 } else {
653                         ST |= ST_EQ;
654                 }
655                 WREG(R0, p >> 16);
656                 WREG(R1, p);
657                 period += 100;
658                 break;
659         default:
660                 illegal(op);
661                 break;
662         }
663 }
664
665 void TMS9995::h0200(uint16_t op)
666 {
667         uint16_t addr = (((op & 0xf) << 1) + WP) & ~1, val;
668         
669         if(((op < 0x2e0) && (op & 0x10)) || ((op >= 0x2e0) && (op & 0x1f))) {
670                 illegal(op);
671                 return;
672         }
673         switch((op & 0x1e0) >> 5)  {
674         case 0: // LI
675                 val = FETCH16();
676                 WM16(addr, val);
677                 setst_lae(val);
678                 period += 12;
679                 break;
680         case 1: //AI
681                 val = FETCH16();
682                 val = setst_add_laeco(RM16(addr), val);
683                 WM16(addr, val);
684                 period += 16;
685                 break;
686         case 2: // ANDI
687                 val = FETCH16();
688                 val = RM16(addr) & val;
689                 WM16(addr, val);
690                 setst_lae(val);
691                 period += 16;
692                 break;
693         case 3: // ORI
694                 val = FETCH16();
695                 val = RM16(addr) | val;
696                 WM16(addr, val);
697                 setst_lae(val);
698                 period += 16;
699                 break;
700         case 4: // CI
701                 val = FETCH16();
702                 setst_c_lae(val, RM16(addr));
703                 period += 16;
704                 break;
705         case 5: // STWP
706                 WM16(addr, WP);
707                 period += 12;
708                 break;
709         case 6: // STST
710                 setstat();
711                 WM16(addr, ST);
712                 period += 12;
713                 break;
714         case 7: // LWPI
715                 WP = FETCH16() & ~1;
716                 period += 16;
717                 break;
718         case 8: // LIMI
719                 val = FETCH16();
720                 ST = (ST & ~ST_IM) | (val & ST_IM);
721                 update_int();
722                 period += 20;
723                 break;
724         case 9: // LMF
725                 illegal(op);
726                 break;
727         case 10: // idle
728                 idle = true;
729                 EXTOUT8(2);
730                 period += 28;
731                 break;
732         case 11: // RSET
733                 ST &= 0xfff0;
734                 update_int();
735                 EXTOUT8(3);
736                 period += 28;
737                 break;
738         case 12: // RTWP
739                 addr = (WP + R13) & ~1;
740                 WP = RM16(addr) & ~1;
741                 addr += 2;
742                 PC = RM16(addr) & ~1;
743                 addr += 2;
744                 ST = RM16(addr);
745                 getstat();
746                 update_int();
747                 period += 24;
748                 break;
749         case 13: // CKON
750         case 14: // CKOF
751         case 15: // LREX
752                 EXTOUT8((op & 0xe0) >> 5);
753                 period += 28;
754                 break;
755         }
756 }
757
758 void TMS9995::h0400(uint16_t op)
759 {
760         uint16_t addr = decipheraddr(op) & ~1, val;
761         
762         switch((op & 0x3c0) >> 6) {
763         case 0: // BLWP
764                 contextswitch(addr);
765                 period += 44;
766                 int_enabled = false;
767                 break;
768         case 1: // B
769                 PC = addr;
770                 period += 12;
771                 break;
772         case 2: // X
773                 execute(RM16(addr));
774                 period += 8;
775                 break;
776         case 3: // CLR
777                 WM16(addr, 0);
778                 period += 12;
779                 break;
780         case 4: // NEG
781                 val = -(int16_t)RM16(addr);
782                 if(val) {
783                         ST &= ~ ST_C;
784                 } else {
785                         ST |= ST_C;
786                 }
787                 setst_laeo(val);
788                 WM16(addr, val);
789                 period += 12;
790                 break;
791         case 5: // INV
792                 val = ~ RM16(addr);
793                 WM16(addr, val);
794                 setst_lae(val);
795                 period += 12;
796                 break;
797         case 6: // INC
798                 val = setst_add_laeco(RM16(addr), 1);
799                 WM16(addr, val);
800                 period += 12;
801                 break;
802         case 7: // INCT
803                 val = setst_add_laeco(RM16(addr), 2);
804                 WM16(addr, val);
805                 period += 12;
806                 break;
807         case 8: // DEC
808                 val = setst_sub_laeco(RM16(addr), 1);
809                 WM16(addr, val);
810                 period += 12;
811                 break;
812         case 9: // DECT
813                 val = setst_sub_laeco(RM16(addr), 2);
814                 WM16(addr, val);
815                 period += 12;
816                 break;
817         case 10: // BL
818                 WREG(R11, PC);
819                 PC = addr;
820                 period += 20;
821                 break;
822         case 11: // SWPB
823                 val = RM16(addr);
824                 val = logical_right_shift(val, 8) | (val << 8);
825                 WM16(addr, val);
826                 period += 52;
827                 break;
828         case 12: // SETO
829                 WM16(addr, 0xffff);
830                 period += 12;
831                 break;
832         case 13: // ABS
833                 ST &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
834                 val = RM16(addr);
835                 period += 12;
836                 if(((int16_t)val) > 0) {
837                         ST |= ST_LGT | ST_AGT;
838                 } else if(((int16_t)val) < 0) {
839                         ST |= ST_LGT;
840                         if(val == 0x8000) {
841                                 ST |= ST_OV;
842                         }
843                         val = -((int16_t)val);
844                 } else {
845                         ST |= ST_EQ;
846                 }
847                 WM16(addr, val);
848                 break;
849         default:
850                 illegal(op);
851                 break;
852         }
853 }
854
855 void TMS9995::h0800(uint16_t op)
856 {
857         uint16_t cnt = (op & 0xf0) >> 4;
858         uint16_t addr = (((op & 0xf) << 1) + WP) & ~1, val;
859         
860         period += 20;
861         if(cnt == 0) {
862                 period += 8;
863                 cnt = RREG(R0) & 0xf;
864                 if(cnt == 0) {
865                         cnt = 16;
866                 }
867         }
868         period += 4 * cnt;
869         
870         switch((op & 0x300) >> 8) {
871         case 0: // SRA
872                 val = setst_sra_laec(RM16(addr), cnt);
873                 WM16(addr, val);
874                 break;
875         case 1: // SRL
876                 val = setst_srl_laec(RM16(addr), cnt);
877                 WM16(addr, val);
878                 break;
879         case 2: // SLA
880                 val = setst_sla_laeco(RM16(addr), cnt);
881                 WM16(addr, val);
882                 break;
883         case 3: // SRC
884                 val = setst_src_laec(RM16(addr), cnt);
885                 WM16(addr, val);
886                 break;
887         }
888 }
889
890 void TMS9995::h1000(uint16_t op)
891 {
892         int16_t ofs = (int8_t)op;
893         
894         switch((op & 0xf00) >> 8) {
895         case 0: // JMP
896                 PC += (ofs + ofs);
897                 period += 12;
898                 break;
899         case 1: // JLT
900                 if(!(ST & (ST_AGT | ST_EQ))) {
901                         PC += (ofs + ofs);
902                 }
903                 period += 12;
904                 break;
905         case 2: // JLE
906                 if((!(ST & ST_LGT)) || (ST & ST_EQ)) {
907                         PC += (ofs + ofs);
908                 }
909                 period += 12;
910                 break;
911         case 3: // JEQ
912                 if(ST & ST_EQ) {
913                         PC += (ofs + ofs);
914                 }
915                 period += 12;
916                 break;
917         case 4: // JHE
918                 if(ST & (ST_LGT | ST_EQ)) {
919                         PC += (ofs + ofs);
920                 }
921                 period += 12;
922                 break;
923         case 5: // JGT
924                 if(ST & ST_AGT) {
925                         PC += (ofs + ofs);
926                 }
927                 period += 12;
928                 break;
929         case 6: // JNE
930                 if(!(ST & ST_EQ)) {
931                         PC += (ofs + ofs);
932                 }
933                 period += 12;
934                 break;
935         case 7: // JNC
936                 if(!(ST & ST_C)) {
937                         PC += (ofs + ofs);
938                 }
939                 period += 12;
940                 break;
941         case 8: // JOC
942                 if(ST & ST_C) {
943                         PC += (ofs + ofs);
944                 }
945                 period += 12;
946                 break;
947         case 9: // JNO
948                 if(!(ST & ST_OV)) {
949                         PC += (ofs + ofs);
950                 }
951                 period += 12;
952                 break;
953         case 10: // JL
954                 if(!(ST & (ST_LGT | ST_EQ))) {
955                         PC += (ofs + ofs);
956                 }
957                 period += 12;
958                 break;
959         case 11: // JH
960                 if((ST & ST_LGT) && !(ST & ST_EQ)) {
961                         PC += (ofs + ofs);
962                 }
963                 period += 12;
964                 break;
965         case 12: { // JOP
966                 int i = 0;
967                 uint8_t a = lastparity;
968                 while(a != 0) {
969                         if(a & 1) {
970                                 i++;
971                         }
972                         a >>= 1;
973                 }
974                 if(i & 1) {
975                         PC += (ofs + ofs);
976                 }
977                 period += 12;
978                 break;
979         }
980         case 13: // SBO
981                 WCRU((RREG(R12) >> 1) + ofs, 1, 1);
982                 period += 32;
983                 break;
984         case 14: // SBZ
985                 WCRU((RREG(R12) >> 1) + ofs, 1, 0);
986                 period += 32;
987                 break;
988         case 15: // TB
989                 setst_e(RCRU((RREG(R12)>> 1) + ofs, 1) & 1, 1);
990                 period += 32;
991                 break;
992         }
993 }
994
995 void TMS9995::h2000(uint16_t op)
996 {
997         uint16_t src = decipheraddr(op) & ~1;
998         uint16_t dst = ((((op & 0x3c0) >> 6) << 1) + WP) & ~1, val, d, h;
999         uint32_t p;
1000         
1001         switch((op & 0x1c00) >> 10) {
1002         case 0: // COC
1003                 val = RM16(src);
1004                 setst_e(val & RM16(dst), val);
1005                 period += 16;
1006                 break;
1007         case 1: // CZC
1008                 val = RM16(src);
1009                 setst_e(val & ~RM16(dst), val);
1010                 period += 16;
1011                 break;
1012         case 2: // XOR
1013                 val = RM16(src) ^ RM16(dst);
1014                 setst_lae(val);
1015                 WM16(dst,val);
1016                 period += 16;
1017                 break;
1018 //      case 3: // XOP
1019 //      case 4: // LDCR
1020 //      case 5: // STCR
1021         case 6: // MPY
1022                 p = (uint32_t)RM16(src) * (uint32_t)RM16(dst);
1023                 WM16(dst, p >> 16);
1024                 WM16((dst + 2) & 0xffff, p);
1025                 period += 92;
1026                 break;
1027         case 7: // DIV
1028                 d = RM16(src);
1029                 h = RM16(dst);
1030                 p = (((uint32_t)h) << 16) | RM16((dst + 2) & 0xffff);
1031                 if(d == 0 || d <= h) {
1032                         ST |= ST_OV;
1033                         period += 24;
1034                 } else {
1035                         ST &= ~ST_OV;
1036                         WM16(dst, p / d);
1037                         WM16((dst + 2) & 0xffff, p % d);
1038                         period += 112;
1039                 }
1040                 break;
1041         }
1042 }
1043
1044 void TMS9995::xop(uint16_t op)
1045 {
1046         uint16_t tmp = (op & 0x3c0) >> 6;
1047         uint16_t val = decipheraddr(op);
1048         
1049         contextswitch(0x40 + (tmp << 2));
1050         ST |= ST_X;
1051         WREG(R11, val);
1052         period += 60;
1053         int_enabled = false;
1054 }
1055
1056 void TMS9995::ldcr_stcr(uint16_t op)
1057 {
1058         uint16_t cnt = (op & 0x3c0) >> 6, addr;
1059         int val;
1060         
1061         if(cnt == 0) {
1062                 cnt = 16;
1063         }
1064         if(cnt <= 8) {
1065                 addr = decipheraddrbyte(op);
1066         } else {
1067                 addr = decipheraddr(op) & ~1;
1068         }
1069         if(op < 0x3400) {
1070                 // LDCR
1071                 if(cnt <= 8) {
1072                         val = RM16(addr & ~1);
1073                         if(addr & 1) {
1074                                 val &= 0xff;
1075                         } else {
1076                                 val = (val >> 8) & 0xff;
1077                         }
1078                         (void)RREG(cnt + cnt);
1079                         setst_byte_laep(val);
1080                 } else {
1081                         val = RM16(addr);
1082                         (void)RREG(cnt + cnt);
1083                         setst_lae(val);
1084                 }
1085                 WCRU((RREG(R12) >> 1), cnt, val);
1086                 period += 36 + cnt + cnt;
1087         } else {
1088                 // STCR
1089                 if(cnt <= 8) {
1090                         int val2 = RM16(addr & ~1);
1091                         (void)RREG(cnt + cnt);
1092                         val = RCRU((RREG(R12) >> 1), cnt);
1093                         setst_byte_laep(val);
1094                         if(addr & 1) {
1095                                 WM16(addr & ~1, (val & 0xff) | (val2 & 0xff00));
1096                         } else {
1097                                 WM16(addr & ~1, (val2 & 0xff) | ((val << 8) & 0xff00));
1098                         }
1099                         period += 76 + cnt;
1100                 } else {
1101                         (void)RM16(addr);
1102                         (void)RREG(cnt + cnt);
1103                         val = RCRU((RREG(R12) >> 1), cnt);
1104                         setst_lae(val);
1105                         WM16(addr, val);
1106                         period += 108 + cnt;
1107                 }
1108         }
1109 }
1110
1111 void TMS9995::h4000w(uint16_t op)
1112 {
1113         uint16_t src = decipheraddr(op) & ~1;
1114         uint16_t dst = decipheraddr(op >> 6) & ~1;
1115         uint16_t val = RM16(src);
1116         
1117         switch((op >> 13) & 7) {
1118         case 2: // SZC
1119                 val = RM16(dst) & ~val;
1120                 setst_lae(val);
1121                 WM16(dst, val);
1122                 period += 16;
1123                 break;
1124         case 3: // S
1125                 val = setst_sub_laeco(RM16(dst), val);
1126                 WM16(dst, val);
1127                 period += 16;
1128                 break;
1129         case 4: // C
1130                 setst_c_lae(RM16(dst), val);
1131                 period += 16;
1132                 break;
1133         case 5: // A
1134                 val = setst_add_laeco(RM16(dst), val);
1135                 WM16(dst, val);
1136                 period += 16;
1137                 break;
1138         case 6: // MOV
1139                 setst_lae(val);
1140                 WM16(dst, val);
1141                 period += 12;
1142                 break;
1143         case 7: // SOC
1144                 val = val | RM16(dst);
1145                 setst_lae(val);
1146                 WM16(dst, val);
1147                 period += 16;
1148                 break;
1149         }
1150 }
1151
1152 void TMS9995::h4000b(uint16_t op)
1153 {
1154         uint16_t src = decipheraddrbyte(op);
1155         uint16_t dst = decipheraddrbyte(op >> 6);
1156         uint8_t val = RM8(src);
1157         
1158         switch((op >> 13) & 7) {
1159         case 2: // SZCB
1160                 val = RM8(dst) & ~val;
1161                 setst_byte_laep(val);
1162                 WM8(dst, val);
1163                 period += 16;
1164                 break;
1165         case 3: // SB
1166                 val = setst_subbyte_laecop(RM8(dst), val);
1167                 WM8(dst, val);
1168                 period += 16;
1169                 break;
1170         case 4: // CB
1171                 setst_c_lae(RM8(dst) << 8, val << 8);
1172                 lastparity = val;
1173                 period += 16;
1174                 break;
1175         case 5: // AB
1176                 val = setst_addbyte_laecop(RM8(dst), val);
1177                 WM8(dst, val);
1178                 period += 16;
1179                 break;
1180         case 6: // MOVB
1181                 setst_byte_laep(val);
1182                 WM8(dst, val);
1183                 period += 12;
1184                 break;
1185         case 7: // SOCB
1186                 val = val | RM8(dst);
1187                 setst_byte_laep(val);
1188                 WM8(dst, val);
1189                 period += 16;
1190                 break;
1191         }
1192 }
1193
1194 void TMS9995::illegal(uint16_t op)
1195 {
1196         mid = true;
1197         contextswitch(8);
1198         ST = (ST & 0xfe00) | 1;
1199         int_enabled = false;
1200 }
1201
1202 uint16_t TMS9995::decipheraddr(uint16_t op)
1203 {
1204         uint16_t reg = (op & 0xf) << 1, tmp;
1205         
1206         switch(op & 0x30) {
1207         case 0x00:
1208                 return reg + WP;
1209         case 0x10:
1210                 period += 4;
1211                 return RM16(reg + WP);
1212         case 0x20:
1213                 tmp = FETCH16();
1214                 if(reg) {
1215                         period += 12;
1216                         return RM16(reg + WP) + tmp;
1217                 } else {
1218                         period += 4;
1219                         return tmp;
1220                 }
1221         default:
1222                 reg += WP;
1223                 period += 12;
1224                 tmp = RM16(reg);
1225                 WM16(reg, tmp + 2);
1226                 return tmp;
1227         }
1228 }
1229
1230 uint16_t TMS9995::decipheraddrbyte(uint16_t op)
1231 {
1232         uint16_t reg = (op & 0xf) << 1, tmp;
1233         
1234         switch(op & 0x30) {
1235         case 0x00:
1236                 return reg + WP;
1237         case 0x10:
1238                 period += 4;
1239                 return RM16(reg + WP);
1240         case 0x20:
1241                 tmp = FETCH16();
1242                 if(reg) {
1243                         period += 12;
1244                         return RM16(reg + WP) + tmp;
1245                 } else {
1246                         period += 4;
1247                         return tmp;
1248                 }
1249         default:
1250                 reg += WP;
1251                 period += 12;
1252                 tmp = RM16(reg);
1253                 WM16(reg, tmp + 1);
1254                 return tmp;
1255         }
1256 }
1257
1258 inline void TMS9995::setstat()
1259 {
1260         ST &= ~ ST_OP;
1261         uint8_t p = lastparity;
1262         for(int i = 0; i < 8; i++) {
1263                 if(p & 1) {
1264                         ST ^= ST_OP;
1265                 }
1266                 p >>= 1;
1267         }
1268 }
1269
1270 inline void TMS9995::getstat()
1271 {
1272         if(ST & ST_OP) {
1273                 lastparity = 1;
1274         } else {
1275                 lastparity = 0;
1276         }
1277 }
1278
1279 inline uint16_t TMS9995::logical_right_shift(uint16_t val, int c)
1280 {
1281         return (val >> c) & right_shift_mask_table[c];
1282 }
1283
1284 inline int16_t TMS9995::arithmetic_right_shift(int16_t val, int c)
1285 {
1286         if(val < 0) {
1287                 return (val >> c) | inverted_right_shift_mask_table[c];
1288         } else {
1289                 return (val >> c) & right_shift_mask_table[c];
1290         }
1291 }
1292
1293 inline void TMS9995::setst_lae(int16_t val)
1294 {
1295         ST &= ~(ST_LGT | ST_AGT | ST_EQ);
1296         if(val > 0) {
1297                 ST |= (ST_LGT | ST_AGT);
1298         } else if(val < 0) {
1299                 ST |= ST_LGT;
1300         } else {
1301                 ST |= ST_EQ;
1302         }
1303 }
1304
1305 inline void TMS9995::setst_byte_laep(int8_t val)
1306 {
1307         ST &= ~(ST_LGT | ST_AGT | ST_EQ);
1308         if(val > 0) {
1309                 ST |= (ST_LGT | ST_AGT);
1310         } else if(val < 0) {
1311                 ST |= ST_LGT;
1312         } else {
1313                 ST |= ST_EQ;
1314         }
1315         lastparity = val;
1316 }
1317
1318 inline void TMS9995::setst_e(uint16_t val, uint16_t to)
1319 {
1320         if(val == to) {
1321                 ST |= ST_EQ;
1322         } else {
1323                 ST &= ~ ST_EQ;
1324         }
1325 }
1326
1327 inline void TMS9995::setst_c_lae(uint16_t to, uint16_t val)
1328 {
1329         ST &= ~(ST_LGT | ST_AGT | ST_EQ);
1330         if(val == to) {
1331                 ST |= ST_EQ;
1332         } else {
1333                 if(((int16_t)val) > ((int16_t)to)) {
1334                         ST |= ST_AGT;
1335                 }
1336                 if(((uint16_t)val) > ((uint16_t)to)) {
1337                         ST |= ST_LGT;
1338                 }
1339         }
1340 }
1341
1342 inline int16_t TMS9995::setst_add_laeco(int a, int b)
1343 {
1344         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
1345         uint32_t res = (a & 0xffff) + (b & 0xffff);
1346         if(res & 0x10000) {
1347                 ST |= ST_C;
1348         }
1349         if((res ^ b) & (res ^ a) & 0x8000) {
1350                 ST |= ST_OV;
1351         }
1352         int16_t res2 = (int16_t)res;
1353         if(res2 > 0) {
1354                 ST |= ST_LGT | ST_AGT;
1355         } else if(res2 < 0) {
1356                 ST |= ST_LGT;
1357         } else {
1358                 ST |= ST_EQ;
1359         }
1360         return res2;
1361 }
1362
1363 inline int16_t TMS9995::setst_sub_laeco(int a, int b)
1364 {
1365         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
1366         uint32_t res = (a & 0xffff) - (b & 0xffff);
1367         if(!(res & 0x10000)) {
1368                 ST |= ST_C;
1369         }
1370         if((a ^ b) & (a ^ res) & 0x8000) {
1371                 ST |= ST_OV;
1372         }
1373         int16_t res2 = (int16_t)res;
1374         if(res2 > 0) {
1375                 ST |= ST_LGT | ST_AGT;
1376         } else if(res2 < 0) {
1377                 ST |= ST_LGT;
1378         } else {
1379                 ST |= ST_EQ;
1380         }
1381         return res2;
1382 }
1383
1384 inline int8_t TMS9995::setst_addbyte_laecop(int a, int b)
1385 {
1386         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV | ST_OP);
1387         uint32_t res = (a & 0xff) + (b & 0xff);
1388         if(res & 0x100) {
1389                 ST |= ST_C;
1390         }
1391         if((res ^ b) & (res ^ a) & 0x80) {
1392                 ST |= ST_OV;
1393         }
1394         int8_t res2 = (int8_t)res;
1395         if(res2 > 0) {
1396                 ST |= ST_LGT | ST_AGT;
1397         } else if(res2 < 0) {
1398                 ST |= ST_LGT;
1399         } else {
1400                 ST |= ST_EQ;
1401         }
1402         lastparity = res2;
1403         return res2;
1404 }
1405
1406 inline int8_t TMS9995::setst_subbyte_laecop(int a, int b)
1407 {
1408         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV | ST_OP);
1409         uint32_t res = (a & 0xff) - (b & 0xff);
1410         if(!(res & 0x100)) {
1411                 ST |= ST_C;
1412         }
1413         if((a ^ b) & (a ^ res) & 0x80) {
1414                 ST |= ST_OV;
1415         }
1416         int8_t res2 = (int8_t)res;
1417         if(res2 > 0) {
1418                 ST |= ST_LGT | ST_AGT;
1419         } else if(res2 < 0) {
1420                 ST |= ST_LGT;
1421         } else {
1422                 ST |= ST_EQ;
1423         }
1424         lastparity = res2;
1425         return res2;
1426 }
1427
1428 inline void TMS9995::setst_laeo(int16_t val)
1429 {
1430         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_OV);
1431         if(val > 0) {
1432                 ST |= ST_LGT | ST_AGT;
1433         } else if(val < 0) {
1434                 ST |= ST_LGT;
1435                 if(((uint16_t)val) == 0x8000) {
1436                         ST |= ST_OV;
1437                 }
1438         } else {
1439                 ST |= ST_EQ;
1440         }
1441 }
1442
1443 inline uint16_t TMS9995::setst_sra_laec(int16_t a, uint16_t c)
1444 {
1445         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C);
1446         if(c != 0) {
1447                 a = arithmetic_right_shift(a, c-1);
1448                 if(a & 1) {
1449                         ST |= ST_C;
1450                 }
1451                 a = arithmetic_right_shift(a, 1);
1452         }
1453         if(a > 0) {
1454                 ST |= ST_LGT | ST_AGT;
1455         } else if(a < 0) {
1456                 ST |= ST_LGT;
1457         } else {
1458                 ST |= ST_EQ;
1459         }
1460         return a;
1461 }
1462
1463 inline uint16_t TMS9995::setst_srl_laec(uint16_t a,uint16_t c)
1464 {
1465         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C);
1466         if(c != 0) {
1467                 a = logical_right_shift(a, c-1);
1468                 if(a & 1) {
1469                         ST |= ST_C;
1470                 }
1471                 a = logical_right_shift(a, 1);
1472         }
1473         if(((int16_t)a) > 0) {
1474                 ST |= ST_LGT | ST_AGT;
1475         } else if(((int16_t)a) < 0) {
1476                 ST |= ST_LGT;
1477         } else {
1478                 ST |= ST_EQ;
1479         }
1480         return a;
1481 }
1482
1483 inline uint16_t TMS9995::setst_src_laec(uint16_t a,uint16_t c)
1484 {
1485         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C);
1486         if(c != 0) {
1487                 a = logical_right_shift(a, c) | (a << (16-c));
1488                 if(a & 0x8000) {
1489                         ST |= ST_C;
1490                 }
1491         }
1492         if(((int16_t)a) > 0) {
1493                 ST |= ST_LGT | ST_AGT;
1494         } else if(((int16_t)a) < 0) {
1495                 ST |= ST_LGT;
1496         } else {
1497                 ST |= ST_EQ;
1498         }
1499         return a;
1500 }
1501
1502 inline uint16_t TMS9995::setst_sla_laeco(uint16_t a, uint16_t c)
1503 {
1504         ST &= ~(ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
1505         if(c != 0) {
1506                 uint16_t mask = 0xFFFF << (16-c-1);
1507                 uint16_t bits = a & mask;
1508                 if(bits) {
1509                         if(bits ^ mask) {
1510                                 ST |= ST_OV;
1511                         }
1512                 }
1513                 a <<= c - 1;
1514                 if(a & 0x8000) {
1515                         ST |= ST_C;
1516                 }
1517                 a <<= 1;
1518         }
1519         if(((int16_t)a) > 0) {
1520                 ST |= ST_LGT | ST_AGT;
1521         } else if(((int16_t)a) < 0) {
1522                 ST |= ST_LGT;
1523         } else {
1524                 ST |= ST_EQ;
1525         }
1526         return a;
1527 }
1528
1529 #ifdef USE_DEBUGGER
1530 void TMS9995::write_debug_data8(uint32_t addr, uint32_t data)
1531 {
1532         this->write_data8(addr, data);
1533 }
1534
1535 uint32_t TMS9995::read_debug_data8(uint32_t addr)
1536 {
1537         return this->read_data8(addr);
1538 }
1539
1540 void TMS9995::write_debug_data16(uint32_t addr, uint32_t data)
1541 {
1542         this->write_data16(addr, data);
1543 }
1544
1545 uint32_t TMS9995::read_debug_data16(uint32_t addr)
1546 {
1547         return this->read_data16(addr);
1548 }
1549
1550 void TMS9995::write_debug_io8(uint32_t addr, uint32_t data)
1551 {
1552         this->write_io8(addr, data);
1553 }
1554
1555 uint32_t TMS9995::read_debug_io8(uint32_t addr)
1556 {
1557         return this->read_io8(addr);
1558 }
1559
1560 bool TMS9995::write_debug_reg(const _TCHAR *reg, uint32_t data)
1561 {
1562         if(_tcsicmp(reg, _T("PC")) == 0) {
1563                 PC = data;
1564         } else if(_tcsicmp(reg, _T("WP")) == 0) {
1565                 WP = data;
1566         } else if(_tcsicmp(reg, _T("ST")) == 0) {
1567                 ST = data;
1568         } else if(_tcsicmp(reg, _T("R0")) == 0) {
1569                 this->write_data16((WP + R0 ) & 0xffff, data);
1570         } else if(_tcsicmp(reg, _T("R1")) == 0) {
1571                 this->write_data16((WP + R1 ) & 0xffff, data);
1572         } else if(_tcsicmp(reg, _T("R2")) == 0) {
1573                 this->write_data16((WP + R2 ) & 0xffff, data);
1574         } else if(_tcsicmp(reg, _T("R3")) == 0) {
1575                 this->write_data16((WP + R3 ) & 0xffff, data);
1576         } else if(_tcsicmp(reg, _T("R4")) == 0) {
1577                 this->write_data16((WP + R4 ) & 0xffff, data);
1578         } else if(_tcsicmp(reg, _T("R5")) == 0) {
1579                 this->write_data16((WP + R5 ) & 0xffff, data);
1580         } else if(_tcsicmp(reg, _T("R6")) == 0) {
1581                 this->write_data16((WP + R6 ) & 0xffff, data);
1582         } else if(_tcsicmp(reg, _T("R7")) == 0) {
1583                 this->write_data16((WP + R7 ) & 0xffff, data);
1584         } else if(_tcsicmp(reg, _T("R8")) == 0) {
1585                 this->write_data16((WP + R8 ) & 0xffff, data);
1586         } else if(_tcsicmp(reg, _T("R9")) == 0) {
1587                 this->write_data16((WP + R9 ) & 0xffff, data);
1588         } else if(_tcsicmp(reg, _T("R10")) == 0) {
1589                 this->write_data16((WP + R10) & 0xffff, data);
1590         } else if(_tcsicmp(reg, _T("R11")) == 0) {
1591                 this->write_data16((WP + R11) & 0xffff, data);
1592         } else if(_tcsicmp(reg, _T("R12")) == 0) {
1593                 this->write_data16((WP + R12) & 0xffff, data);
1594         } else if(_tcsicmp(reg, _T("R13")) == 0) {
1595                 this->write_data16((WP + R13) & 0xffff, data);
1596         } else if(_tcsicmp(reg, _T("R14")) == 0) {
1597                 this->write_data16((WP + R14) & 0xffff, data);
1598         } else if(_tcsicmp(reg, _T("R15")) == 0) {
1599                 this->write_data16((WP + R15) & 0xffff, data);
1600         } else {
1601                 return false;
1602         }
1603         return true;
1604 }
1605
1606 void TMS9995::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
1607 {
1608 /*
1609 ST = 0000 [LGT:0 AGT:0 EQ:0 C:0 OV:0 OP:0 X:0 OVIE:0 IM:0]
1610 PC = 0000 WP = 0000
1611 R0 = 0000 R1 = 0000 R2 = 0000 R3 = 0000 R4 = 0000 R5 = 0000 R6 = 0000 R7 = 0000
1612 R8 = 0000 R9 = 0000 R10= 0000 R11= 0000 R12= 0000 R13= 0000 R14= 0000 R15= 0000
1613 Clocks = 0 (0) Since Scanline = 0/0 (0/0)
1614 */
1615         my_stprintf_s(buffer, buffer_len,
1616         _T("ST = %04X [LGT:%01X AGT:%01X EQ:%01X C:%01X OV:%01X OP:%01X X:%01X OVIE:%01X IM:%01X]\nPC = %04X WP = %04X\nR0 = %04X R1 = %04X R2 = %04X R3 = %04X R4 = %04X R5 = %04X R6 = %04X R7 = %04X\nR8 = %04X R9 = %04X R10= %04X R11= %04X R12= %04X R13= %04X R14= %04X R15= %04X\nClocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
1617         ST,
1618         (ST & ST_LGT ) ? 1 : 0,
1619         (ST & ST_AGT ) ? 1 : 0,
1620         (ST & ST_EQ  ) ? 1 : 0,
1621         (ST & ST_C   ) ? 1 : 0,
1622         (ST & ST_OV  ) ? 1 : 0,
1623         (ST & ST_OP  ) ? 1 : 0,
1624         (ST & ST_LGT ) ? 1 : 0,
1625         (ST & ST_OVIE) ? 1 : 0,
1626         (ST & ST_IM  ),
1627         PC, WP,
1628         this->read_data16((WP + R0 ) & 0xffff),
1629         this->read_data16((WP + R1 ) & 0xffff),
1630         this->read_data16((WP + R2 ) & 0xffff),
1631         this->read_data16((WP + R3 ) & 0xffff),
1632         this->read_data16((WP + R4 ) & 0xffff),
1633         this->read_data16((WP + R5 ) & 0xffff),
1634         this->read_data16((WP + R6 ) & 0xffff),
1635         this->read_data16((WP + R7 ) & 0xffff),
1636         this->read_data16((WP + R8 ) & 0xffff),
1637         this->read_data16((WP + R9 ) & 0xffff),
1638         this->read_data16((WP + R10) & 0xffff),
1639         this->read_data16((WP + R11) & 0xffff),
1640         this->read_data16((WP + R12) & 0xffff),
1641         this->read_data16((WP + R13) & 0xffff),
1642         this->read_data16((WP + R14) & 0xffff),
1643         this->read_data16((WP + R15) & 0xffff),
1644         total_count, total_count - prev_total_count,
1645         get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
1646         prev_total_count = total_count;
1647 }
1648
1649 // disassembler
1650
1651 typedef UINT32  offs_t;
1652
1653 #ifndef logerror
1654 #define logerror(...)
1655 #endif
1656
1657 #ifndef INLINE
1658 #define INLINE inline
1659 #endif
1660
1661 #define CPU_DISASSEMBLE_NAME(name)      cpu_disassemble_##name
1662 #define CPU_DISASSEMBLE(name)           int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, symbol_t *first_symbol)
1663 #define CPU_DISASSEMBLE_CALL(name)      CPU_DISASSEMBLE_NAME(name)(buffer, pc, oprom, opram, d_debugger->first_symbol)
1664
1665 const UINT32 DASMFLAG_SUPPORTED     = 0x80000000;   // are disassembly flags supported?
1666 const UINT32 DASMFLAG_STEP_OUT      = 0x40000000;   // this instruction should be the end of a step out sequence
1667 const UINT32 DASMFLAG_STEP_OVER     = 0x20000000;   // this instruction should be stepped over by setting a breakpoint afterwards
1668 const UINT32 DASMFLAG_OVERINSTMASK  = 0x18000000;   // number of extra instructions to skip when stepping over
1669 const UINT32 DASMFLAG_OVERINSTSHIFT = 27;           // bits to shift after masking to get the value
1670 const UINT32 DASMFLAG_LENGTHMASK    = 0x0000ffff;   // the low 16-bits contain the actual length
1671
1672 enum
1673 {
1674         TI990_10_ID = 1,
1675         TMS9900_ID = 3,
1676         TMS9940_ID = 4,
1677         TMS9980_ID = 5,
1678         TMS9985_ID = 6,
1679         TMS9989_ID = 7,
1680         TMS9995_ID = 9,
1681         TMS99000_ID = 10,
1682         TMS99105A_ID = 11,
1683         TMS99110A_ID = 12
1684 };
1685
1686 #include "mame/emu/cpu/tms9900/9900dasm.c"
1687
1688 int TMS9995::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
1689 {
1690         UINT8 oprom[16], opram[16];
1691         for(int i = 0; i < 16; i++) {
1692                 oprom[i] = opram[i] = this->read_data8((pc + i) & 0xffff);
1693         }
1694         return CPU_DISASSEMBLE_CALL(tms9995) & DASMFLAG_LENGTHMASK;
1695 }
1696 #endif
1697
1698 #define STATE_VERSION   2
1699
1700 bool TMS9995::process_state(FILEIO* state_fio, bool loading)
1701 {
1702         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1703                 return false;
1704         }
1705         if(!state_fio->StateCheckInt32(this_device_id)) {
1706                 return false;
1707         }
1708 #ifdef USE_DEBUGGER
1709         state_fio->StateUint64(total_count);
1710 #endif
1711         state_fio->StateInt32(count);
1712         state_fio->StateInt32(period);
1713         state_fio->StateUint16(WP);
1714         state_fio->StateUint16(PC);
1715         state_fio->StateUint16(prevPC);
1716         state_fio->StateUint16(ST);
1717         state_fio->StateBuffer(RAM, sizeof(RAM), 1);
1718         state_fio->StateUint8(irq_level);
1719         state_fio->StateUint8(int_state);
1720         state_fio->StateUint8(int_latch);
1721         state_fio->StateBool(int_pending);
1722         state_fio->StateBool(int_enabled);
1723         state_fio->StateUint16(dec_count);
1724         state_fio->StateUint16(dec_interval);
1725         state_fio->StateInt32(dec_timer);
1726         state_fio->StateBool(dec_enabled);
1727         state_fio->StateUint16(mode);
1728         state_fio->StateUint8(lastparity);
1729         state_fio->StateBool(nmi);
1730         state_fio->StateBool(mid);
1731         state_fio->StateBool(idle);
1732         
1733 #ifdef USE_DEBUGGER
1734         // post process
1735         if(loading) {
1736                 prev_total_count = total_count;
1737         }
1738 #endif
1739         return true;
1740 }