Previous 199869 Revisions Next

r24860 Monday 12th August, 2013 at 14:44:44 UTC by Dirk Best
i8089.c: added instruction decode and more opcodes, starts executing task blocks now
[src/emu/machine]i8089.c

trunk/src/emu/machine/i8089.c
r24859r24860
4646protected:
4747   // device-level overrides
4848   virtual void device_start();
49   virtual void device_reset();
4950   virtual void execute_run();
5051
5152   int m_icount;
r24859r24860
5354private:
5455
5556   // opcodes
57   void add_rm(int r, int m, int o = 0);
58   void add_mr(int m, int r, int o = 0);
59   void addb_rm(int r, int m, int o = 0);
60   void addb_mr(int m, int r, int o = 0);
61   void addbi_ri(int r, int i);
62   void addbi_mi(int m, int i, int o = 0);
63   void addi_ri(int r, int i);
64   void addi_mi(int m, int i, int o = 0);
65   void and_rm(int r, int m, int o = 0);
66   void and_mr(int m, int r, int o = 0);
67   void andb_rm(int r, int m, int o = 0);
68   void andb_mr(int m, int r, int o = 0);
69   void andbi_ri(int r, int i);
70   void andbi_mi(int m, int i, int o = 0);
71   void andi_ri(int r, int i);
72   void andi_mi(int m, int i, int o = 0);
73   void call(int m, int d, int o = 0);
74   void clr(int m, int b, int o = 0);
75   void dec_r(int r);
76   void dec_m(int m, int o = 0);
77   void decb(int m, int o = 0);
5678   void hlt();
79   void inc_r(int r);
80   void inc_m(int m, int o = 0);
81   void incb(int m, int o = 0);
82   void jbt(int m, int b, int d, int o = 0);
83   void jmce(int m, int d, int o = 0);
84   void jmcne(int m, int d, int o = 0);
85   void jmp(int d);
86   void jnbt(int m, int b, int d, int o = 0);
87   void jnz_r(int r, int d);
88   void jnz_m(int m, int d, int o = 0);
89   void jnzb(int m, int d, int o = 0);
90   void jz_r(int r, int d);
91   void jz_m(int m, int d, int o = 0);
92   void jzb(int m, int d, int o = 0);
93   void lcall(int m, int d, int o = 0);
94   void ljbt(int m, int b, int d, int o = 0);
95   void ljmce(int m, int d, int o = 0);
96   void ljmcne(int m, int d, int o = 0);
97   void ljmp(int d);
98   void ljnbt(int m, int b, int d, int o = 0);
99   void ljnz_r(int r, int d);
100   void ljnz_m(int m, int d, int o = 0);
101   void ljnzb(int m, int d, int o = 0);
102   void ljz_r(int r, int d);
103   void ljz_m(int m, int d, int o = 0);
104   void ljzb(int m, int d, int o = 0);
57105   void lpd(int p, int m, int o = 0);
58106   void lpdi(int p, int i, int o = 0);
107   void mov_mr(int m, int r, int o = 0);
108   void mov_rm(int r, int m, int o = 0);
109   void mov_mm(int m1, int m2, int o1 = 0, int o2 = 0);
59110   void movb_mr(int m, int r, int o = 0);
60111   void movb_rm(int r, int m, int o = 0);
61112   void movb_mm(int m1, int m2, int o1 = 0, int o2 = 0);
r24859r24860
66117   void movp_mp(int m, int p, int o = 0);
67118   void movp_pm(int p, int m, int o = 0);
68119   void nop();
120   void not_r(int r);
121   void not_m(int m, int o = 0);
122   void not_rm(int r, int m, int o = 0);
123   void notb_m(int m, int o = 0);
124   void notb_rm(int r, int m, int o = 0);
125   void or_rm(int r, int m, int o = 0);
126   void or_mr(int m, int r, int o = 0);
127   void orb_rm(int r, int m, int o = 0);
128   void orb_mr(int m, int r, int o = 0);
129   void orbi_ri(int r, int i);
130   void orbi_mi(int m, int i, int o = 0);
131   void ori_ri(int r, int i);
132   void ori_mi(int m, int i, int o = 0);
133   void setb(int m, int b, int o = 0);
69134   void sintr();
135   void tsl(int m, int i, int d, int o = 0);
136   void wid(int s, int d);
137   void xfer();
138   void invalid(int opc);
70139
140   // instruction fetch
141   UINT16 displacement(int wb);
142   UINT8 offset(int aa);
143   UINT8 imm8();
144   UINT16 imm16();
145
71146   void examine_ccw(UINT8 ccw);
72147
73148   devcb2_write_line m_write_sintr;
74149
75   enum
76   {
77      STATE_IDLE,
78      STATE_EXECUTING,
79      STATE_DMA
80   };
81
82150   i8089_device *m_iop;
83151
84   int m_state;
85
86   bool m_interrupts_enabled;
87
88152   // register
89153   enum
90154   {
r24859r24860
115179   device_t(mconfig, I8089_CHANNEL, "Intel 8089 I/O Channel", tag, owner, clock, "i8089_channel", __FILE__),
116180   device_execute_interface(mconfig, *this),
117181   m_icount(0),
118   m_write_sintr(*this),
119   m_state(STATE_IDLE),
120   m_interrupts_enabled(true)
182   m_write_sintr(*this)
121183{
122184}
123185
r24859r24860
133195   m_write_sintr.resolve_safe();
134196
135197   // register for save states
136   save_item(NAME(m_state));
137   save_item(NAME(m_interrupts_enabled));
138
139198   for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
140199   {
141200      save_item(NAME(m_r[i].w), i);
r24859r24860
143202   }
144203}
145204
205void i8089_channel::device_reset()
206{
207   // initialize registers
208   for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
209   {
210      m_r[i].w = 0;
211      m_r[i].t = 0;
212   }
213}
214
215
216//**************************************************************************
217//  IMPLEMENTATION
218//**************************************************************************
219
220UINT16 i8089_channel::displacement(int wb)
221{
222   UINT16 displacement = 0;
223
224   if (wb == 1)
225   {
226      displacement = m_iop->read_byte(m_r[TP].w);
227      m_r[TP].w++;
228   }
229   else if (wb == 2)
230   {
231      displacement = m_iop->read_word(m_r[TP].w);
232      m_r[TP].w += 2;
233   }
234
235   return displacement;
236}
237
238UINT8 i8089_channel::offset(int aa)
239{
240   UINT8 offset = 0;
241
242   if (aa == 1)
243   {
244      offset = m_iop->read_byte(m_r[TP].w);
245      m_r[TP].w++;
246   }
247
248   return offset;
249}
250
251UINT8 i8089_channel::imm8()
252{
253   UINT8 imm8 = m_iop->read_byte(m_r[TP].w);
254   m_r[TP].w++;
255   return imm8;
256}
257
258UINT16 i8089_channel::imm16()
259{
260   UINT8 imm16 = m_iop->read_word(m_r[TP].w);
261   m_r[TP].w += 2;
262   return imm16;
263}
264
146265void i8089_channel::execute_run()
147266{
148267   do
149268   {
150      switch (m_state)
269      // active transfer?
270      if (BIT(m_r[PSW].w, 6))
151271      {
152      case STATE_IDLE:
153272         m_icount = 0;
154         break;
273      }
155274
156      case STATE_DMA:
157         m_icount = 0;
158         break;
275      // executing task block instructions?
276      else if (BIT(m_r[PSW].w, 2))
277      {
278         // fetch first two instruction bytes
279         UINT16 op = m_iop->read_word(m_r[TP].w);
280         m_r[TP].w += 2;
159281
160      case STATE_EXECUTING:
282         // extract parameters
283         UINT8 params = op & 0xff;
284         UINT8 opcode = (op >> 8) & 0xff;
285
286         int brp = (params >> 5) & 0x07;
287         int wb  = (params >> 3) & 0x03;
288         int aa  = (params >> 1) & 0x03;
289         int w   = (params >> 0) & 0x01;
290         int opc = (opcode >> 2) & 0x3f;
291         int mm  = (opcode >> 0) & 0x03;
292
293         // fix-up so we can use our register array
294         if (mm == BC) mm = PP;
295
296         UINT8 o;
297         UINT16 off, seg;
298
299         switch (opc)
300         {
301         case 0x00: // control
302            switch (brp)
303            {
304            case 0: nop(); break;
305            case 1: invalid(opc); break;
306            case 2: sintr(); break;
307            case 3: xfer(); break;
308            default:
309               if (BIT(brp, 2))
310                  wid(BIT(brp, 1), BIT(brp, 0));
311            }
312            break;
313
314         case 0x02: // lpdi
315            off = imm16();
316            seg = imm16();
317            lpdi(brp, seg, off);
318            break;
319
320         case 0x08: // add(b)i r, i
321            if (w) addi_ri(brp, imm16());
322            else   addbi_ri(brp, imm8());
323            break;
324
325         case 0x0a: // and(b)i r, i
326            if (w) andi_ri(brp, imm16());
327            else   andbi_ri(brp, imm8());
328            break;
329
330         case 0x0c: // mov(b)i r, i
331            if (w) movi_ri(brp, imm16());
332            else   movbi_ri(brp, imm8());
333            break;
334
335         case 0x0f: // dec r
336            dec_r(brp);
337            break;
338
339         case 0x12: // hlt
340            if (BIT(brp, 0))
341               hlt();
342            break;
343
344         case 0x22: // lpd
345            o = offset(aa);
346            lpd(brp, mm, o);
347            break;
348
349         case 0x28: // add(b) r, m
350            if (w) add_rm(brp, mm, offset(aa));
351            else   addb_rm(brp, mm, offset(aa));
352            break;
353
354         case 0x2a: // and(b) r, m
355            if (w) and_rm(brp, mm, offset(aa));
356            else   andb_rm(brp, mm, offset(aa));
357            break;
358
359         case 0x27: // call
360            o = offset(aa);
361            call(mm, displacement(wb), o);
362            break;
363
364         case 0x30: // add(b)i m, i
365            o = offset(aa);
366            if (w) addi_mi(mm, imm16(), o);
367            else   addbi_mi(mm, imm8(), o);
368            break;
369
370         case 0x32: // and(b)i m, i
371            o = offset(aa);
372            if (w) andi_mi(mm, imm16());
373            else   andbi_mi(mm, imm8());
374            break;
375
376         case 0x34: // add(b) m, r
377            if (w) add_mr(mm, brp, offset(aa));
378            else   addb_mr(mm, brp, offset(aa));
379            break;
380
381         case 0x36: // and(b) m, r
382            if (w) and_mr(mm, brp, offset(aa));
383            else   andb_mr(mm, brp, offset(aa));
384            break;
385
386         case 0x3b: // dec(b) m
387            if (w) dec_m(mm, offset(aa));
388            else   decb(mm, offset(aa));
389            break;
390
391         case 0x3e: // clr
392            clr(mm, brp, offset(aa));
393            break;
394
395         default:
396            invalid(opc);
397         }
398
161399         m_icount--;
162         break;
163400      }
401
402      // nothing to do
403      else
404      {
405         m_icount--;
406      }
164407   }
165408   while (m_icount > 0);
166409}
r24859r24860
172415
173416bool i8089_channel::bus_load_limit()
174417{
175   return BIT(m_r[CP].w, 5);
418   return BIT(m_r[PSW].w, 5);
176419}
177420
178421bool i8089_channel::priority()
179422{
180   return BIT(m_r[CP].w, 7);
423   return BIT(m_r[PSW].w, 7);
181424}
182425
183426void i8089_channel::examine_ccw(UINT8 ccw)
184427{
185   // interrupt control field
186   switch ((ccw >> 3) & 0x03)
187   {
188   // no effect
189   case 0:
190      break;
428   // priority and bus load limit, bit 7 and 5
429   m_r[PSW].w = (m_r[PSW].w & 0x5f) | (ccw & 0xa0);
191430
192431   // acknowledge interrupt
193   case 1:
194      if (VERBOSE)
195         logerror("%s('%s'): acknowledge interrupt\n", shortname(), tag());
196
432   if (BIT(ccw, 4))
433   {
197434      m_write_sintr(0);
198      break;
435      m_r[PSW].w &= ~(1 << 5);
436   }
199437
200   // enable interrupts
201   case 2:
202      if (VERBOSE)
203         logerror("%s('%s'): interrupts enabled\n", shortname(), tag());
204
205      m_interrupts_enabled = true;
206      break;
207
208   // disable interrupts
209   case 3:
210      if (VERBOSE)
211         logerror("%s('%s'): interrupts disabled\n", shortname(), tag());
212
213      m_write_sintr(0);
214      m_interrupts_enabled = false;
215      break;
438   // interrupt enable
439   if (BIT(ccw, 5))
440   {
441      if (BIT(ccw, 4))
442         m_r[PSW].w &= ~(1 << 4);
443      else
444         m_r[PSW].w |= 1 << 4;
216445   }
217446}
218447
r24859r24860
226455   // no channel command
227456   case 0:
228457      if (VERBOSE)
229         logerror("%s('%s'): command received: no channel command\n", shortname(), tag());
458         logerror("%s('%s'): command received: update psw\n", shortname(), tag());
230459
231460      examine_ccw(ccw);
232461      break;
r24859r24860
242471      movp_pm(TP, PP);
243472      movbi_mi(CP, 0xff, 1);
244473
245      m_state = STATE_EXECUTING;
474      m_r[PSW].w |= 1 << 2;
246475
247476      break;
248477
r24859r24860
264493      lpd(TP, PP);
265494      movbi_mi(CP, 0xff, 1);
266495
267      m_state = STATE_EXECUTING;
496      m_r[PSW].w |= 1 << 2;
268497
269498      if (VERBOSE)
270499      {
r24859r24860
291520      movb_rm(PSW, PP, 3);
292521      movbi_mi(CP, 0xff, 1);
293522
523      m_r[PSW].w |= 1 << 2;
524
525      if (VERBOSE)
526      {
527         logerror("%s('%s'): ---- continuing channel ----\n", shortname(), tag());
528         logerror("%s('%s'): task pointer: %06x\n", shortname(), tag(), m_r[TP].w);
529      }
530
294531      break;
295532
296533   // halt channel, save tp
r24859r24860
333570//  OPCODES
334571//**************************************************************************
335572
573#define UNIMPLEMENTED logerror("%s('%s'): unimplemented opcode: %s\n", shortname(), tag(), __FUNCTION__);
574
575void i8089_channel::add_rm(int r, int m, int o) { UNIMPLEMENTED }
576void i8089_channel::add_mr(int m, int r, int o) { UNIMPLEMENTED }
577void i8089_channel::addb_rm(int r, int m, int o) { UNIMPLEMENTED }
578void i8089_channel::addb_mr(int m, int r, int o) { UNIMPLEMENTED }
579void i8089_channel::addbi_ri(int r, int i) { UNIMPLEMENTED }
580void i8089_channel::addbi_mi(int m, int i, int o) { UNIMPLEMENTED }
581void i8089_channel::addi_ri(int r, int i) { UNIMPLEMENTED }
582void i8089_channel::addi_mi(int m, int i, int o) { UNIMPLEMENTED }
583void i8089_channel::and_rm(int r, int m, int o) { UNIMPLEMENTED }
584void i8089_channel::and_mr(int m, int r, int o) { UNIMPLEMENTED }
585void i8089_channel::andb_rm(int r, int m, int o) { UNIMPLEMENTED }
586void i8089_channel::andb_mr(int m, int r, int o) { UNIMPLEMENTED }
587void i8089_channel::andbi_ri(int r, int i) { UNIMPLEMENTED }
588void i8089_channel::andbi_mi(int m, int i, int o) { UNIMPLEMENTED }
589void i8089_channel::andi_ri(int r, int i) { UNIMPLEMENTED }
590void i8089_channel::andi_mi(int m, int i, int o) { UNIMPLEMENTED }
591void i8089_channel::call(int m, int d, int o) { UNIMPLEMENTED }
592void i8089_channel::clr(int m, int b, int o) { UNIMPLEMENTED }
593void i8089_channel::dec_r(int r) { UNIMPLEMENTED }
594void i8089_channel::dec_m(int m, int o) { UNIMPLEMENTED }
595void i8089_channel::decb(int m, int o) { UNIMPLEMENTED }
596
336597// halt
337598void i8089_channel::hlt()
338599{
339600   movbi_mi(CP, 0x00, 1);
340   m_state = STATE_IDLE;
601   m_r[PSW].w &= ~(1 << 2);
341602}
342603
604void i8089_channel::inc_r(int r) { UNIMPLEMENTED }
605void i8089_channel::inc_m(int m, int o) { UNIMPLEMENTED }
606void i8089_channel::incb(int m, int o) { UNIMPLEMENTED }
607void i8089_channel::jbt(int m, int b, int d, int o) { UNIMPLEMENTED }
608void i8089_channel::jmce(int m, int d, int o) { UNIMPLEMENTED }
609void i8089_channel::jmcne(int m, int d, int o) { UNIMPLEMENTED }
610void i8089_channel::jmp(int d) { UNIMPLEMENTED }
611void i8089_channel::jnbt(int m, int b, int d, int o) { UNIMPLEMENTED }
612void i8089_channel::jnz_r(int r, int d) { UNIMPLEMENTED }
613void i8089_channel::jnz_m(int m, int d, int o) { UNIMPLEMENTED }
614void i8089_channel::jnzb(int m, int d, int o) { UNIMPLEMENTED }
615void i8089_channel::jz_r(int r, int d) { UNIMPLEMENTED }
616void i8089_channel::jz_m(int m, int d, int o) { UNIMPLEMENTED }
617void i8089_channel::jzb(int m, int d, int o) { UNIMPLEMENTED }
618void i8089_channel::lcall(int m, int d, int o) { UNIMPLEMENTED }
619void i8089_channel::ljbt(int m, int b, int d, int o) { UNIMPLEMENTED }
620void i8089_channel::ljmce(int m, int d, int o) { UNIMPLEMENTED }
621void i8089_channel::ljmcne(int m, int d, int o) { UNIMPLEMENTED }
622void i8089_channel::ljmp(int d) { UNIMPLEMENTED }
623void i8089_channel::ljnbt(int m, int b, int d, int o) { UNIMPLEMENTED }
624void i8089_channel::ljnz_r(int r, int d) { UNIMPLEMENTED }
625void i8089_channel::ljnz_m(int m, int d, int o) { UNIMPLEMENTED }
626void i8089_channel::ljnzb(int m, int d, int o) { UNIMPLEMENTED }
627void i8089_channel::ljz_r(int r, int d) { UNIMPLEMENTED }
628void i8089_channel::ljz_m(int m, int d, int o) { UNIMPLEMENTED }
629void i8089_channel::ljzb(int m, int d, int o) { UNIMPLEMENTED }
630
343631// load pointer from memory
344632void i8089_channel::lpd(int p, int m, int o)
345633{
346634   UINT16 offset = m_iop->read_word(m_r[m].w + o);
347635   UINT16 segment = m_iop->read_word(m_r[m].w + o + 2);
348   m_r[p].w = (segment << 4) + (offset & 0xfffff);
636
637   m_r[p].w = ((segment << 4) + offset) & 0xfffff;
349638   m_r[p].t = 0;
350639}
351640
r24859r24860
356645   m_r[p].t = 0;
357646}
358647
648void i8089_channel::mov_mr(int m, int r, int o) { UNIMPLEMENTED }
649void i8089_channel::mov_rm(int r, int m, int o) { UNIMPLEMENTED }
650void i8089_channel::mov_mm(int m1, int m2, int o1, int o2) { UNIMPLEMENTED }
651
359652// move register to memory byte
360653void i8089_channel::movb_mr(int m, int r, int o)
361654{
r24859r24860
414707void i8089_channel::movp_pm(int p, int m, int o)
415708{
416709   UINT16 offset = m_iop->read_word(m_r[m].w + o);
417   UINT16 segment = m_iop->read_word(m_r[m].w +o + 2);
710   UINT16 segment = m_iop->read_word(m_r[m].w + o + 2);
418711
419   m_r[p].w = ((segment << 4) + offset) & 0x0fffff;
712   m_r[p].w = ((segment << 4) + offset) & 0xfffff;
420713   m_r[p].t = segment >> 3 & 0x01;
421714}
422715
r24859r24860
425718{
426719}
427720
721void i8089_channel::not_r(int r) { UNIMPLEMENTED }
722void i8089_channel::not_m(int m, int o) { UNIMPLEMENTED }
723void i8089_channel::not_rm(int r, int m, int o) { UNIMPLEMENTED }
724void i8089_channel::notb_m(int m, int o) { UNIMPLEMENTED }
725void i8089_channel::notb_rm(int r, int m, int o) { UNIMPLEMENTED }
726void i8089_channel::or_rm(int r, int m, int o) { UNIMPLEMENTED }
727void i8089_channel::or_mr(int m, int r, int o) { UNIMPLEMENTED }
728void i8089_channel::orb_rm(int r, int m, int o) { UNIMPLEMENTED }
729void i8089_channel::orb_mr(int m, int r, int o) { UNIMPLEMENTED }
730void i8089_channel::orbi_ri(int r, int i) { UNIMPLEMENTED }
731void i8089_channel::orbi_mi(int m, int i, int o) { UNIMPLEMENTED }
732void i8089_channel::ori_ri(int r, int i) { UNIMPLEMENTED }
733void i8089_channel::ori_mi(int m, int i, int o) { UNIMPLEMENTED }
734void i8089_channel::setb(int m, int b, int o) { UNIMPLEMENTED }
735
428736// set interrupt service flip-flop
429737void i8089_channel::sintr()
430738{
431   if (m_interrupts_enabled)
739   if (BIT(m_r[PSW].w, 4))
740   {
741      m_r[PSW].w |= 1 << 5;
432742      m_write_sintr(1);
743   }
433744}
434745
746void i8089_channel::tsl(int m, int i, int d, int o) { UNIMPLEMENTED }
435747
748// set source and destination logical widths
749void i8089_channel::wid(int s, int d)
750{
751   m_r[PSW].w &= 0x3f;
752   m_r[PSW].w |= d << 0;
753   m_r[PSW].w |= s << 1;
754}
755
756void i8089_channel::xfer() { UNIMPLEMENTED }
757
758void i8089_channel::invalid(int opc)
759{
760   logerror("%s('%s'): invalid opcode: %02x\n", shortname(), tag(), opc);
761}
762
763
436764//**************************************************************************
437765//  DEVICE DEFINITIONS
438766//**************************************************************************
r24859r24860
600928
601929   UINT16 data = 0xffff;
602930
603   if (m_16bit_system)
931   if (m_16bit_system && !(address & 1))
604932   {
605933      data = m_mem->read_word(address);
606934   }
r24859r24860
623951{
624952   assert(m_initialized);
625953
626   if (m_16bit_system)
954   if (m_16bit_system && !(address & 1))
627955   {
628956      m_mem->write_word(address, data);
629957   }

Previous 199869 Revisions Next


© 1997-2024 The MAME Team