Previous 199869 Revisions Next

r23846 Friday 21st June, 2013 at 19:20:52 UTC by Wilbert Pol
apexc.c: Modernized cpu core. (nw)
[src/emu/cpu/apexc]apexc.c apexc.h

trunk/src/emu/cpu/apexc/apexc.c
r23845r23846
327327#include "debugger.h"
328328#include "apexc.h"
329329
330#ifndef SUPPORT_ODD_WORD_SIZES
331#define apexc_readmem(address)  cpustate->program->read_dword((address)<<2)
332#define apexc_writemem(address, data)   cpustate->program->write_dword((address)<<2, (data))
333/* eewww ! - Fortunately, there is no memory mapped I/O, so we can simulate masked write
334without danger */
335#define apexc_writemem_masked(address, data, mask)                                      \
336   apexc_writemem((address), (apexc_readmem(address) & ~(mask)) | ((data) & (mask)))
337#else
338#define apexc_readmem(address)  cpu_readmem13_32(address)
339#define apexc_writemem(address, data)   cpu_writemem13_32((address), (data))
340#define apexc_writemem_masked(address, data, mask)  cpu_writemem13_32masked((address), (data), (mask))
341#endif
342330
331const device_type APEXC = &device_creator<apexc_cpu_device>;
343332
344#define apexc_readop(address)   apexc_readmem(address)
345333
346struct apexc_state
347{
348   UINT32 a;   /* accumulator */
349   UINT32 r;   /* register */
350   UINT32 cr;  /* control register (i.e. instruction register) */
351   int ml;     /* memory location (current track in working store, and requested
352                word position within track) (10 bits) */
353   int working_store;  /* current working store (group of 16 tracks) (1-15) */
354   int current_word;   /* current word position within track (0-31) */
355
356   int running;    /* 1 flag: */
357            /* running: flag implied by the existence of the stop instruction */
358   UINT32 pc;  /* address of next instruction for the disassembler */
359
360   legacy_cpu_device *device;
361   address_space *program;
362   address_space *io;
363   int icount;
364};
365
366334/* decrement ICount by n */
367#define DELAY(n)    {cpustate->icount -= (n); cpustate->current_word = (cpustate->current_word + (n)) & 0x1f;}
335#define DELAY(n)    {m_icount -= (n); m_current_word = (m_current_word + (n)) & 0x1f;}
368336
369337
370INLINE apexc_state *get_safe_token(device_t *device)
338apexc_cpu_device::apexc_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
339   : cpu_device(mconfig, APEXC, "APEXC", tag, owner, clock)
340   , m_program_config("program", ENDIANNESS_BIG, 32, 15, 0)
341   , m_io_config("io", ENDIANNESS_BIG, 8, 1, 0)
371342{
372   assert(device != NULL);
373   assert(device->type() == APEXC);
374   return (apexc_state *)downcast<legacy_cpu_device *>(device)->token();
375343}
376344
377345
r23845r23846
391359
392360/* compute complete word address (i.e. translate a logical track address (expressed
393361in current working store) to an absolute track address) */
394static int effective_address(apexc_state *cpustate, int address)
362UINT32 apexc_cpu_device::effective_address(UINT32 address)
395363{
396364   if (address & 0x200)
397365   {
398      address = (address & 0x1FF) | (cpustate->working_store) << 9;
366      address = (address & 0x1FF) | (m_working_store) << 9;
399367   }
400368
401369   return address;
402370}
403371
404372/* read word */
405static UINT32 word_read(apexc_state *cpustate, int address, int special)
373UINT32 apexc_cpu_device::word_read(UINT32 address, UINT32 special)
406374{
407375   UINT32 result;
408376
409377   /* compute absolute track address */
410   address = effective_address(cpustate, address);
378   address = effective_address(address);
411379
412380   if (special)
413381   {
414382      /* ignore word position in x - use current position instead */
415      address = (address & ~ 0x1f) | cpustate->current_word;
383      address = (address & ~ 0x1f) | m_current_word;
416384   }
417385   else
418386   {
419387      /* wait for requested word to appear under the heads */
420      DELAY(((address /*& 0x1f*/) - cpustate->current_word) & 0x1f);
388      DELAY(((address /*& 0x1f*/) - m_current_word) & 0x1f);
421389   }
422390
423391   /* read 32 bits */
424#if 0
425   /* note that the APEXC reads LSBits first */
426   result = 0;
427   for (i=0; i<31; i++)
428   {
429      /*if (mask & (1 << i))*/
430         result |= bit_read((address << 5) | i) << i;
431   }
432#else
433392   result = apexc_readmem(address);
434#endif
435393
436394   /* read takes one memory cycle */
437395   DELAY(1);
r23845r23846
440398}
441399
442400/* write word (or part of a word, according to mask) */
443static void word_write(apexc_state *cpustate, int address, UINT32 data, UINT32 mask)
401void apexc_cpu_device::word_write(UINT32 address, UINT32 data, UINT32 mask)
444402{
445403   /* compute absolute track address */
446   address = effective_address(cpustate, address);
404   address = effective_address(address);
447405
448406   /* wait for requested word to appear under the heads */
449   DELAY(((address /*& 0x1f*/) - cpustate->current_word) & 0x1f);
407   DELAY(((address /*& 0x1f*/) - m_current_word) & 0x1f);
450408
451409   /* write 32 bits according to mask */
452#if 0
453   /* note that the APEXC reads LSBits first */
454   for (i=0; i<31; i++)
455   {
456      if (mask & (1 << i))
457         bit_write((address << 5) | i, (data >> i) & 1);
458   }
459#else
460410   apexc_writemem_masked(address, data, mask);
461#endif
462411
463412   /* write takes one memory cycle (2, actually, but the 2nd cycle is taken into
464413   account in execute) */
r23845r23846
471420    no address is used, these functions just punch or read 5 bits
472421*/
473422
474static int papertape_read(apexc_state *cpustate)
423UINT8 apexc_cpu_device::papertape_read()
475424{
476   return cpustate->io->read_byte(0) & 0x1f;
425   return m_io->read_byte(0) & 0x1f;
477426}
478427
479static void papertape_punch(apexc_state *cpustate, int data)
428void apexc_cpu_device::papertape_punch(UINT8 data)
480429{
481   cpustate->io->write_byte(0, data);
430   m_io->write_byte(0, data);
482431}
483432
484433/*
r23845r23846
488437/*
489438    set the memory location (i.e. address) register, and compute the associated delay
490439*/
491INLINE int load_ml(apexc_state *cpustate, int address, int vector)
440UINT32 apexc_cpu_device::load_ml(UINT32 address, UINT32 vector)
492441{
493442   int delay;
494443
495444   /* additionnal delay appears if we switch tracks */
496   if (((cpustate->ml & 0x3E0) != (address & 0x3E0)) /*|| vector*/)
445   if (((m_ml & 0x3E0) != (address & 0x3E0)) /*|| vector*/)
497446      delay = 6;  /* if tracks are different, delay to allow for track switching */
498447   else
499448      delay = 0;  /* else, no problem */
500449
501   cpustate->ml = address; /* save ml */
450   m_ml = address; /* save ml */
502451
503452   return delay;
504453}
r23845r23846
518467    execute it.
519468    This solution makes timing simulation much simpler, too.
520469*/
521static void execute(apexc_state *cpustate)
470void apexc_cpu_device::execute()
522471{
523472   int x, y, function, c6, vector; /* instruction fields */
524473   int i = 0;          /* misc counter */
r23845r23846
533482   int delay3; /* pre-operand-fetch delay */
534483
535484   /* first isolate the instruction fields */
536   x = (cpustate->cr >> 22) & 0x3FF;
537   y = (cpustate->cr >> 12) & 0x3FF;
538   function = (cpustate->cr >> 7) & 0x1F;
539   c6 = (cpustate->cr >> 1) & 0x3F;
540   vector = cpustate->cr & 1;
541   cpustate->pc = y<<2;
485   x = (m_cr >> 22) & 0x3FF;
486   y = (m_cr >> 12) & 0x3FF;
487   function = (m_cr >> 7) & 0x1F;
488   c6 = (m_cr >> 1) & 0x3F;
489   vector = m_cr & 1;
490   m_pc = y<<2;
542491
543492   function &= 0x1E;   /* this is a mere guess - the LSBit is reserved for future additions */
544493
r23845r23846
548497   if (has_operand)
549498   {
550499      /* load ml with X */
551      delay1 = load_ml(cpustate, x, vector);
500      delay1 = load_ml(x, vector);
552501      /* burn pre-operand-access delay if needed */
553502      if (delay1)
554503      {
r23845r23846
565514      case 0:
566515         /* stop */
567516
568         cpustate->running = FALSE;
517         m_running = FALSE;
569518
570519         /* BTW, I don't know whether stop loads y into ml or not, and whether
571520         subsequent fetch is done */
r23845r23846
575524         /* I */
576525         /* I do not know whether the CPU does an OR or whatever, but since docs say that
577526         the 5 bits must be cleared initially, an OR kind of makes sense */
578         cpustate->r |= papertape_read(cpustate) << 27;
527         m_r |= papertape_read() << 27;
579528         delay2 = 32;    /* no idea whether this should be counted as an absolute delay
580529                            or as a value in delay2 */
581530         break;
582531
583532      case 4:
584533         /* P */
585         papertape_punch(cpustate, (cpustate->r >> 27) & 0x1f);
534         papertape_punch((m_r >> 27) & 0x1f);
586535         delay2 = 32;    /* no idea whether this should be counted as an absolute delay
587536                            or as a value in delay2 */
588537         break;
r23845r23846
590539      case 6:
591540         /* B<(x)>=(y) */
592541         /* I have no idea what we should do if the vector bit is set */
593         if (cpustate->a & 0x80000000UL)
542         if (m_a & 0x80000000UL)
594543         {
595544            /* load ml with X */
596            delay1 = load_ml(cpustate, x, vector);
597            cpustate->pc = x<<2;
545            delay1 = load_ml(x, vector);
546            m_pc = x<<2;
598547            /* burn pre-fetch delay if needed */
599548            if (delay1)
600549            {
r23845r23846
616565            int shifted_bit = 0;
617566
618567            /* shift and increment c6 */
619            shifted_bit = cpustate->r & 1;
620            cpustate->r >>= 1;
621            if (cpustate->a & 1)
622               cpustate->r |= 0x80000000UL;
623            cpustate->a >>= 1;
568            shifted_bit = m_r & 1;
569            m_r >>= 1;
570            if (m_a & 1)
571               m_r |= 0x80000000UL;
572            m_a >>= 1;
624573            if (shifted_bit)
625               cpustate->a |= 0x80000000UL;
574               m_a |= 0x80000000UL;
626575
627576            c6 = (c6+1) & 0x3f;
628577         }
r23845r23846
637586         while (c6 != 0)
638587         {
639588            /* shift and increment c6 */
640            cpustate->r >>= 1;
641            if (cpustate->a & 1)
642               cpustate->r |= 0x80000000UL;
643            cpustate->a = ((INT32) cpustate->a) >> 1;
589            m_r >>= 1;
590            if (m_a & 1)
591               m_r |= 0x80000000UL;
592            m_a = ((INT32) m_a) >> 1;
644593
645594            c6 = (c6+1) & 0x3f;
646595         }
r23845r23846
661610         {
662611            int shifted_bit;
663612
664            cpustate->a = 0;
613            m_a = 0;
665614            shifted_bit = 0;
666615            while (1)
667616            {
668617               /* note we read word at current word position */
669               if (shifted_bit && ! (cpustate->r & 1))
670                  cpustate->a += word_read(cpustate, x, 1);
671               else if ((! shifted_bit) && (cpustate->r & 1))
672                  cpustate->a -= word_read(cpustate, x, 1);
618               if (shifted_bit && ! (m_r & 1))
619                  m_a += word_read(x, 1);
620               else if ((! shifted_bit) && (m_r & 1))
621                  m_a -= word_read(x, 1);
673622               else
674623                  /* Even if we do not read anything, the loop still takes 1 cycle of
675624                  the memory word clock. */
r23845r23846
685634               c6 = (c6+1) & 0x3f;
686635
687636               /* shift */
688               shifted_bit = cpustate->r & 1;
689               cpustate->r >>= 1;
690               if (cpustate->a & 1)
691                  cpustate->r |= 0x80000000UL;
692               cpustate->a = ((INT32) cpustate->a) >> 1;
637               shifted_bit = m_r & 1;
638               m_r >>= 1;
639               if (m_a & 1)
640                  m_r |= 0x80000000UL;
641               m_a = ((INT32) m_a) >> 1;
693642            }
694643         }
695644
r23845r23846
701650
702651      case 16:
703652         /* +c(x) */
704         cpustate->a = + word_read(cpustate, cpustate->ml, 0);
653         m_a = + word_read(m_ml, 0);
705654         break;
706655
707656      case 18:
708657         /* -c(x) */
709         cpustate->a = - word_read(cpustate, cpustate->ml, 0);
658         m_a = - word_read(m_ml, 0);
710659         break;
711660
712661      case 20:
713662         /* +(x) */
714         cpustate->a += word_read(cpustate, cpustate->ml, 0);
663         m_a += word_read(m_ml, 0);
715664         break;
716665
717666      case 22:
718667         /* -(x) */
719         cpustate->a -= word_read(cpustate, cpustate->ml, 0);
668         m_a -= word_read(m_ml, 0);
720669         break;
721670
722671      case 24:
723672         /* T(x) */
724         cpustate->r = word_read(cpustate, cpustate->ml, 0);
673         m_r = word_read(m_ml, 0);
725674         break;
726675
727676      case 26:
r23845r23846
735684            else
736685               mask = 0xFFFFFFFFUL >> c6;
737686
738            word_write(cpustate, cpustate->ml, cpustate->r, mask);
687            word_write(m_ml, m_r, mask);
739688         }
740689
741         cpustate->r = (cpustate->r & 0x80000000UL) ? 0xFFFFFFFFUL : 0;
690         m_r = (m_r & 0x80000000UL) ? 0xFFFFFFFFUL : 0;
742691
743692         delay2 = 1;
744693         break;
r23845r23846
754703            else
755704               mask = 0xFFFFFFFFUL >> c6;
756705
757            word_write(cpustate, cpustate->ml, cpustate->a, mask);
706            word_write(m_ml, m_a, mask);
758707         }
759708
760709         delay2 = 1;
r23845r23846
762711
763712      case 30:
764713         /* S(x) */
765         cpustate->working_store = (x >> 5) & 0xf;   /* or is it (x >> 6)? */
714         m_working_store = (x >> 5) & 0xf;   /* or is it (x >> 6)? */
766715         DELAY(32);  /* no idea what the value is...  All I know is that it takes much
767716                        more time than track switching (which takes 6 cycles) */
768717         break;
769718      }
770719      if (vector)
771720         /* increment word position in vector operations */
772         cpustate->ml = (cpustate->ml & 0x3E0) | ((cpustate->ml + 1) & 0x1F);
721         m_ml = (m_ml & 0x3E0) | ((m_ml + 1) & 0x1F);
773722   } while (vector && has_operand && (++i < 32));  /* iterate 32 times if vector bit is set */
774723                                       /* the has_operand is a mere guess */
775724
776725   /* load ml with Y */
777   delay3 = load_ml(cpustate, y, 0);
726   delay3 = load_ml(y, 0);
778727
779728   /* compute max(delay2, delay3) */
780729   if (delay2 > delay3)
r23845r23846
791740special_fetch:
792741
793742   /* fetch current instruction into control register */
794   cpustate->cr = word_read(cpustate, cpustate->ml, 0);
743   m_cr = word_read(m_ml, 0);
795744}
796745
797746
798static CPU_INIT( apexc )
747void apexc_cpu_device::device_start()
799748{
800   apexc_state *cpustate = get_safe_token(device);
749   m_program = &space(AS_PROGRAM);
750   m_io = &space(AS_IO);
801751
802   cpustate->device = device;
803   cpustate->program = &device->space(AS_PROGRAM);
804   cpustate->io = &device->space(AS_IO);
752   save_item(NAME(m_a));
753   save_item(NAME(m_r));
754   save_item(NAME(m_cr));
755   save_item(NAME(m_ml));
756   save_item(NAME(m_working_store));
757   save_item(NAME(m_current_word));
758   save_item(NAME(m_running));
759   save_item(NAME(m_pc));
805760
806   device->save_item(NAME(cpustate->a));
807   device->save_item(NAME(cpustate->r));
808   device->save_item(NAME(cpustate->cr));
809   device->save_item(NAME(cpustate->ml));
810   device->save_item(NAME(cpustate->working_store));
811   device->save_item(NAME(cpustate->current_word));
812   device->save_item(NAME(cpustate->running));
813   device->save_item(NAME(cpustate->pc));
814}
761   state_add( APEXC_CR, "CR", m_cr ).formatstr("%08X");
762   state_add( APEXC_A, "A", m_a ).formatstr("%08X");
763   state_add( APEXC_R, "R", m_r ).formatstr("%08X");
764   state_add( APEXC_ML, "ML", m_ml ).mask(0xfff).formatstr("%03X");
765   state_add( APEXC_WS, "WS", m_working_store ).mask(0x01);
766   state_add( APEXC_STATE, "CPU state", m_running ).mask(0x01);
767   state_add( APEXC_PC, "PC", m_pc ).callimport().callexport().formatstr("%03X");
768   state_add( APEXC_ML_FULL, "ML_FULL", m_ml_full ).callimport().callexport().noshow();
815769
816static CPU_RESET( apexc )
817{
818   apexc_state *cpustate = get_safe_token(device);
819
820   /* mmmh...  I don't know what happens on reset with an actual APEXC. */
821
822   cpustate->working_store = 1;    /* mere guess */
823   cpustate->current_word = 0;     /* well, we do have to start somewhere... */
824
825   /* next two lines are just the product of my bold fantasy */
826   cpustate->cr = 0;               /* first instruction executed will be a stop */
827   cpustate->running = TRUE;       /* this causes the CPU to load the instruction at 0/0,
828                                which enables easy booting (just press run on the panel) */
770   m_icountptr = &m_icount;
829771}
830772
831static CPU_EXECUTE( apexc )
832{
833   apexc_state *cpustate = get_safe_token(device);
834773
835   do
836   {
837      debugger_instruction_hook(device, cpustate->pc);
838
839      if (cpustate->running)
840         execute(cpustate);
841      else
842      {
843         DELAY(cpustate->icount);    /* burn cycles once for all */
844      }
845   } while (cpustate->icount > 0);
846}
847
848static CPU_SET_INFO( apexc )
774void apexc_cpu_device::state_import(const device_state_entry &entry)
849775{
850   apexc_state *cpustate = get_safe_token(device);
851
852   switch (state)
776   switch (entry.index())
853777   {
854   /* --- the following bits of info are set as 64-bit signed integers --- */
855   /*case CPUINFO_INT_INPUT_STATE + ...:*/                         /* no interrupts */
778      case APEXC_PC:
779         /* keep address 9 LSBits - 10th bit depends on whether we are accessing the permanent
780         track group or a switchable one */
781         m_ml = m_pc & 0x1ff;
782         if (m_pc & 0x1e00)
783         {   /* we are accessing a switchable track group */
784            m_ml |= 0x200;  /* set 10th bit */
856785
857   case CPUINFO_INT_PC:
858      /* keep address 9 LSBits - 10th bit depends on whether we are accessing the permanent
859      track group or a switchable one */
860      cpustate->ml = info->i & 0x1ff;
861      if (info->i & 0x1e00)
862      {   /* we are accessing a switchable track group */
863         cpustate->ml |= 0x200;  /* set 10th bit */
864
865         if (((info->i >> 9) & 0xf) != cpustate->working_store)
866         {   /* we need to do a store switch */
867            cpustate->working_store = ((info->i >> 9) & 0xf);
786            if (((m_pc >> 9) & 0xf) != m_working_store)
787            {   /* we need to do a store switch */
788               m_working_store = ((m_pc >> 9) & 0xf);
789            }
868790         }
869      }
870      break;
791         break;
792   }
793}
871794
872   case CPUINFO_INT_SP:                        (void) info->i; /* no SP */                 break;
873795
874   case CPUINFO_INT_REGISTER + APEXC_CR:       cpustate->cr = info->i;                         break;
875   case CPUINFO_INT_REGISTER + APEXC_A:        cpustate->a = info->i;                          break;
876   case CPUINFO_INT_REGISTER + APEXC_R:        cpustate->r = info->i;                          break;
877   case CPUINFO_INT_REGISTER + APEXC_ML:       cpustate->ml = info->i & 0x3ff;                 break;
878   case CPUINFO_INT_REGISTER + APEXC_PC:       cpustate->pc = info->i;                 break;
879   case CPUINFO_INT_REGISTER + APEXC_WS:       cpustate->working_store = info->i & 0xf;        break;
880   case CPUINFO_INT_REGISTER + APEXC_STATE:    cpustate->running = info->i ? TRUE : FALSE;     break;
796void apexc_cpu_device::state_export(const device_state_entry &entry)
797{
798   switch (entry.index())
799   {
800      case APEXC_ML_FULL:
801         m_ml_full = effective_address(m_ml);
802         break;
881803   }
882804}
883805
884CPU_GET_INFO( apexc )
885{
886   apexc_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
887806
888   switch (state)
807void apexc_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
808{
809   switch (entry.index())
889810   {
890   case CPUINFO_INT_CONTEXT_SIZE:                  info->i = sizeof(apexc_state);          break;
891   case CPUINFO_INT_INPUT_LINES:                   info->i = 0;                            break;
892   case CPUINFO_INT_DEFAULT_IRQ_VECTOR:            info->i = 0;                            break;
893   case CPUINFO_INT_ENDIANNESS:                    info->i = ENDIANNESS_BIG;   /*don't care*/  break;
894   case CPUINFO_INT_CLOCK_MULTIPLIER:              info->i = 1;                            break;
895   case CPUINFO_INT_CLOCK_DIVIDER:                 info->i = 1;                            break;
896   case CPUINFO_INT_MIN_INSTRUCTION_BYTES:         info->i = 4;                            break;
897   case CPUINFO_INT_MAX_INSTRUCTION_BYTES:         info->i = 4;                            break;
898   case CPUINFO_INT_MIN_CYCLES:                    info->i = 2;    /* IIRC */              break;
899   case CPUINFO_INT_MAX_CYCLES:                    info->i = 75;   /* IIRC */              break;
811      case STATE_GENFLAGS:
812         string.printf("%c", m_running ? "R" : "S" );
813         break;
814   }
815}
900816
901   case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM:    info->i = 32;                   break;
902   case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 15;  /*13+2 ignored bits to make double word address*/   break;
903   case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0;                   break;
904   case CPUINFO_INT_DATABUS_WIDTH + AS_DATA:   info->i = 0;                    break;
905   case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA:   info->i = 0;                    break;
906   case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA:   info->i = 0;                    break;
907   case CPUINFO_INT_DATABUS_WIDTH + AS_IO:     info->i = /*5*/8;   /* no I/O bus, but we use address 0 for punchtape I/O */    break;
908   case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO:     info->i = /*0*/1;   /*0 is quite enough but the MAME core does not understand*/ break;
909   case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO:     info->i = 0;                    break;
910817
911   case CPUINFO_INT_SP:                            info->i = 0;    /* no SP */             break;
912   case CPUINFO_INT_PC:
913   case CPUINFO_INT_PREVIOUSPC:                    info->i = cpustate->pc; /* psuedo-PC */             break;
818void apexc_cpu_device::device_reset()
819{
820   /* mmmh...  I don't know what happens on reset with an actual APEXC. */
914821
915   /*case CPUINFO_INT_INPUT_STATE + ...:*/                         /* no interrupts */
822   m_working_store = 1;    /* mere guess */
823   m_current_word = 0;     /* well, we do have to start somewhere... */
916824
917   case CPUINFO_INT_REGISTER + APEXC_CR:           info->i = cpustate->cr;                     break;
918   case CPUINFO_INT_REGISTER + APEXC_A:            info->i = cpustate->a;                      break;
919   case CPUINFO_INT_REGISTER + APEXC_R:            info->i = cpustate->r;                      break;
920   case CPUINFO_INT_REGISTER + APEXC_ML:           info->i = cpustate->ml;                     break;
921   case CPUINFO_INT_REGISTER + APEXC_PC:           info->i = cpustate->pc;                     break;
922   case CPUINFO_INT_REGISTER + APEXC_WS:           info->i = cpustate->working_store;          break;
923   case CPUINFO_INT_REGISTER + APEXC_STATE:        info->i = cpustate->running;                break;
924   case CPUINFO_INT_REGISTER + APEXC_ML_FULL:      info->i = effective_address(cpustate, cpustate->ml);    break;
825   /* next two lines are just the product of my bold fantasy */
826   m_cr = 0;               /* first instruction executed will be a stop */
827   m_running = TRUE;       /* this causes the CPU to load the instruction at 0/0,
828                              which enables easy booting (just press run on the panel) */
829   m_a = 0;
830   m_r = 0;
831   m_pc = 0;
832   m_ml = 0;
833}
925834
926   case CPUINFO_FCT_SET_INFO:                      info->setinfo = CPU_SET_INFO_NAME(apexc);           break;
927   case CPUINFO_FCT_INIT:                          info->init = CPU_INIT_NAME(apexc);              break;
928   case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(apexc);                break;
929   case CPUINFO_FCT_EXECUTE:                       info->execute = CPU_EXECUTE_NAME(apexc);            break;
930   case CPUINFO_FCT_BURN:                          info->burn = NULL;                      break;
931   case CPUINFO_FCT_DISASSEMBLE:                   info->disassemble = CPU_DISASSEMBLE_NAME(apexc);            break;
932   case CPUINFO_PTR_INSTRUCTION_COUNTER:           info->icount = &cpustate->icount;           break;
933835
934   case CPUINFO_STR_NAME:                          strcpy(info->s, "APEXC"); break;
935   case CPUINFO_STR_FAMILY:                    strcpy(info->s, "APEC"); break;
936   case CPUINFO_STR_VERSION:                   strcpy(info->s, "1.0"); break;
937   case CPUINFO_STR_SOURCE_FILE:                       strcpy(info->s, __FILE__); break;
938   case CPUINFO_STR_CREDITS:                   strcpy(info->s, "Raphael Nabet"); break;
836void apexc_cpu_device::execute_run()
837{
838   do
839   {
840      debugger_instruction_hook(this, m_pc);
939841
940   case CPUINFO_STR_FLAGS:                         sprintf(info->s, "%c", (cpustate->running) ? 'R' : 'S'); break;
842      if (m_running)
843         execute();
844      else
845      {
846         DELAY(m_icount);    /* burn cycles once for all */
847      }
848   } while (m_icount > 0);
849}
941850
942   case CPUINFO_STR_REGISTER + APEXC_CR:           sprintf(info->s, "CR:%08X", cpustate->cr); break;
943   case CPUINFO_STR_REGISTER + APEXC_A:            sprintf(info->s, "A :%08X", cpustate->a); break;
944   case CPUINFO_STR_REGISTER + APEXC_R:            sprintf(info->s, "R :%08X", cpustate->r); break;
945   case CPUINFO_STR_REGISTER + APEXC_ML:           sprintf(info->s, "ML:%03X", cpustate->ml); break;
946   case CPUINFO_STR_REGISTER + APEXC_PC:           sprintf(info->s, "PC:%03X", cpustate->pc); break;
947   case CPUINFO_STR_REGISTER + APEXC_WS:           sprintf(info->s, "WS:%01X", cpustate->working_store); break;
948851
949   case CPUINFO_STR_REGISTER + APEXC_STATE:        sprintf(info->s, "CPU state:%01X", cpustate->running ? TRUE : FALSE); break;
950   }
852offs_t apexc_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
853{
854   extern CPU_DISASSEMBLE( apexc );
855   return CPU_DISASSEMBLE_NAME(apexc)(this, buffer, pc, oprom, opram, options);
951856}
952857
953DEFINE_LEGACY_CPU_DEVICE(APEXC, apexc);
trunk/src/emu/cpu/apexc/apexc.h
r23845r23846
1919   APEXC_PC    /* doesn't actually exist; is there for the disassembler */
2020};
2121
22DECLARE_LEGACY_CPU_DEVICE(APEXC, apexc);
22class apexc_cpu_device : public cpu_device
23{
24public:
25   // construction/destruction
26   apexc_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
2327
24CPU_DISASSEMBLE( apexc );
28protected:
29   // device-level overrides
30   virtual void device_start();
31   virtual void device_reset();
2532
33   // device_execute_interface overrides
34   virtual UINT32 execute_min_cycles() const { return 2; }
35   virtual UINT32 execute_max_cycles() const { return 75; }
36   virtual UINT32 execute_input_lines() const { return 0; }
37   virtual void execute_run();
38
39   // device_memory_interface overrides
40   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : NULL ); }
41
42   // device_state_interface overrides
43   virtual void state_import(const device_state_entry &entry);
44   virtual void state_export(const device_state_entry &entry);
45   void state_string_export(const device_state_entry &entry, astring &string);
46
47   // device_disasm_interface overrides
48   virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
49   virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
50   virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
51
52   inline UINT32 apexc_readmem(UINT32 address) { return m_program->read_dword((address)<<2); }
53   inline void apexc_writemem(UINT32 address, UINT32 data) { m_program->write_dword((address)<<2, (data)); }
54   inline void apexc_writemem_masked(UINT32 address, UINT32 data, UINT32 mask) { apexc_writemem((address), (apexc_readmem(address) & ~(mask)) | ((data) & (mask))); }
55
56   UINT32 effective_address(UINT32 address);
57   UINT32 word_read(UINT32 address, UINT32 special);
58   void word_write(UINT32 address, UINT32 data, UINT32 mask);
59   UINT8 papertape_read();
60   void papertape_punch(UINT8 data);
61
62   UINT32 load_ml(UINT32 address, UINT32 vector);
63   void execute();
64
65   address_space_config m_program_config;
66   address_space_config m_io_config;
67
68   UINT32 m_a;   /* accumulator */
69   UINT32 m_r;   /* register */
70   UINT32 m_cr;  /* control register (i.e. instruction register) */
71   int m_ml;     /* memory location (current track in working store, and requested word position within track) (10 bits) */
72   int m_working_store;  /* current working store (group of 16 tracks) (1-15) */
73   int m_current_word;   /* current word position within track (0-31) */
74
75   int m_running;    /* 1 flag: */
76                     /* running: flag implied by the existence of the stop instruction */
77   UINT32 m_pc;  /* address of next instruction for the disassembler */
78
79   address_space *m_program;
80   address_space *m_io;
81   int m_icount;
82
83   // For state
84   UINT32 m_ml_full;
85   UINT32 m_genpc;
86};
87
88
89extern const device_type APEXC;
90
91
2692#endif /* __APEXC_H__ */

Previous 199869 Revisions Next


© 1997-2024 The MAME Team