| version 1.5, 2003/11/28 08:01:33 | version 1.20, 2004/04/05 09:45:07 | 
| Line 1 | Line 1 | 
 | #include        "compiler.h" | #include        "compiler.h" | 
| #include        "i286.h" | #include        "cpucore.h" | 
 | #include        "pccore.h" | #include        "pccore.h" | 
 | #include        "iocore.h" | #include        "iocore.h" | 
 |  |  | 
 |  |  | 
| static const _PICITEM def_master = { | enum { | 
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | PIC_OCW2_L              = 0x07, | 
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | PIC_OCW2_EOI    = 0x20, | 
| {7, 6, 5, 4, 3, 2, 1, 0}, | PIC_OCW2_SL             = 0x40, | 
| {0, 0x08, 0x00, 0}, | PIC_OCW2_R              = 0x80, | 
| 0x7d, 0, 0, 0, |  | 
| 0, 0, 0, 0}; | PIC_OCW3_RIS    = 0x01, | 
|  | PIC_OCW3_RR             = 0x02, | 
| static const _PICITEM def_slave = { | PIC_OCW3_P              = 0x04, | 
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | PIC_OCW3_SMM    = 0x20, | 
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | PIC_OCW3_ESMM   = 0x40 | 
| {7, 6, 5, 4, 3, 2, 1, 0}, | }; | 
| {0, 0x10, 0x07, 0}, |  | 
| 0x70, 0, 0, 0, |  | 
| 0, 0, 0, 0}; |  | 
|  |  | 
|  |  | 
| // ------------------------------------------------------------ ext. interrupt |  | 
|  |  | 
| // 外部でISRを待避する割り込み対策 |  | 
|  |  | 
| void extirq_push(void) { |  | 
|  |  | 
| PIC             p; |  | 
|  |  | 
| p = &pic; |  | 
| if (!p->ext_irq) { |  | 
| p->ext_irq = 1; |  | 
 |  |  | 
 | p->pi[0].levelsbak = p->pi[0].levels; |  | 
 | *(UINT32 *)(p->pi[0].levelbak+0) = *(UINT32 *)(p->pi[0].level+0); |  | 
 | *(UINT32 *)(p->pi[0].levelbak+4) = *(UINT32 *)(p->pi[0].level+4); |  | 
 | p->pi[0].isrbak = p->pi[0].isr; |  | 
 |  |  | 
 | p->pi[1].levelsbak = p->pi[1].levels; |  | 
 | *(UINT32 *)(p->pi[1].levelbak+0) = *(UINT32 *)(p->pi[1].level+0); |  | 
 | *(UINT32 *)(p->pi[1].levelbak+4) = *(UINT32 *)(p->pi[1].level+4); |  | 
 | p->pi[1].isrbak = p->pi[1].isr; |  | 
 | } |  | 
 | } |  | 
 |  |  | 
 |  |  | 
 | void extirq_pop(void) { |  | 
 |  |  | 
 | PIC             p; |  | 
 |  |  | 
 | p = &pic; |  | 
 | if (p->ext_irq) { |  | 
 | p->ext_irq = 0; |  | 
 |  |  | 
 | p->pi[0].levels = p->pi[0].levelsbak; |  | 
 | *(UINT32 *)(p->pi[0].level+0) = *(UINT32 *)(p->pi[0].levelbak+0); |  | 
 | *(UINT32 *)(p->pi[0].level+4) = *(UINT32 *)(p->pi[0].levelbak+4); |  | 
 | p->pi[0].isr = p->pi[0].isrbak; |  | 
 |  |  | 
 | p->pi[1].levels = p->pi[1].levelsbak; |  | 
 | *(UINT32 *)(p->pi[1].level+0) = *(UINT32 *)(p->pi[1].levelbak+0); |  | 
 | *(UINT32 *)(p->pi[1].level+4) = *(UINT32 *)(p->pi[1].levelbak+4); |  | 
 | p->pi[1].isr = p->pi[1].isrbak; |  | 
 | } |  | 
 | } |  | 
 |  |  | 
 |  | static const _PICITEM def_master = { | 
 |  | {0x11, 0x08, 0x80, 0x1d}, | 
 |  | 0x7d, 0, 0, 0, 0, 0}; | 
 |  |  | 
