HD63450.java
     1: //========================================================================================
     2: //  HD63450.java
     3: //    en:DMA controller
     4: //    ja:DMAコントローラ
     5: //  Copyright (C) 2003-2017 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: //  http://stdkmd.com/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:   //レジスタ
    24:   //  DMA_CERはread-only、その他はread/write
    25:   //  DMA_DCR,DMA_SCR,DMA_MTC,DMA_MAR,DMA_DAR,DMA_MFC,DMA_DFCに動作中(dmaACT[i]!=0)に書き込むとDMA_TIMING_ERRORになる
    26: 
    27:   //Channel Status Register (R/W)
    28:   public static final int DMA_CSR = 0x00;
    29:   public static final int DMA_COC = 0b10000000;  //Channel Operation Complete。1=チャンネル動作完了
    30:   public static final int DMA_BLC = 0b01000000;  //BLock transfer Complete。1=ブロック転送完了
    31:   public static final int DMA_NDT = 0b00100000;  //Normal Device Termination。1=正常終了
    32:   public static final int DMA_ERR = 0b00010000;  //ERRor。1=エラーあり
    33:   public static final int DMA_ACT = 0b00001000;  //channel ACTive。1=チャンネル動作中
    34:   public static final int DMA_DIT = 0b00000100;  //! 非対応。~DONE Input Transition。1=~DONE入力があった
    35:   public static final int DMA_PCT = 0b00000010;  //~PCL Transition。1=~PCLの立下りがあった
    36:   public static final int DMA_PCS = 0b00000001;  //~PCL Status。~PCLの状態
    37: 
    38:   //Channel Error Register (R)
    39:   public static final int DMA_CER = 0x01;
    40:   public static final int DMA_ERROR_CODE           = 0b00011111;  //エラーコード
    41:   public static final int DMA_NO_ERROR             = 0b00000000;  //  エラーなし
    42:   public static final int DMA_CONFIGURATION_ERROR  = 0b00000001;  //  コンフィギュレーションエラー
    43:   public static final int DMA_TIMING_ERROR         = 0b00000010;  //  動作タイミングエラー
    44:   public static final int DMA_MEMORY_ADDRESS_ERROR = 0b00000101;  //  アドレスエラー(メモリアドレス)
    45:   public static final int DMA_DEVICE_ADDRESS_ERROR = 0b00000110;  //  アドレスエラー(デバイスアドレス)
    46:   public static final int DMA_BASE_ADDRESS_ERROR   = 0b00000111;  //  アドレスエラー(ベースアドレス)
    47:   public static final int DMA_MEMORY_BUS_ERROR     = 0b00001001;  //  バスエラー(メモリアドレス)
    48:   public static final int DMA_DEVICE_BUS_ERROR     = 0b00001010;  //  バスエラー(デバイスアドレス)
    49:   public static final int DMA_BASE_BUS_ERROR       = 0b00001011;  //  バスエラー(ベースアドレス)
    50:   public static final int DMA_MEMORY_COUNT_ERROR   = 0b00001101;  //  カウントエラー(メモリカウンタ)
    51:   public static final int DMA_BASE_COUNT_ERROR     = 0b00001111;  //  カウントエラー(ベースカウンタ)
    52:   public static final int DMA_EXTERNAL_ABORT       = 0b00010000;  //! 非対応。外部強制停止
    53:   public static final int DMA_SOFTWARE_ABORT       = 0b00010001;  //  ソフトウェア強制停止
    54: 
    55:   //Device Control Register (R/W)
    56:   public static final int DMA_DCR = 0x04;
    57:   public static final int DMA_XRM                    = 0b11000000;  //eXternal Request Mode
    58:   public static final int DMA_BURST_TRANSFER         = 0b00000000;  //  バースト転送モード
    59:   public static final int DMA_NO_HOLD_CYCLE_STEAL    = 0b10000000;  //  ホールドなしサイクルスチールモード
    60:   public static final int DMA_HOLD_CYCLE_STEAL       = 0b11000000;  //! 非対応。ホールドありサイクルスチールモード。ホールドなしサイクルスチールモードと同じ
    61:   public static final int DMA_DTYP                   = 0b00110000;  //Device TYPe
    62:   public static final int DMA_HD68000_COMPATIBLE     = 0b00000000;  //  HD68000コンパチブル(デュアルアドレスモード)
    63:   public static final int DMA_HD6800_COMPATIBLE      = 0b00010000;  //! 非対応。HD6800コンパチブル(デュアルアドレスモード)
    64:   public static final int DMA_ACK_DEVICE             = 0b00100000;  //! 非対応。~ACK付きデバイス(シングルアドレスモード)
    65:   public static final int DMA_ACK_READY_DEVICE       = 0b00110000;  //! 非対応。~ACK,~READY付きデバイス(シングルアドレスモード)
    66:   public static final int DMA_DPS                    = 0b00001000;  //Device Port Size
    67:   public static final int DMA_PORT_8_BIT             = 0b00000000;  //  8ビットポート
    68:   public static final int DMA_PORT_16_BIT            = 0b00001000;  //  16ビットポート
    69:   public static final int DMA_PCL                    = 0b00000011;  //Peripheral Control Line
    70:   public static final int DMA_STATUS_INPUT           = 0b00000000;  //  STATUS入力
    71:   public static final int DMA_STATUS_INPUT_INTERRUPT = 0b00000001;  //! 非対応。割り込みありSTATUS入力
    72:   public static final int DMA_EIGHTH_START_PULSE     = 0b00000010;  //! 非対応。1/8スタートパルス
    73:   public static final int DMA_ABORT_INPUT            = 0b00000011;  //! 非対応。ABORT入力
    74: 
    75:   //Operation Control Register (R/W)
    76:   public static final int DMA_OCR = 0x05;
    77:   public static final int DMA_DIR                 = 0b10000000;  //DIRection
    78:   public static final int DMA_MEMORY_TO_DEVICE    = 0b00000000;  //  メモリ→デバイス。DMA_MAR→DMA_DAR
    79:   public static final int DMA_DEVICE_TO_MEMORY    = 0b10000000;  //  デバイス→メモリ。DMA_DAR→DMA_MAR
    80:   public static final int DMA_BTD                 = 0b01000000;  //! 非対応。multi Block Transfer with ~DONE mode
    81:   public static final int DMA_SIZE                = 0b00110000;  //operand SIZE
    82:   public static final int DMA_BYTE_SIZE           = 0b00000000;  //  8ビット
    83:   public static final int DMA_WORD_SIZE           = 0b00010000;  //  16ビット
    84:   public static final int DMA_LONG_WORD_SIZE      = 0b00100000;  //  32ビット
    85:   public static final int DMA_UNPACKED_8_BIT      = 0b00110000;  //  パックなし8ビット
    86:   public static final int DMA_CHAIN               = 0b00001100;  //CHAINing operation
    87:   public static final int DMA_NO_CHAINING         = 0b00000000;  //  チェインなし
    88:   public static final int DMA_ARRAY_CHAINING      = 0b00001000;  //  アレイチェイン
    89:   public static final int DMA_LINK_ARRAY_CHAINING = 0b00001100;  //  リンクアレイチェイン
    90:   public static final int DMA_REQG                = 0b00000011;  //DMA REQuest Generation method
    91:   public static final int DMA_AUTO_REQUEST        = 0b00000000;  //  オートリクエスト限定速度。転送中にバスを開放する
    92:   public static final int DMA_AUTO_REQUEST_MAX    = 0b00000001;  //  オートリクエスト最大速度。転送中にバスを開放しない
    93:   public static final int DMA_EXTERNAL_REQUEST    = 0b00000010;  //  外部転送要求
    94:   public static final int DMA_DUAL_REQUEST        = 0b00000011;  //  最初はオートリクエスト、2番目から外部転送要求
    95: 
    96:   //Sequence Control Register (R/W)
    97:   public static final int DMA_SCR = 0x06;
    98:   public static final int DMA_MAC =        0b00001100;  //Memory Address register Count
    99:   public static final int DMA_STATIC_MAR = 0b00000000;  //  DMA_MAR固定
   100:   public static final int DMA_INC_MAR    = 0b00000100;  //  DMA_MAR++
   101:   public static final int DMA_DEC_MAR    = 0b00001000;  //  DMA_MAR--
   102:   public static final int DMA_DAC =        0b00000011;  //Device Address register Count
   103:   public static final int DMA_STATIC_DAR = 0b00000000;  //  DMA_DAR固定
   104:   public static final int DMA_INC_DAR    = 0b00000001;  //  DMA_DAR++
   105:   public static final int DMA_DEC_DAR    = 0b00000010;  //  DMA_DAR--
   106: 
   107:   //Channel Control Register (R/W)
   108:   public static final int DMA_CCR = 0x07;
   109:   public static final int DMA_STR = 0b10000000;  //STaRt operation。1=動作開始
   110:   public static final int DMA_CNT = 0b01000000;  //CoNTinue operation。1=コンティニューあり
   111:   public static final int DMA_HLT = 0b00100000;  //Halt operation。1=動作一時停止
   112:   public static final int DMA_SAB = 0b00010000;  //Software ABort。1=動作中止
   113:   public static final int DMA_ITE = 0b00001000;  //InTerrupt Enable。1=割り込み許可
   114: 
   115:   //Transfer Counter, Address Register
   116:   public static final int DMA_MTC = 0x0a;  //Memory Transfer Counter (R/W)
   117:   public static final int DMA_MAR = 0x0c;  //Memory Address Register (R/W)
   118:   public static final int DMA_DAR = 0x14;  //Device Address Register (R/W)
   119:   public static final int DMA_BTC = 0x1a;  //Base Transfer Counter (R/W)
   120:   public static final int DMA_BAR = 0x1c;  //Base Address Register (R/W)
   121: 
   122:   //Interrupt Vector
   123:   public static final int DMA_NIV = 0x25;  //Normal Interrupt Vector (R/W)
   124:   public static final int DMA_EIV = 0x27;  //Error Interrupt Vector (R/W)
   125: 
   126:   //Function Codes
   127:   public static final int DMA_MFC = 0x29;  //Memory Function Codes (R/W)
   128:   public static final int DMA_FC2 = 0b00000100;  //Function Code 2
   129:   public static final int DMA_FC1 = 0b00000010;  //! 非対応。Function Code 1
   130:   public static final int DMA_FC0 = 0b00000001;  //! 非対応。Function Code 0
   131: 
   132:   //Channel Priority Register (R/W)
   133:   public static final int DMA_CPR = 0x2d;
   134:   public static final int DMA_CP = 0b00000011;  //! 未対応。Channel Priority。0=高,1,2,3=低
   135: 
   136:   //Function Codes
   137:   public static final int DMA_DFC = 0x31;  //Device Function Codes (R/W)
   138:   public static final int DMA_BFC = 0x39;  //Base Function Codes (R/W)
   139: 
   140:   //General Control Register (R/W)
   141:   public static final int DMA_GCR = 0xff;
   142:   public static final int DMA_BT = 0b00001100;  //Burst Time。0=16clk,1=32clk,2=64clk,3=128clk
   143:   public static final int DMA_BR = 0b00000011;  //Bandwidth Ratio。0=1/2,1=1/4,2=1/8,3=1/16
   144: 
   145:   //レジスタ
   146:   //  すべてゼロ拡張
   147:   public static final int[] dmaPCS = new int[4];         //DMA_CSR bit0
   148:   public static final int[] dmaPCT = new int[4];         //        bit1
   149:   public static final int[] dmaDIT = new int[4];         //        bit2
   150:   public static final int[] dmaACT = new int[4];         //        bit3
   151:   public static final int[] dmaERR = new int[4];         //        bit4
   152:   public static final int[] dmaNDT = new int[4];         //        bit5
   153:   public static final int[] dmaBLC = new int[4];         //        bit6
   154:   public static final int[] dmaCOC = new int[4];         //        bit7
   155:   public static final int[] dmaErrorCode = new int[4];   //DMA_CER bit0-4
   156:   public static final int[] dmaPCL = new int[4];         //DMA_DCR bit0-1
   157:   public static final int[] dmaDPS = new int[4];         //        bit3
   158:   public static final int[] dmaDTYP = new int[4];        //        bit4-5
   159:   public static final int[] dmaXRM = new int[4];         //        bit6-7
   160:   public static final int[] dmaREQG = new int[4];        //DMA_OCR bit0-1
   161:   public static final int[] dmaCHAIN = new int[4];       //        bit2-3
   162:   public static final int[] dmaSIZE = new int[4];        //        bit4-5
   163:   public static final int[] dmaBTD = new int[4];         //        bit6
   164:   public static final int[] dmaDIR = new int[4];         //        bit7
   165:   public static final int[] dmaDAC = new int[4];         //DMA_SCR bit0-1
   166:   public static final int[] dmaDACValue = new int[4];    //           dmaDAC==DMA_INC_DAR?1:dmaDAC==DMA_DEC_DAR?-1:0
   167:   public static final int[] dmaMAC = new int[4];         //        bit2-3
   168:   public static final int[] dmaMACValue = new int[4];    //           dmaMAC==DMA_INC_MAR?1:dmaMAC==DMA_DEC_MAR?-1:0
   169:   public static final int[] dmaITE = new int[4];         //DMA_CCR bit3
   170:   public static final int[] dmaSAB = new int[4];         //        bit4
   171:   public static final int[] dmaHLT = new int[4];         //        bit5
   172:   public static final int[] dmaCNT = new int[4];         //        bit6
   173:   public static final int[] dmaSTR = new int[4];         //        bit7
   174:   public static final int[] dmaMTC = new int[4];         //DMA_MTC bit0-15
   175:   public static final int[] dmaMAR = new int[4];         //DMA_MAR bit0-31
   176:   public static final int[] dmaDAR = new int[4];         //DMA_DAR bit0-31
   177:   public static final int[] dmaBTC = new int[4];         //DMA_BTC bit0-15
   178:   public static final int[] dmaBAR = new int[4];         //DMA_BAR bit0-31
   179:   public static final int[] dmaNIV = new int[4];         //DMA_NIV bit0-7
   180:   public static final int[] dmaEIV = new int[4];         //DMA_EIV bit0-7
   181:   public static final int[] dmaMFC = new int[4];         //DMA_MFC bit2
   182:   public static final MemoryMappedDevice[][] dmaMFCMap = new MemoryMappedDevice[4][];  //  DataBreakPoint.DBP_ON?dmaMFC[i]==0?udm:sdm:dmaMFC[i]==0?um:sm
   183:   public static final int[] dmaCP = new int[4];          //DMA_CPR bit0-1
   184:   public static final int[] dmaDFC = new int[4];         //DMA_DFC bit2
   185:   public static final MemoryMappedDevice[][] dmaDFCMap = new MemoryMappedDevice[4][];  //  DataBreakPoint.DBP_ON?dmaDFC[i]==0?udm:sdm:dmaDFC[i]==0?um:sm
   186:   public static final int[] dmaBFC = new int[4];         //DMA_BFC bit2
   187:   public static final MemoryMappedDevice[][] dmaBFCMap = new MemoryMappedDevice[4][];  //  DataBreakPoint.DBP_ON?dmaBFC[i]==0?udm:sdm:dmaBFC[i]==0?um:sm
   188:   public static int dmaBR;                               //DMA_GCR bit0-1。0=1/2,1=1/4,2=1/8,3=1/16
   189:   public static int dmaBT;                               //        bit2-3。0=16clk,1=32clk,2=64clk,3=128clk
   190:   public static long dmaBurstInterval;  //バースト間隔。DMA_CLOCK_UNIT<<4+(dmaBT>>2)
   191:   public static long dmaBurstSpan;  //バースト期間。dmaBurstInterval>>1+(dmaBR&3)
   192:   public static long dmaBurstStart;  //バースト開始時刻
   193:   public static long dmaBurstEnd;  //バースト終了時刻
   194: 
   195:   //割り込み
   196:   public static final int[] dmaInnerRequest = new int[8];  //割り込み要求カウンタ
   197:   public static final int[] dmaInnerAcknowleged = new int[8];  //割り込み受付カウンタ
   198: 
   199:   //クロック
   200:   //  1回のバスアクセスに10MHz固定で1clkかかるものとする
   201:   //  リードとライトで最短2clkかかるので最大転送速度は5Mワード/s
   202:   public static final long DMA_CLOCK_UNIT = XEiJ.TMR_FREQ / (1024 * 1024 * 10);  //DMAのバスアクセス1回あたりの所要時間(XEiJ.TMR_FREQ単位)
   203:   public static final long[] dmaInnerClock = new long[4];  //転送要求時刻(XEiJ.TMR_FREQ単位)
   204: 
   205:   public static final TickerQueue.Ticker[] dmaTickerArray = new TickerQueue.Ticker[] {
   206:     new TickerQueue.Ticker () {
   207:       @Override protected void tick () {
   208:         dmaTransfer (0);
   209:       }
   210:     },
   211:     new TickerQueue.Ticker () {
   212:       @Override protected void tick () {
   213:         dmaTransfer (1);
   214:       }
   215:     },
   216:     new TickerQueue.Ticker () {
   217:       @Override protected void tick () {
   218:         dmaTransfer (2);
   219:       }
   220:     },
   221:     new TickerQueue.Ticker () {
   222:       @Override protected void tick () {
   223:         dmaTransfer (3);
   224:       }
   225:     },
   226:   };
   227: 
   228:   //dmaInit ()
   229:   //  DMAコントローラを初期化する
   230:   public static void dmaInit () {
   231:     //レジスタ
   232:     //dmaPCS = new int[4];
   233:     //dmaPCT = new int[4];
   234:     //dmaDIT = new int[4];
   235:     //dmaACT = new int[4];
   236:     //dmaERR = new int[4];
   237:     //dmaNDT = new int[4];
   238:     //dmaBLC = new int[4];
   239:     //dmaCOC = new int[4];
   240:     //dmaErrorCode = new int[4];
   241:     //dmaPCL = new int[4];
   242:     //dmaDPS = new int[4];
   243:     //dmaDTYP = new int[4];
   244:     //dmaXRM = new int[4];
   245:     //dmaREQG = new int[4];
   246:     //dmaCHAIN = new int[4];
   247:     //dmaSIZE = new int[4];
   248:     //dmaBTD = new int[4];
   249:     //dmaDIR = new int[4];
   250:     //dmaDAC = new int[4];
   251:     //dmaDACValue = new int[4];
   252:     //dmaMAC = new int[4];
   253:     //dmaMACValue = new int[4];
   254:     //dmaITE = new int[4];
   255:     //dmaSAB = new int[4];
   256:     //dmaHLT = new int[4];
   257:     //dmaCNT = new int[4];
   258:     //dmaSTR = new int[4];
   259:     //dmaMTC = new int[4];
   260:     //dmaMAR = new int[4];
   261:     //dmaDAR = new int[4];
   262:     //dmaBTC = new int[4];
   263:     //dmaBAR = new int[4];
   264:     //dmaNIV = new int[4];
   265:     //dmaEIV = new int[4];
   266:     //dmaMFC = new int[4];
   267:     //dmaMFCMap = new MMD[4];
   268:     //dmaCP = new int[4];
   269:     //dmaDFC = new int[4];
   270:     //dmaDFCMap = new MMD[4];
   271:     //dmaBFC = new int[4];
   272:     //dmaBFCMap = new MMD[4];
   273:     //dmaPCSはresetでは操作しない
   274:     for (int i = 0; i < 4; i++) {
   275:       dmaPCS[i] = 0;
   276:     }
   277:     //割り込み
   278:     //dmaInnerRequest = new int[8];
   279:     //dmaInnerAcknowleged = new int[8];
   280:     //クロック
   281:     //dmaInnerClock = new long[4];
   282:     dmaReset ();
   283:   }  //dmaInit()
   284: 
   285:   //リセット
   286:   public static void dmaReset () {
   287:     //レジスタ
   288:     for (int i = 0; i < 4; i++) {
   289:       //dmaPCSはresetでは操作しない
   290:       dmaPCT[i] = 0;
   291:       dmaDIT[i] = 0;
   292:       dmaACT[i] = 0;
   293:       dmaERR[i] = 0;
   294:       dmaNDT[i] = 0;
   295:       dmaBLC[i] = 0;
   296:       dmaCOC[i] = 0;
   297:       dmaErrorCode[i] = 0;
   298:       dmaPCL[i] = 0;
   299:       dmaDPS[i] = 0;
   300:       dmaDTYP[i] = 0;
   301:       dmaXRM[i] = 0;
   302:       dmaREQG[i] = 0;
   303:       dmaCHAIN[i] = 0;
   304:       dmaSIZE[i] = 0;
   305:       dmaBTD[i] = 0;
   306:       dmaDIR[i] = 0;
   307:       dmaDAC[i] = 0;
   308:       dmaDACValue[i] = 0;
   309:       dmaMAC[i] = 0;
   310:       dmaMACValue[i] = 0;
   311:       dmaITE[i] = 0;
   312:       dmaSAB[i] = 0;
   313:       dmaHLT[i] = 0;
   314:       dmaCNT[i] = 0;
   315:       dmaSTR[i] = 0;
   316:       dmaMTC[i] = 0;
   317:       dmaMAR[i] = 0;
   318:       dmaDAR[i] = 0;
   319:       dmaBTC[i] = 0;
   320:       dmaBAR[i] = 0;
   321:       dmaNIV[i] = 0x0f;  //割り込みベクタの初期値は未初期化割り込みを示す0x0f
   322:       dmaEIV[i] = 0x0f;
   323:       dmaMFC[i] = 0;
   324:       if (DataBreakPoint.DBP_ON) {
   325:         dmaMFCMap[i] = DataBreakPoint.dbpUserMap;
   326:       } else {
   327:         dmaMFCMap[i] = XEiJ.busUserMap;
   328:       }
   329:       dmaCP[i] = 0;
   330:       dmaDFC[i] = 0;
   331:       if (DataBreakPoint.DBP_ON) {
   332:         dmaDFCMap[i] = DataBreakPoint.dbpUserMap;
   333:       } else {
   334:         dmaDFCMap[i] = XEiJ.busUserMap;
   335:       }
   336:       dmaBFC[i] = 0;
   337:       if (DataBreakPoint.DBP_ON) {
   338:         dmaBFCMap[i] = DataBreakPoint.dbpUserMap;
   339:       } else {
   340:         dmaBFCMap[i] = XEiJ.busUserMap;
   341:       }
   342:     }
   343:     dmaBR = 0;
   344:     dmaBT = 0;
   345:     dmaBurstInterval = DMA_CLOCK_UNIT << 4 + (dmaBT >> 2);
   346:     dmaBurstSpan = dmaBurstInterval >> 1 + (dmaBR & 3);
   347:     dmaBurstStart = XEiJ.FAR_FUTURE;
   348:     dmaBurstEnd = 0L;
   349:     //割り込み
   350:     for (int i = 0; i < 8; i++) {
   351:       dmaInnerRequest[i] = 0;
   352:       dmaInnerAcknowleged[i] = 0;
   353:     }
   354:     //クロック
   355:     for (int i = 0; i < 4; i++) {
   356:       dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   357:       TickerQueue.tkqRemove (dmaTickerArray[i]);
   358:     }
   359:   }  //dmaReset()
   360: 
   361:   //割り込み受付
   362:   //  コアが割り込み要求を受け付けたときに呼び出す
   363:   //  割り込みベクタ番号を返す
   364:   //  割り込み要求を取り下げる場合は0を返す
   365:   //  オートベクタを使用するデバイスはオートベクタの番号を返すこと
   366:   public static int dmaAcknowledge () {
   367:     for (int i = 0; i < 8; i++) {  //! 未対応。本来はチャンネルプライオリティに従うべき
   368:       int request = dmaInnerRequest[i];
   369:       if (dmaInnerAcknowleged[i] != request) {
   370:         dmaInnerAcknowleged[i] = request;
   371:         return (i & 1) == 0 ? dmaNIV[i >> 1] : dmaEIV[i >> 1];
   372:       }
   373:     }
   374:     return 0;
   375:   }  //dmaAcknowledge()
   376: 
   377:   //割り込み終了
   378:   //  コアが割り込み処理を終了したときに呼び出す
   379:   //  まだ処理されていない割り込みが残っていたら再度割り込み要求を出す
   380:   public static void dmaDone () {
   381:     for (int i = 0; i < 8; i++) {  //! 未対応。本来はチャンネルプライオリティに従うべき
   382:       if (dmaInnerRequest[i] != dmaInnerAcknowleged[i]) {
   383:         XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   384:         return;
   385:       }
   386:     }
   387:   }  //dmaDone()
   388: 
   389:   //dmaStart (i)
   390:   //  DMA転送開始
   391:   public static void dmaStart (int i) {
   392:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   393:       System.out.printf ("%d %08x dmaStart(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   394:       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",
   395:                          dmaCOC[i] | dmaBLC[i] | dmaNDT[i] | dmaERR[i] | dmaACT[i] | dmaDIT[i] | dmaPCT[i] | dmaPCS[i],  //CSR
   396:                          dmaErrorCode[i],  //CER
   397:                          dmaXRM[i] | dmaDTYP[i] | dmaDPS[i] | dmaPCL[i],  //DCR
   398:                          dmaDIR[i] | dmaBTD[i] | dmaSIZE[i] | dmaCHAIN[i] | dmaREQG[i],  //OCR
   399:                          dmaMAC[i] | dmaDAC[i],  //SCR
   400:                          dmaSTR[i] | dmaCNT[i] | dmaHLT[i] | dmaSAB[i] | dmaITE[i],  //CCR
   401:                          dmaMTC[i], dmaMAR[i], dmaDAR[i], dmaBTC[i], dmaBAR[i]);
   402:     }
   403:     if ((dmaCOC[i] | dmaBLC[i] | dmaNDT[i] | dmaERR[i] | dmaACT[i]) != 0) {  //DMA_CSRがクリアされていない状態でSTRをセットしようとした
   404:       dmaErrorExit (i, DMA_TIMING_ERROR);
   405:       return;
   406:     }
   407:     if (((dmaDTYP[i] == DMA_HD68000_COMPATIBLE || dmaDTYP[i] == DMA_HD6800_COMPATIBLE) &&  //デュアルアドレスモードで
   408:          dmaDPS[i] == DMA_PORT_16_BIT && dmaSIZE[i] == DMA_BYTE_SIZE &&  //DMA_DPSが16ビットでSIZEが8ビットで
   409:          (dmaREQG[i] == DMA_EXTERNAL_REQUEST || dmaREQG[i] == DMA_DUAL_REQUEST)) ||  //外部転送要求のとき、または
   410:         dmaXRM[i] == 0b01000000 || dmaMAC[i] == 0b00001100 || dmaDAC[i] == 0b00000011 || dmaCHAIN[i] == 0b00000100 ||  //不正な値が指定されたとき
   411:         (dmaSIZE[i] == 0b00000011 && !((dmaDTYP[i] == DMA_HD68000_COMPATIBLE || dmaDTYP[i] == DMA_HD6800_COMPATIBLE) && dmaDPS[i] == DMA_PORT_8_BIT))) {
   412:       dmaErrorExit (i, DMA_CONFIGURATION_ERROR);
   413:       return;
   414:     }
   415:     //strには書き込まない
   416:     //チャンネル動作開始
   417:     dmaACT[i] = DMA_ACT;
   418:     if (dmaCHAIN[i] == DMA_ARRAY_CHAINING) {  //アレイチェインモードのとき
   419:       if (dmaBTC[i] == 0) {  //カウントエラー
   420:         dmaErrorExit (i, DMA_BASE_COUNT_ERROR);
   421:         return;
   422:       }
   423:       if ((dmaBAR[i] & 1) != 0) {  //アドレスエラー
   424:         dmaErrorExit (i, DMA_BASE_ADDRESS_ERROR);
   425:         return;
   426:       }
   427:       try {
   428:         MemoryMappedDevice[] mm = dmaBFCMap[i];
   429:         int a = dmaBAR[i];
   430:         dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
   431:         dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
   432:         dmaBAR[i] += 6;
   433:       } catch (M68kException e) {  //バスエラー
   434:         dmaErrorExit (i, DMA_BASE_BUS_ERROR);
   435:         return;
   436:       }
   437:       dmaBTC[i]--;
   438:     } else if (dmaCHAIN[i] == DMA_LINK_ARRAY_CHAINING) {  //リンクアレイチェインモードのとき
   439:       if ((dmaBAR[i] & 1) != 0) {  //アドレスエラー
   440:         dmaErrorExit (i, DMA_BASE_ADDRESS_ERROR);
   441:         return;
   442:       }
   443:       try {
   444:         MemoryMappedDevice[] mm = dmaBFCMap[i];
   445:         int a = dmaBAR[i];
   446:         dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
   447:         dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
   448:         dmaBAR[i] = mm[a + 6 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a + 6) << 16 | mm[a + 8 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 8);
   449:       } catch (M68kException e) {  //バスエラー
   450:         dmaErrorExit (i, DMA_BASE_BUS_ERROR);
   451:         return;
   452:       }
   453:     }
   454:     if (dmaMTC[i] == 0) {  //カウントエラー
   455:       dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
   456:       return;
   457:     }
   458:     if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
   459:       dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   460:       return;
   461:     }
   462:     if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && dmaDPS[i] == DMA_PORT_16_BIT && (dmaDAR[i] & 1) != 0) {  //アドレスエラー
   463:       dmaErrorExit (i, DMA_DEVICE_ADDRESS_ERROR);
   464:       return;
   465:     }
   466:     if (dmaREQG[i] == DMA_AUTO_REQUEST) {  //オートリクエスト限定速度
   467:       dmaBurstStart = XEiJ.mpuClockTime;  //今回のバースト開始時刻
   468:       dmaBurstEnd = dmaBurstStart + dmaBurstSpan;  //今回のバースト終了時刻
   469:       dmaTransfer (i);  //最初のデータを転送する
   470:     } else if (dmaREQG[i] != DMA_EXTERNAL_REQUEST ||  //オートリクエスト最大速度または最初はオートリクエスト、2番目から外部転送要求
   471:                dmaPCT[i] != 0) {  //外部転送要求で既に要求がある
   472:       dmaTransfer (i);  //最初のデータを転送する
   473:     }
   474:   }  //dmaStart(int)
   475: 
   476:   //dmaContinue (i)
   477:   //  転送継続
   478:   public static void dmaContinue (int i) {
   479:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   480:       System.out.printf ("%d %08x dmaContinue(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   481:     }
   482:     if (dmaREQG[i] == DMA_AUTO_REQUEST) {  //オートリクエスト限定速度
   483:       if (XEiJ.mpuClockTime < dmaBurstEnd) {  //バースト継続
   484:         //現在時刻に次の予約を入れる
   485:         dmaInnerClock[i] = XEiJ.mpuClockTime;
   486:         TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   487:       } else {  //バースト終了
   488:         dmaBurstStart += dmaBurstInterval;  //次回のバースト開始時刻
   489:         if (dmaBurstStart < XEiJ.mpuClockTime) {
   490:           dmaBurstStart = XEiJ.mpuClockTime + dmaBurstInterval;  //間に合っていないとき1周だけ延期する
   491:         }
   492:         dmaBurstEnd = dmaBurstStart + dmaBurstSpan;  //次回のバースト終了時刻
   493:         //次回のバースト開始時刻に次の予約を入れる
   494:         dmaInnerClock[i] = dmaBurstStart;
   495:         TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   496:       }
   497:     } else if (dmaREQG[i] == DMA_AUTO_REQUEST_MAX) {  //オートリクエスト最大速度
   498:       //現在時刻に次の予約を入れる
   499:       dmaInnerClock[i] = XEiJ.mpuClockTime;
   500:       TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   501:     }
   502:   }  //dmaContinue(int)
   503: 
   504:   //dmaComplete (i)
   505:   //  転送終了
   506:   //  dmaCOC,dmaBLC,dmaNDTは個別に設定すること
   507:   public static void dmaComplete (int i) {
   508:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   509:       System.out.printf ("%d %08x dmaComplete(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   510:     }
   511:     dmaERR[i] = 0;
   512:     dmaACT[i] = 0;
   513:     dmaSTR[i] = 0;
   514:     dmaCNT[i] = 0;
   515:     dmaSAB[i] = 0;
   516:     dmaErrorCode[i] = 0;
   517:     if (dmaITE[i] != 0) {  //インタラプトイネーブル
   518:       dmaInnerRequest[i << 1]++;
   519:       XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   520:     }
   521:     if (dmaInnerClock[i] != XEiJ.FAR_FUTURE) {
   522:       dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   523:       TickerQueue.tkqRemove (dmaTickerArray[i]);
   524:     }
   525:   }  //dmaComplete(int)
   526: 
   527:   //dmaErrorExit (i, code)
   528:   //  エラー終了
   529:   //  dmaCOC,dmaBLC,dmaNDTは操作しない
   530:   public static void dmaErrorExit (int i, int code) {
   531:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   532:       System.out.printf ("%d %08x dmaErrorExit(%d,%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i, code);
   533:     }
   534:     dmaERR[i] = DMA_ERR;
   535:     dmaACT[i] = 0;
   536:     dmaSTR[i] = 0;
   537:     dmaCNT[i] = 0;
   538:     dmaSAB[i] = 0;
   539:     dmaErrorCode[i] = code;
   540:     if (dmaITE[i] != 0) {  //インタラプトイネーブル
   541:       dmaInnerRequest[i << 1 | 1]++;
   542:       XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   543:     }
   544:     if (dmaInnerClock[i] != XEiJ.FAR_FUTURE) {
   545:       dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   546:       TickerQueue.tkqRemove (dmaTickerArray[i]);
   547:     }
   548:   }  //dmaErrorExit(int,int)
   549: 
   550:   //dmaFallPCL (i) {
   551:   //  外部転送要求
   552:   //  X68000ではREQ3とPCL3が直結されているので同時に変化する
   553:   public static void dmaFallPCL (int i) {
   554:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   555:       System.out.printf ("%d %08x dmaFallPCL(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   556:     }
   557:     dmaPCS[i] = 0;
   558:     dmaPCT[i] = DMA_PCT;
   559:     if (dmaACT[i] != 0 &&  //動作中
   560:         (dmaREQG[i] & (DMA_EXTERNAL_REQUEST & DMA_DUAL_REQUEST)) != 0) {  //外部転送要求または最初はオートリクエスト、2番目から外部転送要求
   561:       //現在時刻から1clk後に次の予約を入れる
   562:       //  0clk後だとADPCMの再生に失敗する場合がある
   563:       dmaInnerClock[i] = XEiJ.mpuClockTime + DMA_CLOCK_UNIT * 1;
   564:       TickerQueue.tkqAdd (dmaTickerArray[i], dmaInnerClock[i]);
   565:     }
   566:   }  //dmaFallPCL(int)
   567: 
   568:   //dmaRisePCL (i)
   569:   //  外部転送要求解除
   570:   public static void dmaRisePCL (int i) {
   571:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   572:       System.out.printf ("%d %08x dmaRisePCL(%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i);
   573:     }
   574:     dmaPCS[i] = DMA_PCS;
   575:     dmaPCT[i] = 0;
   576:     dmaInnerClock[i] = XEiJ.FAR_FUTURE;
   577:     TickerQueue.tkqRemove (dmaTickerArray[i]);
   578:   }  //dmaRisePCL(int)
   579: 
   580:   //dmaTransfer (i)
   581:   //  1データ転送する
   582:   public static void dmaTransfer (int i) {
   583:     if (DMA_DEBUG_TRACE != 0 && (DMA_DEBUG_TRACE & 1 << i) != 0) {
   584:       System.out.printf ("%d %08x dmaTransfer(%d,0x%08x,0x%08x,%d)\n", XEiJ.mpuClockTime, XEiJ.regPC0, i,
   585:                          dmaDIR[i] == DMA_MEMORY_TO_DEVICE ? dmaMAR[i] : dmaDAR[i],
   586:                          dmaDIR[i] == DMA_MEMORY_TO_DEVICE ? dmaDAR[i] : dmaMAR[i],
   587:                          dmaSIZE[i] == DMA_BYTE_SIZE || dmaSIZE[i] == DMA_UNPACKED_8_BIT ? 1 : dmaSIZE[i] == DMA_WORD_SIZE ? 2 : 4);
   588:     }
   589:     if (Profiling.PFF_ON) {
   590:       Profiling.pffStart[Profiling.PRF.dmaTransfer.ordinal ()] = System.nanoTime ();
   591:     }
   592:   transfer:
   593:     {
   594:       int code = 0;
   595:       try {
   596:         switch (dmaSIZE[i]) {
   597:         case DMA_BYTE_SIZE:  //オペランドサイズ8ビット、パックあり
   598:           //  オートリクエストで、2バイト以上あり、1バイト目と2バイト目のアドレスの奇遇が異なり、偶数境界を跨がないとき、
   599:           //  2バイト分の転送を1ワードにまとめて行う
   600:           if ((dmaREQG[i] == DMA_AUTO_REQUEST || dmaREQG[i] == DMA_AUTO_REQUEST_MAX) &&  //オートリクエストで
   601:               dmaMTC[i] >= 2) {  //2バイト以上
   602:             boolean mpk = (dmaMAR[i] & 1) == 0 ? dmaMACValue[i] > 0 : dmaMACValue[i] < 0;  //true=メモリをパックできる
   603:             boolean dpk = dmaDPS[i] == DMA_PORT_16_BIT && ((dmaDAR[i] & 1) == 0 ? dmaDACValue[i] > 0 : dmaDACValue[i] < 0);  //true=デバイスをパックできる
   604:             if (mpk || dpk) {  //メモリとデバイスの少なくともどちらか一方をパックできる
   605:               if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリ→デバイス
   606:                 int data1;  //1バイト目
   607:                 int data2;  //2バイト目
   608:                 //メモリからリード
   609:                 code = DMA_MEMORY_BUS_ERROR;
   610:                 MemoryMappedDevice[] mm = dmaMFCMap[i];
   611:                 if (mpk) {  //パックする
   612:                   if (dmaMACValue[i] > 0) {  //インクリメントでパックする
   613:                     int a = dmaMAR[i];
   614:                     int t = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   615:                     data1 = t >> 8;
   616:                     data2 = t & 255;
   617:                     dmaMAR[i] += 2;
   618:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   619:                   } else {  //デクリメントでパックする
   620:                     int a = dmaMAR[i] - 1;
   621:                     int t = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   622:                     data1 = t & 255;
   623:                     data2 = t >> 8;
   624:                     dmaMAR[i] -= 2;
   625:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   626:                   }
   627:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   628:                 } else {  //パックしない
   629:                   int a = dmaMAR[i];
   630:                   data1 = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   631:                   a = dmaMAR[i] += dmaMACValue[i];
   632:                   data2 = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   633:                   dmaMAR[i] += dmaMACValue[i];
   634:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   635:                 }
   636:                 //デバイスへライト
   637:                 code = DMA_DEVICE_BUS_ERROR;
   638:                 mm = dmaDFCMap[i];
   639:                 if (dpk) {  //パックする
   640:                   if (dmaDACValue[i] > 0) {  //インクリメントでパックする
   641:                     int a = dmaDAR[i];
   642:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data1 << 8 | data2);
   643:                     dmaDAR[i] += 2;
   644:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   645:                   } else {  //デクリメントでパックする
   646:                     int a = dmaDAR[i] - 1;
   647:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data2 << 8 | data1);
   648:                     dmaDAR[i] -= 2;
   649:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   650:                   }
   651:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   652:                 } else {  //パックしない
   653:                   if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   654:                     int a = dmaDAR[i];
   655:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data1);
   656:                     a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   657:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data2);
   658:                     dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   659:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   660:                   } else {  //ポートサイズ16ビット
   661:                     int a = dmaDAR[i];
   662:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data1);
   663:                     a = dmaDAR[i] += dmaDACValue[i];
   664:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data2);
   665:                     dmaDAR[i] += dmaDACValue[i];
   666:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   667:                   }
   668:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   669:                 }
   670:               } else {  //デバイス→メモリ
   671:                 int data1;  //1バイト目
   672:                 int data2;  //2バイト目
   673:                 //デバイスからリード
   674:                 code = DMA_DEVICE_BUS_ERROR;
   675:                 MemoryMappedDevice[] mm = dmaDFCMap[i];
   676:                 if (dpk) {  //パックする
   677:                   if (dmaDACValue[i] > 0) {  //インクリメントでパックする
   678:                     int a = dmaDAR[i];
   679:                     int t = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   680:                     data1 = t >> 8;
   681:                     data2 = t & 255;
   682:                     dmaDAR[i] += 2;
   683:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   684:                   } else {  //デクリメントでパックする
   685:                     int a = dmaDAR[i] - 1;
   686:                     int t = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   687:                     data1 = t & 255;
   688:                     data2 = t >> 8;
   689:                     dmaDAR[i] -= 2;
   690:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   691:                   }
   692:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   693:                 } else {  //パックしない
   694:                   if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   695:                     int a = dmaDAR[i];
   696:                     data1 = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   697:                     a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   698:                     data2 = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   699:                     dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   700:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   701:                   } else {  //ポートサイズ16ビット
   702:                     int a = dmaDAR[i];
   703:                     data1 = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   704:                     a = dmaDAR[i] += dmaDACValue[i];
   705:                     data2 = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   706:                     dmaDAR[i] += dmaDACValue[i];
   707:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   708:                   }
   709:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   710:                 }
   711:                 //メモリへライト
   712:                 code = DMA_MEMORY_BUS_ERROR;
   713:                 mm = dmaMFCMap[i];
   714:                 if (mpk) {  //パックする
   715:                   if (dmaMACValue[i] > 0) {  //インクリメントでパックする
   716:                     int a = dmaMAR[i];
   717:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data1 << 8 | data2);
   718:                     dmaMAR[i] += 2;
   719:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   720:                   } else {  //デクリメントでパックする
   721:                     int a = dmaMAR[i] - 1;
   722:                     mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data2 << 8 | data1);
   723:                     dmaMAR[i] -= 2;
   724:                     //XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   725:                   }
   726:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   727:                 } else {  //パックしない
   728:                   int a = dmaMAR[i];
   729:                   mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data1);
   730:                   a = dmaMAR[i] += dmaMACValue[i];
   731:                   mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data2);
   732:                   dmaMAR[i] += dmaMACValue[i];
   733:                   XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   734:                 }
   735:               }
   736:               //パックできた
   737:               dmaMTC[i]--;  //1バイト余分に転送した
   738:               break;
   739:             }  //if mpk||dpk
   740:           }  //if dmaMTC[i]>=2
   741:           //パックできない
   742:         case DMA_UNPACKED_8_BIT:  //オペランドサイズ8ビット、パックなし
   743:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリ→デバイス
   744:             int data;
   745:             //メモリからリード
   746:             code = DMA_MEMORY_BUS_ERROR;
   747:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   748:             int a = dmaMAR[i];
   749:             data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   750:             dmaMAR[i] += dmaMACValue[i];
   751:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   752:             //デバイスへライト
   753:             code = DMA_DEVICE_BUS_ERROR;
   754:             mm = dmaDFCMap[i];
   755:             a = dmaDAR[i];
   756:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);
   757:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   758:               dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   759:             } else {  //ポートサイズ16ビット
   760:               dmaDAR[i] += dmaDACValue[i];
   761:             }
   762:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   763:           } else {  //デバイス→メモリ
   764:             int data;
   765:             //デバイスからリード
   766:             code = DMA_DEVICE_BUS_ERROR;
   767:             MemoryMappedDevice[] mm = dmaDFCMap[i];
   768:             int a = dmaDAR[i];
   769:             data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   770:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   771:               dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   772:             } else {  //ポートサイズ16ビット
   773:               dmaDAR[i] += dmaDACValue[i];
   774:             }
   775:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   776:             //メモリへライト
   777:             code = DMA_MEMORY_BUS_ERROR;
   778:             mm = dmaMFCMap[i];
   779:             a = dmaMAR[i];
   780:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);
   781:             dmaMAR[i] += dmaMACValue[i];
   782:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   783:           }
   784:           break;
   785:         case DMA_WORD_SIZE:  //オペランドサイズ16ビット
   786:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリ→デバイス
   787:             int data;
   788:             //メモリからリード
   789:             code = DMA_MEMORY_BUS_ERROR;
   790:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   791:             int a = dmaMAR[i];
   792:             data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   793:             dmaMAR[i] += dmaMACValue[i] << 1;
   794:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   795:             //デバイスへライト
   796:             code = DMA_DEVICE_BUS_ERROR;
   797:             mm = dmaDFCMap[i];
   798:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   799:               a = dmaDAR[i];
   800:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data >> 8);
   801:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   802:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);
   803:               dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   804:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   805:             } else {  //ポートサイズ16ビット
   806:               a = dmaDAR[i];
   807:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);
   808:               dmaDAR[i] += dmaDACValue[i] << 1;
   809:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   810:             }
   811:           } else {  //デバイス→メモリ
   812:             int data;
   813:             //デバイスからリード
   814:             code = DMA_DEVICE_BUS_ERROR;
   815:             MemoryMappedDevice[] mm = dmaDFCMap[i];
   816:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   817:               int a = dmaDAR[i];
   818:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a) << 8;
   819:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   820:               data |= mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   821:               dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   822:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   823:             } else {  //ポートサイズ16ビット
   824:               int a = dmaDAR[i];
   825:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);;
   826:               dmaDAR[i] += dmaDACValue[i] << 1;
   827:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   828:             }
   829:             //メモリへライト
   830:             code = DMA_MEMORY_BUS_ERROR;
   831:             mm = dmaMFCMap[i];
   832:             int a = dmaMAR[i];
   833:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);
   834:             dmaMAR[i] += dmaMACValue[i] << 1;
   835:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 1;
   836:           }
   837:           break;
   838:         case DMA_LONG_WORD_SIZE:  //オペランドサイズ32ビット
   839:           if (dmaDIR[i] == DMA_MEMORY_TO_DEVICE) {  //メモリ→デバイス
   840:             int data;
   841:             //メモリからリード
   842:             code = DMA_MEMORY_BUS_ERROR;
   843:             MemoryMappedDevice[] mm = dmaMFCMap[i];
   844:             int a = dmaMAR[i];
   845:             data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a) << 16;  //オペランドサイズが32ビットでも16ビットずつアクセスする
   846:             a = dmaMAR[i] += dmaMACValue[i] << 1;
   847:             data |= mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   848:             dmaMAR[i] += dmaMACValue[i] << 1;
   849:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   850:             //デバイスへライト
   851:             code = DMA_DEVICE_BUS_ERROR;
   852:             mm = dmaDFCMap[i];
   853:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   854:               a = dmaDAR[i];
   855:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data >> 24);
   856:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   857:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data >> 16);
   858:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   859:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data >> 8);
   860:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   861:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, data);
   862:               dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   863:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 4;
   864:             } else {  //ポートサイズ16ビット
   865:               a = dmaDAR[i];
   866:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data >> 16);
   867:               a = dmaDAR[i] += dmaDACValue[i] << 1;
   868:               mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);
   869:               dmaDAR[i] += dmaDACValue[i] << 1;
   870:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   871:             }
   872:           } else {  //デバイス→メモリ
   873:             int data;
   874:             //デバイスからリード
   875:             code = DMA_DEVICE_BUS_ERROR;
   876:             MemoryMappedDevice[] mm = dmaDFCMap[i];
   877:             if (dmaDPS[i] == DMA_PORT_8_BIT) {  //ポートサイズ8ビット
   878:               int a = dmaDAR[i];
   879:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a) << 24;
   880:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   881:               data |= mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a) << 16;
   882:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   883:               data |= mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a) << 8;
   884:               a = dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   885:               data |= mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
   886:               dmaDAR[i] += dmaDACValue[i] << 1;  //ポートサイズが8ビットでもDMA_DARは16ビットずつ変化する
   887:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 4;
   888:             } else {  //ポートサイズ16ビット
   889:               int a = dmaDAR[i];
   890:               data = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a) << 16;
   891:               a = dmaDAR[i] += dmaDACValue[i] << 1;
   892:               data |= mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
   893:               dmaDAR[i] += dmaDACValue[i] << 1;
   894:               XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   895:             }
   896:             //メモリへライト
   897:             code = DMA_MEMORY_BUS_ERROR;
   898:             mm = dmaMFCMap[i];
   899:             int a = dmaMAR[i];
   900:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data >> 16);  //オペランドサイズが32ビットでも16ビットずつアクセスする
   901:             a = dmaMAR[i] += dmaMACValue[i] << 1;
   902:             mm[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, data);
   903:             dmaMAR[i] += dmaMACValue[i] << 1;
   904:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 2;
   905:           }
   906:           break;
   907:         }  //switch dmaSIZE[i]
   908:       } catch (M68kException e) {
   909:         dmaErrorExit (i, code);
   910:         break transfer;
   911:       }
   912:       dmaMTC[i]--;
   913:       if (dmaMTC[i] != 0) {  //継続
   914:         dmaContinue (i);
   915:       } else if (dmaCHAIN[i] == DMA_ARRAY_CHAINING) {  //アレイチェーンモードのとき
   916:         if (dmaBTC[i] != 0) {  //継続
   917:           //アドレスエラーのチェックは不要
   918:           try {
   919:             MemoryMappedDevice[] mm = dmaBFCMap[i];
   920:             int a = dmaBAR[i];
   921:             dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
   922:             dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
   923:             dmaBAR[i] += 6;
   924:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 3;
   925:           } catch (M68kException e) {  //バスエラー
   926:             dmaErrorExit (i, DMA_BASE_BUS_ERROR);
   927:             break transfer;
   928:           }
   929:           dmaBTC[i]--;
   930:           if (dmaMTC[i] == 0) {  //カウントエラー
   931:             dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
   932:             break transfer;
   933:           }
   934:           if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
   935:             dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   936:             break transfer;
   937:           }
   938:           dmaContinue (i);
   939:         } else {  //終了
   940:           dmaCOC[i] = DMA_COC;
   941:           dmaBLC[i] = DMA_BLC;
   942:           dmaNDT[i] = 0;
   943:           dmaComplete (i);
   944:         }
   945:       } else if (dmaCHAIN[i] == DMA_LINK_ARRAY_CHAINING) {  //リンクアレイチェーンモードのとき
   946:         if (dmaBAR[i] != 0) {  //継続
   947:           if ((dmaBAR[i] & 1) != 0) {  //アドレスエラー
   948:             dmaErrorExit (i, DMA_BASE_ADDRESS_ERROR);
   949:             break transfer;
   950:           }
   951:           try {
   952:             MemoryMappedDevice[] mm = dmaBFCMap[i];
   953:             int a = dmaBAR[i];
   954:             dmaMAR[i] = mm[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a) << 16 | mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 2);
   955:             dmaMTC[i] = mm[a + 4 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 4);
   956:             dmaBAR[i] = mm[a + 6 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a + 6) << 16 | mm[a + 8 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a + 8);
   957:             XEiJ.mpuClockTime += DMA_CLOCK_UNIT * 5;
   958:           } catch (M68kException e) {  //バスエラー
   959:             dmaErrorExit (i, DMA_BASE_BUS_ERROR);
   960:             break transfer;
   961:           }
   962:           if (dmaMTC[i] == 0) {  //カウントエラー
   963:             dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
   964:             break transfer;
   965:           }
   966:           if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
   967:             dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   968:             break transfer;
   969:           }
   970:           dmaContinue (i);
   971:         } else {  //終了
   972:           dmaCOC[i] = DMA_COC;
   973:           dmaBLC[i] = DMA_BLC;
   974:           dmaNDT[i] = 0;
   975:           dmaComplete (i);
   976:         }
   977:       } else if (dmaCNT[i] != 0) {  //コンティニューモードのとき
   978:         dmaBLC[i] = DMA_BLC;
   979:         dmaCNT[i] = 0;
   980:         if (dmaITE[i] != 0) {  //インタラプトイネーブル
   981:           dmaInnerRequest[i << 1]++;
   982:           XEiJ.mpuIRR |= XEiJ.MPU_DMA_INTERRUPT_MASK;
   983:         }
   984:         dmaMTC[i] = dmaBTC[i];
   985:         dmaMAR[i] = dmaBAR[i];
   986:         if (dmaMTC[i] == 0) {  //カウントエラー
   987:           dmaErrorExit (i, DMA_MEMORY_COUNT_ERROR);
   988:           break transfer;
   989:         }
   990:         if ((dmaSIZE[i] == DMA_WORD_SIZE || dmaSIZE[i] == DMA_LONG_WORD_SIZE) && (dmaMAR[i] & 1) != 0) {  //アドレスエラー
   991:           dmaErrorExit (i, DMA_MEMORY_ADDRESS_ERROR);
   992:           break transfer;
   993:         }
   994:         dmaContinue (i);
   995:       } else {  //終了
   996:         dmaCOC[i] = DMA_COC;
   997:         dmaBLC[i] = 0;
   998:         dmaNDT[i] = 0;
   999:         dmaComplete (i);
  1000:       }
  1001:     }  //transfer
  1002:     if (Profiling.PFF_ON) {
  1003:       Profiling.pffTotal[Profiling.PRF.dmaTransfer.ordinal ()] += System.nanoTime () - Profiling.pffStart[Profiling.PRF.dmaTransfer.ordinal ()];
  1004:       Profiling.pffCount[Profiling.PRF.dmaTransfer.ordinal ()]++;
  1005:     }
  1006:   }  //dmaTransfer
  1007: 
  1008: }  //class HD63450
  1009: 
  1010: 
  1011: