OSDN Git Service

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