| // --------------------------- | static const _PICITEM def_slave = { | 
|  | {0x11, 0x10, 0x07, 0x09}, | 
| static void pic_rolpry(PICITEM pi) { | 0x71, 0, 0, 0, 0, 0}; | 
|  |  | 
| // あははーっ 酷いね…こりゃ |  | 
| *(UINT32 *)(&pi->pry[0]) = |  | 
| (*(UINT32 *)(&pi->pry[0]) + 0x01010101) & 0x07070707; |  | 
| *(UINT32 *)(&pi->pry[4]) = |  | 
| (*(UINT32 *)(&pi->pry[4]) + 0x01010101) & 0x07070707; |  | 
| } |  | 
|  |  | 
|  |  | 
| static void pic_downbylevel(PICITEM picp, BYTE level) { |  | 
|  |  | 
| int             i; |  | 
|  |  | 
| for (i=0; i<8; i++) { |  | 
| if (picp->pry[i] < picp->pry[level]) { |  | 
| (picp->pry[i])++; |  | 
| } |  | 
| } |  | 
| picp->pry[level] = 0; |  | 
| } |  | 
|  |  | 
|  |  | 
| // eoi処理 |  | 
| static void pic_forceeoibylevel(PICITEM picp, BYTE level) { |  | 
|  |  | 
| int             i; |  | 
 |  |  | 
 | if (picp->isr & (1 << level)) { |  | 
 | picp->isr &= ~(1 << level); |  | 
 | (picp->levels)--; |  | 
 | for (i=0; (i<picp->levels) && (picp->level[i] != level); i++) { } |  | 
 | for (; i<picp->levels; i++) { |  | 
 | picp->level[i] = picp->level[i+1]; |  | 
 | } |  | 
 | } |  | 
 | } |  | 
 |  |  | 
 |  | // ---- | 
 |  |  | 
 | void pic_irq(void) { | void pic_irq(void) { | 
 |  |  | 
 | int             i; |  | 
 | BYTE    bit; |  | 
 | char    pry; |  | 
 | BYTE    irq; |  | 
 | BYTE    sirq; |  | 
 | BYTE    targetbit; |  | 
 | PIC             p; | PIC             p; | 
|  | REG8    mir; | 
|  | REG8    sir; | 
|  | REG8    dat; | 
|  | REG8    num; | 
|  | REG8    bit; | 
|  | REG8    slave; | 
|  |  | 
|  | // 割込み許可? | 
|  | if (!CPU_isEI) { | 
|  | return; | 
|  | } | 
 | p = &pic; | p = &pic; | 
 |  |  | 
| // 割込み許可で 要求あり? | mir = p->pi[0].irr & (~p->pi[0].imr); | 
| if ((isI286EI) && (!p->ext_irq) && | sir = p->pi[1].irr & (~p->pi[1].imr); | 
| ((p->pi[0].irr & (~p->pi[0].imr)) || | if ((mir == 0) && (sir == 0)) { | 
| (p->pi[1].irr & (~p->pi[1].imr)))) { | return; | 
|  | } | 
| // マスターの処理 |  | 
| if (!p->pi[0].levels) { | slave = 1 << (p->pi[1].icw[2] & 7); | 
| pry = -1; | dat = mir; | 
| } | if (sir) { | 
| else { | dat |= slave; | 
| pry = (char)p->pi[0].pry[p->pi[0].level[p->pi[0].levels - 1]]; | } | 
| } | if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { | 
| irq = 0xff; | dat |= p->pi[0].isr; | 
| targetbit = 0; | } | 
| for (bit=1, i=0; bit; bit<<=1, i++) { | num = p->pi[0].pry; | 
| if ((p->pi[0].irr & bit) && | bit = 1 << num; | 
| (!((p->pi[0].imr | p->pi[0].isr) & bit))) { | while(!(dat & bit)) { | 
| if ((char)p->pi[0].pry[i] > pry) { | num = (num + 1) & 7; | 
| pry = p->pi[0].pry[i]; | bit = 1 << num; | 
| irq = (BYTE)i; | } | 
| targetbit = bit; | if (p->pi[0].icw[2] & bit) {                                    // スレーヴ | 
| } | dat = sir; | 
| } | if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { | 
| } | dat |= p->pi[1].isr; | 
| // スレーヴの要求はある? | } | 
| if (!(p->pi[1].irr & (~p->pi[1].imr))) { | num = p->pi[1].pry; | 
| sirq = 0xff; | bit = 1 << num; | 
| } | while(!(dat & bit)) { | 
| else { | num = (num + 1) & 7; | 
| sirq = p->pi[1].icw[2] & 7; | bit = 1 << num; | 
| bit = 1 << sirq; | } | 
| if (!((p->pi[0].imr | p->pi[0].isr) & bit)) { | if (!(p->pi[1].isr & bit)) { | 
| if ((char)p->pi[0].pry[sirq] > pry) { | p->pi[0].isr |= slave; | 
| irq = sirq; | p->pi[0].irr &= ~slave; | 
| targetbit = bit; | p->pi[1].isr |= bit; | 
| } | p->pi[1].irr &= ~bit; | 
| } | //                      TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); | 
| } | CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | num), 0); | 
| // マスタの割込 | } | 
| if (irq != sirq) { | } | 
| if (targetbit) { | else if (!(p->pi[0].isr & bit)) {                               // マスター | 
| if (p->pi[0].ext & targetbit) {                         // ver0.30 | p->pi[0].isr |= bit; | 
| extirq_push(); | p->pi[0].irr &= ~bit; | 
| } | if (num == 0) { | 
| p->pi[0].isr |= targetbit; | nevent_reset(NEVENT_PICMASK); | 
| p->pi[0].irr &= ~targetbit; |  | 
| p->pi[0].level[p->pi[0].levels++] = irq; |  | 
| if (irq == 0) {                                                                 // ver0.28 |  | 
| nevent_reset(NEVENT_PICMASK); |  | 
| } |  | 
| i286_interrupt((BYTE)((p->pi[0].icw[1] & 0xf8) | irq)); |  | 
| // TRACEOUT(("hardware-int %.2x", (p->pi[0].icw[1] & 0xf8) | irq)); |  | 
| return; |  | 
| } |  | 
| if ((!p->pi[0].levels) || |  | 
| (p->pi[0].level[p->pi[0].levels - 1] != sirq)) { |  | 
| return; |  | 
| } |  | 
| } |  | 
| // スレーヴの処理 |  | 
| if (!p->pi[1].levels) { |  | 
| pry = -1; |  | 
| } |  | 
| else { |  | 
| pry = (char)p->pi[1].pry[p->pi[1].level[p->pi[1].levels - 1]]; |  | 
| } |  | 
| targetbit = 0; |  | 
| for (bit=1, i=0; bit; bit<<=1, i++) { |  | 
| if ((p->pi[1].irr & bit) && |  | 
| (!((p->pi[1].imr | p->pi[1].isr) & bit))) { |  | 
| if ((char)p->pi[1].pry[i] > pry) { |  | 
| pry = p->pi[1].pry[i]; |  | 
| irq = (BYTE)i; |  | 
| targetbit = bit; |  | 
| } |  | 
| } |  | 
| } |  | 
| // スレーヴの割込 |  | 
| if (targetbit) { |  | 
| if (!(p->pi[0].icw[2] & targetbit)) { |  | 
| if (p->pi[1].ext & targetbit) {                         // ver0.30 |  | 
| extirq_push(); |  | 
| } |  | 
| p->pi[1].isr |= targetbit; |  | 
| p->pi[1].irr &= ~targetbit; |  | 
| p->pi[1].level[p->pi[1].levels++] = irq; |  | 
| if ((!p->pi[0].levels) || |  | 
| (p->pi[0].level[p->pi[0].levels - 1] != sirq)) { |  | 
| p->pi[0].isr |= (1 << sirq); |  | 
| p->pi[0].irr &= ~(1 << sirq); |  | 
| p->pi[0].level[p->pi[0].levels++] = sirq; |  | 
| } |  | 
| // TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | irq)); |  | 
| i286_interrupt((BYTE)((p->pi[1].icw[1] & 0xf8) | irq)); |  | 
| } |  | 
 | } | } | 
 |  | //              TRACEOUT(("hardware-int %.2x", (p->pi[0].icw[1] & 0xf8) | num)); | 
 |  | CPU_INTERRUPT((REG8)((p->pi[0].icw[1] & 0xf8) | num), 0); | 
 | } | } | 
 | } | } | 
 |  |  | 
