HD63450.java
     1: //========================================================================================
     2: //  HD63450.java
     3: //    en:DMA controller
     4: //    ja:DMAコントローラ
     5: //  Copyright (C) 2003-2026 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: package xeij;
    14: 
    15: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    16: 
    17: public class HD63450 {
    18: 
    19:   //フラグ
    20:   //                                          3210
    21:   public static final int DMA_DEBUG_TRACE = 0b0000;  //トレースするチャンネルをセット
    22: 
    23:   public static final boolean DMA_ALERT_HIMEM = true;  //MAR,DAR,BARにハイメモリのアドレスが書き込まれた報告する
    24: 
    25:   //レジスタ
    26:   //  DMA_CERはread-only、その他はread/write
    27:   //  DMA_DCR,DMA_SCR,DMA_MTC,DMA_MAR,DMA_DAR,DMA_MFC,DMA_DFCに動作中(dmaACT[i]!=0)に書き込むとDMA_TIMING_ERRORになる
    28: 
    29:   //Channel Status Register (R/W)
    30:   public static final int DMA_CSR = 0x00;
    31:   public static final int DMA_COC = 0b10000000;  //Channel Operation Complete。1=チャンネル動作完了
    32:   public static final int DMA_BLC = 0b01000000;  //BLock transfer Complete。1=ブロック転送完了
    33:   public static final int DMA_NDT = 0b00100000;  //Normal Device Termination。1=正常終了
    34:   public static final int DMA_ERR = 0b00010000;  //ERRor。1=エラーあり
    35:   public static final int DMA_ACT = 0b00001000;  //channel ACTive。1=チャンネル動作中
    36:   public static final int DMA_DIT = 0b00000100;  //! 非対応。~DONE Input Transition。1=~DONE入力があった
    37:   public static final int DMA_PCT = 0b00000010;  //~PCL Transition。1=~PCLの立下りがあった
    38:   public static final int DMA_PCS = 0b00000001;  //~PCL Status。~PCLの状態
    39: 
    40:   //Channel Error Register (R)
    41:   public static final int DMA_CER = 0x01;
    42:   public static final int DMA_ERROR_CODE           = 0b00011111;  //エラーコード
    43:   public static final int DMA_NO_ERROR             = 0b00000000;  //  エラーなし
    44:   public static final int DMA_CONFIGURATION_ERROR  = 0b00000001;  //  コンフィギュレーションエラー
    45:   public static final int DMA_TIMING_ERROR         = 0b00000010;  //  動作タイミングエラー
    46:   public static final int DMA_MEMORY_ADDRESS_ERROR = 0b00000101;  //  アドレスエラー(メモリアドレス)
    47:   public static final int DMA_DEVICE_ADDRESS_ERROR = 0b00000110;  //  アドレスエラー(デバイスアドレス)
    48:   public static final int DMA_BASE_ADDRESS_ERROR   = 0b00000111;  //  アドレスエラー(ベースアドレス)
    49:   public static final int DMA_MEMORY_BUS_ERROR     = 0b00001001;  //  バスエラー(メモリアドレス)
    50:   public static final int DMA_DEVICE_BUS_ERROR     = 0b00001010;  //  バスエラー(デバイスアドレス)
    51:   public static final int DMA_BASE_BUS_ERROR       = 0b00001011;  //  バスエラー(ベースアドレス)
    52:   public static final int DMA_MEMORY_COUNT_ERROR   = 0b00001101;  //  カウントエラー(メモリカウンタ)
    53:   public static final int DMA_BASE_COUNT_ERROR     = 0b00001111;  //  カウントエラー(ベースカウンタ)
    54:   public static final int DMA_EXTERNAL_ABORT       = 0b00010000;  //! 非対応。外部強制停止
    55:   public static final int DMA_SOFTWARE_ABORT       = 0b00010001;  //  ソフトウェア強制停止
    56: 
    57:   //Device Control Register (R/W)
    58:   public static final int DMA_DCR = 0x04;
    59:   public static final int DMA_XRM                    = 0b11000000;  //eXternal Request Mode
    60:   public static final int DMA_BURST_TRANSFER         = 0b00000000;  //  バースト転送モード
    61:   public static final int DMA_NO_HOLD_CYCLE_STEAL    = 0b10000000;  //  ホールドなしサイクルスチールモード
    62:   public static final int DMA_HOLD_CYCLE_STEAL       = 0b11000000;  //! 非対応。ホールドありサイクルスチールモード。ホールドなしサイクルスチールモードと同じ
    63:   public static final int DMA_DTYP                   = 0b00110000;  //Device TYPe
    64:   public static final int DMA_HD68000_COMPATIBLE     = 0b00000000;  //  HD68000コンパチブル(デュアルアドレスモード)
    65:   public static final int DMA_HD6800_COMPATIBLE      = 0b00010000;  //! 非対応。HD6800コンパチブル(デュアルアドレスモード)
    66:   public static final int DMA_ACK_DEVICE             = 0b00100000;  //! 非対応。~ACK付きデバイス(シングルアドレスモード)
    67:   public static final int DMA_ACK_READY_DEVICE       = 0b00110000;  //! 非対応。~ACK,~READY付きデバイス(シングルアドレスモード)
    68:   public static final int DMA_DPS                    = 0b00001000;  //Device Port Size
    69:   public static final int DMA_PORT_8_BIT             = 0b00000000;  //  8ビットポート
    70:   public static final int DMA_PORT_16_BIT            = 0b00001000;  //  16ビットポート
    71:   public static final int DMA_PCL                    = 0b00000011;  //Peripheral Control Line
    72:   public static final int DMA_STATUS_INPUT           = 0b00000000;  //  STATUS入力
    73:   public static final int DMA_STATUS_INPUT_INTERRUPT = 0b00000001;  //! 非対応。割り込みありSTATUS入力
    74:   public static final int DMA_EIGHTH_START_PULSE     = 0b00000010;  //! 非対応。1/8スタートパルス
    75:   public static final int DMA_ABORT_INPUT            = 0b00000011;  //! 非対応。ABORT入力
    76: 
    77:   //Operation Control Register (R/W)
    78:   public static final int DMA_OCR = 0x05;
    79:   public static final int DMA_DIR                 = 0b10000000;  //DIRection
    80:   public static final int DMA_MEMORY_TO_DEVICE    = 0b00000000;  //  メモリ→デバイス。DMA_MAR→DMA_DAR
    81:   public static final int DMA_DEVICE_TO_MEMORY    = 0b10000000;  //  デバイス→メモリ。DMA_DAR→DMA_MAR
    82:   public static final int DMA_BTD                 = 0b01000000;  //! 非対応。multi Block Transfer with ~DONE mode
    83:   public static final int DMA_SIZE                = 0b00110000;  //operand SIZE
    84:   public static final int DMA_BYTE_SIZE           = 0b00000000;  //  8ビット
    85:   public static final int DMA_WORD_SIZE           = 0b00010000;  //  16ビット
    86:   public static final int DMA_LONG_WORD_SIZE      = 0b00100000;  //  32ビット
    87:   public static final int DMA_UNPACKED_8_BIT      = 0b00110000;  //  パックなし8ビット
    88:   public static final int DMA_CHAIN               = 0b00001100;  //CHAINing operation
    89:   public static final int DMA_NO_CHAINING         = 0b00000000;  //  チェインなし
    90:   public static final int DMA_ARRAY_CHAINING      = 0b00001000;  //  アレイチェイン
    91:   public static final int DMA_LINK_ARRAY_CHAINING = 0b00001100;  //  リンクアレイチェイン
    92:   public static final int DMA_REQG                = 0b00000011;  //DMA REQuest Generation method
    93:   public static final int DMA_AUTO_REQUEST        = 0b00000000;  //  オートリクエスト限定速度。転送中にバスを開放する
    94:   public static final int DMA_AUTO_REQUEST_MAX    = 0b00000001;  //  オートリクエスト最大速度。転送中にバスを開放しない
    95:   public static final int DMA_EXTERNAL_REQUEST    = 0b00000010;  //  外部転送要求
    96:   public static final int DMA_DUAL_REQUEST        = 0b00000011;  //  最初はオートリクエスト、2番目から外部転送要求
    97: 
    98:   //Sequence Control Register (R/W)
    99:   public static final int DMA_SCR = 0x06;
   100:   public static final int DMA_MAC =        0b00001100;  //Memory Address register Count
   101:   public static final int DMA_STATIC_MAR = 0b00000000;  //  DMA_MAR固定
   102:   public static final int DMA_INC_MAR    = 0b00000100;  //  DMA_MAR++
   103:   public static final int DMA_DEC_MAR    = 0b00001000;  //  DMA_MAR--
   104:   public static final int DMA_DAC =        0b00000011;  //Device Address register Count
   105:   public static final int DMA_STATIC_DAR = 0b00000000;  //  DMA_DAR固定
   106:   public static final int DMA_INC_DAR    = 0b00000001;  //  DMA_DAR++
   107:   public static final int DMA_DEC_DAR    = 0b00000010;  //  DMA_DAR--
   108: 
   109:   //Channel Control Register (R/W)
   110:   public static final int DMA_CCR = 0x07;
   111:   public static final int DMA_STR = 0b10000000;  //STaRt operation。1=動作開始
   112:   public static final int DMA_CNT = 0b01000000;  //CoNTinue operation。1=コンティニューあり
   113:   public static final int DMA_HLT = 0b00100000;  //Halt operation。1=動作一時停止
   114:   public static final int DMA_SAB = 0b00010000;  //Software ABort。1=動作中止
   115:   public static final int DMA_ITE = 0b00001000;  //InTerrupt Enable。1=割り込み許可
   116: 
   117:   //Transfer Counter, Address Register
   118:   public static final int DMA_MTC = 0x0a;  //Memory Transfer Counter (R/W)
   119:   public static final int DMA_MAR = 0x0c;  //Memory Address Register (R/W)
   120:   public static final int DMA_DAR = 0x14;  //Device Address Register (R/W)
   121:   public static final int DMA_BTC = 0x1a;  //Base Transfer Counter (R/W)
   122:   public static final int DMA_BAR = 0x1c;  //Base Address Register (R/W)
   123: 
   124:   //Interrupt Vector
   125:   public static final int DMA_NIV = 0x25;  //Normal Interrupt Vector (R/W)
   126:   public static final int DMA_EIV = 0x27;  //Error Interrupt Vector (R/W)
   127: 
   128:   //Function Codes
   129:   public static final int DMA_MFC = 0x29;  //Memory Function Codes (R/W)
   130:   public static final int DMA_FC2 = 0b00000100;  //Function Code 2
   131:   public static final int DMA_FC1 = 0b00000010;  //! 非対応。Function Code 1
   132:   public static final int DMA_FC0 = 0b00000001;  //! 非対応。Function Code 0
   133: 
   134:   //Channel Priority Register (R/W)
   135:   public static final int DMA_CPR = 0x2d;
   136:   public static final int DMA_CP = 0b00000011;  //! 未対応。Channel Priority。0=高,1,2,3=低
   137: 
   138:   //Function Codes
   139:   public static final int DMA_DFC = 0x31;  //Device Function Codes (R/W)
   140:   public static final int DMA_BFC = 0x39;  //Base Function Codes (R/W)
   141: 
   142:   //General Control Register (R/W)
   143:   public static final int DMA_GCR = 0xff;
   144:   public static final int DMA_BT = 0b00001100;  //Burst Time。0=16clk,1=32clk,2=64clk,3=128clk
   145:   public static final int DMA_BR = 0b00000011;  //Bandwidth Ratio。0=1/2,1=1/4,2=1/8,3=1/16
   146: 
   147:   //レジスタ
   148:   //  すべてゼロ拡張
   149:   public static final int[] dmaPCS = new int[4];         //DMA_CSR bit0
   150:   public static final int[] dmaPCT = new int[4];         //        bit1
   151:   public static final int[] dmaDIT = new int[4];         //        bit2
   152:   public static final int[] dmaACT = new int[4];         //        bit3
   153:   public static final int[] dmaERR = new int[4];         //        bit4
   154:   public static final int[] dmaNDT = new int[4];         //        bit5
   155:   public static final int[] dmaBLC = new int[4];         //        bit6
   156:   public static final int[] dmaCOC = new int[4];         //        bit7
   157:   public static final int[] dmaErrorCode = new int[4];   //DMA_CER bit0-4
   158:   public static final int[] dmaPCL = new int[4];         //DMA_DCR bit0-1
   159:   public static final int[] dmaDPS = new int[4];         //        bit3
   160:   public static final int[] dmaDTYP = new int[4];        //        bit4-5
   161:   public static final int[] dmaXRM = new int[4];         //        bit6-7
   162:   public static final int[] dmaREQG = new int[4];        //DMA_OCR bit0-1
   163:   public static final int[] dmaCHAIN = new int[4];       //        bit2-3
   164:   public static final int[] dmaSIZE = new int[4];        //        bit4-5
   165:   public static final int[] dmaBTD = new int[4];         //        bit6
   166:   public static final int[] dmaDIR = new int[4];         //        bit7
   167:   public static final int[] dmaDAC = new int[4];         //DMA_SCR bit0-1
   168:   public static final int[] dmaDACValue = new int[4];    //           dmaDAC==(DMA_INC_DAR?1:dmaDAC==DMA_DEC_DAR?-1:0)*(dmaDPS==DMA_PORT_8_BIT?2:1)
   169:   public static final int[] dmaMAC = new int[4];         //        bit2-3
   170:   public static final int[] dmaMACValue = new int[4];    //           dmaMAC==DMA_INC_MAR?1:dmaMAC==DMA_DEC_MAR?-1:0
   171:   public static final int[] dmaITE = new int[4];         //DMA_CCR bit3
   172:   public static final int[] dmaSAB = new int[4];         //        bit4
   173:   public static final int[] dmaHLT = new int[4];         //        bit5
   174:   public static final int[] dmaCNT = new int[4];         //        bit6
   175:   public static final int[] dmaSTR = new int[4];         //        bit7
   176:   public static final int[] dmaMTC = new int[4];         //DMA_MTC bit0-15
   177:   public static final int[] dmaMAR = new int[4];         //DMA_MAR bit0-31
   178:   public static final int[] dmaDAR = new int[4];         //DMA_DAR bit0-31
   179:   public static final int[] dmaBTC = new int[4];         //DMA_BTC bit0-15
   180:   public static final int[] dmaBAR = new int[4];         //DMA_BAR bit0-31
   181:   public static final int[] dmaNIV = new int[4];         //DMA_NIV bit0-7
   182:   public static final int[] dmaEIV = new int[4];         //DMA_EIV bit0-7
   183:   public static final int[] dmaMFC = new int[4];         //DMA_MFC bit2
   184:   public static final MemoryMappedDevice[][] dmaMFCMap = new MemoryMappedDevice[4][];  //  DataBreakPoint.DBP_ON?dmaMFC[i]==0?udm:sdm:dmaMFC[i]==0?um:sm
   185:   public static final int[] dmaCP = new int[4];          //DMA_CPR bit0-1
   186:   public static final int[] dmaDFC = new int[4];         //DMA_DFC bit2
   187:   public static final MemoryMappedDevice[][] dmaDFCMap = new MemoryMappedDevice[4][];  //  DataBreakPoint.DBP_ON?dmaDFC[i]==0?udm:sdm:dmaDFC[i]==0?um:sm
   188:   public static final int[] dmaBFC = new int[4];         //DMA_BFC bit2
   189:   public static final MemoryMappedDevice[][] dmaBFCMap = new MemoryMappedDevice[4][];  //  DataBreakPoint.DBP_ON?dmaBFC[i]==0?udm:sdm:dmaBFC[i]==0?um:sm
   190:   public static int dmaBR;                               //DMA_GCR bit0-1。0=1/2,1=1/4,2=1/8,3=1/16
   191:   public static int dmaBT;                               //        bit2-3。0=16clk,1=32clk,2=64clk,3=128clk
   192:   public static long dmaBurstSpan;  //バースト期間。XEiJ.dmaCycleUnit<<(4+(dmaBT>>2))。MC68450 5-6
   193:   public static long dmaBurstInterval;  //バースト間隔。dmaBurstSpan<<(1+(dmaBR&3))
   194:   public static long dmaBurstStart;  //バースト開始時刻
   195:   public static long dmaBurstEnd;  //バースト終了時刻
   196:   public static long[] dmaRequestTime = new long[4];  //動作開始時刻。オートリクエスト最大速度のとき次の予約を入れる時刻
   197: 
   198:   //割り込み
   199:   public static final int[] dmaInnerRequest = new int[8];  //割り込み要求カウンタ
   200:   public static final int[] dmaInnerAcknowleged = new int[8];  //割り込み受付カウンタ
   201: 
   202:   //クロック
   203:   public static final long[] dmaInnerClock = new long[4];  //転送要求時刻(XEiJ.TMR_FREQ単位)
   204: 
   205:   //パックあり
   206:   public static final int[] dmaMemoryCarry = new int[4];  //メモリでパックするために繰り越したデータ
   207:   public static final int[] dmaDeviceCarry = new int[4];  //デバイスでパックするために繰り越したデータ
   208: 
   209:   //サイクル数補正
   210:   public static final int[] dmaAdditionalCycles = new int[4];  //追加のサイクル数
   211: 
   212:   //アクセスサイクル数
   213:   public static int dmaReadCycles;  //1ワードリードの所要サイクル数
   214:   public static int dmaWriteCycles;  //1ワードライトの所要サイクル数
   215: 
   216:   public static final TickerQueue.Ticker[] dmaTickerArray = new TickerQueue.Ticker[] {
   217:     new TickerQueue.Ticker () {
   218:       @Override protected void tick () {
   219:         dmaTransfer (0);
   220:       }
   221:     },
   222:     new TickerQueue.Ticker () {
   223:       @Override protected void tick () {
   224:         dmaTransfer (1);
   225:       }
   226:     },
   227:     new TickerQueue.Ticker () {
   228:       @Override protected void tick () {
   229:         dmaTransfer (2);
   230:       }
   231:     },
   232:     new TickerQueue.Ticker () {
   233:       @Override protected void tick () {
   234:         dmaTransfer (3);
   235:       }
   236:     },
   237:   };
   238: 
   239:   //dmaInit ()
   240:   //  DMAコントローラを初期化する
   241:   public static void dmaInit () {
   242:     //レジスタ
   243:     //dmaPCS = new int[4];
   244:     //dmaPCT = new int[4];
   245:     //dmaDIT = new int[4];
   246:     //dmaACT = new int[4];
   247:     //dmaERR = new int[4];
   248:     //dmaNDT = new int[4];
   249:     //dmaBLC = new int[4];
   250:     //dmaCOC = new int[4];
   251:     //dmaErrorCode = new int[4];
   252:     //dmaPCL = new int[4];
   253:     //dmaDPS = new int[4];
   254:     //dmaDTYP = new int[4];
   255:     //dmaXRM = new int[4];
   256:     //dmaREQG = new int[4];
   257:     //dmaCHAIN = new int[4];
   258:     //dmaSIZE = new int[4];
   259:     //dmaBTD = new int[4];
   260:     //dmaDIR = new int[4];
   261:     //dmaDAC = new int[4];
   262:     //dmaDACValue = new int[4];
   263:     //dmaMAC = new int[4];
   264:     //dmaMACValue = new int[4];
   265:     //dmaITE = new int[4];
   266:     //dmaSAB = new int[4];
   267:     //dmaHLT = new int[4];
   268:     //dmaCNT = new int[4];
   269:     //dmaSTR = new int[4];
   270:     //dmaMTC = new int[4];
   271:     //dmaMAR = new int[4];
   272:     //dmaDAR = new int[4];
   273:     //dmaBTC = new int[4];
   274:     //dmaBAR = new int[4];
   275:     //dmaNIV = new int[4];
   276:     //dmaEIV = new int[4];
   277:     //dmaMFC = new int[4];
   278:     //dmaMFCMap = new MMD[4];
   279:     //dmaCP = new int[4];
   280:     //dmaDFC = new int[4];
   281:     //dmaDFCMap = new MMD[4];
   282:     //dmaBFC = new int[4];
   283:     //dmaBFCMap = new MMD[4];
   284:     //dmaRequestTime = new long[4];
   285:     //dmaPCSはresetでは操作しない
   286:     dmaPCS[0] = 0;  //外部垂直同期信号。スーパーインポーズしていなければ0
   287:     dmaPCS[1] = 0;  //プルアップされている。常に0
   288:     dmaPCS[2] = 1;  //拡張スロットの~EXPCL。何もなければ1
   289:     dmaPCS[3] = 0;  //ADPCMの~ADPCMREQ。PCL[3]とREQ[3]は直結
   290:     //割り込み
   291:     //dmaInnerRequest = new int[8];
   292:     //dmaInnerAcknowleged = new int[8];
   293:     //クロック
   294:     //dmaInnerClock = new long[4];
   295:     //パックあり
   296:     //dmaMemoryCarry = new int[4];
   297:     //dmaDeviceCarry = new int[4];
   298:     //サイクル数補正
   299:     //dmaAdditionalCycles = new int[4];
   300:     dmaReset ();
   301:   }  //dmaInit()
   302: 
   303:   //リセット
   304:   public static void dmaReset () {
   305:     //レジスタ
   306:     for (int i = 0; i < 4; i++) {
   307:       //dmaPCSはresetでは操作しない
   308:       dmaPCT[i] = 0;
   309:       dmaDIT[i] = 0;
   310:       dmaACT[i] = 0;
   311:       dmaERR[i] = 0;
   312:       dmaNDT[i] = 0;
   313:       dmaBLC[i] = 0;
   314:       dmaCOC[i] = 0;
   315:       dmaErrorCode[i] = 0;
   316:       dmaPCL[i] = 0;
   317:       dmaDPS[i] = 0;
   318:       dmaDTYP[i] = 0;
   319:       dmaXRM[i] = 0;
   320:       dmaREQG[i] = 0;
   321:       dmaCHAIN[i] = 0;
   322:       dmaSIZE[i] = 0;
   323:       dmaBTD[i] = 0;
   324:       dmaDIR[i] = 0;
   325:       dmaDAC[i] = 0;
   326:       dmaDACValue[i] = 0;
   327:       dmaMAC[i] = 0;
   328:       dmaMACValue[i] = 0;
   329:       dmaITE[i] = 0;
   330:       dmaSAB[i] = 0;
   331:       dmaHLT[i] = 0;
   332:       dmaCNT[i] = 0;
   333:       dmaSTR[i] = 0;
   334:       dmaMTC[i] = 0;
   335:       dmaMAR[i] = 0;
   336:       dmaDAR[i] = 0;
   337:       dmaBTC[i] = 0;
   338:       dmaBAR[i] = 0;
   339:       dmaNIV[i] = 0x0f;  //割り込みベクタの初期値は未初期化割り込みを示す0x0f
   340:       dmaEIV[i] = 0x0f;
   341:       dmaMFC[i] = 0;
   342:       if (DataBreakPoint.DBP_ON) {
   343:         dmaMFCMap[i] = DataBreakPoint.dbpUserMap;
   344:       } else {
   345:         dmaMFCMap[i] = XEiJ.busUserMap;
   346:       }
   347:       dmaCP[i] = 0;
   348:       dmaDFC[i] = 0;
   349:       if (DataBreakPoint.DBP_ON) {
   350:         dmaDFCMap[i] = DataBreakPoint.dbpUserMap;
   351:       } else {
   352:         dmaDFCMap[i] = XEiJ.busUserMap;
   353:       }
   354:       dmaBFC[i] = 0;
   355:       if (DataBreakPoint.DBP_ON) {
   356:         dmaBFCMap[i] = DataBreakPoint.dbpUserMap;
   357:       } else {
   358:         dmaBFCMap[i] = XEiJ.busUserMap;
   359:       }
   360:       dmaRequestTime[i] = XEiJ.FAR_FUTURE;
   361:     }
   362:     dmaBR = 0;
   363:     dmaBT = 0;
   364:     dmaBurstSpan = XEiJ.dmaCycleUnit << (4 + (dmaBT >> 2));
   365:     dmaBurstInterval = dmaBurstSpan << (1 + (dmaBR & 3));
   366:     dmaBurstStart = XEiJ.FAR_FUTURE;
   367:     dmaBurstEnd = 0L;
   368:     //割り込み
   369:     for (int i = 0; i < 8; i++) {
   370:       dmaInnerRequest[i] = 0;
   371:       dmaInnerAcknowleged[i] = 0;
   372:     }
   373:     //クロック
   374:     for (int i = 0; i < 4; i++) {
   375:       dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   376:       TickerQueue.tkqRemove (dmaTickerArray[i]);
   377:     }
   378:   }  //dmaReset()
   379: 
   380:   //割り込み受付
   381:   //  コアが割り込み要求を受け付けたときに呼び出す
   382:   //  割り込みベクタ番号を返す
   383:   //  割り込み要求を取り下げる場合は0を返す
   384:   //  オートベクタを使用するデバイスはオートベクタの番号を返すこと
   385:   public static int dmaAcknowledge () {
   386:     for (int i = 0; i < 8; i++) {  //! 未対応。本来はチャンネルプライオリティに従うべき
   387:       int request = dmaInnerRequest[i];
   388:       if (dmaInnerAcknowleged[i] != request) {
   389:         dmaInnerAcknowleged[i] = request;
   390:         return (i & 1) == 0 ? dmaNIV[i >> 1] : dmaEIV[i >> 1];
   391:       }
   392:     }
   393:     return 0;
   394:   }  //dmaAcknowledge()
   395: 
   396:   //割り込み終了
   397:   //  コアが割り込み処理を終了したときに呼び出す
   398:   //  まだ処理されていない割り込みが残っていたら再度割り込み要求を出す
   399:   public static void dmaDone () {
   400:     for (int i = 0; i < 8; i++) {  //! 未対応。本来はチャンネルプライオリティに従うべき
   401:       if (dmaInnerRequest[i] != dmaInnerAcknowleged[i]) {
   402:         XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   403:         return;
   404:       }
   405:     }
   406:   }  //dmaDone()
   407: 
   408:   //dmaStart (i)
   409:   //  DMA転送開始
   410:   public static void dmaStart (int i) {
   411:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   412:       System.out.printf ("%d %08x dmaStart(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   413:       System.out.printf ("CSR=0x%02x,CER=0x%02x,DCR=0x%02x,OCR=0x%02x,SCR=0x%02x,CCR=0x%02x,MTC=0x%04x,MAR=0x%08x,DAR=0x%08x,BTC=0x%04x,BAR=0x%08x\n",
   414:                          dmaCOC[i] | dmaBLC[i] | dmaNDT[i] | dmaERR[i] | dmaACT[i] | dmaDIT[i] | dmaPCT[i] | dmaPCS[i],  //CSR
   415:                          dmaErrorCode[i],  //CER
   416:                          dmaXRM[i] | dmaDTYP[i] | dmaDPS[i] | dmaPCL[i],  //DCR
   417:                          dmaDIR[i] | dmaBTD[i] | dmaSIZE[i] | dmaCHAIN[i] | dmaREQG[i],  //OCR
   418:                          dmaMAC[i] | dmaDAC[i],  //SCR
   419:                          dmaSTR[i] | dmaCNT[i] | dmaHLT[i] | dmaSAB[i] | dmaITE[i],  //CCR
   420:                          dmaMTC[i], dmaMAR[i], dmaDAR[i], dmaBTC[i], dmaBAR[i]);
   421:     }
   422:     //タイミングを確認する
   423:     if ((dmaCOC[i] | dmaBLC[i] | dmaNDT[i] | dmaERR[i] | dmaACT[i]) != 0) {  //DMA_CSRがクリアされていない状態でSTRをセットしようとした
   424:       dmaErrorExit (i, DMA_TIMING_ERROR);
   425:       return;
   426:     }
   427:     //設定を確認する
   428:     if (((dmaDTYP[i] == DMA_HD68000_COMPATIBLE || dmaDTYP[i] == DMA_HD6800_COMPATIBLE) &&  //デュアルアドレスモードで
   429:          dmaDPS[i] == DMA_PORT_16_BIT && dmaSIZE[i] == DMA_BYTE_SIZE &&  //DMA_DPSが16ビットでSIZEが8ビットで
   430:          (dmaREQG[i] == DMA_EXTERNAL_REQUEST || dmaREQG[i] == DMA_DUAL_REQUEST)) ||  //外部転送要求のとき、または
   431:         dmaXRM[i] == 0b01000000 || dmaMAC[i] == 0b00001100 || dmaDAC[i] == 0b00000011 || dmaCHAIN[i] == 0b00000100 ||  //不正な値が指定されたとき
   432:         (dmaSIZE[i] == 0b00000011 && !((dmaDTYP[i] == DMA_HD68000_COMPATIBLE || dmaDTYP[i] == DMA_HD6800_COMPATIBLE) && dmaDPS[i] == DMA_PORT_8_BIT))) {
   433:       dmaErrorExit (i, DMA_CONFIGURATION_ERROR);
   434:       return;
   435:     }
   436:     if (dmaDPS[i] == DMA_PORT_16_BIT &&  //16ビットポートかつ
   437:         dmaSIZE[i] == DMA_UNPACKED_8_BIT) {  //パックなし8ビット
   438:       dmaErrorExit (i, DMA_CONFIGURATION_ERROR);  //コンフィギュレーションエラー
   439:       return;
   440:     }
   441:     //パックありの準備
   442:     dmaMemoryCarry[i] = -1;
   443:     dmaDeviceCarry[i] = -1;
   444:     //strには書き込まない
   445:     //チャンネル動作開始
   446:     dmaRequestTime[i] = XEiJ.mpuClockTime;
   447:     dmaACT[i] = DMA_ACT;
   448:     if (dmaCHAIN[i] == DMA_ARRAY_CHAINING) {  //アレイチェインモードのとき
   449:       if (dmaBTC[i] == 0) {  //カウントエラー
   450:         dmaErrorExit (i, DMA_BASE_COUNT_ERROR);
   451:         return;
   452:       }
   453:       if ((dmaBAR[i] & 1) != 0) {  //アドレスエラー
   454:         dmaErrorExit (i, DMA_BASE_ADDRESS_ERROR);
   455:         return;
   456:       }
   457:       try {
   458:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.dmaWaitTime : XEiJ.dmaNoWaitTime;
   459:         MemoryMappedDevice[] mm = dmaBFCMap[i];
   460:         int a = dmaBAR[i];
   461:         dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
   462:         dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
   463:         dmaBAR[i] += 6;
   464:         XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 3;
   465:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
   466:       } catch (M68kException e) {  //バスエラー
   467:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
   468:         dmaErrorExit (i, DMA_BASE_BUS_ERROR);
   469:         return;
   470:       }
   471:       dmaBTC[i]--;
   472:     } else if (dmaCHAIN[i] == DMA_LINK_ARRAY_CHAINING) {  //リンクアレイチェインモードのとき
   473:       if ((dmaBAR[i] & 1) != 0) {  //アドレスエラー
   474:         dmaErrorExit (i, DMA_BASE_ADDRESS_ERROR);
   475:         return;
   476:       }
   477:       try {
   478:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.dmaWaitTime : XEiJ.dmaNoWaitTime;
   479:         MemoryMappedDevice[] mm = dmaBFCMap[i];
   480:         int a = dmaBAR[i];
   481:         dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
   482:         dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
   483:         dmaBAR[i] = mm[a + 6 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a + 6) << 16 | mm[a + 8 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 8);
   484:         XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 5;
   485:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
   486:       } catch (M68kException e) {  //バスエラー
   487:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
   488:         dmaErrorExit (i, DMA_BASE_BUS_ERROR);
   489:         return;
   490:       }
   491:     }
   492:     //カウントを確認する
   493:     //  アレイチェーンとリンクアレイチェーンはMTCが確定してから行うこと
   494:     if (dmaMTC[i] == 0) {  //カウントが0
   495:       dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);  //カウントエラー
   496:       return;
   497:     }
   498:     //サイクル数補正を準備する
   499:     //  アレイチェーンとリンクアレイチェーンはMARが確定してから行うこと
   500:     dmaAdditionalCycles[i] = (dmaDPS[i] == DMA_PORT_8_BIT ?  //8ビットポート
   501:                               dmaSIZE[i] == DMA_BYTE_SIZE ?  //パックあり
   502:                               (dmaMAR[i] & 1) == 0 && dmaMACValue[i] == 0 ? 6 :  //メモリが偶数アドレスかつカウントしないとき6、
   503:                               (dmaMAR[i] & 1) != 0 && dmaMACValue[i] == 0 ? 8 :  //メモリが奇数アドレスかつカウントしないとき8、
   504:                               dmaDIR[i] == DMA_MEMORY_TO_DEVICE ? 8 : 10 :  //メモリからデバイスへは8、デバイスからメモリへは10
   505:                               dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE ?  //ワードまたはロング
   506:                               dmaDIR[i] == DMA_MEMORY_TO_DEVICE ? 4 : 0 :  //メモリからデバイスへは4、デバイスからメモリへは0
   507:                               0  //パックなしは0
   508:                               :  //16ビットポート
   509:                               dmaSIZE[i] == DMA_BYTE_SIZE ?  //パックあり
   510:                               4 + //基本は4
   511:                               ((dmaMAR[i] & 1) != 0 && dmaMACValue[i] == 0 ? 1 : 0) +  //メモリが奇数アドレスかつカウントしないとき1追加
   512:                               ((dmaDAR[i] & 1) != 0 && dmaDACValue[i] == 0 ? 1 : 0) :  //デバイスが奇数アドレスかつカウントしないとき1追加
   513:                               0);  //ワードまたはロングまたはパックなしは0
   514:     if (dmaREQG[i] == DMA_AUTO_REQUEST) {  //オートリクエスト限定速度
   515:       dmaBurstStart = XEiJ.mpuClockTime;  //今回のバースト開始時刻
   516:       dmaBurstEnd = dmaBurstStart + dmaBurstSpan;  //今回のバースト終了時刻
   517:       dmaTransfer (i);  //最初のデータを転送する
   518:     } else if (dmaREQG[i] != DMA_EXTERNAL_REQUEST ||  //オートリクエスト最大速度または最初はオートリクエスト、2番目から外部転送要求
   519:                dmaPCT[i] != 0) {  //外部転送要求で既に要求がある
   520:       dmaTransfer (i);  //最初のデータを転送する
   521:     }
   522:   }  //dmaStart(int)
   523: 
   524:   //dmaContinue (i)
   525:   //  転送継続
   526:   public static void dmaContinue (int i) {
   527:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   528:       System.out.printf ("%d %08x dmaContinue(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   529:     }
   530:     if (dmaREQG[i] == DMA_AUTO_REQUEST) {  //オートリクエスト限定速度
   531:       if (XEiJ.mpuClockTime < dmaBurstEnd) {  //バースト継続
   532:         //現在時刻に次の予約を入れる
   533:         //dmaInnerClock[i] = XEiJ.mpuClockTime;
   534:         //動作開始時刻に次の予約を入れる
   535:         dmaInnerClock[i] = dmaRequestTime[i];
   536:         TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   537:       } else {  //バースト終了
   538:         dmaBurstStart += dmaBurstInterval;  //次回のバースト開始時刻
   539:         if (dmaBurstStart < XEiJ.mpuClockTime) {
   540:           dmaBurstStart = XEiJ.mpuClockTime + dmaBurstInterval;  //間に合っていないとき1周だけ延期する
   541:         }
   542:         dmaBurstEnd = dmaBurstStart + dmaBurstSpan;  //次回のバースト終了時刻
   543:         //次回のバースト開始時刻に次の予約を入れる
   544:         dmaInnerClock[i] = dmaBurstStart;
   545:         TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   546:       }
   547:     } else if (dmaREQG[i] == DMA_AUTO_REQUEST_MAX) {  //オートリクエスト最大速度
   548:       //現在時刻に次の予約を入れる
   549:       //dmaInnerClock[i] = XEiJ.mpuClockTime;
   550:       //動作開始時刻に次の予約を入れる
   551:       dmaInnerClock[i] = dmaRequestTime[i];
   552:       TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   553:     }
   554:   }  //dmaContinue(int)
   555: 
   556:   //dmaHalt (i,hlt)
   557:   //  停止と再開
   558:   public static void dmaHalt (int i, int hlt) {
   559:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   560:       System.out.printf ("%d %08x dmaHalt(%d,%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i, hlt);
   561:     }
   562:     if ((~dmaHLT[i] & hlt) != 0) {  //動作→停止
   563:       if (dmaACT[i] == 0) {  //動作中でないときHLTをセットしようとした
   564:         dmaErrorExit (i, DMA_TIMING_ERROR);
   565:         return;
   566:       }
   567:       dmaHLT[i] = DMA_HLT;
   568:       dmaRequestTime[i] = XEiJ.FAR_FUTURE;
   569:       if (dmaInnerClock[i] != XEiJ.FAR_FUTURE) {
   570:         dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   571:         TickerQueue.tkqRemove (dmaTickerArray[i]);
   572:       }
   573:     } else if ((dmaHLT[i] & ~hlt) != 0) {  //停止→動作
   574:       dmaHLT[i] = 0;
   575:       if (dmaACT[i] == 0) {
   576:         return;
   577:       }
   578:       dmaRequestTime[i] = XEiJ.mpuClockTime;
   579:       if (dmaREQG[i] == DMA_AUTO_REQUEST) {  //オートリクエスト限定速度
   580:         dmaBurstStart = XEiJ.mpuClockTime;
   581:         dmaBurstEnd = dmaBurstStart + dmaBurstSpan;
   582:       }
   583:       dmaContinue (i);
   584:     }
   585:   }
   586: 
   587:   //dmaComplete (i)
   588:   //  転送終了
   589:   //  dmaBLC,dmaNDTは個別に設定すること
   590:   public static void dmaComplete (int i) {
   591:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   592:       System.out.printf ("%d %08x dmaComplete(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   593:     }
   594:     dmaRequestTime[i] = XEiJ.FAR_FUTURE;
   595:     dmaCOC[i] = DMA_COC;
   596:     dmaERR[i] = 0;
   597:     dmaACT[i] = 0;
   598:     dmaSTR[i] = 0;
   599:     dmaCNT[i] = 0;
   600:     dmaSAB[i] = 0;
   601:     dmaErrorCode[i] = 0;
   602:     if (dmaITE[i] != 0) {  //インタラプトイネーブル
   603:       dmaInnerRequest[i << 1]++;
   604:       XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   605:     }
   606:     if (dmaInnerClock[i] != XEiJ.FAR_FUTURE) {
   607:       dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   608:       TickerQueue.tkqRemove (dmaTickerArray[i]);
   609:     }
   610:   }  //dmaComplete(int)
   611: 
   612:   //dmaErrorExit (i, code)
   613:   //  エラー終了
   614:   //  dmaBLC,dmaNDTは操作しない
   615:   public static void dmaErrorExit (int i, int code) {
   616:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   617:       System.out.printf ("%d %08x dmaErrorExit(%d,%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i, code);
   618:     }
   619:     dmaRequestTime[i] = XEiJ.FAR_FUTURE;
   620:     dmaCOC[i] = DMA_COC;
   621:     dmaERR[i] = DMA_ERR;
   622:     dmaACT[i] = 0;
   623:     dmaSTR[i] = 0;
   624:     dmaCNT[i] = 0;
   625:     dmaHLT[i] = 0;
   626:     dmaSAB[i] = 0;
   627:     dmaErrorCode[i] = code;
   628:     if (dmaITE[i] != 0) {  //インタラプトイネーブル
   629:       dmaInnerRequest[i << 1 | 1]++;
   630:       XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   631:     }
   632:     if (dmaInnerClock[i] != XEiJ.FAR_FUTURE) {
   633:       dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   634:       TickerQueue.tkqRemove (dmaTickerArray[i]);
   635:     }
   636:   }  //dmaErrorExit(int,int)
   637: 
   638:   //dmaFallPCL (i) {
   639:   public static void dmaFallPCL (int i) {
   640:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   641:       System.out.printf ("%d %08x dmaFallPCL(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   642:     }
   643:     dmaPCS[i] = 0;
   644:     dmaPCT[i] = DMA_PCT;
   645:   }  //dmaFallPCL
   646: 
   647:   //dmaRisePCL (i)
   648:   public static void dmaRisePCL (int i) {
   649:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   650:       System.out.printf ("%d %08x dmaRisePCL(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   651:     }
   652:     dmaPCS[i] = DMA_PCS;
   653:     dmaPCT[i] = 0;
   654:   }  //dmaRisePCL
   655: 
   656:   //dmaFallREQ (i) {
   657:   //  外部転送要求
   658:   public static void dmaFallREQ (int i) {
   659:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   660:       System.out.printf ("%d %08x dmaFallREQ(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   661:     }
   662:     if (dmaACT[i] != 0 &&  //動作中
   663:         (dmaREQG[i] & (DMA_EXTERNAL_REQUEST & DMA_DUAL_REQUEST)) != 0) {  //外部転送要求または最初はオートリクエスト、2番目から外部転送要求
   664:       //現在時刻から1clk後に次の予約を入れる
   665:       //  0clk後だとADPCMの再生に失敗する場合がある
   666:       dmaInnerClock[i] = XEiJ.mpuClockTime + XEiJ.dmaCycleUnit * 1;
   667:       TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   668:     }
   669:   }  //dmaFallREQ
   670: 
   671:   //dmaRiseREQ (i)
   672:   //  外部転送要求解除
   673:   public static void dmaRiseREQ (int i) {
   674:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   675:       System.out.printf ("%d %08x dmaRiseREQ(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   676:     }
   677:     dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   678:     TickerQueue.tkqRemove (dmaTickerArray[i]);
   679:   }  //dmaRiseREQ
   680: 
   681:   //dmaTransfer (i)
   682:   //  1データ転送する
   683:   @SuppressWarnings ("fallthrough") public static void dmaTransfer (int i) {
   684:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   685:       System.out.printf ("%d %08x dmaTransfer(%d,0x%08x,0x%08x,%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i,
   686:                          dmaDIR[i] == DMA_MEMORY_TO_DEVICE ? dmaMAR[i] : dmaDAR[i],
   687:                          dmaDIR[i] == DMA_MEMORY_TO_DEVICE ? dmaDAR[i] : dmaMAR[i],
   688:                          dmaSIZE[i] == DMA_BYTE_SIZE || dmaSIZE[i] == DMA_UNPACKED_8_BIT ? 1 : dmaSIZE[i] == DMA_WORD_SIZE ? 2 : 4);
   689:     }
   690:     if (dmaHLT[i] != 0) {  //一時停止中
   691:       return;  //何もしない
   692:     }
   693:   transfer:
   694:     {
   695:       int code = 0;
   696:       try {
   697:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.dmaWaitTime : XEiJ.dmaNoWaitTime;
   698:         switch (dmaSIZE[i]) {
   699:         case DMA_BYTE_SIZE:  //バイト、パックあり
   700:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリからデバイスへ
   701:             //メモリから読み出す
   702:             code = DMA_MEMORY_BUS_ERROR;
   703:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   704:             int a = dmaMAR[i];  //メモリアドレス
   705:             int ac = dmaMACValue[i];  //メモリアドレスカウント
   706:             int data = dmaMemoryCarry[i];  //繰り越したデータ
   707:             if (0 <= data) {  //繰り越したデータがある。繰り越したデータを使う
   708:               dmaMemoryCarry[i] = -1;
   709:             } else if ((a & 1) == 0 && ac == 1 && 2 <= dmaMTC[i]) {  //偶数アドレスで1ずつ増えて最後ではない
   710:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);  //ワードで読み出す
   711:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   712:               dmaMemoryCarry[i] = data & 255;  //下位バイトを繰り越す
   713:               data >>= 8;  //上位バイトを使う
   714:             } else if ((a & 1) != 0 && ac == -1 && 2 <= dmaMTC[i]) {  //奇数アドレスで1ずつ減って最後ではない
   715:               data = mm[(a - 1) >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a - 1);  //ワードで読み出す
   716:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   717:               dmaMemoryCarry[i] = data >> 8;  //上位バイトを繰り越す
   718:               data &= 255;  //下位バイトを使う
   719:             } else {  //その他
   720:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);  //バイトで読み出して使う
   721:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   722:             }
   723:             dmaMAR[i] = a + ac;  //メモリアドレスを更新する
   724:             //EXACKの処理
   725:             if (i == 2) {
   726:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   727:                 MercuryUnit.mu4ExackStart ();
   728:               }
   729:             }
   730:             //デバイスへ書き込む
   731:             code = DMA_DEVICE_BUS_ERROR;
   732:             mm = dmaDFCMap[i];
   733:             a = dmaDAR[i];  //デバイスアドレス
   734:             ac = dmaDACValue[i];  //デバイスアドレスカウント
   735:             int carry = dmaDeviceCarry[i];  //繰り越したデータ
   736:             if (0 <= carry) {  //繰り越したデータがある
   737:               if ((a & 1) != 0) {  //奇数アドレス
   738:                 data = carry << 8 | data;  //繰り越したデータを上位バイト、今回のデータを下位バイトとする
   739:                 mm[(a - 1) >>> XEiJ.BUS_PAGE_BITS].mmdWw (a - 1, data);  //偶数アドレスにワードで書き込む
   740:               } else {  //偶数アドレス
   741:                 data = data << 8 | carry;  //今回のデータを上位バイト、繰り越したデータを下位バイトとする
   742:                 mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);  //ワードで書き込む
   743:               }
   744:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   745:               dmaDeviceCarry[i] = -1;
   746:             } else if (((a & 1) == 0 ? ac == 1 : ac == -1) && 2 <= dmaMTC[i]) {  //偶数アドレスで1ずつ増えるか奇数アドレスで1ずつ減って、最後ではない
   747:               dmaDeviceCarry[i] = data;  //繰り越す
   748:             } else {  //その他
   749:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);  //今回のデータをバイトで書き込む
   750:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   751:             }
   752:             dmaDAR[i] = a + ac;  //デバイスアドレスを更新する
   753:           } else {  //デバイスからメモリへ
   754:             //EXACKの処理
   755:             if (i == 2) {
   756:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   757:                 MercuryUnit.mu4ExackStart ();
   758:               }
   759:             }
   760:             //デバイスから読み出す
   761:             code = DMA_DEVICE_BUS_ERROR;
   762:             MemoryMappedDevice[] mm = dmaDFCMap[i];
   763:             int a = dmaDAR[i];  //デバイスアドレス
   764:             int ac = dmaDACValue[i];  //デバイスアドレスカウント
   765:             int data = dmaDeviceCarry[i];  //繰り越したデータ
   766:             if (0 <= data) {  //繰り越したデータがある。繰り越したデータを使う
   767:               dmaDeviceCarry[i] = -1;
   768:             } else if ((a & 1) == 0 && ac == 1 && 2 <= dmaMTC[i]) {  //偶数アドレスで1ずつ増えて最後ではない
   769:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);  //ワードで読み出す
   770:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   771:               dmaDeviceCarry[i] = data & 255;  //下位バイトを繰り越す
   772:               data >>= 8;  //上位バイトを使う
   773:             } else if ((a & 1) != 0 && ac == -1 && 2 <= dmaMTC[i]) {  //奇数アドレスで1ずつ減って最後ではない
   774:               data = mm[(a - 1) >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a - 1);  //ワードで読み出す
   775:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   776:               dmaDeviceCarry[i] = data >> 8;  //上位バイトを繰り越す
   777:               data &= 255;  //下位バイトを使う
   778:             } else {  //その他
   779:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);  //バイトで読み出して使う
   780:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   781:             }
   782:             dmaDAR[i] = a + ac;  //デバイスアドレスを更新する
   783:             //メモリへ書き込む
   784:             code = DMA_MEMORY_BUS_ERROR;
   785:             mm = dmaMFCMap[i];
   786:             a = dmaMAR[i];  //メモリアドレス
   787:             ac = dmaMACValue[i];  //メモリアドレスカウント
   788:             int carry = dmaMemoryCarry[i];  //繰り越したデータ
   789:             if (0 <= carry) {  //繰り越したデータがある
   790:               if ((a & 1) != 0) {  //奇数アドレス
   791:                 data = carry << 8 | data;  //繰り越したデータを上位バイト、今回のデータを下位バイトとする
   792:                 mm[(a - 1) >>> XEiJ.BUS_PAGE_BITS].mmdWw (a - 1, data);  //偶数アドレスにワードで書き込む
   793:               } else {  //偶数アドレス
   794:                 data = data << 8 | carry;  //今回のデータを上位バイト、繰り越したデータを下位バイトとする
   795:                 mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);  //ワードで書き込む
   796:               }
   797:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   798:               dmaMemoryCarry[i] = -1;
   799:             } else if (((a & 1) == 0 ? ac == 1 : ac == -1) && 2 <= dmaMTC[i]) {  //偶数アドレスで1ずつ増えるか奇数アドレスで1ずつ減って、最後ではない
   800:               dmaMemoryCarry[i] = data;  //繰り越す
   801:             } else {  //その他
   802:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);  //今回のデータをバイトで書き込む
   803:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   804:             }
   805:             dmaMAR[i] = a + ac;  //メモリアドレスを更新する
   806:           }
   807:           break;
   808:           //
   809:         case DMA_WORD_SIZE:  //ワード
   810:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリからデバイスへ
   811:             //メモリから読み出す
   812:             code = DMA_MEMORY_BUS_ERROR;
   813:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   814:             int a = dmaMAR[i];  //メモリアドレス
   815:             int ac = dmaMACValue[i];  //メモリアドレスカウント
   816:             if ((a & 1) != 0) {  //アドレスエラー
   817:               dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   818:               break transfer;
   819:             }
   820:             int data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);  //ワードで読み出す
   821:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   822:             dmaMAR[i] = a + ac * 2;  //メモリアドレスを更新する
   823:             //EXACKの処理
   824:             if (i == 2) {
   825:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   826:                 MercuryUnit.mu4ExackStart ();
   827:               }
   828:             }
   829:             //デバイスへ書き込む
   830:             code = DMA_DEVICE_BUS_ERROR;
   831:             mm = dmaDFCMap[i];
   832:             a = dmaDAR[i];  //デバイスアドレス
   833:             ac = dmaDACValue[i];  //デバイスアドレスカウント
   834:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //8ビットポート
   835:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data >> 8);  //上位バイトをバイトで書き込む
   836:               mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdWb (a + 2, data);  //下位バイトをバイトで書き込む
   837:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles * 2;
   838:             } else {  //16ビットポート
   839:               if ((a & 1) != 0) {  //アドレスエラー
   840:                 dmaErrorExit (i, DMA_DEVICE_ADDRESS_ERROR);
   841:                 break transfer;
   842:               }
   843:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);  //ワードで書き込む
   844:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   845:             }
   846:             dmaDAR[i] = a + ac * 2;  //デバイスアドレスを更新する
   847:           } else {  //デバイスからメモリへ
   848:             //EXACKの処理
   849:             if (i == 2) {
   850:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   851:                 MercuryUnit.mu4ExackStart ();
   852:               }
   853:             }
   854:             //デバイスから読み出す
   855:             code = DMA_DEVICE_BUS_ERROR;
   856:             MemoryMappedDevice[] mm = dmaDFCMap[i];
   857:             int a = dmaDAR[i];  //デバイスアドレス
   858:             int ac = dmaDACValue[i];  //デバイスアドレスカウント
   859:             int data;
   860:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //8ビットポート
   861:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a) << 8;  //上位バイトをバイトで読み出す
   862:               data |= mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a + 2);  //下位バイトをバイトで読み出す
   863:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 2;
   864:             } else {  //16ビットポート
   865:               if ((a & 1) != 0) {  //アドレスエラー
   866:                 dmaErrorExit (i, DMA_DEVICE_ADDRESS_ERROR);
   867:                 break transfer;
   868:               }
   869:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);  //ワードで読み出す
   870:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   871:             }
   872:             dmaDAR[i] = a + ac * 2;  //デバイスアドレスを更新する
   873:             //メモリへ書き込む
   874:             code = DMA_MEMORY_BUS_ERROR;
   875:             mm = dmaMFCMap[i];
   876:             a = dmaMAR[i];  //メモリアドレス
   877:             ac = dmaMACValue[i];  //メモリアドレスカウント
   878:             if ((a & 1) != 0) {  //アドレスエラー
   879:               dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   880:               break transfer;
   881:             }
   882:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);  //ワードで書き込む
   883:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   884:             dmaMAR[i] = a + ac * 2;  //メモリアドレスを更新する
   885:           }
   886:           break;
   887:           //
   888:         case DMA_LONG_WORD_SIZE:  //ロング
   889:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリからデバイスへ
   890:             //メモリから読み出す
   891:             code = DMA_MEMORY_BUS_ERROR;
   892:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   893:             int a = dmaMAR[i];  //メモリアドレス
   894:             int ac = dmaMACValue[i];  //メモリアドレスカウント
   895:             if ((a & 1) != 0) {  //アドレスエラー
   896:               dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   897:               break transfer;
   898:             }
   899:             int data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a) << 16;  //上位ワードをワードで読み出す
   900:             data |= mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);  //下位ワードをワードで読み出す
   901:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 2;
   902:             dmaMAR[i] = a + ac * 4;  //メモリアドレスを更新する
   903:             //EXACKの処理
   904:             if (i == 2) {
   905:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   906:                 MercuryUnit.mu4ExackStart ();
   907:               }
   908:             }
   909:             //デバイスへ書き込む
   910:             code = DMA_DEVICE_BUS_ERROR;
   911:             mm = dmaDFCMap[i];
   912:             a = dmaDAR[i];  //デバイスアドレス
   913:             ac = dmaDACValue[i];  //デバイスアドレスカウント
   914:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //8ビットポート
   915:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data >> 24);  //上位ワードの上位バイトをバイトで書き込む
   916:               mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdWb (a + 2, data >> 16);  //上位ワードの下位バイトをバイトで書き込む
   917:               mm[(a + 4) >>> XEiJ.BUS_PAGE_BITS].mmdWb (a + 4, data >> 8);  //下位ワードの上位バイトをバイトで書き込む
   918:               mm[(a + 6) >>> XEiJ.BUS_PAGE_BITS].mmdWb (a + 6, data);  //下位ワードの下位バイトをバイトで書き込む
   919:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles * 4;
   920:             } else {  //16ビットポート
   921:               if ((a & 1) != 0) {  //アドレスエラー
   922:                 dmaErrorExit (i, DMA_DEVICE_ADDRESS_ERROR);
   923:                 break transfer;
   924:               }
   925:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data >> 16);  //上位ワードをワードで書き込む
   926:               mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdWw (a + 2, data);  //下位ワードをワードで書き込む
   927:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles * 2;
   928:             }
   929:             dmaDAR[i] = a + ac * 4;  //デバイスアドレスを更新する
   930:           } else {  //デバイスからメモリへ
   931:             //EXACKの処理
   932:             if (i == 2) {
   933:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   934:                 MercuryUnit.mu4ExackStart ();
   935:               }
   936:             }
   937:             //デバイスから読み出す
   938:             code = DMA_DEVICE_BUS_ERROR;
   939:             MemoryMappedDevice[] mm = dmaDFCMap[i];
   940:             int a = dmaDAR[i];  //デバイスアドレス
   941:             int ac = dmaDACValue[i];  //デバイスアドレスカウント
   942:             int data;
   943:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //8ビットポート
   944:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a) << 24;  //上位ワードの上位バイトをバイトで読み出す
   945:               data |= mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a + 2) << 16;  //上位ワードの下位バイトをバイトで読み出す
   946:               data |= mm[(a + 4) >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a + 4) << 8;  //下位ワードの上位バイトをバイトで読み出す
   947:               data |= mm[(a + 6) >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a + 6);  //下位ワードの下位バイトをバイトで読み出す
   948:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 4;
   949:             } else {  //16ビットポート
   950:               if ((a & 1) != 0) {  //アドレスエラー
   951:                 dmaErrorExit (i, DMA_DEVICE_ADDRESS_ERROR);
   952:                 break transfer;
   953:               }
   954:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a) << 16;  //上位ワードをワードで読み出す
   955:               data |= mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);  //下位ワードをワードで読み出す
   956:               XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 2;
   957:             }
   958:             dmaDAR[i] = a + ac * 4;  //デバイスアドレスを更新する
   959:             //メモリへ書き込む
   960:             code = DMA_MEMORY_BUS_ERROR;
   961:             mm = dmaMFCMap[i];
   962:             a = dmaMAR[i];  //メモリアドレス
   963:             ac = dmaMACValue[i];  //メモリアドレスカウント
   964:             if ((a & 1) != 0) {  //アドレスエラー
   965:               dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   966:               break transfer;
   967:             }
   968:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data >> 16);  //上位ワードをワードで書き込む
   969:             mm[(a + 2) >>> XEiJ.BUS_PAGE_BITS].mmdWw (a + 2, data);  //下位ワードをワードで書き込む
   970:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles * 2;
   971:             dmaMAR[i] = a + ac * 4;  //メモリアドレスを更新する
   972:           }
   973:           break;
   974:           //
   975:         case DMA_UNPACKED_8_BIT:  //バイト、パックなし
   976:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリからデバイスへ
   977:             //メモリから読み出す
   978:             code = DMA_MEMORY_BUS_ERROR;
   979:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   980:             int a = dmaMAR[i];  //メモリアドレス
   981:             int ac = dmaMACValue[i];  //メモリアドレスカウント
   982:             int data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);  //バイトで読み出す
   983:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
   984:             dmaMAR[i] = a + ac;  //メモリアドレスを更新する
   985:             //EXACKの処理
   986:             if (i == 2) {
   987:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
   988:                 MercuryUnit.mu4ExackStart ();
   989:               }
   990:             }
   991:             //デバイスへ書き込む
   992:             code = DMA_DEVICE_BUS_ERROR;
   993:             mm = dmaDFCMap[i];
   994:             a = dmaDAR[i];  //デバイスアドレス
   995:             ac = dmaDACValue[i];  //デバイスアドレスカウント
   996:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);  //バイトで書き込む
   997:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
   998:             dmaDAR[i] = a + ac;  //デバイスアドレスを更新する
   999:           } else {  //デバイスからメモリへ
  1000:             //EXACKの処理
  1001:             if (i == 2) {
  1002:               if (MercuryUnit.MU4_ON && MercuryUnit.mu4On) {
  1003:                 MercuryUnit.mu4ExackStart ();
  1004:               }
  1005:             }
  1006:             //デバイスから読み出す
  1007:             code = DMA_DEVICE_BUS_ERROR;
  1008:             MemoryMappedDevice[] mm = dmaDFCMap[i];
  1009:             int a = dmaDAR[i];  //デバイスアドレス
  1010:             int ac = dmaDACValue[i];  //デバイスアドレスカウント
  1011:             int data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);  //バイトで読み出す
  1012:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles;
  1013:             dmaDAR[i] = a + ac;  //デバイスアドレスを更新する
  1014:             //メモリへ書き込む
  1015:             code = DMA_MEMORY_BUS_ERROR;
  1016:             mm = dmaMFCMap[i];
  1017:             a = dmaMAR[i];  //メモリアドレス
  1018:             ac = dmaMACValue[i];  //メモリアドレスカウント
  1019:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);  //バイトで書き込む
  1020:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaWriteCycles;
  1021:             dmaMAR[i] = a + ac;  //メモリアドレスを更新する
  1022:           }
  1023:           break;
  1024:         }  //switch dmaSIZE[i]
  1025:         //サイクル数を補正する
  1026:         XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaAdditionalCycles[i];
  1027:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
  1028:       } catch (M68kException e) {
  1029:         XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
  1030:         dmaErrorExit (i, code);
  1031:         break transfer;
  1032:       }
  1033:       dmaMTC[i]--;
  1034:       if (dmaMTC[i] != 0) {  //継続
  1035:         dmaContinue (i);
  1036:       } else if (dmaCHAIN[i] == DMA_ARRAY_CHAINING) {  //アレイチェーンモードのとき
  1037:         if (dmaBTC[i] != 0) {  //継続
  1038:           //アドレスエラーのチェックは不要
  1039:           try {
  1040:             XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.dmaWaitTime : XEiJ.dmaNoWaitTime;
  1041:             MemoryMappedDevice[] mm = dmaBFCMap[i];
  1042:             int a = dmaBAR[i];
  1043:             dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
  1044:             dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
  1045:             dmaBAR[i] += 6;
  1046:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 3;
  1047:             XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
  1048:           } catch (M68kException e) {  //バスエラー
  1049:             XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
  1050:             dmaErrorExit (i, DMA_BASE_BUS_ERROR);
  1051:             break transfer;
  1052:           }
  1053:           dmaBTC[i]--;
  1054:           if (dmaMTC[i] == 0) {  //カウントエラー
  1055:             dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
  1056:             break transfer;
  1057:           }
  1058:           if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
  1059:             dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
  1060:             break transfer;
  1061:           }
  1062:           dmaContinue (i);
  1063:         } else {  //終了
  1064:           dmaBLC[i] = DMA_BLC;
  1065:           dmaNDT[i] = 0;
  1066:           dmaComplete (i);
  1067:         }
  1068:       } else if (dmaCHAIN[i] == DMA_LINK_ARRAY_CHAINING) {  //リンクアレイチェーンモードのとき
  1069:         if (dmaBAR[i] != 0) {  //継続
  1070:           if ((dmaBAR[i] & 1) != 0) {  //アドレスエラー
  1071:             dmaErrorExit (i, DMA_BASE_ADDRESS_ERROR);
  1072:             break transfer;
  1073:           }
  1074:           try {
  1075:             XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.dmaWaitTime : XEiJ.dmaNoWaitTime;
  1076:             MemoryMappedDevice[] mm = dmaBFCMap[i];
  1077:             int a = dmaBAR[i];
  1078:             dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
  1079:             dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
  1080:             dmaBAR[i] = mm[a + 6 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a + 6) << 16 | mm[a + 8 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 8);
  1081:             XEiJ.mpuClockTime += XEiJ.dmaCycleUnit * dmaReadCycles * 5;
  1082:             XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
  1083:           } catch (M68kException e) {  //バスエラー
  1084:             XEiJ.busWaitTime = XEiJ.busWaitCycles ? XEiJ.mpuWaitTime : XEiJ.mpuNoWaitTime;
  1085:             dmaErrorExit (i, DMA_BASE_BUS_ERROR);
  1086:             break transfer;
  1087:           }
  1088:           if (dmaMTC[i] == 0) {  //カウントエラー
  1089:             dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
  1090:             break transfer;
  1091:           }
  1092:           if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
  1093:             dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
  1094:             break transfer;
  1095:           }
  1096:           dmaContinue (i);
  1097:         } else {  //終了
  1098:           dmaBLC[i] = DMA_BLC;
  1099:           dmaNDT[i] = 0;
  1100:           dmaComplete (i);
  1101:         }
  1102:       } else if (dmaCNT[i] != 0) {  //コンティニューモードのとき
  1103:         dmaBLC[i] = DMA_BLC;
  1104:         dmaCNT[i] = 0;
  1105:         if (dmaITE[i] != 0) {  //インタラプトイネーブル
  1106:           dmaInnerRequest[i << 1]++;
  1107:           XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
  1108:         }
  1109:         dmaMTC[i] = dmaBTC[i];
  1110:         dmaMAR[i] = dmaBAR[i];
  1111:         if (dmaMTC[i] == 0) {  //カウントエラー
  1112:           dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
  1113:           break transfer;
  1114:         }
  1115:         if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
  1116:           dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
  1117:           break transfer;
  1118:         }
  1119:         dmaContinue (i);
  1120:       } else {  //終了
  1121:         dmaBLC[i] = 0;
  1122:         dmaNDT[i] = 0;
  1123:         dmaComplete (i);
  1124:       }
  1125:     }  //transfer
  1126:   }  //dmaTransfer
  1127: 
  1128: 
  1129: 
  1130:   public static int dmaReadByte (int a) {
  1131:     int d;
  1132:     int al = a & 0xff;
  1133:     if (al == DMA_GCR) {
  1134:       d = dmaBT | dmaBR;
  1135:       if (DMA_DEBUG_TRACE != 0) {
  1136:         System.out.printf ("%d %08x dmaRbz(0x%08x)=0x%02x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1137:       }
  1138:     } else {
  1139:       int i = al >> 6;  //チャンネル
  1140:       switch (al & 0x3f) {
  1141:       case DMA_CSR:
  1142:         d = dmaCOC[i] | dmaBLC[i] | dmaNDT[i] | dmaERR[i] | dmaACT[i] | dmaDIT[i] | dmaPCT[i] | dmaPCS[i];
  1143:         break;
  1144:       case DMA_CER:
  1145:         d = dmaErrorCode[i];
  1146:         break;
  1147:       case DMA_DCR:
  1148:         d = dmaXRM[i] | dmaDTYP[i] | dmaDPS[i] | dmaPCL[i];
  1149:         break;
  1150:       case DMA_OCR:
  1151:         d = dmaDIR[i] | dmaBTD[i] | dmaSIZE[i] | dmaCHAIN[i] | dmaREQG[i];
  1152:         break;
  1153:       case DMA_SCR:
  1154:         d = dmaMAC[i] | dmaDAC[i];
  1155:         break;
  1156:       case DMA_CCR:
  1157:         d = dmaSTR[i] | dmaCNT[i] | dmaHLT[i] | dmaSAB[i] | dmaITE[i];
  1158:         break;
  1159:       case DMA_MTC:
  1160:         d = dmaMTC[i] >> 8;
  1161:         break;
  1162:       case DMA_MTC + 1:
  1163:         d = dmaMTC[i] & 0xff;
  1164:         break;
  1165:       case DMA_MAR:
  1166:         d = dmaMAR[i] >>> 24;
  1167:         break;
  1168:       case DMA_MAR + 1:
  1169:         d = dmaMAR[i] >> 16 & 0xff;
  1170:         break;
  1171:       case DMA_MAR + 2:
  1172:         d = (char) dmaMAR[i] >> 8;
  1173:         break;
  1174:       case DMA_MAR + 3:
  1175:         d = dmaMAR[i] & 0xff;
  1176:         break;
  1177:       case DMA_DAR:
  1178:         d = dmaDAR[i] >>> 24;
  1179:         break;
  1180:       case DMA_DAR + 1:
  1181:         d = dmaDAR[i] >> 16 & 0xff;
  1182:         break;
  1183:       case DMA_DAR + 2:
  1184:         d = (char) dmaDAR[i] >> 8;
  1185:         break;
  1186:       case DMA_DAR + 3:
  1187:         d = dmaDAR[i] & 0xff;
  1188:         break;
  1189:       case DMA_BTC:
  1190:         d = dmaBTC[i] >> 8;
  1191:         break;
  1192:       case DMA_BTC + 1:
  1193:         d = dmaBTC[i] & 0xff;
  1194:         break;
  1195:       case DMA_BAR:
  1196:         d = dmaBAR[i] >>> 24;
  1197:         break;
  1198:       case DMA_BAR + 1:
  1199:         d = dmaBAR[i] >> 16 & 0xff;
  1200:         break;
  1201:       case DMA_BAR + 2:
  1202:         d = (char) dmaBAR[i] >> 8;
  1203:         break;
  1204:       case DMA_BAR + 3:
  1205:         d = dmaBAR[i] & 0xff;
  1206:         break;
  1207:       case DMA_NIV:
  1208:         d = dmaNIV[i];
  1209:         break;
  1210:       case DMA_EIV:
  1211:         d = dmaEIV[i];
  1212:         break;
  1213:       case DMA_MFC:
  1214:         d = dmaMFC[i];
  1215:         break;
  1216:       case DMA_CPR:
  1217:         d = dmaCP[i];
  1218:         break;
  1219:       case DMA_DFC:
  1220:         d = dmaDFC[i];
  1221:         break;
  1222:       case DMA_BFC:
  1223:         d = dmaBFC[i];
  1224:         break;
  1225:       default:
  1226:         d = 0;
  1227:       }
  1228:       if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
  1229:         System.out.printf ("%d %08x dmaRbz(0x%08x)=0x%02x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1230:       }
  1231:     }
  1232:     return d;
  1233:   }  //dmaReadByte
  1234: 
  1235:   public static int dmaReadWord (int a) {
  1236:     int d;
  1237:     int al = a & 0xff;
  1238:     int i = al >> 6;  //チャンネル
  1239:     switch (al & 0x3f) {
  1240:     case DMA_MTC:
  1241:       d = dmaMTC[i];
  1242:       break;
  1243:     case DMA_MAR:
  1244:       d = dmaMAR[i] >>> 16;
  1245:       break;
  1246:     case DMA_MAR + 2:
  1247:       d = (char) dmaMAR[i];
  1248:       break;
  1249:     case DMA_DAR:
  1250:       d = dmaDAR[i] >>> 16;
  1251:       break;
  1252:     case DMA_DAR + 2:
  1253:       d = (char) dmaDAR[i];
  1254:       break;
  1255:     case DMA_BTC:
  1256:       d = dmaBTC[i];
  1257:       break;
  1258:     case DMA_BAR:
  1259:       d = dmaBAR[i] >>> 16;
  1260:       break;
  1261:     case DMA_BAR + 2:
  1262:       d = (char) dmaBAR[i];
  1263:       break;
  1264:     default:
  1265:       d = dmaReadByte (a) << 8 | dmaReadByte (a + 1);
  1266:     }
  1267:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
  1268:       System.out.printf ("%d %08x dmaRwz(0x%08x)=0x%04x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1269:     }
  1270:     return d;
  1271:   }  //dmaReadWord
  1272: 
  1273:   public static int dmaReadLong (int a) {
  1274:     a &= XEiJ.BUS_MOTHER_MASK;
  1275:     int d;
  1276:     int al = a & 0xff;
  1277:     int i = al >> 6;  //チャンネル
  1278:     switch (al & 0x3f) {
  1279:     case DMA_MAR:
  1280:       d = dmaMAR[i];
  1281:       break;
  1282:     case DMA_DAR:
  1283:       d = dmaDAR[i];
  1284:       break;
  1285:     case DMA_BAR:
  1286:       d = dmaBAR[i];
  1287:       break;
  1288:     default:
  1289:       d = dmaReadWord (a) << 16 | dmaReadWord (a + 2);
  1290:     }
  1291:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
  1292:       System.out.printf ("%d %08x dmaRls(0x%08x)=0x%08x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1293:     }
  1294:     return d;
  1295:   }  //dmaReadLong
  1296: 
  1297:   public static void dmaWriteByte (int a, int d) {
  1298:     d &= 0xff;
  1299:     int al = a & 0xff;
  1300:     if (al == DMA_GCR) {
  1301:       if (DMA_DEBUG_TRACE != 0) {
  1302:         System.out.printf ("%d %08x dmaWb(0x%08x,0x%02x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1303:       }
  1304:       dmaBT = d & DMA_BT;
  1305:       dmaBR = d & DMA_BR;
  1306:       dmaBurstSpan = XEiJ.dmaCycleUnit << (4 + (dmaBT >> 2));
  1307:       dmaBurstInterval = dmaBurstSpan << (1 + (dmaBR & 3));
  1308:       return;
  1309:     }
  1310:     int i = al >> 6;  //チャンネル
  1311:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
  1312:       System.out.printf ("%d %08x dmaWb(0x%08x,0x%02x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1313:     }
  1314:     switch (al & 0x3f) {
  1315:     case DMA_CSR:
  1316:       //HD63450,-Y,-P,-PS,-CP CMOS DMAC 1989 p37
  1317:       //  COC,PCT,BTC,NDT,ERR,DITは1を書き込むかリセットするとクリアされる
  1318:       //  PCSは書き込んでも変化しない
  1319:       //  ACTは転送が終了するかリセットするとクリアされる
  1320:       if ((d & DMA_COC) != 0) {
  1321:         dmaCOC[i] = 0;
  1322:       }
  1323:       //if ((d & DMA_PCT) != 0) {
  1324:       //  dmaPCT[i] = 0;
  1325:       //}
  1326:       if ((d & DMA_BLC) != 0) {
  1327:         dmaBLC[i] = 0;  //名前注意
  1328:       }
  1329:       if ((d & DMA_NDT) != 0) {
  1330:         dmaNDT[i] = 0;
  1331:       }
  1332:       if ((d & DMA_ERR) != 0) {
  1333:         dmaERR[i] = 0;
  1334:         dmaErrorCode[i] = 0;  //CSRのERRに1を書き込んでクリアするとCERも同時にクリアされる
  1335:       }
  1336:       if ((d & DMA_DIT) != 0) {
  1337:         dmaDIT[i] = 0;
  1338:       }
  1339:       return;
  1340:     case DMA_CER:
  1341:       //DMA_CERはread-only
  1342:       return;
  1343:     case DMA_DCR:
  1344:       if (dmaACT[i] != 0) {
  1345:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1346:         return;
  1347:       }
  1348:       dmaXRM[i] = d & DMA_XRM;
  1349:       dmaDTYP[i] = d & DMA_DTYP;
  1350:       dmaDPS[i] = d & DMA_DPS;
  1351:       dmaDACValue[i] = (dmaDAC[i] == DMA_INC_DAR ? 1 : dmaDAC[i] == DMA_DEC_DAR ? -1 : 0) * (dmaDPS[i] == DMA_PORT_8_BIT ? 2 : 1);
  1352:       dmaPCL[i] = d & DMA_PCL;
  1353:       return;
  1354:     case DMA_OCR:
  1355:       dmaDIR[i] = d & DMA_DIR;
  1356:       dmaBTD[i] = d & DMA_BTD;
  1357:       dmaSIZE[i] = d & DMA_SIZE;
  1358:       dmaCHAIN[i] = d & DMA_CHAIN;
  1359:       dmaREQG[i] = d & DMA_REQG;
  1360:       return;
  1361:     case DMA_SCR:
  1362:       if (dmaACT[i] != 0) {
  1363:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1364:         return;
  1365:       }
  1366:       dmaMAC[i] = d & DMA_MAC;
  1367:       dmaMACValue[i] = dmaMAC[i] == DMA_INC_MAR ? 1 : dmaMAC[i] == DMA_DEC_MAR ? -1 : 0;
  1368:       dmaDAC[i] = d & DMA_DAC;
  1369:       dmaDACValue[i] = (dmaDAC[i] == DMA_INC_DAR ? 1 : dmaDAC[i] == DMA_DEC_DAR ? -1 : 0) * (dmaDPS[i] == DMA_PORT_8_BIT ? 2 : 1);
  1370:       return;
  1371:     case DMA_CCR:
  1372:       if (dmaHLT[i] != (d & DMA_HLT)) {
  1373:         dmaHalt (i, (d & DMA_HLT));
  1374:       }
  1375:       dmaITE[i] = d & DMA_ITE;
  1376:       //DMA_CNT
  1377:       if ((d & DMA_CNT) != 0) {
  1378:         if ((dmaACT[i] == 0 && (d & DMA_STR) == 0) || dmaBLC[i] != 0) {  //動作中でないかブロック転送完了済みの状態でDMA_CNTをセットしようとした
  1379:           dmaErrorExit (i, DMA_TIMING_ERROR);
  1380:           return;
  1381:         }
  1382:         if (dmaCHAIN[i] != DMA_NO_CHAINING) {  //チェインモードのときDMA_CNTをセットしようとした
  1383:           dmaErrorExit (i, DMA_CONFIGURATION_ERROR);
  1384:           return;
  1385:         }
  1386:         dmaCNT[i] = DMA_CNT;  //DMA_CNTに0を書き込んでもクリアされない
  1387:       }
  1388:       //DMA_SAB
  1389:       if ((d & DMA_SAB) != 0) {
  1390:         //dmaSABには書き込まない。SABは読み出すと常に0
  1391:         dmaCOC[i] = 0;
  1392:         dmaBLC[i] = 0;
  1393:         dmaNDT[i] = 0;
  1394:         dmaHLT[i] = 0;
  1395:         dmaCNT[i] = 0;
  1396:         if (dmaACT[i] != 0 || (d & DMA_STR) != 0) {  //動作中
  1397:           dmaErrorExit (i, DMA_SOFTWARE_ABORT);
  1398:         }
  1399:         return;
  1400:       }
  1401:       //DMA_STR
  1402:       if ((d & DMA_STR) != 0) {
  1403:         dmaStart (i);
  1404:       }
  1405:       return;
  1406:     case DMA_MTC:
  1407:       if (dmaACT[i] != 0) {
  1408:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1409:         return;
  1410:       }
  1411:       dmaMTC[i] = d << 8 | (dmaMTC[i] & 0xff);
  1412:       return;
  1413:     case DMA_MTC + 1:
  1414:       if (dmaACT[i] != 0) {
  1415:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1416:         return;
  1417:       }
  1418:       dmaMTC[i] = (dmaMTC[i] & ~0xff) | d;
  1419:       return;
  1420:     case DMA_MAR:
  1421:       if (dmaACT[i] != 0) {
  1422:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1423:         return;
  1424:       }
  1425:       dmaMAR[i] = d << 24 | (dmaMAR[i] & ~(0xff << 24));
  1426:       return;
  1427:     case DMA_MAR + 1:
  1428:       if (dmaACT[i] != 0) {
  1429:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1430:         return;
  1431:       }
  1432:       dmaMAR[i] = d << 16 | (dmaMAR[i] & ~(0xff << 16));
  1433:       return;
  1434:     case DMA_MAR + 2:
  1435:       if (dmaACT[i] != 0) {
  1436:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1437:         return;
  1438:       }
  1439:       dmaMAR[i] = (dmaMAR[i] & ~(0xff << 8)) | d << 8;
  1440:       return;
  1441:     case DMA_MAR + 3:
  1442:       if (dmaACT[i] != 0) {
  1443:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1444:         return;
  1445:       }
  1446:       dmaMAR[i] = (dmaMAR[i] & ~0xff) | d;
  1447:       return;
  1448:     case DMA_DAR:
  1449:       if (dmaACT[i] != 0) {
  1450:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1451:         return;
  1452:       }
  1453:       dmaDAR[i] = d << 24 | (dmaDAR[i] & ~(0xff << 24));
  1454:       return;
  1455:     case DMA_DAR + 1:
  1456:       if (dmaACT[i] != 0) {
  1457:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1458:         return;
  1459:       }
  1460:       dmaDAR[i] = d << 16 | (dmaDAR[i] & ~(0xff << 16));
  1461:       return;
  1462:     case DMA_DAR + 2:
  1463:       if (dmaACT[i] != 0) {
  1464:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1465:         return;
  1466:       }
  1467:       dmaDAR[i] = (dmaDAR[i] & ~(0xff << 8)) | d << 8;
  1468:       return;
  1469:     case DMA_DAR + 3:
  1470:       if (dmaACT[i] != 0) {
  1471:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1472:         return;
  1473:       }
  1474:       dmaDAR[i] = (dmaDAR[i] & ~0xff) | d;
  1475:       return;
  1476:     case DMA_BTC:
  1477:       dmaBTC[i] = d << 8 | (dmaBTC[i] & 0xff);
  1478:       return;
  1479:     case DMA_BTC + 1:
  1480:       dmaBTC[i] = (dmaBTC[i] & ~0xff) | d;
  1481:       return;
  1482:     case DMA_BAR:
  1483:       dmaBAR[i] = d << 24 | (dmaBAR[i] & ~(0xff << 24));
  1484:       return;
  1485:     case DMA_BAR + 1:
  1486:       dmaBAR[i] = d << 16 | (dmaBAR[i] & ~(0xff << 16));
  1487:       return;
  1488:     case DMA_BAR + 2:
  1489:       dmaBAR[i] = (dmaBAR[i] & ~(0xff << 8)) | d << 8;
  1490:       return;
  1491:     case DMA_BAR + 3:
  1492:       dmaBAR[i] = (dmaBAR[i] & ~0xff) | d;
  1493:       return;
  1494:     case DMA_NIV:
  1495:       dmaNIV[i] = d;
  1496:       return;
  1497:     case DMA_EIV:
  1498:       dmaEIV[i] = d;
  1499:       return;
  1500:     case DMA_MFC:
  1501:       if (dmaACT[i] != 0) {
  1502:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1503:         return;
  1504:       }
  1505:       dmaMFC[i] = d & DMA_FC2;
  1506:       if (DataBreakPoint.DBP_ON) {
  1507:         dmaMFCMap[i] = dmaMFC[i] == 0 ? DataBreakPoint.dbpUserMap : DataBreakPoint.dbpSuperMap;
  1508:       } else {
  1509:         dmaMFCMap[i] = dmaMFC[i] == 0 ? XEiJ.busUserMap : XEiJ.busSuperMap;
  1510:       }
  1511:       return;
  1512:     case DMA_CPR:
  1513:       dmaCP[i] = d & DMA_CP;
  1514:       return;
  1515:     case DMA_DFC:
  1516:       if (dmaACT[i] != 0) {
  1517:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1518:         return;
  1519:       }
  1520:       dmaDFC[i] = d & DMA_FC2;
  1521:       if (DataBreakPoint.DBP_ON) {
  1522:         dmaDFCMap[i] = dmaDFC[i] == 0 ? DataBreakPoint.dbpUserMap : DataBreakPoint.dbpSuperMap;
  1523:       } else {
  1524:         dmaDFCMap[i] = dmaDFC[i] == 0 ? XEiJ.busUserMap : XEiJ.busSuperMap;
  1525:       }
  1526:       return;
  1527:     case DMA_BFC:
  1528:       dmaBFC[i] = d & DMA_FC2;
  1529:       if (DataBreakPoint.DBP_ON) {
  1530:         dmaBFCMap[i] = dmaBFC[i] == 0 ? DataBreakPoint.dbpUserMap : DataBreakPoint.dbpSuperMap;
  1531:       } else {
  1532:         dmaBFCMap[i] = dmaBFC[i] == 0 ? XEiJ.busUserMap : XEiJ.busSuperMap;
  1533:       }
  1534:       return;
  1535:     default:
  1536:       return;
  1537:     }
  1538:   }  //dmaWriteByte
  1539: 
  1540:   public static void dmaWriteWord (int a, int d) {
  1541:     d = (char) d;
  1542:     int al = a & 0xff;
  1543:     int i = al >> 6;  //チャンネル
  1544:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
  1545:       System.out.printf ("%d %08x dmaWw(0x%08x,0x%04x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1546:     }
  1547:     switch (al & 0x3f) {
  1548:     case DMA_MTC:
  1549:       if (dmaACT[i] != 0) {
  1550:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1551:       } else {
  1552:         dmaMTC[i] = d;
  1553:       }
  1554:       return;
  1555:     case DMA_MAR:
  1556:       if (dmaACT[i] != 0) {
  1557:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1558:       } else {
  1559:         dmaMAR[i] = d << 16 | (char) dmaMAR[i];
  1560:       }
  1561:       return;
  1562:     case DMA_MAR + 2:
  1563:       if (dmaACT[i] != 0) {
  1564:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1565:       } else {
  1566:         dmaMAR[i] = (dmaMAR[i] & ~0xffff) | d;
  1567:       }
  1568:       return;
  1569:     case DMA_DAR:
  1570:       if (dmaACT[i] != 0) {
  1571:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1572:       } else {
  1573:         dmaDAR[i] = d << 16 | (char) dmaDAR[i];
  1574:       }
  1575:       return;
  1576:     case DMA_DAR + 2:
  1577:       if (dmaACT[i] != 0) {
  1578:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1579:       } else {
  1580:         dmaDAR[i] = (dmaDAR[i] & ~0xffff) | d;
  1581:       }
  1582:       return;
  1583:     case DMA_BTC:
  1584:       dmaBTC[i] = (char) d;
  1585:       return;
  1586:     case DMA_BAR:
  1587:       dmaBAR[i] = d << 16 | (char) dmaBAR[i];
  1588:       return;
  1589:     case DMA_BAR + 2:
  1590:       dmaBAR[i] = (dmaBAR[i] & ~0xffff) | d;
  1591:       return;
  1592:     default:
  1593:       dmaWriteByte (a, d >> 8);
  1594:       dmaWriteByte (a + 1, d);
  1595:     }
  1596:   }  //dmaWriteWord
  1597: 
  1598:   public static void dmaWriteLong (int a, int d) {
  1599:     int al = a & 0xff;
  1600:     int i = al >> 6;  //チャンネル
  1601:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
  1602:       System.out.printf ("%d %08x dmaWl(0x%08x,0x%08x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  1603:     }
  1604:     switch (al & 0x3f) {
  1605:     case DMA_MAR:
  1606:       if (dmaACT[i] != 0) {
  1607:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1608:       } else {
  1609:         dmaMAR[i] = d;
  1610:         if (DMA_ALERT_HIMEM) {
  1611:           if ((d & 0xff000000) != 0 && Model.MPU_MC68020 <= XEiJ.currentMPU) {
  1612:             System.out.printf ("%08x DMA_MAR[%d]=%08X\n", XEiJ.regPC0, i, d);
  1613:           }
  1614:         }
  1615:       }
  1616:       return;
  1617:     case DMA_DAR:
  1618:       if (dmaACT[i] != 0) {
  1619:         dmaErrorExit (i, DMA_TIMING_ERROR);
  1620:       } else {
  1621:         dmaDAR[i] = d;
  1622:         if (DMA_ALERT_HIMEM) {
  1623:           if ((d & 0xff000000) != 0 && Model.MPU_MC68020 <= XEiJ.currentMPU) {
  1624:             System.out.printf ("%08x DMA_DAR[%d]=%08X\n", XEiJ.regPC0, i, d);
  1625:           }
  1626:         }
  1627:       }
  1628:       return;
  1629:     case DMA_BAR:
  1630:       dmaBAR[i] = d;
  1631:       if (DMA_ALERT_HIMEM) {
  1632:         if ((d & 0xff000000) != 0 && Model.MPU_MC68020 <= XEiJ.currentMPU) {
  1633:           System.out.printf ("%08x DMA_BAR[%d]=%08X\n", XEiJ.regPC0, i, d);
  1634:         }
  1635:       }
  1636:       return;
  1637:     default:
  1638:       dmaWriteWord (a, d >> 16);
  1639:       dmaWriteWord (a + 2, d);
  1640:     }
  1641:   }
  1642: 
  1643: 
  1644: 
  1645: }  //class HD63450
  1646: 
  1647: 
  1648: