home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / Z80 emulator / 68K version / Z80_proc.c < prev    next >
Encoding:
Text File  |  1995-11-01  |  7.4 KB  |  302 lines  |  [TEXT/CWIE]

  1.  
  2. /*    Z80 Emulator
  3.     Copyright (C) 1994 G.Woigk
  4.     
  5.     This file is part of Mac Spectacle and it is free software
  6.     See application.c for details
  7.             
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  11.  
  12.     This file must be #included in Z80.m68.c to work
  13.     It contains the body of Z80() or Z80_T(), depending on #defines
  14. */
  15.  
  16.  
  17.  
  18. // -----    Register usage -------------------------------------------------------------
  19. #define    target    a0        // general use as target pointer
  20.  
  21. #define    ai        a1        // index register pointer in ix/iy cmnd processing
  22. #define    ir        (a1)        // access ix or iy
  23. #define    ih        (a1)        // access XH or YH
  24. #define    il        1(a1)    // access XL or YL
  25. #define    air        -2(a1)    // access AIX or AIY
  26.  
  27. #define    ip        a2        // instruction pointer:     zreg.IP.ptr
  28. #define    rp        a3        // return stack pointer:     zreg.RP.ptr
  29. #define    loop        a4        // -> main instruction dispatcher
  30. #define    logflags    a6        // -> array mlog_flags[]
  31.  
  32. #define    scratch    d0
  33. #define    scratch2    d1
  34.  
  35. #define    rom_end    d2
  36. #define    core        d3        // upper half = CORE base address
  37. #define    db        d4        // 0x000000XX:    upper 3 bytes are always 0; db MUST be D4 
  38. #define    a        d5        // 0x00AA00AA:    a.b = A; upper half = A'
  39. #define    f        d6        // 0x00FF00FF:    f.b = F; upper half = F'
  40. #define    cc        d7        // T cycle counter:    count down to 0;  Z80_T() only
  41.  
  42.  
  43. // -----    option depending code macros ----------------------------------------
  44. #if exact_timing
  45. #define    used_regs        a2-a4/a6/d3-d7
  46. #define    sto_cc        move.l    cc,CYCLES
  47. #define    ld_cc        move.l    CYCLES,cc
  48. #define    more1        subq.l    #1,cc    
  49. #define    more2        subq.l    #2,cc    
  50. #define    more3        subq.l    #3,cc    
  51. #define    more4        subq.l    #4,cc    
  52. #define    more5        subq.l    #5,cc    
  53. #define    more6        subq.l    #6,cc    
  54. #define    more7        subq.l    #7,cc    
  55. #define    more8        subq.l    #8,cc    
  56.  
  57. #else
  58. #define    used_regs        a2-a4/a6/d3-d6
  59. #define    sto_cc
  60. #define    ld_cc
  61. #define    more1
  62. #define    more2
  63. #define    more3
  64. #define    more4
  65. #define    more5
  66. #define    more6
  67. #define    more7
  68. #define    more8
  69. #endif
  70.  
  71.  
  72. #if rom_protection
  73. #define    load_rom_end    move.l  core,rom_end;    move.w  #0x4000,rom_end
  74. #define    if_rom(LBL)    cmpa.l  rom_end,a0;    bcs  LBL
  75. #define    store_db        if_rom(store_byte);    move.b    db,(a0);    m_next
  76. #else
  77. #define    load_rom_end
  78. #define    if_rom(LBL)
  79. #define    store_db        move.b    db,(a0);    m_next
  80. #endif
  81.  
  82.  
  83. // =====    Z80 ENGINE BODY ===========================================
  84.  
  85. //short asm Z80 ( )        {
  86. //short asm Z80_T ( )    {
  87.  
  88. // save registers
  89.     movem.l    used_regs,-(a7)
  90.  
  91. // load frequently needed constants into mc68020 registers:
  92.     move.l    CORE,core    
  93.     moveq    #0,db
  94.     lea        mlog_flags,logflags
  95.     lea        nxtcmnd,loop
  96.  
  97. // load the Z80 registers, which are held in mc68020 registers:
  98.     ld_cc                    // cc
  99.     load_r                    // r (optional)
  100.     load_rom_end
  101.  
  102.     move.l    zreg.aa2,a        // A2 and A
  103.  
  104.     move.l    zreg.ff2,f            // F2 and F
  105.     lea        m68flags,a0
  106.     move.b    (a0,f.w),f            // konvert F to m68 layout
  107.     swap     f
  108.     move.b    (a0,f.w),f            // konvert F' to m68 layout
  109.     swap     f
  110.  
  111.     movea.l    APC,ip            // PC
  112.  
  113.     movea.l    ASP,rp            // SP
  114.     cmp.l    core,rp            // sp == 0x0000 ?
  115.     bne.s     spok
  116.     adda.l    #0x00010000,rp;    spok:
  117.  
  118. // check WUFF to see, whether an NMI or IRPT is pending:
  119. check_wuff:
  120.     tst.b     WUFF
  121.     beq        nxtcmnd            // no flag set
  122.     bmi.s     handle_nmi        // bit7: nmi
  123. //    bgt.s     handle_irpt        // bit0-6: irpt
  124.  
  125.  
  126. // ------    Interrupt dispatcher --------------------------------------------------
  127. handle_irpt:
  128.     tst.b        IFF1
  129.     beq        nxtcmnd            // interrupts are disabled
  130.     do_info_irpt
  131.     subq.b    #1,WUFF        // clear interrupt request
  132.     clr.w    IFF1            // disable iff1 & iff2
  133.     cmp.b    #1,IM        // which irpt mode ?
  134.     bgt.s        im2                // irpt mode 2:  indirect call
  135.     blt.s      im0                // irpt mode 0:  read irpt instruction
  136. im1:    move.w    #56,core        // ---- irpt mode 1:  rst 56
  137. j13:    more5                    // 13 T cycles
  138. j08:    more8                    // 
  139. j00:    move.w    ip,d0                // push PC
  140.     rol.w    #8,d0            // ...
  141.     move.w    d0,-(rp)            // ...
  142.     movea.l    core,ip            // load irpt routine address
  143.     m_next                    // next instruction
  144.  
  145. im2:    more6                // ---- irpt mode2:  19 T cycles ((6+8+5))
  146.     move.w    RI,core        // read both: i-register & IRPTCMD !!!
  147.     movea.l    core,a0
  148.     move.w    (a0),core
  149.     rol.w    #8,core
  150.     bra.s     j13
  151.  
  152. im0:    more5                // ---- irpt mode 0:  1 T cycle + normal instruction timing
  153.     move.b    IRPTCMD,db        // irpt mode 0 => read instruction from bus
  154.     bra        xx_im0            // perform instruction (multi-byte instructions not supported!)
  155.     
  156. handle_nmi:                // ---- nmi
  157.     do_info_nmi
  158.     more3                    // nmi: 11 T cycles  ((3+8))
  159.     move.b    IFF1,IFF2            // save iff1
  160.     sf        IFF1                // di
  161.     bclr        #7,WUFF            // clear nmi flag
  162.     move.w    #0x0066,core        // nmi address
  163.     bra.s        j08
  164.  
  165.  
  166. // -----    T cycle counter reached 0 --------------------------------------
  167. #if exact_timing
  168. cycle00:    
  169.     addq.l    #4,cc            // undo last subq
  170.     sto_cc                    // update CYCLES
  171.     jsr        Do_Cycles         // do whatever must be done
  172.     load_rom_end
  173.     ld_cc                    // get CYCLES again
  174.     tst.b        EXIT
  175.     bne        exit_watchdog        // watchdog => exit!
  176.     tst.b     WUFF
  177.     beq.s     nxtcmnd            // no flag set
  178.     bgt         handle_irpt        // irpt
  179.     blt.s        handle_nmi        // nmi
  180. #endif
  181.  
  182.  
  183. // =====    BRANCHING =========================================
  184.  
  185.  
  186. xx32:    btst    #2,f;    beq.s     xx24;    more3;    addq.l    #1,ip;    m_next    // JR NZ,dis
  187. xx40:    btst    #2,f;    bne.s     xx24;    more3;    addq.l    #1,ip;    m_next    // JR Z,dis
  188. xx48:    btst    #0,f;    beq.s     xx24;    more3;    addq.l    #1,ip;    m_next    // JR NC,dis
  189. xx56:    btst    #0,f;    bne.s     xx24;    more3;    addq.l    #1,ip;    m_next    // JR C,dis
  190.  
  191. xx16a:    addq.l #1,ip;    more4;    m_next
  192. xx16:    subq.b #1,RB;    beq.s xx16a;    more1;    // ---- DJNZ dis: Handler (( the most frequent instruction! ))
  193.         
  194. xx24:                    // JR dis
  195.     more8                // 12 T cycles if branched; except DJNZ: 13 T cycles
  196.     move.b    (ip)+,core
  197.     ext.w    core
  198.     add.w    ip,core
  199.  
  200. nxtjmp:                    // ---- complete jump instruction
  201.     movea.l    core,ip
  202.  
  203. nxtirpt:                    // ---- next instr. with test for EXIT  ((Z80() only))
  204. #if !exact_timing
  205.     tst.b     EXIT
  206.     bne        exit_watchdog
  207. #endif
  208.  
  209.  
  210. // -----    THE MAIN INSTRUCTION DISPATCHER --------------------------------
  211.  
  212. nxtcmnd:
  213. #include    "cmd_xx.c"        // used for all instructions which do not modify the PC 
  214. #include    "cmd_CB.c"        // cmd_CB:
  215. #include    "cmd_ED.c"        // cmd_ED:
  216. #include    "cmd_IX/iy.c"        // cmd_IX:  and  cmd_IY:
  217. #include    "cmd_IX/IY_CB.c"    // XYCB:
  218. #include    "cmd_DAA.c"
  219.  
  220.  
  221. // -----    Handling of ROM write accesses -------------------------------------
  222. #if rom_protection
  223. store_byte:            // move.b  db,(a0)
  224.     move.b    db,-(a7)
  225.     move.w    a0,-(a7)
  226.     jsr    write_to_rom
  227.     addq.l    #4,a7
  228.     load_rom_end
  229.     m_next
  230.  
  231. store_word:            // move.w  d0,(a0)
  232.     move.b    d0,-(a7)
  233.     move.w    a0,-(a7)
  234.     ror.w    #8,d0
  235.     addq.l    #1,a0
  236.     move.b    d0,-(a7)
  237.     move.w    a0,-(a7)
  238.     jsr    write_to_rom
  239.     addq.l    #4,a7
  240.     jsr    write_to_rom
  241.     addq.l    #4,a7
  242.     load_rom_end
  243.     m_next
  244. #endif
  245.  
  246.  
  247. // -----    Exit points -------------------------------------------------------------
  248.  
  249. exit_illinstr4:    subq.l    #2,ip
  250. exit_illinstr2:    subq.l    #1,ip
  251. exit_illinstr1:    subq.l    #1,ip
  252. exit_illinstr:    moveq    #nimp_instr,d0
  253.             bra.s         exit_z80
  254.  
  255. exit_rst0:    moveq    #rst0_instr,d0
  256.             bra.s     exit_z80
  257.  
  258. exit_halt:        moveq    #halt_instr,d0
  259.             bra.s     exit_z80
  260.  
  261. exit_watchdog:    sf        EXIT                // clear watchdog flag
  262.             moveq    #watchdog_irpt,d0        // select return code
  263.  
  264. exit_z80:        move.w    ip,PC
  265.             move.w    rp,SP
  266.             move.l    a,zreg.aa2            // A2 and A
  267.  
  268.             lea        z80flags,a0
  269.             move.b    (a0,f.w),f                // konvert F to z80 layout
  270.             swap     f
  271.             move.b    (a0,f.w),f                // konvert F' to z80 layout
  272.             swap     f
  273.             move.l    f,zreg.ff2
  274.  
  275.             sto_cc                        // cc (optional)
  276.             store_r                        // r (optional)
  277.             movem.l    (a7)+,used_regs        // restore old m68 registers
  278.             rts
  279.  
  280. //    }    end of Z80() or Z80_T()
  281.  
  282.  
  283. #undef    exact_timing
  284. #undef    rom_protection
  285. #undef    more1
  286. #undef    more2
  287. #undef    more3
  288. #undef    more4
  289. #undef    more5
  290. #undef    more6
  291. #undef    more7
  292. #undef    more8
  293. #undef    sto_cc
  294. #undef    ld_cc
  295. #undef    store_db
  296. #undef    if_rom
  297. #undef    used_regs
  298. #undef    load_rom_end
  299. #undef    exact_bit
  300. #undef    exact_xy_bit
  301.  
  302.