| Line 231  void picmask(NEVENTITEM item) { | Line 108  void picmask(NEVENTITEM item) { | 
 | } | } | 
 | } | } | 
 |  |  | 
| void pic_setirq(BYTE irq) { | void pic_setirq(REG8 irq) { | 
 |  |  | 
 | PICITEM pi; | PICITEM pi; | 
| BYTE    bit; | REG8    bit; | 
 |  |  | 
 | pi = pic.pi; | pi = pic.pi; | 
 | bit = 1 << (irq & 7); | bit = 1 << (irq & 7); | 
| Line 242  void pic_setirq(BYTE irq) { | Line 119  void pic_setirq(BYTE irq) { | 
 | pi[0].irr |= bit; | pi[0].irr |= bit; | 
 | if (pi[0].imr & bit) { | if (pi[0].imr & bit) { | 
 | if (bit & PIC_SYSTEMTIMER) { | if (bit & PIC_SYSTEMTIMER) { | 
| if ((pit.mode[0] & 0x0c) == 0x04) { | if ((pit.ch[0].ctrl & 0x0c) == 0x04) { | 
 | SINT32 cnt;                                                                             // ver0.29 | SINT32 cnt;                                                                             // ver0.29 | 
| if (pit.value[0] > 8) { | if (pit.ch[0].value > 8) { | 
| cnt = pc.multiple * pit.value[0]; | cnt = pccore.multiple * pit.ch[0].value; | 
 | cnt >>= 2; | cnt >>= 2; | 
 | } | } | 
 | else { | else { | 
| cnt = pc.multiple << (16 - 2); | cnt = pccore.multiple << (16 - 2); | 
 | } | } | 
 | nevent_set(NEVENT_PICMASK, cnt, picmask, NEVENT_ABSOLUTE); | nevent_set(NEVENT_PICMASK, cnt, picmask, NEVENT_ABSOLUTE); | 
 | } | } | 
| Line 267  void pic_setirq(BYTE irq) { | Line 144  void pic_setirq(BYTE irq) { | 
 | } | } | 
 | } | } | 
 |  |  | 
| void pic_resetirq(BYTE irq) { | void pic_resetirq(REG8 irq) { | 
 |  |  | 
 | PICITEM         pi; | PICITEM         pi; | 
 |  |  | 
| Line 276  void pic_resetirq(BYTE irq) { | Line 153  void pic_resetirq(BYTE irq) { | 
 | } | } | 
 |  |  | 
 |  |  | 
 | void pic_registext(BYTE irq) { |  | 
 |  |  | 
 | PICITEM         pi; |  | 
 |  |  | 
 | pi = pic.pi + ((irq >> 3) & 1); |  | 
 | pi->ext |= (1 << (irq & 7)); |  | 
 | } |  | 
 |  |  | 
 |  |  | 
 | // ---- I/O | // ---- I/O | 
 |  |  | 
| static void IOOUTCALL pic_o00(UINT port, BYTE dat) { | static void IOOUTCALL pic_o00(UINT port, REG8 dat) { | 
 |  |  | 
| PICITEM         picp; | PICITEM picp; | 
| BYTE            level; | REG8    level; | 
|  | UINT8   ocw3; | 
 |  |  | 
 | //      TRACEOUT(("pic %x %x", port, dat)); | //      TRACEOUT(("pic %x %x", port, dat)); | 
 | picp = &pic.pi[(port >> 3) & 1]; | picp = &pic.pi[(port >> 3) & 1]; | 
 | picp->writeicw = 0; | picp->writeicw = 0; | 
 | switch(dat & 0x18) { | switch(dat & 0x18) { | 
| case 0x00:                                              // eoi | case 0x00:                                              // ocw2 | 
| if (dat & 0x40) { | if (dat & PIC_OCW2_SL) { | 
| level = dat & 7; | level = dat & PIC_OCW2_L; | 
 | } | } | 
 | else { | else { | 
| if (picp->levels == 0) { | if (!picp->isr) { | 
 | break; | break; | 
 | } | } | 
| level = picp->level[picp->levels - 1]; | level = picp->pry; | 
| } | while(!(picp->isr & (1 << level))) { | 
| if (dat & 0x80) { | level = (level + 1) & 7; | 
| if (!(dat & 0x40)) { |  | 
| pic_rolpry(picp); |  | 
| } |  | 
| else { |  | 
| pic_downbylevel(picp, level); |  | 
 | } | } | 
 | } | } | 
| if (dat & 0x20) { | if (dat & PIC_OCW2_R) { | 
| pic_forceeoibylevel(picp, level); | picp->pry = (level + 1) & 7; | 
|  | } | 
|  | if (dat & PIC_OCW2_EOI) { | 
|  | picp->isr &= ~(1 << level); | 
 | } | } | 
 | nevent_forceexit();                             // mainloop exit | nevent_forceexit();                             // mainloop exit | 
 | break; | break; | 
 |  |  | 
 | case 0x08:                                                      // ocw3 | case 0x08:                                                      // ocw3 | 
 |  | ocw3 = picp->ocw3; | 
 |  | if (!(dat & PIC_OCW3_RR)) { | 
 |  | dat &= PIC_OCW3_RIS; | 
 |  | dat |= (ocw3 & PIC_OCW3_RIS); | 
 |  | } | 
 |  | if (!(dat & PIC_OCW3_ESMM)) { | 
 |  | dat &= ~PIC_OCW3_SMM; | 
 |  | dat |= (ocw3 & PIC_OCW3_SMM); | 
 |  | } | 
 | picp->ocw3 = dat; | picp->ocw3 = dat; | 
 | break; | break; | 
 |  |  | 
 | default: | default: | 
 | picp->icw[0] = dat; | picp->icw[0] = dat; | 
 | picp->imr = 0; | picp->imr = 0; | 
| picp->irr = 0;                                                                          // ver0.28 | picp->irr = 0; | 
| picp->ocw3 = 0;                                                                         // ver0.25 | picp->ocw3 = 0; | 
 | #if 0 | #if 0 | 
 | picp->levels = 0; | picp->levels = 0; | 
 | picp->isr = 0; | picp->isr = 0; | 
 | #endif | #endif | 
 |  | picp->pry = 0; | 
 | picp->writeicw = 1; | picp->writeicw = 1; | 
 | break; | break; | 
 | } | } | 
 | } | } | 
 |  |  | 
| static void IOOUTCALL pic_o02(UINT port, BYTE dat) { | static void IOOUTCALL pic_o02(UINT port, REG8 dat) { | 
 |  |  | 
 | PICITEM         picp; | PICITEM         picp; | 
 |  |  | 
 | //      TRACEOUT(("pic %x %x", port, dat)); | //      TRACEOUT(("pic %x %x", port, dat)); | 
 | picp = &pic.pi[(port >> 3) & 1]; | picp = &pic.pi[(port >> 3) & 1]; | 
 | if (!picp->writeicw) { | if (!picp->writeicw) { | 
 |  | #if 1 | 
 |  | UINT8   set; | 
 |  | set = picp->imr & (~dat); | 
 |  | // リセットされたビットは割り込みある? | 
 |  | if ((CPU_isDI) || (!(picp->irr & set))) { | 
 |  | picp->imr = dat; | 
 |  | return; | 
 |  | } | 
 |  | #endif | 
 | picp->imr = dat; | picp->imr = dat; | 
 | } | } | 
 | else { | else { | 
| Line 357  static void IOOUTCALL pic_o02(UINT port, | Line 243  static void IOOUTCALL pic_o02(UINT port, | 
 | nevent_forceexit(); | nevent_forceexit(); | 
 | } | } | 
 |  |  | 
| static BYTE IOINPCALL pic_i00(UINT port) { | static REG8 IOINPCALL pic_i00(UINT port) { | 
 |  |  | 
 | PICITEM         picp; | PICITEM         picp; | 
 |  |  | 
 | picp = &pic.pi[(port >> 3) & 1]; | picp = &pic.pi[(port >> 3) & 1]; | 
| switch(picp->ocw3 & 0x03) { | if (!(picp->ocw3 & PIC_OCW3_RIS)) { | 
| case 0x02:                                              // read irr | return(picp->irr);                      // read irr | 
| return(picp->irr); | } | 
|  | else { | 
| case 0x03:                                              // read isr | return(picp->isr);                      // read isr | 
| return(picp->isr); |  | 
|  |  | 
| default: |  | 
| return(0x00);                           // can can bunny |  | 
 | } | } | 
 | } | } | 
 |  |  | 
| static BYTE IOINPCALL pic_i02(UINT port) { | static REG8 IOINPCALL pic_i02(UINT port) { | 
 |  |  | 
 | PICITEM         picp; | PICITEM         picp; | 
 |  |  | 
| Line 385  static BYTE IOINPCALL pic_i02(UINT port) | Line 267  static BYTE IOINPCALL pic_i02(UINT port) | 
 |  |  | 
 | // ---- I/F | // ---- I/F | 
 |  |  | 
 |  | #if !defined(SUPPORT_PC9821) | 
 | static const IOOUT pico00[2] = { | static const IOOUT pico00[2] = { | 
 | pic_o00,        pic_o02}; | pic_o00,        pic_o02}; | 
 |  |  | 
 | static const IOINP pici00[2] = { | static const IOINP pici00[2] = { | 
 | pic_i00,        pic_i02}; | pic_i00,        pic_i02}; | 
 |  | #else | 
 |  | static const IOOUT pico00[4] = { | 
 |  | pic_o00,        pic_o02,        NULL,   NULL}; | 
 |  |  | 
 |  | static const IOINP pici00[4] = { | 
 |  | pic_i00,        pic_i02,        NULL,   NULL}; | 
 |  | #endif | 
 |  |  | 
 | void pic_reset(void) { | void pic_reset(void) { | 
 |  |  | 
| Line 399  void pic_reset(void) { | Line 289  void pic_reset(void) { | 
 |  |  | 
 | void pic_bind(void) { | void pic_bind(void) { | 
 |  |  | 
 |  | #if !defined(SUPPORT_PC9821) | 
 | iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); | iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); | 
 | iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); | iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); | 
 |  | #else | 
 |  | iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 4); | 
 |  | iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 4); | 
 |  | #endif | 
 | } | } | 
 |  |  |