xeij/MC68060.java (2/3)
1 2 3 //TPVS.W #<data> |A|--2346|-|---*-|-----| |0101_100_111_111_010-{data} [TRAPVS.W #<data>]
//TRAPNVC.W #<data> |A|--2346|-|---*-|-----| |0101_100_111_111_010-{data} [TRAPVS.W #<data>]
//TRAPVS.L #<data> |-|--2346|-|---*-|-----| |0101_100_111_111_011-{data}
//TPNVC.L #<data> |A|--2346|-|---*-|-----| |0101_100_111_111_011-{data} [TRAPVS.L #<data>]
//TPVS.L #<data> |A|--2346|-|---*-|-----| |0101_100_111_111_011-{data} [TRAPVS.L #<data>]
//TRAPNVC.L #<data> |A|--2346|-|---*-|-----| |0101_100_111_111_011-{data} [TRAPVS.L #<data>]
//TRAPVS |-|--2346|-|---*-|-----| |0101_100_111_111_100
//TPNVC |A|--2346|-|---*-|-----| |0101_100_111_111_100 [TRAPVS]
//TPVS |A|--2346|-|---*-|-----| |0101_100_111_111_100 [TRAPVS]
//TRAPNVC |A|--2346|-|---*-|-----| |0101_100_111_111_100 [TRAPVS]
public static void irpSvs () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBVS.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VS << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SVS.B Dr
if (XEiJ.MPU_CC_VS << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPVS.W/TRAPVS.L/TRAPVS
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_VS << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SVS.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_VS << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSvs
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SPL.B <ea> |-|012346|-|-*---|-----|D M+-WXZ |0101_101_011_mmm_rrr
//SNMI.B <ea> |A|012346|-|-*---|-----|D M+-WXZ |0101_101_011_mmm_rrr [SPL.B <ea>]
//DBPL.W Dr,<label> |-|012346|-|-*---|-----| |0101_101_011_001_rrr-{offset}
//DBNMI.W Dr,<label> |A|012346|-|-*---|-----| |0101_101_011_001_rrr-{offset} [DBPL.W Dr,<label>]
//TRAPPL.W #<data> |-|--2346|-|-*---|-----| |0101_101_011_111_010-{data}
//TPNMI.W #<data> |A|--2346|-|-*---|-----| |0101_101_011_111_010-{data} [TRAPPL.W #<data>]
//TPPL.W #<data> |A|--2346|-|-*---|-----| |0101_101_011_111_010-{data} [TRAPPL.W #<data>]
//TRAPNMI.W #<data> |A|--2346|-|-*---|-----| |0101_101_011_111_010-{data} [TRAPPL.W #<data>]
//TRAPPL.L #<data> |-|--2346|-|-*---|-----| |0101_101_011_111_011-{data}
//TPNMI.L #<data> |A|--2346|-|-*---|-----| |0101_101_011_111_011-{data} [TRAPPL.L #<data>]
//TPPL.L #<data> |A|--2346|-|-*---|-----| |0101_101_011_111_011-{data} [TRAPPL.L #<data>]
//TRAPNMI.L #<data> |A|--2346|-|-*---|-----| |0101_101_011_111_011-{data} [TRAPPL.L #<data>]
//TRAPPL |-|--2346|-|-*---|-----| |0101_101_011_111_100
//TPNMI |A|--2346|-|-*---|-----| |0101_101_011_111_100 [TRAPPL]
//TPPL |A|--2346|-|-*---|-----| |0101_101_011_111_100 [TRAPPL]
//TRAPNMI |A|--2346|-|-*---|-----| |0101_101_011_111_100 [TRAPPL]
public static void irpSpl () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBPL.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_PL << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SPL.B Dr
if (XEiJ.MPU_CC_PL << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPPL.W/TRAPPL.L/TRAPPL
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_PL << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SPL.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_PL << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSpl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SMI.B <ea> |-|012346|-|-*---|-----|D M+-WXZ |0101_101_111_mmm_rrr
//SNPL.B <ea> |A|012346|-|-*---|-----|D M+-WXZ |0101_101_111_mmm_rrr [SMI.B <ea>]
//DBMI.W Dr,<label> |-|012346|-|-*---|-----| |0101_101_111_001_rrr-{offset}
//DBNPL.W Dr,<label> |A|012346|-|-*---|-----| |0101_101_111_001_rrr-{offset} [DBMI.W Dr,<label>]
//TRAPMI.W #<data> |-|--2346|-|-*---|-----| |0101_101_111_111_010-{data}
//TPMI.W #<data> |A|--2346|-|-*---|-----| |0101_101_111_111_010-{data} [TRAPMI.W #<data>]
//TPNPL.W #<data> |A|--2346|-|-*---|-----| |0101_101_111_111_010-{data} [TRAPMI.W #<data>]
//TRAPNPL.W #<data> |A|--2346|-|-*---|-----| |0101_101_111_111_010-{data} [TRAPMI.W #<data>]
//TRAPMI.L #<data> |-|--2346|-|-*---|-----| |0101_101_111_111_011-{data}
//TPMI.L #<data> |A|--2346|-|-*---|-----| |0101_101_111_111_011-{data} [TRAPMI.L #<data>]
//TPNPL.L #<data> |A|--2346|-|-*---|-----| |0101_101_111_111_011-{data} [TRAPMI.L #<data>]
//TRAPNPL.L #<data> |A|--2346|-|-*---|-----| |0101_101_111_111_011-{data} [TRAPMI.L #<data>]
//TRAPMI |-|--2346|-|-*---|-----| |0101_101_111_111_100
//TPMI |A|--2346|-|-*---|-----| |0101_101_111_111_100 [TRAPMI]
//TPNPL |A|--2346|-|-*---|-----| |0101_101_111_111_100 [TRAPMI]
//TRAPNPL |A|--2346|-|-*---|-----| |0101_101_111_111_100 [TRAPMI]
public static void irpSmi () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBMI.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_MI << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SMI.B Dr
if (XEiJ.MPU_CC_MI << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPMI.W/TRAPMI.L/TRAPMI
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_MI << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SMI.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_MI << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSmi
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SGE.B <ea> |-|012346|-|-*-*-|-----|D M+-WXZ |0101_110_011_mmm_rrr
//SNLT.B <ea> |A|012346|-|-*-*-|-----|D M+-WXZ |0101_110_011_mmm_rrr [SGE.B <ea>]
//DBGE.W Dr,<label> |-|012346|-|-*-*-|-----| |0101_110_011_001_rrr-{offset}
//DBNLT.W Dr,<label> |A|012346|-|-*-*-|-----| |0101_110_011_001_rrr-{offset} [DBGE.W Dr,<label>]
//TRAPGE.W #<data> |-|--2346|-|-*-*-|-----| |0101_110_011_111_010-{data}
//TPGE.W #<data> |A|--2346|-|-*-*-|-----| |0101_110_011_111_010-{data} [TRAPGE.W #<data>]
//TPNLT.W #<data> |A|--2346|-|-*-*-|-----| |0101_110_011_111_010-{data} [TRAPGE.W #<data>]
//TRAPNLT.W #<data> |A|--2346|-|-*-*-|-----| |0101_110_011_111_010-{data} [TRAPGE.W #<data>]
//TRAPGE.L #<data> |-|--2346|-|-*-*-|-----| |0101_110_011_111_011-{data}
//TPGE.L #<data> |A|--2346|-|-*-*-|-----| |0101_110_011_111_011-{data} [TRAPGE.L #<data>]
//TPNLT.L #<data> |A|--2346|-|-*-*-|-----| |0101_110_011_111_011-{data} [TRAPGE.L #<data>]
//TRAPNLT.L #<data> |A|--2346|-|-*-*-|-----| |0101_110_011_111_011-{data} [TRAPGE.L #<data>]
//TRAPGE |-|--2346|-|-*-*-|-----| |0101_110_011_111_100
//TPGE |A|--2346|-|-*-*-|-----| |0101_110_011_111_100 [TRAPGE]
//TPNLT |A|--2346|-|-*-*-|-----| |0101_110_011_111_100 [TRAPGE]
//TRAPNLT |A|--2346|-|-*-*-|-----| |0101_110_011_111_100 [TRAPGE]
public static void irpSge () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBGE.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GE << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SGE.B Dr
if (XEiJ.MPU_CC_GE << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPGE.W/TRAPGE.L/TRAPGE
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_GE << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SGE.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_GE << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSge
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SLT.B <ea> |-|012346|-|-*-*-|-----|D M+-WXZ |0101_110_111_mmm_rrr
//SNGE.B <ea> |A|012346|-|-*-*-|-----|D M+-WXZ |0101_110_111_mmm_rrr [SLT.B <ea>]
//DBLT.W Dr,<label> |-|012346|-|-*-*-|-----| |0101_110_111_001_rrr-{offset}
//DBNGE.W Dr,<label> |A|012346|-|-*-*-|-----| |0101_110_111_001_rrr-{offset} [DBLT.W Dr,<label>]
//TRAPLT.W #<data> |-|--2346|-|-*-*-|-----| |0101_110_111_111_010-{data}
//TPLT.W #<data> |A|--2346|-|-*-*-|-----| |0101_110_111_111_010-{data} [TRAPLT.W #<data>]
//TPNGE.W #<data> |A|--2346|-|-*-*-|-----| |0101_110_111_111_010-{data} [TRAPLT.W #<data>]
//TRAPNGE.W #<data> |A|--2346|-|-*-*-|-----| |0101_110_111_111_010-{data} [TRAPLT.W #<data>]
//TRAPLT.L #<data> |-|--2346|-|-*-*-|-----| |0101_110_111_111_011-{data}
//TPLT.L #<data> |A|--2346|-|-*-*-|-----| |0101_110_111_111_011-{data} [TRAPLT.L #<data>]
//TPNGE.L #<data> |A|--2346|-|-*-*-|-----| |0101_110_111_111_011-{data} [TRAPLT.L #<data>]
//TRAPNGE.L #<data> |A|--2346|-|-*-*-|-----| |0101_110_111_111_011-{data} [TRAPLT.L #<data>]
//TRAPLT |-|--2346|-|-*-*-|-----| |0101_110_111_111_100
//TPLT |A|--2346|-|-*-*-|-----| |0101_110_111_111_100 [TRAPLT]
//TPNGE |A|--2346|-|-*-*-|-----| |0101_110_111_111_100 [TRAPLT]
//TRAPNGE |A|--2346|-|-*-*-|-----| |0101_110_111_111_100 [TRAPLT]
public static void irpSlt () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBLT.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LT << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SLT.B Dr
if (XEiJ.MPU_CC_LT << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPLT.W/TRAPLT.L/TRAPLT
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_LT << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SLT.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_LT << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSlt
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SGT.B <ea> |-|012346|-|-***-|-----|D M+-WXZ |0101_111_011_mmm_rrr
//SNLE.B <ea> |A|012346|-|-***-|-----|D M+-WXZ |0101_111_011_mmm_rrr [SGT.B <ea>]
//DBGT.W Dr,<label> |-|012346|-|-***-|-----| |0101_111_011_001_rrr-{offset}
//DBNLE.W Dr,<label> |A|012346|-|-***-|-----| |0101_111_011_001_rrr-{offset} [DBGT.W Dr,<label>]
//TRAPGT.W #<data> |-|--2346|-|-***-|-----| |0101_111_011_111_010-{data}
//TPGT.W #<data> |A|--2346|-|-***-|-----| |0101_111_011_111_010-{data} [TRAPGT.W #<data>]
//TPNLE.W #<data> |A|--2346|-|-***-|-----| |0101_111_011_111_010-{data} [TRAPGT.W #<data>]
//TRAPNLE.W #<data> |A|--2346|-|-***-|-----| |0101_111_011_111_010-{data} [TRAPGT.W #<data>]
//TRAPGT.L #<data> |-|--2346|-|-***-|-----| |0101_111_011_111_011-{data}
//TPGT.L #<data> |A|--2346|-|-***-|-----| |0101_111_011_111_011-{data} [TRAPGT.L #<data>]
//TPNLE.L #<data> |A|--2346|-|-***-|-----| |0101_111_011_111_011-{data} [TRAPGT.L #<data>]
//TRAPNLE.L #<data> |A|--2346|-|-***-|-----| |0101_111_011_111_011-{data} [TRAPGT.L #<data>]
//TRAPGT |-|--2346|-|-***-|-----| |0101_111_011_111_100
//TPGT |A|--2346|-|-***-|-----| |0101_111_011_111_100 [TRAPGT]
//TPNLE |A|--2346|-|-***-|-----| |0101_111_011_111_100 [TRAPGT]
//TRAPNLE |A|--2346|-|-***-|-----| |0101_111_011_111_100 [TRAPGT]
public static void irpSgt () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBGT.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GT << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SGT.B Dr
if (XEiJ.MPU_CC_GT << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPGT.W/TRAPGT.L/TRAPGT
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_GT << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SGT.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_GT << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSgt
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SLE.B <ea> |-|012346|-|-***-|-----|D M+-WXZ |0101_111_111_mmm_rrr
//SNGT.B <ea> |A|012346|-|-***-|-----|D M+-WXZ |0101_111_111_mmm_rrr [SLE.B <ea>]
//DBLE.W Dr,<label> |-|012346|-|-***-|-----| |0101_111_111_001_rrr-{offset}
//DBNGT.W Dr,<label> |A|012346|-|-***-|-----| |0101_111_111_001_rrr-{offset} [DBLE.W Dr,<label>]
//TRAPLE.W #<data> |-|--2346|-|-***-|-----| |0101_111_111_111_010-{data}
//TPLE.W #<data> |A|--2346|-|-***-|-----| |0101_111_111_111_010-{data} [TRAPLE.W #<data>]
//TPNGT.W #<data> |A|--2346|-|-***-|-----| |0101_111_111_111_010-{data} [TRAPLE.W #<data>]
//TRAPNGT.W #<data> |A|--2346|-|-***-|-----| |0101_111_111_111_010-{data} [TRAPLE.W #<data>]
//TRAPLE.L #<data> |-|--2346|-|-***-|-----| |0101_111_111_111_011-{data}
//TPLE.L #<data> |A|--2346|-|-***-|-----| |0101_111_111_111_011-{data} [TRAPLE.L #<data>]
//TPNGT.L #<data> |A|--2346|-|-***-|-----| |0101_111_111_111_011-{data} [TRAPLE.L #<data>]
//TRAPNGT.L #<data> |A|--2346|-|-***-|-----| |0101_111_111_111_011-{data} [TRAPLE.L #<data>]
//TRAPLE |-|--2346|-|-***-|-----| |0101_111_111_111_100
//TPLE |A|--2346|-|-***-|-----| |0101_111_111_111_100 [TRAPLE]
//TPNGT |A|--2346|-|-***-|-----| |0101_111_111_111_100 [TRAPLE]
//TRAPNGT |A|--2346|-|-***-|-----| |0101_111_111_111_100 [TRAPLE]
public static void irpSle () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //DBLE.W Dr,<label>
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LE << XEiJ.regCCR < 0) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
} else { //条件が成立していないのでデクリメント
int rrr = XEiJ.regOC & 7;
int s = XEiJ.regRn[rrr];
if ((short) s == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = s + 65535;
} else { //Drの下位16bitが0でないので分岐
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = s - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (t);
}
}
} else if (ea < XEiJ.EA_AR) { //SLE.B Dr
if (XEiJ.MPU_CC_LE << XEiJ.regCCR < 0) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if ((XEiJ.EAM_PW | XEiJ.EAM_PX | XEiJ.EAM_IM) << ea < 0L) { //TRAPLE.W/TRAPLE.L/TRAPLE
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (XEiJ.MPU_CC_LE << XEiJ.regCCR < 0) {
//条件が成立しているのでTRAPする
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
} else {
//条件が成立していないのでTRAPしない
XEiJ.mpuCycleCount++;
}
} else { //SLE.B <mem>
XEiJ.mpuCycleCount++;
mmuWriteByteData (efaMltByte (ea), XEiJ.MPU_CC_LE << XEiJ.regCCR >> 31, XEiJ.regSRS);
}
} //irpSle
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BRA.W <label> |-|012346|-|-----|-----| |0110_000_000_000_000-{offset}
//JBRA.W <label> |A|012346|-|-----|-----| |0110_000_000_000_000-{offset} [BRA.W <label>]
//BRA.S <label> |-|012346|-|-----|-----| |0110_000_000_sss_sss (s is not equal to 0)
//JBRA.S <label> |A|012346|-|-----|-----| |0110_000_000_sss_sss (s is not equal to 0) [BRA.S <label>]
public static void irpBrasw () throws M68kException {
XEiJ.mpuCycleCount++; //0clkにしない
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //オフセット
if (s == 0) { //BRA.W
XEiJ.regPC = t + 2;
s = mmuReadWordSignExword (t, XEiJ.regSRS); //pcws
}
irpSetPC (t + s); //pc0+2+オフセット
} //irpBrasw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BRA.S <label> |-|012346|-|-----|-----| |0110_000_001_sss_sss
//JBRA.S <label> |A|012346|-|-----|-----| |0110_000_001_sss_sss [BRA.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BRA.S <label> |-|012346|-|-----|-----| |0110_000_010_sss_sss
//JBRA.S <label> |A|012346|-|-----|-----| |0110_000_010_sss_sss [BRA.S <label>]
public static void irpBras () throws M68kException {
XEiJ.mpuCycleCount++; //0clkにしない
irpSetPC (XEiJ.regPC + (byte) XEiJ.regOC); //pc0+2+オフセット
} //irpBras
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BRA.S <label> |-|--2346|-|-----|-----| |0110_000_011_sss_sss (s is not equal to 63)
//JBRA.S <label> |A|--2346|-|-----|-----| |0110_000_011_sss_sss (s is not equal to 63) [BRA.S <label>]
//BRA.L <label> |-|--2346|-|-----|-----| |0110_000_011_111_111-{offset}
public static void irpBrasl () throws M68kException {
XEiJ.mpuCycleCount++; //0clkにしない
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //オフセット
if (s == -1) { //BRA.L
XEiJ.regPC = t + 4;
s = mmuReadLongExword (t, XEiJ.regSRS); //pcls
}
irpSetPC (t + s); //pc0+2+オフセット
} //irpBrasl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BSR.W <label> |-|012346|-|-----|-----| |0110_000_100_000_000-{offset}
//JBSR.W <label> |A|012346|-|-----|-----| |0110_000_100_000_000-{offset} [BSR.W <label>]
//BSR.S <label> |-|012346|-|-----|-----| |0110_000_100_sss_sss (s is not equal to 0)
//JBSR.S <label> |A|012346|-|-----|-----| |0110_000_100_sss_sss (s is not equal to 0) [BSR.S <label>]
public static void irpBsrsw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //オフセット
if (s == 0) { //BSR.W
XEiJ.regPC = t + 2;
s = mmuReadWordSignExword (t, XEiJ.regSRS); //pcws
}
m60Incremented -= 4L << (7 << 3);
int sp = m60Address = XEiJ.regRn[15] -= 4;
mmuWriteLongData (sp, XEiJ.regPC, XEiJ.regSRS); //pushl
irpSetPC (t + s); //pc0+2+オフセット
} //irpBsrsw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BSR.S <label> |-|012346|-|-----|-----| |0110_000_101_sss_sss
//JBSR.S <label> |A|012346|-|-----|-----| |0110_000_101_sss_sss [BSR.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BSR.S <label> |-|012346|-|-----|-----| |0110_000_110_sss_sss
//JBSR.S <label> |A|012346|-|-----|-----| |0110_000_110_sss_sss [BSR.S <label>]
public static void irpBsrs () throws M68kException {
XEiJ.mpuCycleCount++;
m60Incremented -= 4L << (7 << 3);
int sp = m60Address = XEiJ.regRn[15] -= 4;
mmuWriteLongData (sp, XEiJ.regPC, XEiJ.regSRS); //pushl
irpSetPC (XEiJ.regPC + (byte) XEiJ.regOC); //pc0+2+オフセット
} //irpBsrs
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BSR.S <label> |-|--2346|-|-----|-----| |0110_000_111_sss_sss (s is not equal to 63)
//JBSR.S <label> |A|--2346|-|-----|-----| |0110_000_111_sss_sss (s is not equal to 63) [BSR.S <label>]
//BSR.L <label> |-|--2346|-|-----|-----| |0110_000_111_111_111-{offset}
public static void irpBsrsl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //オフセット
if (s == -1) { //BSR.L
XEiJ.regPC = t + 4;
s = mmuReadLongExword (t, XEiJ.regSRS); //pcls
}
m60Incremented -= 4L << (7 << 3);
int sp = m60Address = XEiJ.regRn[15] -= 4;
mmuWriteLongData (sp, XEiJ.regPC, XEiJ.regSRS); //pushl
irpSetPC (t + s); //pc0+2+オフセット
} //irpBsrsl
//irpBccAddressError (int t)
public static void irpBccAddressError (int t) throws M68kException {
M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
m60Address = t & -2; //偶数にする
M68kException.m6eDirection = XEiJ.MPU_WR_READ;
M68kException.m6eSize = XEiJ.MPU_SS_WORD;
throw M68kException.m6eSignal;
}
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BHI.W <label> |-|012346|-|--*-*|-----| |0110_001_000_000_000-{offset}
//BNLS.W <label> |A|012346|-|--*-*|-----| |0110_001_000_000_000-{offset} [BHI.W <label>]
//JBHI.W <label> |A|012346|-|--*-*|-----| |0110_001_000_000_000-{offset} [BHI.W <label>]
//JBNLS.W <label> |A|012346|-|--*-*|-----| |0110_001_000_000_000-{offset} [BHI.W <label>]
//BHI.S <label> |-|012346|-|--*-*|-----| |0110_001_000_sss_sss (s is not equal to 0)
//BNLS.S <label> |A|012346|-|--*-*|-----| |0110_001_000_sss_sss (s is not equal to 0) [BHI.S <label>]
//JBHI.S <label> |A|012346|-|--*-*|-----| |0110_001_000_sss_sss (s is not equal to 0) [BHI.S <label>]
//JBNLS.S <label> |A|012346|-|--*-*|-----| |0110_001_000_sss_sss (s is not equal to 0) [BHI.S <label>]
//JBLS.L <label> |A|012346|-|--*-*|-----| |0110_001_000_000_110-0100111011111001-{address} [BHI.S (*)+8;JMP <label>]
//JBNHI.L <label> |A|012346|-|--*-*|-----| |0110_001_000_000_110-0100111011111001-{address} [BHI.S (*)+8;JMP <label>]
public static void irpBhisw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_HI << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBhisw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BHI.S <label> |-|012346|-|--*-*|-----| |0110_001_001_sss_sss
//BNLS.S <label> |A|012346|-|--*-*|-----| |0110_001_001_sss_sss [BHI.S <label>]
//JBHI.S <label> |A|012346|-|--*-*|-----| |0110_001_001_sss_sss [BHI.S <label>]
//JBNLS.S <label> |A|012346|-|--*-*|-----| |0110_001_001_sss_sss [BHI.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BHI.S <label> |-|012346|-|--*-*|-----| |0110_001_010_sss_sss
//BNLS.S <label> |A|012346|-|--*-*|-----| |0110_001_010_sss_sss [BHI.S <label>]
//JBHI.S <label> |A|012346|-|--*-*|-----| |0110_001_010_sss_sss [BHI.S <label>]
//JBNLS.S <label> |A|012346|-|--*-*|-----| |0110_001_010_sss_sss [BHI.S <label>]
public static void irpBhis () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_HI << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBhis
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BHI.S <label> |-|--2346|-|--*-*|-----| |0110_001_011_sss_sss (s is not equal to 63)
//BNLS.S <label> |A|--2346|-|--*-*|-----| |0110_001_011_sss_sss (s is not equal to 63) [BHI.S <label>]
//JBHI.S <label> |A|--2346|-|--*-*|-----| |0110_001_011_sss_sss (s is not equal to 63) [BHI.S <label>]
//JBNLS.S <label> |A|--2346|-|--*-*|-----| |0110_001_011_sss_sss (s is not equal to 63) [BHI.S <label>]
//BHI.L <label> |-|--2346|-|--*-*|-----| |0110_001_011_111_111-{offset}
//BNLS.L <label> |A|--2346|-|--*-*|-----| |0110_001_011_111_111-{offset} [BHI.L <label>]
public static void irpBhisl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_HI << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBhisl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLS.W <label> |-|012346|-|--*-*|-----| |0110_001_100_000_000-{offset}
//BNHI.W <label> |A|012346|-|--*-*|-----| |0110_001_100_000_000-{offset} [BLS.W <label>]
//JBLS.W <label> |A|012346|-|--*-*|-----| |0110_001_100_000_000-{offset} [BLS.W <label>]
//JBNHI.W <label> |A|012346|-|--*-*|-----| |0110_001_100_000_000-{offset} [BLS.W <label>]
//BLS.S <label> |-|012346|-|--*-*|-----| |0110_001_100_sss_sss (s is not equal to 0)
//BNHI.S <label> |A|012346|-|--*-*|-----| |0110_001_100_sss_sss (s is not equal to 0) [BLS.S <label>]
//JBLS.S <label> |A|012346|-|--*-*|-----| |0110_001_100_sss_sss (s is not equal to 0) [BLS.S <label>]
//JBNHI.S <label> |A|012346|-|--*-*|-----| |0110_001_100_sss_sss (s is not equal to 0) [BLS.S <label>]
//JBHI.L <label> |A|012346|-|--*-*|-----| |0110_001_100_000_110-0100111011111001-{address} [BLS.S (*)+8;JMP <label>]
//JBNLS.L <label> |A|012346|-|--*-*|-----| |0110_001_100_000_110-0100111011111001-{address} [BLS.S (*)+8;JMP <label>]
public static void irpBlssw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlssw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLS.S <label> |-|012346|-|--*-*|-----| |0110_001_101_sss_sss
//BNHI.S <label> |A|012346|-|--*-*|-----| |0110_001_101_sss_sss [BLS.S <label>]
//JBLS.S <label> |A|012346|-|--*-*|-----| |0110_001_101_sss_sss [BLS.S <label>]
//JBNHI.S <label> |A|012346|-|--*-*|-----| |0110_001_101_sss_sss [BLS.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLS.S <label> |-|012346|-|--*-*|-----| |0110_001_110_sss_sss
//BNHI.S <label> |A|012346|-|--*-*|-----| |0110_001_110_sss_sss [BLS.S <label>]
//JBLS.S <label> |A|012346|-|--*-*|-----| |0110_001_110_sss_sss [BLS.S <label>]
//JBNHI.S <label> |A|012346|-|--*-*|-----| |0110_001_110_sss_sss [BLS.S <label>]
public static void irpBlss () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlss
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLS.S <label> |-|--2346|-|--*-*|-----| |0110_001_111_sss_sss (s is not equal to 63)
//BNHI.S <label> |A|--2346|-|--*-*|-----| |0110_001_111_sss_sss (s is not equal to 63) [BLS.S <label>]
//JBLS.S <label> |A|--2346|-|--*-*|-----| |0110_001_111_sss_sss (s is not equal to 63) [BLS.S <label>]
//JBNHI.S <label> |A|--2346|-|--*-*|-----| |0110_001_111_sss_sss (s is not equal to 63) [BLS.S <label>]
//BLS.L <label> |-|--2346|-|--*-*|-----| |0110_001_111_111_111-{offset}
//BNHI.L <label> |A|--2346|-|--*-*|-----| |0110_001_111_111_111-{offset} [BLS.L <label>]
public static void irpBlssl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlssl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCC.W <label> |-|012346|-|----*|-----| |0110_010_000_000_000-{offset}
//BHS.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//BNCS.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//BNLO.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//JBCC.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//JBHS.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//JBNCS.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//JBNLO.W <label> |A|012346|-|----*|-----| |0110_010_000_000_000-{offset} [BCC.W <label>]
//BCC.S <label> |-|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0)
//BHS.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//BNCS.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//BNLO.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//JBCC.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//JBHS.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//JBNCS.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//JBNLO.S <label> |A|012346|-|----*|-----| |0110_010_000_sss_sss (s is not equal to 0) [BCC.S <label>]
//JBCS.L <label> |A|012346|-|----*|-----| |0110_010_000_000_110-0100111011111001-{address} [BCC.S (*)+8;JMP <label>]
//JBLO.L <label> |A|012346|-|----*|-----| |0110_010_000_000_110-0100111011111001-{address} [BCC.S (*)+8;JMP <label>]
//JBNCC.L <label> |A|012346|-|----*|-----| |0110_010_000_000_110-0100111011111001-{address} [BCC.S (*)+8;JMP <label>]
//JBNHS.L <label> |A|012346|-|----*|-----| |0110_010_000_000_110-0100111011111001-{address} [BCC.S (*)+8;JMP <label>]
public static void irpBhssw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_HS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBhssw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCC.S <label> |-|012346|-|----*|-----| |0110_010_001_sss_sss
//BHS.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//BNCS.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//BNLO.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//JBCC.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//JBHS.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//JBNCS.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//JBNLO.S <label> |A|012346|-|----*|-----| |0110_010_001_sss_sss [BCC.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCC.S <label> |-|012346|-|----*|-----| |0110_010_010_sss_sss
//BHS.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
//BNCS.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
//BNLO.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
//JBCC.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
//JBHS.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
//JBNCS.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
//JBNLO.S <label> |A|012346|-|----*|-----| |0110_010_010_sss_sss [BCC.S <label>]
public static void irpBhss () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_HS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBhss
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCC.S <label> |-|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63)
//BHS.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//BNCS.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//BNLO.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//JBCC.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//JBHS.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//JBNCS.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//JBNLO.S <label> |A|--2346|-|----*|-----| |0110_010_011_sss_sss (s is not equal to 63) [BCC.S <label>]
//BCC.L <label> |-|--2346|-|----*|-----| |0110_010_011_111_111-{offset}
//BHS.L <label> |A|--2346|-|----*|-----| |0110_010_011_111_111-{offset} [BCC.L <label>]
//BNCS.L <label> |A|--2346|-|----*|-----| |0110_010_011_111_111-{offset} [BCC.L <label>]
//BNLO.L <label> |A|--2346|-|----*|-----| |0110_010_011_111_111-{offset} [BCC.L <label>]
public static void irpBhssl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_HS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBhssl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCS.W <label> |-|012346|-|----*|-----| |0110_010_100_000_000-{offset}
//BLO.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//BNCC.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//BNHS.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//JBCS.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//JBLO.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//JBNCC.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//JBNHS.W <label> |A|012346|-|----*|-----| |0110_010_100_000_000-{offset} [BCS.W <label>]
//BCS.S <label> |-|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0)
//BLO.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//BNCC.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//BNHS.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//JBCS.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//JBLO.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//JBNCC.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//JBNHS.S <label> |A|012346|-|----*|-----| |0110_010_100_sss_sss (s is not equal to 0) [BCS.S <label>]
//JBCC.L <label> |A|012346|-|----*|-----| |0110_010_100_000_110-0100111011111001-{address} [BCS.S (*)+8;JMP <label>]
//JBHS.L <label> |A|012346|-|----*|-----| |0110_010_100_000_110-0100111011111001-{address} [BCS.S (*)+8;JMP <label>]
//JBNCS.L <label> |A|012346|-|----*|-----| |0110_010_100_000_110-0100111011111001-{address} [BCS.S (*)+8;JMP <label>]
//JBNLO.L <label> |A|012346|-|----*|-----| |0110_010_100_000_110-0100111011111001-{address} [BCS.S (*)+8;JMP <label>]
public static void irpBlosw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LO << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlosw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCS.S <label> |-|012346|-|----*|-----| |0110_010_101_sss_sss
//BLO.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//BNCC.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//BNHS.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//JBCS.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//JBLO.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//JBNCC.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//JBNHS.S <label> |A|012346|-|----*|-----| |0110_010_101_sss_sss [BCS.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCS.S <label> |-|012346|-|----*|-----| |0110_010_110_sss_sss
//BLO.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
//BNCC.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
//BNHS.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
//JBCS.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
//JBLO.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
//JBNCC.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
//JBNHS.S <label> |A|012346|-|----*|-----| |0110_010_110_sss_sss [BCS.S <label>]
public static void irpBlos () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LO << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlos
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BCS.S <label> |-|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63)
//BLO.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//BNCC.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//BNHS.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//JBCS.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//JBLO.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//JBNCC.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//JBNHS.S <label> |A|--2346|-|----*|-----| |0110_010_111_sss_sss (s is not equal to 63) [BCS.S <label>]
//BCS.L <label> |-|--2346|-|----*|-----| |0110_010_111_111_111-{offset}
//BLO.L <label> |A|--2346|-|----*|-----| |0110_010_111_111_111-{offset} [BCS.L <label>]
//BNCC.L <label> |A|--2346|-|----*|-----| |0110_010_111_111_111-{offset} [BCS.L <label>]
//BNHS.L <label> |A|--2346|-|----*|-----| |0110_010_111_111_111-{offset} [BCS.L <label>]
public static void irpBlosl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LO << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlosl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BNE.W <label> |-|012346|-|--*--|-----| |0110_011_000_000_000-{offset}
//BNEQ.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//BNZ.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//BNZE.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//JBNE.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//JBNEQ.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//JBNZ.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//JBNZE.W <label> |A|012346|-|--*--|-----| |0110_011_000_000_000-{offset} [BNE.W <label>]
//BNE.S <label> |-|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0)
//BNEQ.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//BNZ.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//BNZE.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//JBNE.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//JBNEQ.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//JBNZ.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//JBNZE.S <label> |A|012346|-|--*--|-----| |0110_011_000_sss_sss (s is not equal to 0) [BNE.S <label>]
//JBEQ.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
//JBNEQ.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
//JBNNE.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
//JBNNZ.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
//JBNZ.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
//JBNZE.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
//JBZE.L <label> |A|012346|-|--*--|-----| |0110_011_000_000_110-0100111011111001-{address} [BNE.S (*)+8;JMP <label>]
public static void irpBnesw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_NE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBnesw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BNE.S <label> |-|012346|-|--*--|-----| |0110_011_001_sss_sss
//BNEQ.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//BNZ.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//BNZE.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//JBNE.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//JBNEQ.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//JBNZ.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//JBNZE.S <label> |A|012346|-|--*--|-----| |0110_011_001_sss_sss [BNE.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BNE.S <label> |-|012346|-|--*--|-----| |0110_011_010_sss_sss
//BNEQ.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
//BNZ.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
//BNZE.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
//JBNE.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
//JBNEQ.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
//JBNZ.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
//JBNZE.S <label> |A|012346|-|--*--|-----| |0110_011_010_sss_sss [BNE.S <label>]
public static void irpBnes () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_NE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBnes
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BNE.S <label> |-|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63)
//BNEQ.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//BNZ.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//BNZE.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//JBNE.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//JBNEQ.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//JBNZ.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//JBNZE.S <label> |A|--2346|-|--*--|-----| |0110_011_011_sss_sss (s is not equal to 63) [BNE.S <label>]
//BNE.L <label> |-|--2346|-|--*--|-----| |0110_011_011_111_111-{offset}
//BNEQ.L <label> |A|--2346|-|--*--|-----| |0110_011_011_111_111-{offset} [BNE.L <label>]
//BNZ.L <label> |A|--2346|-|--*--|-----| |0110_011_011_111_111-{offset} [BNE.L <label>]
//BNZE.L <label> |A|--2346|-|--*--|-----| |0110_011_011_111_111-{offset} [BNE.L <label>]
public static void irpBnesl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_NE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBnesl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BEQ.W <label> |-|012346|-|--*--|-----| |0110_011_100_000_000-{offset}
//BNNE.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//BNNZ.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//BZE.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//JBEQ.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//JBNNE.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//JBNNZ.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//JBZE.W <label> |A|012346|-|--*--|-----| |0110_011_100_000_000-{offset} [BEQ.W <label>]
//BEQ.S <label> |-|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0)
//BNNE.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//BNNZ.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//BZE.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//JBEQ.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//JBNNE.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//JBNNZ.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//JBZE.S <label> |A|012346|-|--*--|-----| |0110_011_100_sss_sss (s is not equal to 0) [BEQ.S <label>]
//JBNE.L <label> |A|012346|-|--*--|-----| |0110_011_100_000_110-0100111011111001-{address} [BEQ.S (*)+8;JMP <label>]
public static void irpBeqsw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_EQ << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBeqsw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BEQ.S <label> |-|012346|-|--*--|-----| |0110_011_101_sss_sss
//BNNE.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//BNNZ.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//BZE.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//JBEQ.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//JBNNE.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//JBNNZ.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//JBZE.S <label> |A|012346|-|--*--|-----| |0110_011_101_sss_sss [BEQ.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BEQ.S <label> |-|012346|-|--*--|-----| |0110_011_110_sss_sss
//BNNE.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
//BNNZ.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
//BZE.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
//JBEQ.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
//JBNNE.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
//JBNNZ.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
//JBZE.S <label> |A|012346|-|--*--|-----| |0110_011_110_sss_sss [BEQ.S <label>]
public static void irpBeqs () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_EQ << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBeqs
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BEQ.S <label> |-|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63)
//BNNE.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//BNNZ.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//BZE.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//JBEQ.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//JBNNE.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//JBNNZ.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//JBZE.S <label> |A|--2346|-|--*--|-----| |0110_011_111_sss_sss (s is not equal to 63) [BEQ.S <label>]
//BEQ.L <label> |-|--2346|-|--*--|-----| |0110_011_111_111_111-{offset}
//BNNE.L <label> |A|--2346|-|--*--|-----| |0110_011_111_111_111-{offset} [BEQ.L <label>]
//BNNZ.L <label> |A|--2346|-|--*--|-----| |0110_011_111_111_111-{offset} [BEQ.L <label>]
//BZE.L <label> |A|--2346|-|--*--|-----| |0110_011_111_111_111-{offset} [BEQ.L <label>]
public static void irpBeqsl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_EQ << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBeqsl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVC.W <label> |-|012346|-|---*-|-----| |0110_100_000_000_000-{offset}
//BNVS.W <label> |A|012346|-|---*-|-----| |0110_100_000_000_000-{offset} [BVC.W <label>]
//JBNVS.W <label> |A|012346|-|---*-|-----| |0110_100_000_000_000-{offset} [BVC.W <label>]
//JBVC.W <label> |A|012346|-|---*-|-----| |0110_100_000_000_000-{offset} [BVC.W <label>]
//BVC.S <label> |-|012346|-|---*-|-----| |0110_100_000_sss_sss (s is not equal to 0)
//BNVS.S <label> |A|012346|-|---*-|-----| |0110_100_000_sss_sss (s is not equal to 0) [BVC.S <label>]
//JBNVS.S <label> |A|012346|-|---*-|-----| |0110_100_000_sss_sss (s is not equal to 0) [BVC.S <label>]
//JBVC.S <label> |A|012346|-|---*-|-----| |0110_100_000_sss_sss (s is not equal to 0) [BVC.S <label>]
//JBNVC.L <label> |A|012346|-|---*-|-----| |0110_100_000_000_110-0100111011111001-{address} [BVC.S (*)+8;JMP <label>]
//JBVS.L <label> |A|012346|-|---*-|-----| |0110_100_000_000_110-0100111011111001-{address} [BVC.S (*)+8;JMP <label>]
public static void irpBvcsw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VC << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBvcsw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVC.S <label> |-|012346|-|---*-|-----| |0110_100_001_sss_sss
//BNVS.S <label> |A|012346|-|---*-|-----| |0110_100_001_sss_sss [BVC.S <label>]
//JBNVS.S <label> |A|012346|-|---*-|-----| |0110_100_001_sss_sss [BVC.S <label>]
//JBVC.S <label> |A|012346|-|---*-|-----| |0110_100_001_sss_sss [BVC.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVC.S <label> |-|012346|-|---*-|-----| |0110_100_010_sss_sss
//BNVS.S <label> |A|012346|-|---*-|-----| |0110_100_010_sss_sss [BVC.S <label>]
//JBNVS.S <label> |A|012346|-|---*-|-----| |0110_100_010_sss_sss [BVC.S <label>]
//JBVC.S <label> |A|012346|-|---*-|-----| |0110_100_010_sss_sss [BVC.S <label>]
public static void irpBvcs () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VC << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBvcs
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVC.S <label> |-|--2346|-|---*-|-----| |0110_100_011_sss_sss (s is not equal to 63)
//BNVS.S <label> |A|--2346|-|---*-|-----| |0110_100_011_sss_sss (s is not equal to 63) [BVC.S <label>]
//JBNVS.S <label> |A|--2346|-|---*-|-----| |0110_100_011_sss_sss (s is not equal to 63) [BVC.S <label>]
//JBVC.S <label> |A|--2346|-|---*-|-----| |0110_100_011_sss_sss (s is not equal to 63) [BVC.S <label>]
//BVC.L <label> |-|--2346|-|---*-|-----| |0110_100_011_111_111-{offset}
//BNVS.L <label> |A|--2346|-|---*-|-----| |0110_100_011_111_111-{offset} [BVC.L <label>]
public static void irpBvcsl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VC << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBvcsl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVS.W <label> |-|012346|-|---*-|-----| |0110_100_100_000_000-{offset}
//BNVC.W <label> |A|012346|-|---*-|-----| |0110_100_100_000_000-{offset} [BVS.W <label>]
//JBNVC.W <label> |A|012346|-|---*-|-----| |0110_100_100_000_000-{offset} [BVS.W <label>]
//JBVS.W <label> |A|012346|-|---*-|-----| |0110_100_100_000_000-{offset} [BVS.W <label>]
//BVS.S <label> |-|012346|-|---*-|-----| |0110_100_100_sss_sss (s is not equal to 0)
//BNVC.S <label> |A|012346|-|---*-|-----| |0110_100_100_sss_sss (s is not equal to 0) [BVS.S <label>]
//JBNVC.S <label> |A|012346|-|---*-|-----| |0110_100_100_sss_sss (s is not equal to 0) [BVS.S <label>]
//JBVS.S <label> |A|012346|-|---*-|-----| |0110_100_100_sss_sss (s is not equal to 0) [BVS.S <label>]
//JBNVS.L <label> |A|012346|-|---*-|-----| |0110_100_100_000_110-0100111011111001-{address} [BVS.S (*)+8;JMP <label>]
//JBVC.L <label> |A|012346|-|---*-|-----| |0110_100_100_000_110-0100111011111001-{address} [BVS.S (*)+8;JMP <label>]
public static void irpBvssw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBvssw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVS.S <label> |-|012346|-|---*-|-----| |0110_100_101_sss_sss
//BNVC.S <label> |A|012346|-|---*-|-----| |0110_100_101_sss_sss [BVS.S <label>]
//JBNVC.S <label> |A|012346|-|---*-|-----| |0110_100_101_sss_sss [BVS.S <label>]
//JBVS.S <label> |A|012346|-|---*-|-----| |0110_100_101_sss_sss [BVS.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVS.S <label> |-|012346|-|---*-|-----| |0110_100_110_sss_sss
//BNVC.S <label> |A|012346|-|---*-|-----| |0110_100_110_sss_sss [BVS.S <label>]
//JBNVC.S <label> |A|012346|-|---*-|-----| |0110_100_110_sss_sss [BVS.S <label>]
//JBVS.S <label> |A|012346|-|---*-|-----| |0110_100_110_sss_sss [BVS.S <label>]
public static void irpBvss () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBvss
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BVS.S <label> |-|--2346|-|---*-|-----| |0110_100_111_sss_sss (s is not equal to 63)
//BNVC.S <label> |A|--2346|-|---*-|-----| |0110_100_111_sss_sss (s is not equal to 63) [BVS.S <label>]
//JBNVC.S <label> |A|--2346|-|---*-|-----| |0110_100_111_sss_sss (s is not equal to 63) [BVS.S <label>]
//JBVS.S <label> |A|--2346|-|---*-|-----| |0110_100_111_sss_sss (s is not equal to 63) [BVS.S <label>]
//BVS.L <label> |-|--2346|-|---*-|-----| |0110_100_111_111_111-{offset}
//BNVC.L <label> |A|--2346|-|---*-|-----| |0110_100_111_111_111-{offset} [BVS.L <label>]
public static void irpBvssl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_VS << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBvssl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BPL.W <label> |-|012346|-|-*---|-----| |0110_101_000_000_000-{offset}
//BNMI.W <label> |A|012346|-|-*---|-----| |0110_101_000_000_000-{offset} [BPL.W <label>]
//JBNMI.W <label> |A|012346|-|-*---|-----| |0110_101_000_000_000-{offset} [BPL.W <label>]
//JBPL.W <label> |A|012346|-|-*---|-----| |0110_101_000_000_000-{offset} [BPL.W <label>]
//BPL.S <label> |-|012346|-|-*---|-----| |0110_101_000_sss_sss (s is not equal to 0)
//BNMI.S <label> |A|012346|-|-*---|-----| |0110_101_000_sss_sss (s is not equal to 0) [BPL.S <label>]
//JBNMI.S <label> |A|012346|-|-*---|-----| |0110_101_000_sss_sss (s is not equal to 0) [BPL.S <label>]
//JBPL.S <label> |A|012346|-|-*---|-----| |0110_101_000_sss_sss (s is not equal to 0) [BPL.S <label>]
//JBMI.L <label> |A|012346|-|-*---|-----| |0110_101_000_000_110-0100111011111001-{address} [BPL.S (*)+8;JMP <label>]
//JBNPL.L <label> |A|012346|-|-*---|-----| |0110_101_000_000_110-0100111011111001-{address} [BPL.S (*)+8;JMP <label>]
public static void irpBplsw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_PL << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBplsw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BPL.S <label> |-|012346|-|-*---|-----| |0110_101_001_sss_sss
//BNMI.S <label> |A|012346|-|-*---|-----| |0110_101_001_sss_sss [BPL.S <label>]
//JBNMI.S <label> |A|012346|-|-*---|-----| |0110_101_001_sss_sss [BPL.S <label>]
//JBPL.S <label> |A|012346|-|-*---|-----| |0110_101_001_sss_sss [BPL.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BPL.S <label> |-|012346|-|-*---|-----| |0110_101_010_sss_sss
//BNMI.S <label> |A|012346|-|-*---|-----| |0110_101_010_sss_sss [BPL.S <label>]
//JBNMI.S <label> |A|012346|-|-*---|-----| |0110_101_010_sss_sss [BPL.S <label>]
//JBPL.S <label> |A|012346|-|-*---|-----| |0110_101_010_sss_sss [BPL.S <label>]
public static void irpBpls () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_PL << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBpls
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BPL.S <label> |-|--2346|-|-*---|-----| |0110_101_011_sss_sss (s is not equal to 63)
//BNMI.S <label> |A|--2346|-|-*---|-----| |0110_101_011_sss_sss (s is not equal to 63) [BPL.S <label>]
//JBNMI.S <label> |A|--2346|-|-*---|-----| |0110_101_011_sss_sss (s is not equal to 63) [BPL.S <label>]
//JBPL.S <label> |A|--2346|-|-*---|-----| |0110_101_011_sss_sss (s is not equal to 63) [BPL.S <label>]
//BPL.L <label> |-|--2346|-|-*---|-----| |0110_101_011_111_111-{offset}
//BNMI.L <label> |A|--2346|-|-*---|-----| |0110_101_011_111_111-{offset} [BPL.L <label>]
public static void irpBplsl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_PL << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBplsl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BMI.W <label> |-|012346|-|-*---|-----| |0110_101_100_000_000-{offset}
//BNPL.W <label> |A|012346|-|-*---|-----| |0110_101_100_000_000-{offset} [BMI.W <label>]
//JBMI.W <label> |A|012346|-|-*---|-----| |0110_101_100_000_000-{offset} [BMI.W <label>]
//JBNPL.W <label> |A|012346|-|-*---|-----| |0110_101_100_000_000-{offset} [BMI.W <label>]
//BMI.S <label> |-|012346|-|-*---|-----| |0110_101_100_sss_sss (s is not equal to 0)
//BNPL.S <label> |A|012346|-|-*---|-----| |0110_101_100_sss_sss (s is not equal to 0) [BMI.S <label>]
//JBMI.S <label> |A|012346|-|-*---|-----| |0110_101_100_sss_sss (s is not equal to 0) [BMI.S <label>]
//JBNPL.S <label> |A|012346|-|-*---|-----| |0110_101_100_sss_sss (s is not equal to 0) [BMI.S <label>]
//JBNMI.L <label> |A|012346|-|-*---|-----| |0110_101_100_000_110-0100111011111001-{address} [BMI.S (*)+8;JMP <label>]
//JBPL.L <label> |A|012346|-|-*---|-----| |0110_101_100_000_110-0100111011111001-{address} [BMI.S (*)+8;JMP <label>]
public static void irpBmisw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_MI << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBmisw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BMI.S <label> |-|012346|-|-*---|-----| |0110_101_101_sss_sss
//BNPL.S <label> |A|012346|-|-*---|-----| |0110_101_101_sss_sss [BMI.S <label>]
//JBMI.S <label> |A|012346|-|-*---|-----| |0110_101_101_sss_sss [BMI.S <label>]
//JBNPL.S <label> |A|012346|-|-*---|-----| |0110_101_101_sss_sss [BMI.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BMI.S <label> |-|012346|-|-*---|-----| |0110_101_110_sss_sss
//BNPL.S <label> |A|012346|-|-*---|-----| |0110_101_110_sss_sss [BMI.S <label>]
//JBMI.S <label> |A|012346|-|-*---|-----| |0110_101_110_sss_sss [BMI.S <label>]
//JBNPL.S <label> |A|012346|-|-*---|-----| |0110_101_110_sss_sss [BMI.S <label>]
public static void irpBmis () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_MI << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBmis
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BMI.S <label> |-|--2346|-|-*---|-----| |0110_101_111_sss_sss (s is not equal to 63)
//BNPL.S <label> |A|--2346|-|-*---|-----| |0110_101_111_sss_sss (s is not equal to 63) [BMI.S <label>]
//JBMI.S <label> |A|--2346|-|-*---|-----| |0110_101_111_sss_sss (s is not equal to 63) [BMI.S <label>]
//JBNPL.S <label> |A|--2346|-|-*---|-----| |0110_101_111_sss_sss (s is not equal to 63) [BMI.S <label>]
//BMI.L <label> |-|--2346|-|-*---|-----| |0110_101_111_111_111-{offset}
//BNPL.L <label> |A|--2346|-|-*---|-----| |0110_101_111_111_111-{offset} [BMI.L <label>]
public static void irpBmisl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_MI << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBmisl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGE.W <label> |-|012346|-|-*-*-|-----| |0110_110_000_000_000-{offset}
//BNLT.W <label> |A|012346|-|-*-*-|-----| |0110_110_000_000_000-{offset} [BGE.W <label>]
//JBGE.W <label> |A|012346|-|-*-*-|-----| |0110_110_000_000_000-{offset} [BGE.W <label>]
//JBNLT.W <label> |A|012346|-|-*-*-|-----| |0110_110_000_000_000-{offset} [BGE.W <label>]
//BGE.S <label> |-|012346|-|-*-*-|-----| |0110_110_000_sss_sss (s is not equal to 0)
//BNLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_000_sss_sss (s is not equal to 0) [BGE.S <label>]
//JBGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_000_sss_sss (s is not equal to 0) [BGE.S <label>]
//JBNLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_000_sss_sss (s is not equal to 0) [BGE.S <label>]
//JBLT.L <label> |A|012346|-|-*-*-|-----| |0110_110_000_000_110-0100111011111001-{address} [BGE.S (*)+8;JMP <label>]
//JBNGE.L <label> |A|012346|-|-*-*-|-----| |0110_110_000_000_110-0100111011111001-{address} [BGE.S (*)+8;JMP <label>]
public static void irpBgesw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBgesw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGE.S <label> |-|012346|-|-*-*-|-----| |0110_110_001_sss_sss
//BNLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_001_sss_sss [BGE.S <label>]
//JBGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_001_sss_sss [BGE.S <label>]
//JBNLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_001_sss_sss [BGE.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGE.S <label> |-|012346|-|-*-*-|-----| |0110_110_010_sss_sss
//BNLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_010_sss_sss [BGE.S <label>]
//JBGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_010_sss_sss [BGE.S <label>]
//JBNLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_010_sss_sss [BGE.S <label>]
public static void irpBges () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBges
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGE.S <label> |-|--2346|-|-*-*-|-----| |0110_110_011_sss_sss (s is not equal to 63)
//BNLT.S <label> |A|--2346|-|-*-*-|-----| |0110_110_011_sss_sss (s is not equal to 63) [BGE.S <label>]
//JBGE.S <label> |A|--2346|-|-*-*-|-----| |0110_110_011_sss_sss (s is not equal to 63) [BGE.S <label>]
//JBNLT.S <label> |A|--2346|-|-*-*-|-----| |0110_110_011_sss_sss (s is not equal to 63) [BGE.S <label>]
//BGE.L <label> |-|--2346|-|-*-*-|-----| |0110_110_011_111_111-{offset}
//BNLT.L <label> |A|--2346|-|-*-*-|-----| |0110_110_011_111_111-{offset} [BGE.L <label>]
public static void irpBgesl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBgesl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLT.W <label> |-|012346|-|-*-*-|-----| |0110_110_100_000_000-{offset}
//BNGE.W <label> |A|012346|-|-*-*-|-----| |0110_110_100_000_000-{offset} [BLT.W <label>]
//JBLT.W <label> |A|012346|-|-*-*-|-----| |0110_110_100_000_000-{offset} [BLT.W <label>]
//JBNGE.W <label> |A|012346|-|-*-*-|-----| |0110_110_100_000_000-{offset} [BLT.W <label>]
//BLT.S <label> |-|012346|-|-*-*-|-----| |0110_110_100_sss_sss (s is not equal to 0)
//BNGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_100_sss_sss (s is not equal to 0) [BLT.S <label>]
//JBLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_100_sss_sss (s is not equal to 0) [BLT.S <label>]
//JBNGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_100_sss_sss (s is not equal to 0) [BLT.S <label>]
//JBGE.L <label> |A|012346|-|-*-*-|-----| |0110_110_100_000_110-0100111011111001-{address} [BLT.S (*)+8;JMP <label>]
//JBNLT.L <label> |A|012346|-|-*-*-|-----| |0110_110_100_000_110-0100111011111001-{address} [BLT.S (*)+8;JMP <label>]
public static void irpBltsw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LT << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBltsw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLT.S <label> |-|012346|-|-*-*-|-----| |0110_110_101_sss_sss
//BNGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_101_sss_sss [BLT.S <label>]
//JBLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_101_sss_sss [BLT.S <label>]
//JBNGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_101_sss_sss [BLT.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLT.S <label> |-|012346|-|-*-*-|-----| |0110_110_110_sss_sss
//BNGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_110_sss_sss [BLT.S <label>]
//JBLT.S <label> |A|012346|-|-*-*-|-----| |0110_110_110_sss_sss [BLT.S <label>]
//JBNGE.S <label> |A|012346|-|-*-*-|-----| |0110_110_110_sss_sss [BLT.S <label>]
public static void irpBlts () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LT << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlts
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLT.S <label> |-|--2346|-|-*-*-|-----| |0110_110_111_sss_sss (s is not equal to 63)
//BNGE.S <label> |A|--2346|-|-*-*-|-----| |0110_110_111_sss_sss (s is not equal to 63) [BLT.S <label>]
//JBLT.S <label> |A|--2346|-|-*-*-|-----| |0110_110_111_sss_sss (s is not equal to 63) [BLT.S <label>]
//JBNGE.S <label> |A|--2346|-|-*-*-|-----| |0110_110_111_sss_sss (s is not equal to 63) [BLT.S <label>]
//BLT.L <label> |-|--2346|-|-*-*-|-----| |0110_110_111_111_111-{offset}
//BNGE.L <label> |A|--2346|-|-*-*-|-----| |0110_110_111_111_111-{offset} [BLT.L <label>]
public static void irpBltsl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LT << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBltsl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGT.W <label> |-|012346|-|-***-|-----| |0110_111_000_000_000-{offset}
//BNLE.W <label> |A|012346|-|-***-|-----| |0110_111_000_000_000-{offset} [BGT.W <label>]
//JBGT.W <label> |A|012346|-|-***-|-----| |0110_111_000_000_000-{offset} [BGT.W <label>]
//JBNLE.W <label> |A|012346|-|-***-|-----| |0110_111_000_000_000-{offset} [BGT.W <label>]
//BGT.S <label> |-|012346|-|-***-|-----| |0110_111_000_sss_sss (s is not equal to 0)
//BNLE.S <label> |A|012346|-|-***-|-----| |0110_111_000_sss_sss (s is not equal to 0) [BGT.S <label>]
//JBGT.S <label> |A|012346|-|-***-|-----| |0110_111_000_sss_sss (s is not equal to 0) [BGT.S <label>]
//JBNLE.S <label> |A|012346|-|-***-|-----| |0110_111_000_sss_sss (s is not equal to 0) [BGT.S <label>]
//JBLE.L <label> |A|012346|-|-***-|-----| |0110_111_000_000_110-0100111011111001-{address} [BGT.S (*)+8;JMP <label>]
//JBNGT.L <label> |A|012346|-|-***-|-----| |0110_111_000_000_110-0100111011111001-{address} [BGT.S (*)+8;JMP <label>]
public static void irpBgtsw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GT << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBgtsw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGT.S <label> |-|012346|-|-***-|-----| |0110_111_001_sss_sss
//BNLE.S <label> |A|012346|-|-***-|-----| |0110_111_001_sss_sss [BGT.S <label>]
//JBGT.S <label> |A|012346|-|-***-|-----| |0110_111_001_sss_sss [BGT.S <label>]
//JBNLE.S <label> |A|012346|-|-***-|-----| |0110_111_001_sss_sss [BGT.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGT.S <label> |-|012346|-|-***-|-----| |0110_111_010_sss_sss
//BNLE.S <label> |A|012346|-|-***-|-----| |0110_111_010_sss_sss [BGT.S <label>]
//JBGT.S <label> |A|012346|-|-***-|-----| |0110_111_010_sss_sss [BGT.S <label>]
//JBNLE.S <label> |A|012346|-|-***-|-----| |0110_111_010_sss_sss [BGT.S <label>]
public static void irpBgts () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GT << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBgts
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BGT.S <label> |-|--2346|-|-***-|-----| |0110_111_011_sss_sss (s is not equal to 63)
//BNLE.S <label> |A|--2346|-|-***-|-----| |0110_111_011_sss_sss (s is not equal to 63) [BGT.S <label>]
//JBGT.S <label> |A|--2346|-|-***-|-----| |0110_111_011_sss_sss (s is not equal to 63) [BGT.S <label>]
//JBNLE.S <label> |A|--2346|-|-***-|-----| |0110_111_011_sss_sss (s is not equal to 63) [BGT.S <label>]
//BGT.L <label> |-|--2346|-|-***-|-----| |0110_111_011_111_111-{offset}
//BNLE.L <label> |A|--2346|-|-***-|-----| |0110_111_011_111_111-{offset} [BGT.L <label>]
public static void irpBgtsl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_GT << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBgtsl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLE.W <label> |-|012346|-|-***-|-----| |0110_111_100_000_000-{offset}
//BNGT.W <label> |A|012346|-|-***-|-----| |0110_111_100_000_000-{offset} [BLE.W <label>]
//JBLE.W <label> |A|012346|-|-***-|-----| |0110_111_100_000_000-{offset} [BLE.W <label>]
//JBNGT.W <label> |A|012346|-|-***-|-----| |0110_111_100_000_000-{offset} [BLE.W <label>]
//BLE.S <label> |-|012346|-|-***-|-----| |0110_111_100_sss_sss (s is not equal to 0)
//BNGT.S <label> |A|012346|-|-***-|-----| |0110_111_100_sss_sss (s is not equal to 0) [BLE.S <label>]
//JBLE.S <label> |A|012346|-|-***-|-----| |0110_111_100_sss_sss (s is not equal to 0) [BLE.S <label>]
//JBNGT.S <label> |A|012346|-|-***-|-----| |0110_111_100_sss_sss (s is not equal to 0) [BLE.S <label>]
//JBGT.L <label> |A|012346|-|-***-|-----| |0110_111_100_000_110-0100111011111001-{address} [BLE.S (*)+8;JMP <label>]
//JBNLE.L <label> |A|012346|-|-***-|-----| |0110_111_100_000_110-0100111011111001-{address} [BLE.S (*)+8;JMP <label>]
public static void irpBlesw () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == 0) { //Bcc.W
XEiJ.regPC = t + 2; //pc0+4
s = mmuReadWordSignExword (t, XEiJ.regSRS); //16bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlesw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLE.S <label> |-|012346|-|-***-|-----| |0110_111_101_sss_sss
//BNGT.S <label> |A|012346|-|-***-|-----| |0110_111_101_sss_sss [BLE.S <label>]
//JBLE.S <label> |A|012346|-|-***-|-----| |0110_111_101_sss_sss [BLE.S <label>]
//JBNGT.S <label> |A|012346|-|-***-|-----| |0110_111_101_sss_sss [BLE.S <label>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLE.S <label> |-|012346|-|-***-|-----| |0110_111_110_sss_sss
//BNGT.S <label> |A|012346|-|-***-|-----| |0110_111_110_sss_sss [BLE.S <label>]
//JBLE.S <label> |A|012346|-|-***-|-----| |0110_111_110_sss_sss [BLE.S <label>]
//JBNGT.S <label> |A|012346|-|-***-|-----| |0110_111_110_sss_sss [BLE.S <label>]
public static void irpBles () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBles
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BLE.S <label> |-|--2346|-|-***-|-----| |0110_111_111_sss_sss (s is not equal to 63)
//BNGT.S <label> |A|--2346|-|-***-|-----| |0110_111_111_sss_sss (s is not equal to 63) [BLE.S <label>]
//JBLE.S <label> |A|--2346|-|-***-|-----| |0110_111_111_sss_sss (s is not equal to 63) [BLE.S <label>]
//JBNGT.S <label> |A|--2346|-|-***-|-----| |0110_111_111_sss_sss (s is not equal to 63) [BLE.S <label>]
//BLE.L <label> |-|--2346|-|-***-|-----| |0110_111_111_111_111-{offset}
//BNGT.L <label> |A|--2346|-|-***-|-----| |0110_111_111_111_111-{offset} [BLE.L <label>]
public static void irpBlesl () throws M68kException {
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
int s = (byte) XEiJ.regOC; //8bitディスプレースメント
if (s == -1) { //Bcc.L
XEiJ.regPC = t + 4; //pc0+6
s = mmuReadLongExword (t, XEiJ.regSRS); //32bitディスプレースメント
}
t += s; //pc0+2+ディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.MPU_CC_LE << XEiJ.regCCR < 0) { //分岐する
irpSetPC (t);
}
} //irpBlesl
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//IOCS <name> |A|012346|-|UUUUU|UUUUU| |0111_000_0dd_ddd_ddd-0100111001001111 [MOVEQ.L #<data>,D0;TRAP #15]
//MOVEQ.L #<data>,Dq |-|012346|-|-UUUU|-**00| |0111_qqq_0dd_ddd_ddd
public static void irpMoveq () throws M68kException {
XEiJ.mpuCycleCount++;
int z;
XEiJ.regRn[XEiJ.regOC >> 9 & 7] = z = (byte) XEiJ.regOC;
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpMoveq
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MVS.B <ea>,Dq |-|------|-|-UUUU|-**00|D M+-WXZPI|0111_qqq_100_mmm_rrr (ISA_B)
//
//MVS.B <ea>,Dq
// バイトデータをロングに符号拡張してDqの全体を更新する
public static void irpMvsByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z;
XEiJ.regRn[XEiJ.regOC >> 9 & 7] = z = ea < XEiJ.EA_AR ? (byte) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteSignData (efaAnyByte (ea), XEiJ.regSRS); //pcbs。イミディエイトを分離
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpMvsByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MVS.W <ea>,Dq |-|------|-|-UUUU|-**00|D M+-WXZPI|0111_qqq_101_mmm_rrr (ISA_B)
//
//MVS.W <ea>,Dq
// ワードデータをロングに符号拡張してDqの全体を更新する
public static void irpMvsWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z;
XEiJ.regRn[XEiJ.regOC >> 9 & 7] = z = ea < XEiJ.EA_AR ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //pcws。イミディエイトを分離
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpMvsWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MVZ.B <ea>,Dq |-|------|-|-UUUU|-0*00|D M+-WXZPI|0111_qqq_110_mmm_rrr (ISA_B)
//
//MVZ.B <ea>,Dq
// バイトデータをロングにゼロ拡張してDqの全体を更新する
public static void irpMvzByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z;
XEiJ.regRn[XEiJ.regOC >> 9 & 7] = z = ea < XEiJ.EA_AR ? 0xff & XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteZeroExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteZeroData (efaAnyByte (ea), XEiJ.regSRS); //pcbz。イミディエイトを分離
XEiJ.regCCR = XEiJ.REG_CCR_X & XEiJ.regCCR | (z == 0 ? XEiJ.REG_CCR_Z : 0);
} //irpMvzByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MVZ.W <ea>,Dq |-|------|-|-UUUU|-0*00|D M+-WXZPI|0111_qqq_111_mmm_rrr (ISA_B)
//
//MVZ.W <ea>,Dq
// ワードデータをロングにゼロ拡張してDqの全体を更新する
public static void irpMvzWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z;
XEiJ.regRn[XEiJ.regOC >> 9 & 7] = z = ea < XEiJ.EA_AR ? (char) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordZeroData (efaAnyWord (ea), XEiJ.regSRS); //pcwz。イミディエイトを分離
XEiJ.regCCR = XEiJ.REG_CCR_X & XEiJ.regCCR | (z == 0 ? XEiJ.REG_CCR_Z : 0);
} //irpMvzWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//OR.B <ea>,Dq |-|012346|-|-UUUU|-**00|D M+-WXZPI|1000_qqq_000_mmm_rrr
public static void irpOrToRegByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.MPU_TSTB_TABLE[255 & (XEiJ.regRn[XEiJ.regOC >> 9 & 7] |= 255 & (ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteSignData (efaAnyByte (ea), XEiJ.regSRS)))]; //ccr_tst_byte。pcbs。イミディエイトを分離。0拡張してからOR
} //irpOrToRegByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//OR.W <ea>,Dq |-|012346|-|-UUUU|-**00|D M+-WXZPI|1000_qqq_001_mmm_rrr
public static void irpOrToRegWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z = (short) (XEiJ.regRn[XEiJ.regOC >> 9 & 7] |= ea < XEiJ.EA_AR ? (char) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordZeroData (efaAnyWord (ea), XEiJ.regSRS)); //pcwz。イミディエイトを分離。0拡張してからOR
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpOrToRegWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//OR.L <ea>,Dq |-|012346|-|-UUUU|-**00|D M+-WXZPI|1000_qqq_010_mmm_rrr
public static void irpOrToRegLong () throws M68kException {
int ea = XEiJ.regOC & 63;
int z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] |= ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //pcls。イミディエイトを分離
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpOrToRegLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//DIVU.W <ea>,Dq |-|012346|-|-UUUU|-***0|D M+-WXZPI|1000_qqq_011_mmm_rrr
//
//DIVU.W <ea>,Dq
// M68000PRMでDIVU.Wのオーバーフローの条件が16bit符号あり整数と書かれているのは16bit符号なし整数の間違い
public static void irpDivuWord () throws M68kException {
// X 変化しない
// N ゼロ除算またはオーバーフローのとき不定。商が負のときセット。それ以外はクリア
// Z ゼロ除算またはオーバーフローのとき不定。商が0のときセット。それ以外はクリア
// V ゼロ除算のとき不定。オーバーフローのときセット。それ以外はクリア
// C 常にクリア
XEiJ.mpuCycleCount += 22; //最大
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int y = ea < XEiJ.EA_AR ? (char) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordZeroData (efaAnyWord (ea), XEiJ.regSRS); //除数。pcwz。イミディエイトを分離
int x = XEiJ.regRn[qqq]; //被除数
if (y == 0) { //ゼロ除算
//Dqは変化しない
XEiJ.regCCR = (XEiJ.regCCR & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_N | XEiJ.REG_CCR_Z | XEiJ.REG_CCR_V) //XとNとZとVは変化しない
); //Cは常にクリア
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_DIVIDE_BY_ZERO;
throw M68kException.m6eSignal;
}
//無理にintで符号なし除算をやろうとするよりもdoubleにキャストしてから割ったほうが速い
// intの除算をdoubleの除算器で行うプロセッサならばなおさら
//被除数を符号なし32ビットとみなすためlongを経由してdoubleに変換する
//doubleからlongやintへのキャストは小数点以下が切り捨てられ、オーバーフローは表現できる絶対値最大の値になる
//doubleから直接intに戻しているので0xffffffff/0x0001=0xffffffffが絶対値最大の0x7fffffffになってしまうが、
//DIVU.Wではオーバーフローになることに変わりはないのでよいことにする
// 符号なし32ビットの0xffffffffにしたいときは戻すときもlongを経由すればよい
int z = (int) ((double) ((long) x & 0xffffffffL) / (double) y); //商
if (z >>> 16 != 0) { //オーバーフローあり
//Dqは変化しない
XEiJ.regCCR = (XEiJ.regCCR & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_N | XEiJ.REG_CCR_Z) | //XとNとZは変化しない
XEiJ.REG_CCR_V //Vは常にセット
); //Cは常にクリア
} else { //オーバーフローなし
XEiJ.regRn[qqq] = x - y * z << 16 | z; //余り<<16|商
z = (short) z;
XEiJ.regCCR = (XEiJ.regCCR & XEiJ.REG_CCR_X | //Xは変化しない
(z < 0 ? XEiJ.REG_CCR_N : 0) | //Nは商が負のときセット、さもなくばクリア
(z == 0 ? XEiJ.REG_CCR_Z : 0) //Zは商が0のときセット、さもなくばクリア
//Vは常にクリア
); //Cは常にクリア
} //if オーバーフローあり/オーバーフローなし
} //irpDivuWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SBCD.B Dr,Dq |-|012346|-|UUUUU|*U*U*| |1000_qqq_100_000_rrr
//SBCD.B -(Ar),-(Aq) |-|012346|-|UUUUU|*U*U*| |1000_qqq_100_001_rrr
//OR.B Dq,<ea> |-|012346|-|-UUUU|-**00| M+-WXZ |1000_qqq_100_mmm_rrr
public static void irpOrToMemByte () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >= XEiJ.EA_MM) { //OR.B Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltByte (ea);
int z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] | mmuReadByteSignData (a, XEiJ.regSRS);
mmuWriteByteData (a, z, XEiJ.regSRS);
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.MPU_TSTB_TABLE[255 & z]; //ccr_tst_byte
} else if (ea < XEiJ.EA_AR) { //SBCD.B Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
int x;
XEiJ.regRn[qqq] = ~0xff & (x = XEiJ.regRn[qqq]) | irpSbcd (x, XEiJ.regRn[ea]);
} else { //SBCD.B -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 1L << (ea << 3);
int a = m60Address = --XEiJ.regRn[ea]; //このr[ea]はアドレスレジスタ
int y = mmuReadByteZeroData (a, XEiJ.regSRS);
int aqq = (XEiJ.regOC >> 9) - (64 - 8);
m60Incremented -= 1L << (aqq << 3);
a = m60Address = --XEiJ.regRn[aqq];
mmuWriteByteData (a, irpSbcd (mmuModifyByteZeroData (a, XEiJ.regSRS), y), XEiJ.regSRS);
}
} //irpOrToMemByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//PACK Dr,Dq,#<data> |-|--2346|-|-----|-----| |1000_qqq_101_000_rrr-{data}
//PACK -(Ar),-(Aq),#<data> |-|--2346|-|-----|-----| |1000_qqq_101_001_rrr-{data}
//OR.W Dq,<ea> |-|012346|-|-UUUU|-**00| M+-WXZ |1000_qqq_101_mmm_rrr
//
//PACK Dr,Dq,#<data>
//PACK -(Ar),-(Aq),#<data>
// PACK/UNPKは第1オペランドのソースと第2オペランドのデスティネーションのサイズが違う。パックされていない方がワードでされている方がバイト
// 10の位を4ビット右または左にシフトする。第3オペランドの補正値はワードでパックされていない方に加算する。CCRは変化しない
public static void irpOrToMemWord () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >= XEiJ.EA_MM) { //OR.W Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltWord (ea);
int z;
mmuWriteWordData (a, z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] | mmuModifyWordSignData (a, XEiJ.regSRS), XEiJ.regSRS);
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (char) z - 1 >> 31 & XEiJ.REG_CCR_Z | ((short) z < 0 ? XEiJ.REG_CCR_N : 0); //ccr_tst_word
} else if (ea < XEiJ.EA_AR) { //PACK Dr,Dq,#<data>
XEiJ.mpuCycleCount += 2;
int qqq = XEiJ.regOC >> 9 & 7;
int t = XEiJ.regRn[ea] + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcws
XEiJ.regRn[qqq] = ~0xff & XEiJ.regRn[qqq] | t >> 4 & 0xf0 | t & 15;
} else { //PACK -(Ar),-(Aq),#<data>
int o = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcws
m60Incremented -= 2L << (ea << 3);
int a = m60Address = XEiJ.regRn[ea] -= 2;
int t = mmuReadWordSignData (a, XEiJ.regSRS) + o; //020以上なのでアドレスエラーは出ない
int aqq = (XEiJ.regOC >> 9) - (64 - 8);
m60Incremented -= 1L << (aqq << 3);
a = m60Address = --XEiJ.regRn[aqq];
mmuWriteByteData (a, t >> 4 & 0xf0 | t & 15, XEiJ.regSRS);
}
} //irpOrToMemWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//UNPK Dr,Dq,#<data> |-|--2346|-|-----|-----| |1000_qqq_110_000_rrr-{data}
//UNPK -(Ar),-(Aq),#<data> |-|--2346|-|-----|-----| |1000_qqq_110_001_rrr-{data}
//OR.L Dq,<ea> |-|012346|-|-UUUU|-**00| M+-WXZ |1000_qqq_110_mmm_rrr
//
//UNPK Dr,Dq,#<data>
//UNPK -(Ar),-(Aq),#<data>
// PACK/UNPKは第1オペランドのソースと第2オペランドのデスティネーションのサイズが違う。パックされていない方がワードでされている方がバイト
// 10の位を4ビット右または左にシフトする。第3オペランドの補正値はワードでパックされていない方に加算する。CCRは変化しない
public static void irpOrToMemLong () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >= XEiJ.EA_MM) { //OR.L Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltLong (ea);
int z;
mmuWriteLongData (a, z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] | mmuModifyLongData (a, XEiJ.regSRS), XEiJ.regSRS);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} else if (ea < XEiJ.EA_AR) { //UNPK Dr,Dq,#<data>
int qqq = XEiJ.regOC >> 9 & 7;
int t = XEiJ.regRn[ea];
XEiJ.regRn[qqq] = ~0xffff & XEiJ.regRn[qqq] | (char) ((t << 4 & 0x0f00 | t & 15) + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS)); //pcws
} else { //UNPK -(Ar),-(Aq),#<data>
int o = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcws
m60Incremented -= 1L << (ea << 3);
int a = m60Address = --XEiJ.regRn[ea];
int t = mmuReadByteSignData (a, XEiJ.regSRS);
int aqq = (XEiJ.regOC >> 9) - (64 - 8);
m60Incremented -= 2L << (aqq << 3);
a = m60Address = XEiJ.regRn[aqq] -= 2;
mmuWriteWordData (a, (t << 4 & 0x0f00 | t & 15) + o, XEiJ.regSRS); //020以上なのでアドレスエラーは出ない
}
} //irpOrToMemLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//DIVS.W <ea>,Dq |-|012346|-|-UUUU|-***0|D M+-WXZPI|1000_qqq_111_mmm_rrr
//
//DIVS.W <ea>,Dq
// DIVSの余りの符号は被除数と一致
// M68000PRMでDIVS.Wのアドレッシングモードがデータ可変と書かれているのはデータの間違い
public static void irpDivsWord () throws M68kException {
// X 変化しない
// N ゼロ除算またはオーバーフローのとき不定。商が負のときセット。それ以外はクリア
// Z ゼロ除算またはオーバーフローのとき不定。商が0のときセット。それ以外はクリア
// V ゼロ除算のとき不定。オーバーフローのときセット。それ以外はクリア
// C 常にクリア
//divsの余りの符号は被除数と一致
//Javaの除算演算子の挙動
// 10 / 3 == 3 10 % 3 == 1 10 = 3 * 3 + 1
// 10 / -3 == -3 10 % -3 == 1 10 = -3 * -3 + 1
// -10 / 3 == -3 -10 % 3 == -1 -10 = 3 * -3 + -1
// -10 / -3 == 3 -10 % -3 == -1 -10 = -3 * 3 + -1
XEiJ.mpuCycleCount += 22; //最大
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int y = ea < XEiJ.EA_AR ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //除数。pcws。イミディエイトを分離
int x = XEiJ.regRn[qqq]; //被除数
if (y == 0) { //ゼロ除算
//Dqは変化しない
XEiJ.regCCR = (XEiJ.regCCR & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_N | XEiJ.REG_CCR_Z | XEiJ.REG_CCR_V) //XとNとZとVは変化しない
); //Cは常にクリア
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_DIVIDE_BY_ZERO;
throw M68kException.m6eSignal;
}
int z = x / y; //商
if ((short) z != z) { //オーバーフローあり
//Dqは変化しない
XEiJ.regCCR = (XEiJ.regCCR & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_N | XEiJ.REG_CCR_Z) | //XとNとZは変化しない
XEiJ.REG_CCR_V //Vは常にセット
); //Cは常にクリア
} else { //オーバーフローなし
XEiJ.regRn[qqq] = x - y * z << 16 | (char) z; //Dqは余り<<16|商&$ffff
XEiJ.regCCR = (XEiJ.regCCR & XEiJ.REG_CCR_X | //Xは変化しない
(z < 0 ? XEiJ.REG_CCR_N : 0) | //Nは商が負のときセット、さもなくばクリア
(z == 0 ? XEiJ.REG_CCR_Z : 0) //Zは商が0のときセット、さもなくばクリア
//Vは常にクリア
); //Cは常にクリア
}
} //irpDivsWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUB.B <ea>,Dq |-|012346|-|UUUUU|*****|D M+-WXZPI|1001_qqq_000_mmm_rrr
public static void irpSubToRegByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int x, y, z;
y = ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteSignData (efaAnyByte (ea), XEiJ.regSRS); //pcbs。イミディエイトを分離
x = XEiJ.regRn[qqq];
z = x - y;
XEiJ.regRn[qqq] = ~255 & x | 255 & z;
XEiJ.regCCR = (XEiJ.MPU_TSTB_TABLE[255 & z] |
((x ^ y) & (x ^ z)) >> 6 & XEiJ.REG_CCR_V |
(byte) (x & (y ^ z) ^ (y | z)) >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_sub_byte
} //irpSubToRegByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUB.W <ea>,Dq |-|012346|-|UUUUU|*****|DAM+-WXZPI|1001_qqq_001_mmm_rrr
public static void irpSubToRegWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int x, y, z;
y = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcws。イミディエイトを分離
x = XEiJ.regRn[qqq];
z = x - y;
XEiJ.regRn[qqq] = ~65535 & x | (char) z;
XEiJ.regCCR = (z >> 12 & XEiJ.REG_CCR_N | (char) z - 1 >> 14 & XEiJ.REG_CCR_Z |
((x ^ y) & (x ^ z)) >> 14 & XEiJ.REG_CCR_V |
(short) (x & (y ^ z) ^ (y | z)) >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_sub_word
} //irpSubToRegWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUB.L <ea>,Dq |-|012346|-|UUUUU|*****|DAM+-WXZPI|1001_qqq_010_mmm_rrr
public static void irpSubToRegLong () throws M68kException {
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
int x, y, z;
y = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcls。イミディエイトを分離
x = XEiJ.regRn[qqq];
z = x - y;
XEiJ.regRn[qqq] = z;
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) |
((x ^ y) & (x ^ z)) >> 30 & XEiJ.REG_CCR_V |
(x & (y ^ z) ^ (y | z)) >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_sub
} //irpSubToRegLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUBA.W <ea>,Aq |-|012346|-|-----|-----|DAM+-WXZPI|1001_qqq_011_mmm_rrr
//SUB.W <ea>,Aq |A|012346|-|-----|-----|DAM+-WXZPI|1001_qqq_011_mmm_rrr [SUBA.W <ea>,Aq]
//CLR.W Ar |A|012346|-|-----|-----| A |1001_rrr_011_001_rrr [SUBA.W Ar,Ar]
//
//SUBA.W <ea>,Aq
// ソースを符号拡張してロングで減算する
public static void irpSubaWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
//ADDA/CMPA/SUBA.wl <ea>,Aqで<ea>が(Ar)+,-(Ar)でAr==Aqのとき1サイクル追加
if (XEiJ.EA_MP <= ea && ea < XEiJ.EA_MW &&
(ea & 7) == ((XEiJ.regOC >> 9) & 7)) {
XEiJ.mpuCycleCount++;
}
int z = ea < XEiJ.EA_MM ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcws。イミディエイトを分離。ここでAqが変化する可能性があることに注意
XEiJ.regRn[XEiJ.regOC >> 9 & 15] -= z; //r[op >> 9 & 15] -= ea < XEiJ.EA_MM ? (short) r[ea] : rws (efaAnyWord (ea));は不可
//ccrは変化しない
} //irpSubaWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUBX.B Dr,Dq |-|012346|-|*UUUU|*****| |1001_qqq_100_000_rrr
//SUBX.B -(Ar),-(Aq) |-|012346|-|*UUUU|*****| |1001_qqq_100_001_rrr
//SUB.B Dq,<ea> |-|012346|-|UUUUU|*****| M+-WXZ |1001_qqq_100_mmm_rrr
public static void irpSubToMemByte () throws M68kException {
int ea = XEiJ.regOC & 63;
int a, x, y, z;
if (ea < XEiJ.EA_MM) {
if (ea < XEiJ.EA_AR) { //SUBX.B Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
y = XEiJ.regRn[ea];
x = XEiJ.regRn[qqq];
z = x - y - (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
XEiJ.regRn[qqq] = ~255 & x | 255 & z;
} else { //SUBX.B -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 1L << (ea << 3);
a = m60Address = --XEiJ.regRn[ea];
y = mmuReadByteSignData (a, XEiJ.regSRS); //このr[ea]はアドレスレジスタ
int aqq = XEiJ.regOC >> 9 & 15; //1qqq=aqq
m60Incremented -= 1L << (aqq << 3);
a = m60Address = --XEiJ.regRn[aqq];
x = mmuModifyByteSignData (a, XEiJ.regSRS);
z = x - y - (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
mmuWriteByteData (a, z, XEiJ.regSRS);
}
XEiJ.regCCR = (z >> 4 & XEiJ.REG_CCR_N | (255 & z) - 1 >> 6 & XEiJ.regCCR & XEiJ.REG_CCR_Z | //SUBXはZをクリアすることはあるがセットすることはない
((x ^ y) & (x ^ z)) >> 6 & XEiJ.REG_CCR_V |
(byte) (x & (y ^ z) ^ (y | z)) >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_subx_byte
} else { //SUB.B Dq,<ea>
XEiJ.mpuCycleCount++;
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7];
a = efaMltByte (ea);
x = mmuModifyByteSignData (a, XEiJ.regSRS);
z = x - y;
mmuWriteByteData (a, z, XEiJ.regSRS);
XEiJ.regCCR = (XEiJ.MPU_TSTB_TABLE[255 & z] |
((x ^ y) & (x ^ z)) >> 6 & XEiJ.REG_CCR_V |
(byte) (x & (y ^ z) ^ (y | z)) >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_sub_byte
}
} //irpSubToMemByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUBX.W Dr,Dq |-|012346|-|*UUUU|*****| |1001_qqq_101_000_rrr
//SUBX.W -(Ar),-(Aq) |-|012346|-|*UUUU|*****| |1001_qqq_101_001_rrr
//SUB.W Dq,<ea> |-|012346|-|UUUUU|*****| M+-WXZ |1001_qqq_101_mmm_rrr
public static void irpSubToMemWord () throws M68kException {
int ea = XEiJ.regOC & 63;
int a, x, y, z;
if (ea < XEiJ.EA_MM) {
if (ea < XEiJ.EA_AR) { //SUBX.W Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
y = XEiJ.regRn[ea];
x = XEiJ.regRn[qqq];
z = x - y - (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
XEiJ.regRn[qqq] = ~65535 & x | (char) z;
} else { //SUBX.W -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 2L << (ea << 3);
a = m60Address = XEiJ.regRn[ea] -= 2;
y = mmuReadWordSignData (a, XEiJ.regSRS); //このr[ea]はアドレスレジスタ
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented -= 2L << (aqq << 3);
a = m60Address = XEiJ.regRn[aqq] -= 2;
x = mmuModifyWordSignData (a, XEiJ.regSRS);
z = x - y - (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
mmuWriteWordData (a, z, XEiJ.regSRS);
}
XEiJ.regCCR = (z >> 12 & XEiJ.REG_CCR_N | (char) z - 1 >> 14 & XEiJ.regCCR & XEiJ.REG_CCR_Z | //ADDXはZをクリアすることはあるがセットすることはない
((x ^ y) & (x ^ z)) >> 14 & XEiJ.REG_CCR_V |
(short) (x & (y ^ z) ^ (y | z)) >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_subx_word
} else { //SUB.W Dq,<ea>
XEiJ.mpuCycleCount++;
y = (short) XEiJ.regRn[XEiJ.regOC >> 9 & 7];
a = efaMltWord (ea);
x = mmuModifyWordSignData (a, XEiJ.regSRS);
z = x - y;
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = (z >> 12 & XEiJ.REG_CCR_N | (char) z - 1 >> 14 & XEiJ.REG_CCR_Z |
((x ^ y) & (x ^ z)) >> 14 & XEiJ.REG_CCR_V |
(short) (x & (y ^ z) ^ (y | z)) >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_sub_word
}
} //irpSubToMemWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUBX.L Dr,Dq |-|012346|-|*UUUU|*****| |1001_qqq_110_000_rrr
//SUBX.L -(Ar),-(Aq) |-|012346|-|*UUUU|*****| |1001_qqq_110_001_rrr
//SUB.L Dq,<ea> |-|012346|-|UUUUU|*****| M+-WXZ |1001_qqq_110_mmm_rrr
public static void irpSubToMemLong () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea < XEiJ.EA_MM) {
int x;
int y;
int z;
if (ea < XEiJ.EA_AR) { //SUBX.L Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
XEiJ.regRn[qqq] = z = (x = XEiJ.regRn[qqq]) - (y = XEiJ.regRn[ea]) - (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
} else { //SUBX.L -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 4L << (ea << 3);
int a = m60Address = XEiJ.regRn[ea] -= 4; //このr[ea]はアドレスレジスタ
y = mmuReadLongData (a, XEiJ.regSRS);
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented -= 4L << (aqq << 3);
a = m60Address = XEiJ.regRn[aqq] -= 4;
mmuWriteLongData (a, z = (x = mmuModifyLongData (a, XEiJ.regSRS)) - y - (XEiJ.regCCR >> 4), XEiJ.regSRS); //Xの左側はすべて0なのでCCR_X&を省略
}
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_Z : 0) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_subx
} else { //SUB.L Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltLong (ea);
int x;
int y;
int z;
mmuWriteLongData (a, z = (x = mmuModifyLongData (a, XEiJ.regSRS)) - (y = XEiJ.regRn[XEiJ.regOC >> 9 & 7]), XEiJ.regSRS);
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_sub
}
} //irpSubToMemLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SUBA.L <ea>,Aq |-|012346|-|-----|-----|DAM+-WXZPI|1001_qqq_111_mmm_rrr
//SUB.L <ea>,Aq |A|012346|-|-----|-----|DAM+-WXZPI|1001_qqq_111_mmm_rrr [SUBA.L <ea>,Aq]
//CLR.L Ar |A|012346|-|-----|-----| A |1001_rrr_111_001_rrr [SUBA.L Ar,Ar]
public static void irpSubaLong () throws M68kException {
int ea = XEiJ.regOC & 63;
XEiJ.mpuCycleCount++;
//ADDA/CMPA/SUBA.wl <ea>,Aqで<ea>が(Ar)+,-(Ar)でAr==Aqのとき1サイクル追加
if (XEiJ.EA_MP <= ea && ea < XEiJ.EA_MW &&
(ea & 7) == ((XEiJ.regOC >> 9) & 7)) {
XEiJ.mpuCycleCount++;
}
int z = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcls。イミディエイトを分離。ここでAqが変化する可能性があることに注意
XEiJ.regRn[XEiJ.regOC >> 9 & 15] -= z; //r[op >> 9 & 15] -= ea < XEiJ.EA_MM ? r[ea] : rls (efaAnyLong (ea));は不可
//ccrは変化しない
} //irpSubaLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//SXCALL <name> |A|012346|-|UUUUU|*****| |1010_0dd_ddd_ddd_ddd [ALINE #<data>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ALINE #<data> |-|012346|-|UUUUU|*****| |1010_ddd_ddd_ddd_ddd (line 1010 emulator)
public static void irpAline () throws M68kException {
irpExceptionFormat0 (M68kException.M6E_LINE_1010_EMULATOR << 2, XEiJ.regPC0); //pcは命令の先頭
} //irpAline
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CMP.B <ea>,Dq |-|012346|-|-UUUU|-****|D M+-WXZPI|1011_qqq_000_mmm_rrr
public static void irpCmpByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int x;
int y;
int z = (byte) ((x = (byte) XEiJ.regRn[XEiJ.regOC >> 9 & 7]) - (y = ea < XEiJ.EA_AR ? (byte) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteSignData (efaAnyByte (ea), XEiJ.regSRS))); //pcbs。イミディエイトを分離
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} //irpCmpByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CMP.W <ea>,Dq |-|012346|-|-UUUU|-****|DAM+-WXZPI|1011_qqq_001_mmm_rrr
public static void irpCmpWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int x;
int y;
int z = (short) ((x = (short) XEiJ.regRn[XEiJ.regOC >> 9 & 7]) - (y = ea < XEiJ.EA_MM ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS))); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcws。イミディエイトを分離
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} //irpCmpWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CMP.L <ea>,Dq |-|012346|-|-UUUU|-****|DAM+-WXZPI|1011_qqq_010_mmm_rrr
public static void irpCmpLong () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int x;
int y;
int z = (x = XEiJ.regRn[XEiJ.regOC >> 9 & 7]) - (y = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS)); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcls。イミディエイトを分離
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} //irpCmpLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CMPA.W <ea>,Aq |-|012346|-|-UUUU|-****|DAM+-WXZPI|1011_qqq_011_mmm_rrr
//CMP.W <ea>,Aq |A|012346|-|-UUUU|-****|DAM+-WXZPI|1011_qqq_011_mmm_rrr [CMPA.W <ea>,Aq]
//
//CMPA.W <ea>,Aq
// ソースを符号拡張してロングで比較する
public static void irpCmpaWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
//ADDA/CMPA/SUBA.wl <ea>,Aqで<ea>が(Ar)+,-(Ar)でAr==Aqのとき1サイクル追加
if (XEiJ.EA_MP <= ea && ea < XEiJ.EA_MW &&
(ea & 7) == ((XEiJ.regOC >> 9) & 7)) {
XEiJ.mpuCycleCount++;
}
//ソースを符号拡張してからロングで比較する
int y = ea < XEiJ.EA_MM ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcws。イミディエイトを分離。ここでAqが変化する可能性があることに注意
int x;
int z = (x = XEiJ.regRn[XEiJ.regOC >> 9 & 15]) - y;
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} //irpCmpaWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//EOR.B Dq,<ea> |-|012346|-|-UUUU|-**00|D M+-WXZ |1011_qqq_100_mmm_rrr
//CMPM.B (Ar)+,(Aq)+ |-|012346|-|-UUUU|-****| |1011_qqq_100_001_rrr
public static void irpEorByte () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //CMPM.B (Ar)+,(Aq)+
XEiJ.mpuCycleCount += 2;
m60Incremented += 1L << (ea << 3);
int a = m60Address = XEiJ.regRn[ea]++; //このr[ea]はアドレスレジスタ
int y = mmuReadByteSignData (a, XEiJ.regSRS);
int x;
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented += 1L << (aqq << 3);
a = m60Address = XEiJ.regRn[aqq]++;
int z = (byte) ((x = mmuReadByteSignData (a, XEiJ.regSRS)) - y);
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} else {
int qqq = XEiJ.regOC >> 9 & 7;
int z;
if (ea < XEiJ.EA_AR) { //EOR.B Dq,Dr
XEiJ.mpuCycleCount++;
z = XEiJ.regRn[ea] ^= 255 & XEiJ.regRn[qqq]; //0拡張してからEOR
} else { //EOR.B Dq,<mem>
XEiJ.mpuCycleCount++;
int a = efaMltByte (ea);
mmuWriteByteData (a, z = XEiJ.regRn[qqq] ^ mmuModifyByteSignData (a, XEiJ.regSRS), XEiJ.regSRS);
}
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.MPU_TSTB_TABLE[255 & z]; //ccr_tst_byte
}
} //irpEorByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//EOR.W Dq,<ea> |-|012346|-|-UUUU|-**00|D M+-WXZ |1011_qqq_101_mmm_rrr
//CMPM.W (Ar)+,(Aq)+ |-|012346|-|-UUUU|-****| |1011_qqq_101_001_rrr
public static void irpEorWord () throws M68kException {
int ea = XEiJ.regOC & 63;
int rrr = XEiJ.regOC & 7;
int mmm = ea >> 3;
if (mmm == XEiJ.MMM_AR) { //CMPM.W (Ar)+,(Aq)+
XEiJ.mpuCycleCount += 2;
m60Incremented += 2L << (ea << 3);
int a = m60Address = (XEiJ.regRn[ea] += 2) - 2; //このr[ea]はアドレスレジスタ
int y = mmuReadWordSignData (a, XEiJ.regSRS);
int x;
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented += 2L << (aqq << 3);
a = m60Address = (XEiJ.regRn[aqq] += 2) - 2;
int z = (short) ((x = mmuReadWordSignData (a, XEiJ.regSRS)) - y);
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} else {
int qqq = XEiJ.regOC >> 9 & 7;
int z;
if (ea < XEiJ.EA_AR) { //EOR.W Dq,Dr
XEiJ.mpuCycleCount++;
z = XEiJ.regRn[rrr] ^= (char) XEiJ.regRn[qqq]; //0拡張してからEOR
} else { //EOR.W Dq,<mem>
XEiJ.mpuCycleCount++;
int a = efaMltWord (ea);
mmuWriteWordData (a, z = XEiJ.regRn[qqq] ^ mmuModifyWordSignData (a, XEiJ.regSRS), XEiJ.regSRS);
}
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (char) z - 1 >> 31 & XEiJ.REG_CCR_Z | ((short) z < 0 ? XEiJ.REG_CCR_N : 0); //ccr_tst_word
}
} //irpEorWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//EOR.L Dq,<ea> |-|012346|-|-UUUU|-**00|D M+-WXZ |1011_qqq_110_mmm_rrr
//CMPM.L (Ar)+,(Aq)+ |-|012346|-|-UUUU|-****| |1011_qqq_110_001_rrr
public static void irpEorLong () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >> 3 == XEiJ.MMM_AR) { //CMPM.L (Ar)+,(Aq)+
XEiJ.mpuCycleCount += 2;
m60Incremented += 4L << (ea << 3);
int a = m60Address = (XEiJ.regRn[ea] += 4) - 4; //このr[ea]はアドレスレジスタ
int y = mmuReadLongData (a, XEiJ.regSRS);
int x;
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented += 4L << (aqq << 3);
a = m60Address = (XEiJ.regRn[aqq] += 4) - 4;
int z = (x = mmuReadLongData (a, XEiJ.regSRS)) - y;
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} else {
int qqq = XEiJ.regOC >> 9 & 7;
int z;
if (ea < XEiJ.EA_AR) { //EOR.L Dq,Dr
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] = z = XEiJ.regRn[ea] ^ XEiJ.regRn[qqq];
} else { //EOR.L Dq,<mem>
XEiJ.mpuCycleCount++;
int a = efaMltLong (ea);
mmuWriteLongData (a, z = mmuModifyLongData (a, XEiJ.regSRS) ^ XEiJ.regRn[qqq], XEiJ.regSRS);
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
}
} //irpEorLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CMPA.L <ea>,Aq |-|012346|-|-UUUU|-****|DAM+-WXZPI|1011_qqq_111_mmm_rrr
//CMP.L <ea>,Aq |A|012346|-|-UUUU|-****|DAM+-WXZPI|1011_qqq_111_mmm_rrr [CMPA.L <ea>,Aq]
public static void irpCmpaLong () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
//ADDA/CMPA/SUBA.wl <ea>,Aqで<ea>が(Ar)+,-(Ar)でAr==Aqのとき1サイクル追加
if (XEiJ.EA_MP <= ea && ea < XEiJ.EA_MW &&
(ea & 7) == ((XEiJ.regOC >> 9) & 7)) {
XEiJ.mpuCycleCount++;
}
int y = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcls。イミディエイトを分離。ここでAqが変化する可能性があることに注意
int x;
int z = (x = XEiJ.regRn[XEiJ.regOC >> 9 & 15]) - y;
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) |
((x ^ y) & (x ^ z)) >>> 31 << 1 |
(x & (y ^ z) ^ (y | z)) >>> 31); //ccr_cmp
} //irpCmpaLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//AND.B <ea>,Dq |-|012346|-|-UUUU|-**00|D M+-WXZPI|1100_qqq_000_mmm_rrr
public static void irpAndToRegByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.MPU_TSTB_TABLE[255 & (XEiJ.regRn[XEiJ.regOC >> 9 & 7] &= ~255 | (ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteSignData (efaAnyByte (ea), XEiJ.regSRS)))]; //ccr_tst_byte。pcbs。イミディエイトを分離。1拡張してからAND
} //irpAndToRegByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//AND.W <ea>,Dq |-|012346|-|-UUUU|-**00|D M+-WXZPI|1100_qqq_001_mmm_rrr
public static void irpAndToRegWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] &= ~65535 | (ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS)); //pcws。イミディエイトを分離。1拡張してからAND
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (char) z - 1 >> 31 & XEiJ.REG_CCR_Z | ((short) z < 0 ? XEiJ.REG_CCR_N : 0); //ccr_tst_word
} //irpAndToRegWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//AND.L <ea>,Dq |-|012346|-|-UUUU|-**00|D M+-WXZPI|1100_qqq_010_mmm_rrr
public static void irpAndToRegLong () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] &= ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //pcls。イミディエイトを分離
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpAndToRegLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MULU.W <ea>,Dq |-|012346|-|-UUUU|-***0|D M+-WXZPI|1100_qqq_011_mmm_rrr
public static void irpMuluWord () throws M68kException {
XEiJ.mpuCycleCount += 2;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int y = ea < XEiJ.EA_AR ? (char) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordZeroData (efaAnyWord (ea), XEiJ.regSRS); //pcwz。イミディエイトを分離
int z;
XEiJ.regRn[qqq] = z = (char) XEiJ.regRn[qqq] * y; //積の下位32ビット。オーバーフローは無視
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpMuluWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ABCD.B Dr,Dq |-|012346|-|UUUUU|*U*U*| |1100_qqq_100_000_rrr
//ABCD.B -(Ar),-(Aq) |-|012346|-|UUUUU|*U*U*| |1100_qqq_100_001_rrr
//AND.B Dq,<ea> |-|012346|-|-UUUU|-**00| M+-WXZ |1100_qqq_100_mmm_rrr
public static void irpAndToMemByte () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea >= XEiJ.EA_MM) { //AND.B Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltByte (ea);
int z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & mmuModifyByteSignData (a, XEiJ.regSRS);
mmuWriteByteData (a, z, XEiJ.regSRS);
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.MPU_TSTB_TABLE[255 & z]; //ccr_tst_byte
} else if (ea < XEiJ.EA_AR) { //ABCD.B Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
XEiJ.regRn[qqq] = ~0xff & XEiJ.regRn[qqq] | irpAbcd (XEiJ.regRn[qqq], XEiJ.regRn[ea]);
} else { //ABCD.B -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 1L << (ea << 3);
int a = m60Address = --XEiJ.regRn[ea]; //このr[ea]はアドレスレジスタ
int y = mmuReadByteZeroData (a, XEiJ.regSRS);
int aqq = (XEiJ.regOC >> 9) - (96 - 8);
m60Incremented -= 1L << (aqq << 3);
a = m60Address = --XEiJ.regRn[aqq];
mmuWriteByteData (a, irpAbcd (mmuModifyByteZeroData (a, XEiJ.regSRS), y), XEiJ.regSRS);
}
} //irpAndToMemByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//EXG.L Dq,Dr |-|012346|-|-----|-----| |1100_qqq_101_000_rrr
//EXG.L Aq,Ar |-|012346|-|-----|-----| |1100_qqq_101_001_rrr
//AND.W Dq,<ea> |-|012346|-|-UUUU|-**00| M+-WXZ |1100_qqq_101_mmm_rrr
public static void irpAndToMemWord () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea < XEiJ.EA_MM) { //EXG
XEiJ.mpuCycleCount++;
if (ea < XEiJ.EA_AR) { //EXG.L Dq,Dr
int qqq = XEiJ.regOC >> 9 & 7;
int t = XEiJ.regRn[qqq];
XEiJ.regRn[qqq] = XEiJ.regRn[ea];
XEiJ.regRn[ea] = t;
} else { //EXG.L Aq,Ar
int aqq = (XEiJ.regOC >> 9) - (96 - 8);
int t = XEiJ.regRn[aqq];
XEiJ.regRn[aqq] = XEiJ.regRn[ea]; //このr[ea]アドレスレジスタ
XEiJ.regRn[ea] = t; //このr[ea]はアドレスレジスタ
}
} else { //AND.W Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltWord (ea);
int z = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & mmuModifyWordSignData (a, XEiJ.regSRS);
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (char) z - 1 >> 31 & XEiJ.REG_CCR_Z | ((short) z < 0 ? XEiJ.REG_CCR_N : 0); //ccr_tst_word
}
} //irpAndToMemWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//EXG.L Dq,Ar |-|012346|-|-----|-----| |1100_qqq_110_001_rrr
//AND.L Dq,<ea> |-|012346|-|-UUUU|-**00| M+-WXZ |1100_qqq_110_mmm_rrr
public static void irpAndToMemLong () throws M68kException {
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
if (ea >> 3 == XEiJ.MMM_AR) { //EXG.L Dq,Ar
XEiJ.mpuCycleCount++;
int t = XEiJ.regRn[qqq];
XEiJ.regRn[qqq] = XEiJ.regRn[ea]; //このr[ea]はアドレスレジスタ
XEiJ.regRn[ea] = t; //このr[ea]はアドレスレジスタ
} else { //AND.L Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltLong (ea);
int z;
mmuWriteLongData (a, z = mmuModifyLongData (a, XEiJ.regSRS) & XEiJ.regRn[qqq], XEiJ.regSRS);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
}
} //irpAndToMemLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MULS.W <ea>,Dq |-|012346|-|-UUUU|-***0|D M+-WXZPI|1100_qqq_111_mmm_rrr
public static void irpMulsWord () throws M68kException {
XEiJ.mpuCycleCount += 2;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int y = ea < XEiJ.EA_AR ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //pcws。イミディエイトを分離
int z;
XEiJ.regRn[qqq] = z = (short) XEiJ.regRn[qqq] * y; //積の下位32ビット。オーバーフローは無視
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpMulsWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADD.B <ea>,Dq |-|012346|-|UUUUU|*****|D M+-WXZPI|1101_qqq_000_mmm_rrr
public static void irpAddToRegByte () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int x, y, z;
y = ea < XEiJ.EA_AR ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS) : mmuReadByteSignData (efaAnyByte (ea), XEiJ.regSRS); //pcbs。イミディエイトを分離
x = XEiJ.regRn[qqq];
z = x + y;
XEiJ.regRn[qqq] = ~255 & x | 255 & z;
XEiJ.regCCR = (XEiJ.MPU_TSTB_TABLE[255 & z] |
((x ^ z) & (y ^ z)) >> 6 & XEiJ.REG_CCR_V |
(byte) ((x | y) ^ (x ^ y) & z) >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_add_byte
} //irpAddToRegByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADD.W <ea>,Dq |-|012346|-|UUUUU|*****|DAM+-WXZPI|1101_qqq_001_mmm_rrr
public static void irpAddToRegWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int x, y, z;
y = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcws。イミディエイトを分離
x = XEiJ.regRn[qqq];
z = x + y;
XEiJ.regRn[qqq] = ~65535 & x | (char) z;
XEiJ.regCCR = (z >> 12 & XEiJ.REG_CCR_N | (char) z - 1 >> 14 & XEiJ.REG_CCR_Z |
((x ^ z) & (y ^ z)) >> 14 & XEiJ.REG_CCR_V |
(short) ((x | y) ^ (x ^ y) & z) >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_add_word
} //irpAddToRegWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADD.L <ea>,Dq |-|012346|-|UUUUU|*****|DAM+-WXZPI|1101_qqq_010_mmm_rrr
public static void irpAddToRegLong () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int qqq = XEiJ.regOC >> 9 & 7;
int x, y, z;
y = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcls。イミディエイトを分離
x = XEiJ.regRn[qqq];
z = x + y;
XEiJ.regRn[qqq] = z;
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) |
((x ^ z) & (y ^ z)) >> 30 & XEiJ.REG_CCR_V |
((x | y) ^ (x ^ y) & z) >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_add
} //irpAddToRegLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADDA.W <ea>,Aq |-|012346|-|-----|-----|DAM+-WXZPI|1101_qqq_011_mmm_rrr
//ADD.W <ea>,Aq |A|012346|-|-----|-----|DAM+-WXZPI|1101_qqq_011_mmm_rrr [ADDA.W <ea>,Aq]
//
//ADDA.W <ea>,Aq
// ソースを符号拡張してロングで加算する
public static void irpAddaWord () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
//ADDA/CMPA/SUBA.wl <ea>,Aqで<ea>が(Ar)+,-(Ar)でAr==Aqのとき1サイクル追加
if (XEiJ.EA_MP <= ea && ea < XEiJ.EA_MW &&
(ea & 7) == ((XEiJ.regOC >> 9) & 7)) {
XEiJ.mpuCycleCount++;
}
int z = ea < XEiJ.EA_MM ? (short) XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : mmuReadWordSignData (efaAnyWord (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcws。イミディエイトを分離。ここでAqが変化する可能性があることに注意
XEiJ.regRn[XEiJ.regOC >> 9 & 15] += z; //r[op >> 9 & 15] += ea < XEiJ.EA_MM ? (short) r[ea] : rws (efaAnyWord (ea));は不可
//ccrは変化しない
} //irpAddaWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADDX.B Dr,Dq |-|012346|-|*UUUU|*****| |1101_qqq_100_000_rrr
//ADDX.B -(Ar),-(Aq) |-|012346|-|*UUUU|*****| |1101_qqq_100_001_rrr
//ADD.B Dq,<ea> |-|012346|-|UUUUU|*****| M+-WXZ |1101_qqq_100_mmm_rrr
public static void irpAddToMemByte () throws M68kException {
int ea = XEiJ.regOC & 63;
int a, x, y, z;
if (ea < XEiJ.EA_MM) {
if (ea < XEiJ.EA_AR) { //ADDX.B Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
y = XEiJ.regRn[ea];
x = XEiJ.regRn[qqq];
z = x + y + (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
XEiJ.regRn[qqq] = ~255 & x | 255 & z;
} else { //ADDX.B -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 1L << (ea << 3);
a = m60Address = --XEiJ.regRn[ea]; //このr[ea]はアドレスレジスタ
y = mmuReadByteSignData (a, XEiJ.regSRS);
int aqq = XEiJ.regOC >> 9 & 15; //1qqq=aqq
m60Incremented -= 1L << (aqq << 3);
a = m60Address = --XEiJ.regRn[aqq];
x = mmuModifyByteSignData (a, XEiJ.regSRS);
z = x + y + (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
mmuWriteByteData (a, z, XEiJ.regSRS);
}
XEiJ.regCCR = (z >> 4 & XEiJ.REG_CCR_N | (255 & z) - 1 >> 6 & XEiJ.regCCR & XEiJ.REG_CCR_Z | //ADDXはZをクリアすることはあるがセットすることはない
((x ^ z) & (y ^ z)) >> 6 & XEiJ.REG_CCR_V |
(byte) ((x | y) ^ (x ^ y) & z) >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_addx_byte
} else { //ADD.B Dq,<ea>
XEiJ.mpuCycleCount++;
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7];
a = efaMltByte (ea);
x = mmuModifyByteSignData (a, XEiJ.regSRS);
z = x + y;
mmuWriteByteData (a, z, XEiJ.regSRS);
XEiJ.regCCR = (XEiJ.MPU_TSTB_TABLE[255 & z] |
((x ^ z) & (y ^ z)) >> 6 & XEiJ.REG_CCR_V |
(byte) ((x | y) ^ (x ^ y) & z) >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_add_byte
}
} //irpAddToMemByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADDX.W Dr,Dq |-|012346|-|*UUUU|*****| |1101_qqq_101_000_rrr
//ADDX.W -(Ar),-(Aq) |-|012346|-|*UUUU|*****| |1101_qqq_101_001_rrr
//ADD.W Dq,<ea> |-|012346|-|UUUUU|*****| M+-WXZ |1101_qqq_101_mmm_rrr
public static void irpAddToMemWord () throws M68kException {
int ea = XEiJ.regOC & 63;
int a, x, y, z;
if (ea < XEiJ.EA_MM) {
if (ea < XEiJ.EA_AR) { //ADDX.W Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
y = XEiJ.regRn[ea];
x = XEiJ.regRn[qqq];
z = x + y + (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
XEiJ.regRn[qqq] = ~65535 & x | (char) z;
} else { //ADDX.W -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 2L << (ea << 3);
a = m60Address = XEiJ.regRn[ea] -= 2; //このr[ea]はアドレスレジスタ
y = mmuReadWordSignData (a, XEiJ.regSRS);
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented -= 2L << (aqq << 3);
a = m60Address = XEiJ.regRn[aqq] -= 2;
x = mmuModifyWordSignData (a, XEiJ.regSRS);
z = x + y + (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
mmuWriteWordData (a, z, XEiJ.regSRS);
}
XEiJ.regCCR = (z >> 12 & XEiJ.REG_CCR_N | (char) z - 1 >> 14 & XEiJ.regCCR & XEiJ.REG_CCR_Z | //ADDXはZをクリアすることはあるがセットすることはない
((x ^ z) & (y ^ z)) >> 14 & XEiJ.REG_CCR_V |
(short) ((x | y) ^ (x ^ y) & z) >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_addx_word
} else { //ADD.W Dq,<ea>
XEiJ.mpuCycleCount++;
a = efaMltWord (ea);
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7];
x = mmuModifyWordSignData (a, XEiJ.regSRS);
z = x + y;
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = (z >> 12 & XEiJ.REG_CCR_N | (char) z - 1 >> 14 & XEiJ.REG_CCR_Z |
((x ^ z) & (y ^ z)) >> 14 & XEiJ.REG_CCR_V |
(short) ((x | y) ^ (x ^ y) & z) >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_add_word
}
} //irpAddToMemWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADDX.L Dr,Dq |-|012346|-|*UUUU|*****| |1101_qqq_110_000_rrr
//ADDX.L -(Ar),-(Aq) |-|012346|-|*UUUU|*****| |1101_qqq_110_001_rrr
//ADD.L Dq,<ea> |-|012346|-|UUUUU|*****| M+-WXZ |1101_qqq_110_mmm_rrr
public static void irpAddToMemLong () throws M68kException {
int ea = XEiJ.regOC & 63;
if (ea < XEiJ.EA_MM) {
int x;
int y;
int z;
if (ea < XEiJ.EA_AR) { //ADDX.L Dr,Dq
int qqq = XEiJ.regOC >> 9 & 7;
XEiJ.mpuCycleCount++;
XEiJ.regRn[qqq] = z = (x = XEiJ.regRn[qqq]) + (y = XEiJ.regRn[ea]) + (XEiJ.regCCR >> 4); //Xの左側はすべて0なのでCCR_X&を省略
} else { //ADDX.L -(Ar),-(Aq)
XEiJ.mpuCycleCount += 2;
m60Incremented -= 4L << (ea << 3);
int a = m60Address = XEiJ.regRn[ea] -= 4; //このr[ea]はアドレスレジスタ
y = mmuReadLongData (a, XEiJ.regSRS);
int aqq = XEiJ.regOC >> 9 & 15;
m60Incremented -= 4L << (aqq << 3);
a = m60Address = XEiJ.regRn[aqq] -= 4;
mmuWriteLongData (a, z = (x = mmuModifyLongData (a, XEiJ.regSRS)) + y + (XEiJ.regCCR >> 4), XEiJ.regSRS); //Xの左側はすべて0なのでCCR_X&を省略
}
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_Z : 0) |
((x ^ z) & (y ^ z)) >>> 31 << 1 |
((x | y) ^ (x ^ y) & z) >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_addx
} else { //ADD.L Dq,<ea>
XEiJ.mpuCycleCount++;
int a = efaMltLong (ea);
int x;
int y;
int z;
mmuWriteLongData (a, z = (x = mmuModifyLongData (a, XEiJ.regSRS)) + (y = XEiJ.regRn[XEiJ.regOC >> 9 & 7]), XEiJ.regSRS);
XEiJ.regCCR = (z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) |
((x ^ z) & (y ^ z)) >>> 31 << 1 |
((x | y) ^ (x ^ y) & z) >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //ccr_add
}
} //irpAddToMemLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ADDA.L <ea>,Aq |-|012346|-|-----|-----|DAM+-WXZPI|1101_qqq_111_mmm_rrr
//ADD.L <ea>,Aq |A|012346|-|-----|-----|DAM+-WXZPI|1101_qqq_111_mmm_rrr [ADDA.L <ea>,Aq]
public static void irpAddaLong () throws M68kException {
int ea = XEiJ.regOC & 63;
XEiJ.mpuCycleCount++;
//ADDA/CMPA/SUBA.wl <ea>,Aqで<ea>が(Ar)+,-(Ar)でAr==Aqのとき1サイクル追加
if (XEiJ.EA_MP <= ea && ea < XEiJ.EA_MW &&
(ea & 7) == ((XEiJ.regOC >> 9) & 7)) {
XEiJ.mpuCycleCount++;
}
int z = ea < XEiJ.EA_MM ? XEiJ.regRn[ea] : ea == XEiJ.EA_IM ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : mmuReadLongData (efaAnyLong (ea), XEiJ.regSRS); //このr[ea]はデータレジスタまたはアドレスレジスタ。pcls。イミディエイトを分離。ここでAqが変化する可能性があることに注意
XEiJ.regRn[XEiJ.regOC >> 9 & 15] += z; //r[op >> 9 & 15] += ea < XEiJ.EA_MM ? r[ea] : rls (efaAnyLong (ea));は不可
//ccrは変化しない
} //irpAddaLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASR.B #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_000_000_rrr
//LSR.B #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_000_001_rrr
//ROXR.B #<data>,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_000_010_rrr
//ROR.B #<data>,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_000_011_rrr
//ASR.B Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_000_100_rrr
//LSR.B Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_000_101_rrr
//ROXR.B Dq,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_000_110_rrr
//ROR.B Dq,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_000_111_rrr
//ASR.B Dr |A|012346|-|UUUUU|***0*| |1110_001_000_000_rrr [ASR.B #1,Dr]
//LSR.B Dr |A|012346|-|UUUUU|***0*| |1110_001_000_001_rrr [LSR.B #1,Dr]
//ROXR.B Dr |A|012346|-|*UUUU|***0*| |1110_001_000_010_rrr [ROXR.B #1,Dr]
//ROR.B Dr |A|012346|-|-UUUU|-**0*| |1110_001_000_011_rrr [ROR.B #1,Dr]
//
//ASR.B #<data>,Dr
//ASR.B Dq,Dr
// 算術右シフトバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*00 Z=アイウエオカキク==0
// 1 ........................アアイウエオカキ クア*0ク Z=アイウエオカキ==0
// 2 ........................アアアイウエオカ キア*0キ Z=アイウエオカ==0
// 3 ........................アアアアイウエオ カア*0カ Z=アイウエオ==0
// 4 ........................アアアアアイウエ オア*0オ Z=アイウエ==0
// 5 ........................アアアアアアイウ エア*0エ Z=アイウ==0
// 6 ........................アアアアアアアイ ウア*0ウ Z=アイ==0
// 7 ........................アアアアアアアア イア*0イ Z=ア==0
// 8 ........................アアアアアアアア アア*0ア Z=ア==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//LSR.B #<data>,Dr
//LSR.B Dq,Dr
// 論理右シフトバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*00 Z=アイウエオカキク==0
// 1 ........................0アイウエオカキ ク0*0ク Z=アイウエオカキ==0
// 2 ........................00アイウエオカ キ0*0キ Z=アイウエオカ==0
// 3 ........................000アイウエオ カ0*0カ Z=アイウエオ==0
// 4 ........................0000アイウエ オ0*0オ Z=アイウエ==0
// 5 ........................00000アイウ エ0*0エ Z=アイウ==0
// 6 ........................000000アイ ウ0*0ウ Z=アイ==0
// 7 ........................0000000ア イ0*0イ Z=ア==0
// 8 ........................00000000 ア010ア
// 9 ........................00000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//ROR.B #<data>,Dr
//ROR.B Dq,Dr
// 右ローテートバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*00 Z=アイウエオカキク==0
// 1 ........................クアイウエオカキ Xク*0ク Z=アイウエオカキク==0
// :
// 7 ........................イウエオカキクア Xイ*0イ Z=アイウエオカキク==0
// 8 ........................アイウエオカキク Xア*0ア Z=アイウエオカキク==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最上位ビット
//
//ROXR.B #<data>,Dr
//ROXR.B Dq,Dr
// 拡張右ローテートバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*0X Z=アイウエオカキク==0
// 1 ........................Xアイウエオカキ クX*0ク Z=アイウエオカキX==0
// 2 ........................クXアイウエオカ キク*0キ Z=アイウエオカクX==0
// 3 ........................キクXアイウエオ カキ*0カ Z=アイウエオキクX==0
// 4 ........................カキクXアイウエ オカ*0オ Z=アイウエカキクX==0
// 5 ........................オカキクXアイウ エオ*0エ Z=アイウオカキクX==0
// 6 ........................エオカキクXアイ ウエ*0ウ Z=アイエオカキクX==0
// 7 ........................ウエオカキクXア イウ*0イ Z=アウエオカキクX==0
// 8 ........................イウエオカキクX アイ*0ア Z=イウエオカキクX==0
// 9 ........................アイウエオカキク Xア*0X Z=アイウエオカキク==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpXxrToRegByte () throws M68kException {
int rrr;
int x = XEiJ.regRn[rrr = XEiJ.regOC & 7];
int y;
int z;
int t;
XEiJ.mpuCycleCount++;
switch (XEiJ.regOC >> 3 & 0b111_000 >> 3) {
case 0b000_000 >> 3: //ASR.B #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (t = (byte) x >> y) >> 1);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b001_000 >> 3: //LSR.B #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xff & x | (z = (t = (0xff & x) >>> y) >>> 1);
XEiJ.regCCR = (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b010_000 >> 3: //ROXR.B #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
z = (XEiJ.regCCR & XEiJ.REG_CCR_X) << 7 - 4 | (0xff & x) >>> 1;
if (y == 1 - 1) { //y=data-1=1-1
t = x;
} else { //y=data-1=2-1~8-1
z = x << 9 - 1 - y | (t = z >>> y - (2 - 1)) >>> 1;
}
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) z);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b011_000 >> 3: //ROR.B #<data>,Dr
y = XEiJ.regOC >> 9 & 7; //y=data&7
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) (x << 8 - y | (0xff & x) >>> y));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | z >>> 7 & 1; //Xは変化しない。Cは結果の最上位ビット
break;
case 0b100_000 >> 3: //ASR.B Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = (byte) x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (t = (byte) x >> (y <= 8 ? y - 1 : 7)) >> 1);
t = -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b101_000 >> 3: //LSR.B Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = (byte) x;
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (z < 0 ? XEiJ.REG_CCR_N : z == 0 ? XEiJ.REG_CCR_Z : 0); //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = ~0xff & x | (z = (t = y <= 8 ? (0xff & x) >>> y - 1 : 0) >>> 1);
XEiJ.regCCR = (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
break;
case 0b110_000 >> 3: //ROXR.B Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
//y %= 9;
y = (y & 7) - (y >> 3); //y=data=-7~7
y += y >> 3 & 9; //y=data=0~8
if (y == 0) { //y=data=0
z = (byte) x;
t = -(XEiJ.regCCR >> 4 & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //Xは変化しない。CはXのコピー
} else { //y=data=1~8
z = (XEiJ.regCCR & XEiJ.REG_CCR_X) << 7 - 4 | (0xff & x) >>> 1;
if (y == 1) { //y=data=1
t = x; //Cは最後に押し出されたビット
} else { //y=data=2~8
z = x << 9 - y | (t = z >>> y - 2) >>> 1;
}
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) z);
t = -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b111_000 >> 3: //ROR.B Dq,Dr
default:
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) {
z = (byte) x;
t = 0; //Cはクリア
} else {
y &= 7; //y=data=0~7
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) (x << 8 - y | (0xff & x) >>> y));
t = z >>> 7 & 1; //Cは結果の最上位ビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | t; //Xは変化しない
}
} //irpXxrToRegByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASR.W #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_001_000_rrr
//LSR.W #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_001_001_rrr
//ROXR.W #<data>,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_001_010_rrr
//ROR.W #<data>,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_001_011_rrr
//ASR.W Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_001_100_rrr
//LSR.W Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_001_101_rrr
//ROXR.W Dq,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_001_110_rrr
//ROR.W Dq,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_001_111_rrr
//ASR.W Dr |A|012346|-|UUUUU|***0*| |1110_001_001_000_rrr [ASR.W #1,Dr]
//LSR.W Dr |A|012346|-|UUUUU|***0*| |1110_001_001_001_rrr [LSR.W #1,Dr]
//ROXR.W Dr |A|012346|-|*UUUU|***0*| |1110_001_001_010_rrr [ROXR.W #1,Dr]
//ROR.W Dr |A|012346|-|-UUUU|-**0*| |1110_001_001_011_rrr [ROR.W #1,Dr]
//
//ASR.W #<data>,Dr
//ASR.W Dq,Dr
//ASR.W <ea>
// 算術右シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................アアイウエオカキクケコサシスセソ タア*0タ Z=アイウエオカキクケコサシスセソ==0
// :
// 15 ................アアアアアアアアアアアアアアアア イア*0イ Z=ア==0
// 16 ................アアアアアアアアアアアアアアアア アア*0ア Z=ア==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//LSR.W #<data>,Dr
//LSR.W Dq,Dr
//LSR.W <ea>
// 論理右シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................0アイウエオカキクケコサシスセソ タ0*0タ Z=アイウエオカキクケコサシスセソ==0
// :
// 15 ................000000000000000ア イ0*0イ Z=ア==0
// 16 ................0000000000000000 ア010ア
// 17 ................0000000000000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//ROR.W #<data>,Dr
//ROR.W Dq,Dr
//ROR.W <ea>
// 右ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................タアイウエオカキクケコサシスセソ Xタ*0タ Z=アイウエオカキクケコサシスセソタ==0
// :
// 15 ................イウエオカキクケコサシスセソタア Xイ*0イ Z=アイウエオカキクケコサシスセソタ==0
// 16 ................アイウエオカキクケコサシスセソタ Xア*0ア Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最上位ビット
//
//ROXR.W #<data>,Dr
//ROXR.W Dq,Dr
//ROXR.W <ea>
// 拡張右ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// 1 ................Xアイウエオカキクケコサシスセソ タX*0タ Z=アイウエオカキクケコサシスセソX==0
// 2 ................タXアイウエオカキクケコサシスセ ソタ*0ソ Z=アイウエオカキクケコサシスセタX==0
// :
// 15 ................ウエオカキクケコサシスセソタXア イウ*0イ Z=アウエオカキクケコサシスセソタX==0
// 16 ................イウエオカキクケコサシスセソタX アイ*0ア Z=イウエオカキクケコサシスセソタX==0
// 17 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpXxrToRegWord () throws M68kException {
int rrr;
int x = XEiJ.regRn[rrr = XEiJ.regOC & 7];
int y;
int z;
int t;
XEiJ.mpuCycleCount++;
switch (XEiJ.regOC >> 3 & 0b111_000 >> 3) {
case 0b000_000 >> 3: //ASR.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (t = (short) x >> y) >> 1);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b001_000 >> 3: //LSR.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xffff & x | (z = (t = (char) x >>> y) >>> 1);
XEiJ.regCCR = (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b010_000 >> 3: //ROXR.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
z = (XEiJ.regCCR & XEiJ.REG_CCR_X) << 15 - 4 | (char) x >>> 1;
if (y == 1 - 1) { //y=data-1=1-1
t = x;
} else { //y=data-1=2-1~8-1
z = x << 17 - 1 - y | (t = z >>> y - (2 - 1)) >>> 1;
}
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) z);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b011_000 >> 3: //ROR.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) (x << 16 - 1 - y | (char) x >>> y + 1));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | z >>> 15 & 1; //Xは変化しない。Cは結果の最上位ビット
break;
case 0b100_000 >> 3: //ASR.W Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = (short) x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (t = (short) x >> (y <= 16 ? y - 1 : 15)) >> 1);
t = -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b101_000 >> 3: //LSR.W Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = (short) x;
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (z < 0 ? XEiJ.REG_CCR_N : z == 0 ? XEiJ.REG_CCR_Z : 0); //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = ~0xffff & x | (z = (t = y <= 16 ? (char) x >>> y - 1 : 0) >>> 1);
XEiJ.regCCR = (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
break;
case 0b110_000 >> 3: //ROXR.W Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
//y %= 17;
y = (y & 15) - (y >> 4); //y=data=-3~15
y += y >> 4 & 17; //y=data=0~16
if (y == 0) { //y=data=0
z = (short) x;
t = -(XEiJ.regCCR >> 4 & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //Xは変化しない。CはXのコピー
} else { //y=data=1~16
z = (XEiJ.regCCR & XEiJ.REG_CCR_X) << 15 - 4 | (char) x >>> 1;
if (y == 1) { //y=data=1
t = x; //Cは最後に押し出されたビット
} else { //y=data=2~16
z = x << 17 - y | (t = z >>> y - 2) >>> 1;
}
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) z);
t = -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b111_000 >> 3: //ROR.W Dq,Dr
default:
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) {
z = (short) x;
t = 0; //Cはクリア
} else {
y &= 15; //y=data=0~15
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) (x << 16 - y | (char) x >>> y));
t = z >>> 15 & 1; //Cは結果の最上位ビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | t; //Xは変化しない
}
} //irpXxrToRegWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASR.L #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_010_000_rrr
//LSR.L #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_010_001_rrr
//ROXR.L #<data>,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_010_010_rrr
//ROR.L #<data>,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_010_011_rrr
//ASR.L Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_010_100_rrr
//LSR.L Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_010_101_rrr
//ROXR.L Dq,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_010_110_rrr
//ROR.L Dq,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_010_111_rrr
//ASR.L Dr |A|012346|-|UUUUU|***0*| |1110_001_010_000_rrr [ASR.L #1,Dr]
//LSR.L Dr |A|012346|-|UUUUU|***0*| |1110_001_010_001_rrr [LSR.L #1,Dr]
//ROXR.L Dr |A|012346|-|*UUUU|***0*| |1110_001_010_010_rrr [ROXR.L #1,Dr]
//ROR.L Dr |A|012346|-|-UUUU|-**0*| |1110_001_010_011_rrr [ROR.L #1,Dr]
//
//ASR.L #<data>,Dr
//ASR.L Dq,Dr
// 算術右シフトロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*00 Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 アアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミア*0ミ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ==0
// :
// 31 アアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアア イア*0イ Z=ア==0
// 32 アアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアア アア*0ア Z=ア==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//LSR.L #<data>,Dr
//LSR.L Dq,Dr
// 論理右シフトロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*00 Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 0アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミ0*0ミ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ==0
// :
// 31 0000000000000000000000000000000ア イ0*0イ Z=ア==0
// 32 00000000000000000000000000000000 ア010ア
// 33 00000000000000000000000000000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//ROR.L #<data>,Dr
//ROR.L Dq,Dr
// 右ローテートロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*00 Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 ミアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ Xミ*0ミ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// :
// 31 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミア Xイ*0イ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 32 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*0ア Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最上位ビット
//
//ROXR.L #<data>,Dr
//ROXR.L Dq,Dr
// 拡張右ローテートロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*0X Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 Xアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミX*0ミ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマX==0
// 2 ミXアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホ マミ*0マ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホミX==0
// :
// 31 ウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミXア イウ*0イ Z=アウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX==0
// 32 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX アイ*0ア Z=イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX==0
// 33 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*0X Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpXxrToRegLong () throws M68kException {
int rrr;
int x = XEiJ.regRn[rrr = XEiJ.regOC & 7];
int y;
int z;
int t;
XEiJ.mpuCycleCount++;
switch (XEiJ.regOC >> 3 & 0b111_000 >> 3) {
case 0b000_000 >> 3: //ASR.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = z = (t = x >> y) >> 1;
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b001_000 >> 3: //LSR.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = z = (t = x >>> y) >>> 1;
XEiJ.regCCR = (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b010_000 >> 3: //ROXR.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
z = (XEiJ.regCCR & XEiJ.REG_CCR_X) << 31 - 4 | x >>> 1;
if (y == 1 - 1) { //y=data-1=1-1
t = x;
} else { //y=data-1=2-1~8-1
z = x << -y | (t = z >>> y - (2 - 1)) >>> 1; //Javaのシフト演算子は5ビットでマスクされるので33-1-yを-yに省略
}
XEiJ.regRn[rrr] = z;
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b011_000 >> 3: //ROR.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = z = x << ~y | x >>> y + 1; //Javaのシフト演算子は5ビットでマスクされるので32-1-yを~yに省略
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | z >>> 31; //Xは変化しない。Cは結果の最上位ビット
break;
case 0b100_000 >> 3: //ASR.L Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = z = (t = x >> (y <= 32 ? y - 1 : 31)) >> 1;
t = -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b101_000 >> 3: //LSR.L Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = x;
XEiJ.regCCR = XEiJ.regCCR & XEiJ.REG_CCR_X | (z < 0 ? XEiJ.REG_CCR_N : z == 0 ? XEiJ.REG_CCR_Z : 0); //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = z = (t = y <= 32 ? x >>> y - 1 : 0) >>> 1;
XEiJ.regCCR = (z == 0 ? XEiJ.REG_CCR_Z : 0) | -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
break;
case 0b110_000 >> 3: //ROXR.L Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
//y %= 33;
y -= 32 - y >> 6 & 33; //y=data=0~32
if (y == 0) { //y=data=0
z = x;
t = -(XEiJ.regCCR >> 4 & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //Xは変化しない。CはXのコピー
} else { //y=data=1~32
z = (XEiJ.regCCR & XEiJ.REG_CCR_X) << 31 - 4 | x >>> 1;
if (y == 1) { //y=data=1
t = x; //Cは最後に押し出されたビット
} else { //y=data=2~32
z = x << 33 - y | (t = z >>> y - 2) >>> 1;
}
XEiJ.regRn[rrr] = z;
t = -(t & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b111_000 >> 3: //ROR.L Dq,Dr
default:
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) {
z = x;
t = 0; //Cはクリア
} else {
y &= 31; //y=data=0~31
XEiJ.regRn[rrr] = z = x << -y | x >>> y; //Javaのシフト演算子は5ビットでマスクされるので32-yを-yに省略。y=32のときx|xになるが問題ない
t = z >>> 31; //Cは結果の最上位ビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | t; //Xは変化しない
}
} //irpXxrToRegLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASR.W <ea> |-|012346|-|UUUUU|***0*| M+-WXZ |1110_000_011_mmm_rrr
//
//ASR.W #<data>,Dr
//ASR.W Dq,Dr
//ASR.W <ea>
// 算術右シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................アアイウエオカキクケコサシスセソ タア*0タ Z=アイウエオカキクケコサシスセソ==0
// :
// 15 ................アアアアアアアアアアアアアアアア イア*0イ Z=ア==0
// 16 ................アアアアアアアアアアアアアアアア アア*0ア Z=ア==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
public static void irpAsrToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordSignData (a, XEiJ.regSRS);
int z = x >> 1;
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = ((z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
-(x & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //XとCは最後に押し出されたビット
} //irpAsrToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASL.B #<data>,Dr |-|012346|-|UUUUU|*****| |1110_qqq_100_000_rrr
//LSL.B #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_100_001_rrr
//ROXL.B #<data>,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_100_010_rrr
//ROL.B #<data>,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_100_011_rrr
//ASL.B Dq,Dr |-|012346|-|UUUUU|*****| |1110_qqq_100_100_rrr
//LSL.B Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_100_101_rrr
//ROXL.B Dq,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_100_110_rrr
//ROL.B Dq,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_100_111_rrr
//ASL.B Dr |A|012346|-|UUUUU|*****| |1110_001_100_000_rrr [ASL.B #1,Dr]
//LSL.B Dr |A|012346|-|UUUUU|***0*| |1110_001_100_001_rrr [LSL.B #1,Dr]
//ROXL.B Dr |A|012346|-|*UUUU|***0*| |1110_001_100_010_rrr [ROXL.B #1,Dr]
//ROL.B Dr |A|012346|-|-UUUU|-**0*| |1110_001_100_011_rrr [ROL.B #1,Dr]
//
//ASL.B #<data>,Dr
//ASL.B Dq,Dr
// 算術左シフトバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*00 Z=アイウエオカキク==0
// 1 ........................イウエオカキク0 アイ**ア Z=イウエオカキク==0,V=アイ!=0/-1
// :
// 7 ........................ク0000000 キク**キ Z=ク==0,V=アイウエオカキク!=0/-1
// 8 ........................00000000 ク01*ク V=アイウエオカキク!=0
// 9 ........................00000000 001*0 V=アイウエオカキク!=0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V ASRで元に戻せないときセット。他はクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//LSL.B #<data>,Dr
//LSL.B Dq,Dr
// 論理左シフトバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*00 Z=アイウエオカキク==0
// 1 ........................イウエオカキク0 アイ*0ア Z=イウエオカキク==0
// :
// 7 ........................ク0000000 キク*0キ Z=ク==0
// 8 ........................00000000 ク010ク
// 9 ........................00000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//ROL.B #<data>,Dr
//ROL.B Dq,Dr
// 左ローテートバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*00 Z=アイウエオカキク==0
// 1 ........................イウエオカキクア Xイ*0ア Z=アイウエオカキク==0
// :
// 7 ........................クアイウエオカキ Xク*0キ Z=アイウエオカキク==0
// 8 ........................アイウエオカキク Xア*0ク Z=アイウエオカキク==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最下位ビット
//
//ROXL.B #<data>,Dr
//ROXL.B Dq,Dr
// 拡張左ローテートバイト
// ........................アイウエオカキク XNZVC
// 0 ........................アイウエオカキク Xア*0X Z=アイウエオカキク==0
// 1 ........................イウエオカキクX アイ*0ア Z=イウエオカキクX==0
// 2 ........................ウエオカキクXア イウ*0イ Z=アウエオカキクX==0
// :
// 7 ........................クXアイウエオカ キク*0キ Z=アイウエオカクX==0
// 8 ........................Xアイウエオカキ クX*0ク Z=アイウエオカキX==0
// 9 ........................アイウエオカキク Xア*0X Z=アイウエオカキク==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpXxlToRegByte () throws M68kException {
int rrr;
int x = XEiJ.regRn[rrr = XEiJ.regOC & 7];
int y;
int z;
int t;
XEiJ.mpuCycleCount++;
switch (XEiJ.regOC >> 3 & 0b111_000 >> 3) {
case 0b000_000 >> 3: //ASL.B #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) ((t = x << y) << 1));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (z >> y + 1 != (byte) x ? XEiJ.REG_CCR_V : 0) | (byte) t >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //VはASRで元に戻せないときセット。XとCは最後に押し出されたビット
break;
case 0b001_000 >> 3: //LSL.B #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) ((t = x << y) << 1));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (byte) t >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b010_000 >> 3: //ROXL.B #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
z = x << 1 | XEiJ.regCCR >> 4 & 1;
if (y == 1 - 1) { //y=data-1=1-1
t = x;
} else { //y=data-1=2-1~8-1
z = (t = z << y - (2 - 1)) << 1 | (0xff & x) >>> 9 - 1 - y;
}
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) z);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (byte) t >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b011_000 >> 3: //ROL.B #<data>,Dr
y = XEiJ.regOC >> 9 & 7; //y=data&7
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) (x << y | (0xff & x) >>> 8 - y));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | z & 1; //Xは変化しない。Cは結果の最下位ビット
break;
case 0b100_000 >> 3: //ASL.B Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y <= 7) { //y=data=0~7
if (y == 0) { //y=data=0
z = (byte) x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。VとCはクリア
} else { //y=data=1~7
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) ((t = x << y - 1) << 1));
t = (z >> y != (byte) x ? XEiJ.REG_CCR_V : 0) | (byte) t >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //VはASRで元に戻せないときセット。XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
} else { //y=data=8~63
XEiJ.regRn[rrr] = ~0xff & x;
XEiJ.regCCR = XEiJ.REG_CCR_Z | ((byte) x != 0 ? XEiJ.REG_CCR_V : 0) | (y == 8 ? -(x & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C) : 0);
}
break;
case 0b101_000 >> 3: //LSL.B Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = (byte) x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) ((t = y <= 8 ? x << y - 1 : 0) << 1));
t = (byte) t >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b110_000 >> 3: //ROXL.B Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
//y %= 9;
y = (y & 7) - (y >> 3); //y=data=-7~7
y += y >> 3 & 9; //y=data=0~8
if (y == 0) { //y=data=0
z = (byte) x;
t = -(XEiJ.regCCR >> 4 & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //Xは変化しない。CはXのコピー
} else { //y=data=1~8
z = x << 1 | XEiJ.regCCR >> 4 & 1;
if (y == 1) { //y=data=1
t = x; //Cは最後に押し出されたビット
} else { //y=data=2~8
z = (t = z << y - 2) << 1 | (0xff & x) >>> 9 - y;
}
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) z);
t = (byte) t >> 7 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b111_000 >> 3: //ROL.B Dq,Dr
default:
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) {
z = (byte) x;
t = 0; //Cはクリア
} else {
y &= 7; //y=data=0~7
XEiJ.regRn[rrr] = ~0xff & x | 0xff & (z = (byte) (x << y | (0xff & x) >>> 8 - y));
t = z & 1; //Cは結果の最下位ビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | t; //Xは変化しない
}
} //irpXxlToRegByte
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASL.W #<data>,Dr |-|012346|-|UUUUU|*****| |1110_qqq_101_000_rrr
//LSL.W #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_101_001_rrr
//ROXL.W #<data>,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_101_010_rrr
//ROL.W #<data>,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_101_011_rrr
//ASL.W Dq,Dr |-|012346|-|UUUUU|*****| |1110_qqq_101_100_rrr
//LSL.W Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_101_101_rrr
//ROXL.W Dq,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_101_110_rrr
//ROL.W Dq,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_101_111_rrr
//ASL.W Dr |A|012346|-|UUUUU|*****| |1110_001_101_000_rrr [ASL.W #1,Dr]
//LSL.W Dr |A|012346|-|UUUUU|***0*| |1110_001_101_001_rrr [LSL.W #1,Dr]
//ROXL.W Dr |A|012346|-|*UUUU|***0*| |1110_001_101_010_rrr [ROXL.W #1,Dr]
//ROL.W Dr |A|012346|-|-UUUU|-**0*| |1110_001_101_011_rrr [ROL.W #1,Dr]
//
//ASL.W #<data>,Dr
//ASL.W Dq,Dr
//ASL.W <ea>
// 算術左シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタ0 アイ**ア Z=イウエオカキクケコサシスセソタ==0,V=アイ!=0/-1
// :
// 15 ................タ000000000000000 ソタ**ソ Z=タ==0,V=アイウエオカキクケコサシスセソタ!=0/-1
// 16 ................0000000000000000 タ01*タ V=アイウエオカキクケコサシスセソタ!=0
// 17 ................0000000000000000 001*0 V=アイウエオカキクケコサシスセソタ!=0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V ASRで元に戻せないときセット。他はクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//LSL.W #<data>,Dr
//LSL.W Dq,Dr
//LSL.W <ea>
// 論理左シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタ0 アイ*0ア Z=イウエオカキクケコサシスセソタ==0
// :
// 15 ................タ000000000000000 ソタ*0ソ Z=タ==0
// 16 ................0000000000000000 タ010タ
// 17 ................0000000000000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//ROL.W #<data>,Dr
//ROL.W Dq,Dr
//ROL.W <ea>
// 左ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタア Xイ*0ア Z=アイウエオカキクケコサシスセソタ==0
// :
// 15 ................タアイウエオカキクケコサシスセソ Xタ*0ソ Z=アイウエオカキクケコサシスセソタ==0
// 16 ................アイウエオカキクケコサシスセソタ Xア*0タ Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最下位ビット
//
//ROXL.W #<data>,Dr
//ROXL.W Dq,Dr
//ROXL.W <ea>
// 拡張左ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタX アイ*0ア Z=イウエオカキクケコサシスセソタX==0
// 2 ................ウエオカキクケコサシスセソタXア イウ*0イ Z=アウエオカキクケコサシスセソタX==0
// :
// 15 ................タXアイウエオカキクケコサシスセ ソタ*0ソ Z=アイウエオカキクケコサシスセタX==0
// 16 ................Xアイウエオカキクケコサシスセソ タX*0タ Z=アイウエオカキクケコサシスセソX==0
// 17 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpXxlToRegWord () throws M68kException {
int rrr;
int x = XEiJ.regRn[rrr = XEiJ.regOC & 7];
int y;
int z;
int t;
XEiJ.mpuCycleCount++;
switch (XEiJ.regOC >> 3 & 0b111_000 >> 3) {
case 0b000_000 >> 3: //ASL.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) ((t = x << y) << 1));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (z >> y + 1 != (short) x ? XEiJ.REG_CCR_V : 0) | (short) t >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //VはASRで元に戻せないときセット。XとCは最後に押し出されたビット
break;
case 0b001_000 >> 3: //LSL.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) ((t = x << y) << 1));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (short) t >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b010_000 >> 3: //ROXL.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
z = x << 1 | XEiJ.regCCR >> 4 & 1;
if (y == 1 - 1) { //y=data-1=1-1
t = x;
} else { //y=data-1=2-1~8-1
z = (t = z << y - (2 - 1)) << 1 | (char) x >>> 17 - 1 - y;
}
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) z);
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (short) t >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b011_000 >> 3: //ROL.W #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) (x << y + 1 | (char) x >>> 16 - 1 - y));
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | z & 1; //Xは変化しない。Cは結果の最下位ビット
break;
case 0b100_000 >> 3: //ASL.W Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y <= 15) { //y=data=0~15
if (y == 0) { //y=data=0
z = (short) x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。VとCはクリア
} else { //y=data=1~15
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) ((t = x << y - 1) << 1));
t = (z >> y != (short) x ? XEiJ.REG_CCR_V : 0) | (short) t >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //VはASRで元に戻せないときセット。XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
} else { //y=data=16~63
XEiJ.regRn[rrr] = ~0xffff & x;
XEiJ.regCCR = XEiJ.REG_CCR_Z | ((short) x != 0 ? XEiJ.REG_CCR_V : 0) | (y == 16 ? -(x & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C) : 0);
}
break;
case 0b101_000 >> 3: //LSL.W Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = (short) x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) ((t = y <= 16 ? x << y - 1 : 0) << 1));
t = (short) t >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b110_000 >> 3: //ROXL.W Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
//y %= 17;
y = (y & 15) - (y >> 4); //y=data=-3~15
y += y >> 4 & 17; //y=data=0~16
if (y == 0) { //y=data=0
z = (short) x;
t = -(XEiJ.regCCR >> 4 & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //Xは変化しない。CはXのコピー
} else { //y=data=1~16
z = x << 1 | XEiJ.regCCR >> 4 & 1;
if (y == 1) { //y=data=1
t = x; //Cは最後に押し出されたビット
} else { //y=data=2~16
z = (t = z << y - 2) << 1 | (char) x >>> 17 - y;
}
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) z);
t = (short) t >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b111_000 >> 3: //ROL.W Dq,Dr
default:
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) {
z = (short) x;
t = 0; //Cはクリア
} else {
y &= 15; //y=data=0~15
XEiJ.regRn[rrr] = ~0xffff & x | (char) (z = (short) (x << y | (char) x >>> 16 - y));
t = z & 1; //Cは結果の最下位ビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | t; //Xは変化しない
}
} //irpXxlToRegWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASL.L #<data>,Dr |-|012346|-|UUUUU|*****| |1110_qqq_110_000_rrr
//LSL.L #<data>,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_110_001_rrr
//ROXL.L #<data>,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_110_010_rrr
//ROL.L #<data>,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_110_011_rrr
//ASL.L Dq,Dr |-|012346|-|UUUUU|*****| |1110_qqq_110_100_rrr
//LSL.L Dq,Dr |-|012346|-|UUUUU|***0*| |1110_qqq_110_101_rrr
//ROXL.L Dq,Dr |-|012346|-|*UUUU|***0*| |1110_qqq_110_110_rrr
//ROL.L Dq,Dr |-|012346|-|-UUUU|-**0*| |1110_qqq_110_111_rrr
//ASL.L Dr |A|012346|-|UUUUU|*****| |1110_001_110_000_rrr [ASL.L #1,Dr]
//LSL.L Dr |A|012346|-|UUUUU|***0*| |1110_001_110_001_rrr [LSL.L #1,Dr]
//ROXL.L Dr |A|012346|-|*UUUU|***0*| |1110_001_110_010_rrr [ROXL.L #1,Dr]
//ROL.L Dr |A|012346|-|-UUUU|-**0*| |1110_001_110_011_rrr [ROL.L #1,Dr]
//
//ASL.L #<data>,Dr
//ASL.L Dq,Dr
// 算術左シフトロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア**0 Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ0 アイ**ア Z=イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0,V=アイ!=0/-1
// :
// 31 ミ0000000000000000000000000000000 マミ**マ Z=ミ==0,V=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ!=0/-1
// 32 00000000000000000000000000000000 ミ01*ミ V=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ!=0
// 33 00000000000000000000000000000000 001*0 V=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ!=0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V ASRで元に戻せないときセット。他はクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//LSL.L #<data>,Dr
//LSL.L Dq,Dr
// 論理左シフトロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*00 Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ0 アイ*0ア Z=イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// :
// 31 ミ0000000000000000000000000000000 マミ*0マ Z=ミ==0
// 32 00000000000000000000000000000000 ミ010ミ
// 33 00000000000000000000000000000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
//
//ROL.L #<data>,Dr
//ROL.L Dq,Dr
// 左ローテートロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*00 Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミア Xイ*0ア Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// :
// 31 ミアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ Xミ*0マ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 32 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*0ミ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最下位ビット
//
//ROXL.L #<data>,Dr
//ROXL.L Dq,Dr
// 拡張左ローテートロング
// アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ XNZVC
// 0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*0X Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// 1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX アイ*0ア Z=イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX==0
// 2 ウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミXア イウ*0イ Z=アウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX==0
// :
// 31 ミXアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホ マミ*0マ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホミX==0
// 32 Xアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミX*0ミ Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマX==0
// 33 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ Xア*0X Z=アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpXxlToRegLong () throws M68kException {
int rrr;
int x = XEiJ.regRn[rrr = XEiJ.regOC & 7];
int y;
int z;
int t;
XEiJ.mpuCycleCount++;
switch (XEiJ.regOC >> 3 & 0b111_000 >> 3) {
case 0b000_000 >> 3: //ASL.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = z = (t = x << y) << 1;
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | (z >> y + 1 != x ? XEiJ.REG_CCR_V : 0) | t >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //VはASRで元に戻せないときセット。XとCは最後に押し出されたビット
break;
case 0b001_000 >> 3: //LSL.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = z = (t = x << y) << 1;
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b010_000 >> 3: //ROXL.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
z = x << 1 | XEiJ.regCCR >> 4 & 1;
if (y == 1 - 1) { //y=data-1=1-1
t = x;
} else { //y=data-1=2-1~8-1
z = (t = z << y - (2 - 1)) << 1 | x >>> -y; //Javaのシフト演算子は5ビットでマスクされるので33-1-yを-yに省略
}
XEiJ.regRn[rrr] = z;
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
break;
case 0b011_000 >> 3: //ROL.L #<data>,Dr
y = (XEiJ.regOC >> 9) - 1 & 7; //y=data-1=1-1~8-1
XEiJ.regRn[rrr] = z = x << y + 1 | x >>> ~y; //Javaのシフト演算子は5ビットでマスクされるので32-1-yを~yに省略
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | z & 1; //Xは変化しない。Cは結果の最下位ビット
break;
case 0b100_000 >> 3: //ASL.L Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y <= 31) { //y=data=0~31
if (y == 0) { //y=data=0
z = x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。VとCはクリア
} else { //y=data=1~31
XEiJ.regRn[rrr] = z = (t = x << y - 1) << 1;
t = (z >> y != x ? XEiJ.REG_CCR_V : 0) | t >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //VはASRで元に戻せないときセット。XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
} else { //y=data=32~63
XEiJ.regRn[rrr] = 0;
XEiJ.regCCR = XEiJ.REG_CCR_Z | (x != 0 ? XEiJ.REG_CCR_V : 0) | (y == 32 ? -(x & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C) : 0);
}
break;
case 0b101_000 >> 3: //LSL.L Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) { //y=data=0
z = x;
t = XEiJ.regCCR & XEiJ.REG_CCR_X; //Xは変化しない。Cはクリア
} else { //y=data=1~63
XEiJ.regRn[rrr] = z = (t = y <= 32 ? x << y - 1 : 0) << 1;
t = t >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b110_000 >> 3: //ROXL.L Dq,Dr
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
//y %= 33;
y -= 32 - y >> 6 & 33; //y=data=0~32
if (y == 0) { //y=data=0
z = x;
t = -(XEiJ.regCCR >> 4 & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //Xは変化しない。CはXのコピー
} else { //y=data=1~32
z = x << 1 | XEiJ.regCCR >> 4 & 1;
if (y == 1) { //y=data=1
t = x; //Cは最後に押し出されたビット
} else { //y=data=2~32
z = (t = z << y - 2) << 1 | x >>> 33 - y;
}
XEiJ.regRn[rrr] = z;
t = t >> 31 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C); //XとCは最後に押し出されたビット
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.REG_CCR_Z : 0) | t;
break;
case 0b111_000 >> 3: //ROL.L Dq,Dr
default:
y = XEiJ.regRn[XEiJ.regOC >> 9 & 7] & 63; //y=0~63。Javaのシフト演算子は5ビットでマスクされることに注意
if (y == 0) {
z = x;
t = 0; //Cはクリア
} else {
XEiJ.regRn[rrr] = z = x << y | x >>> -y; //Javaのシフト演算子は5ビットでマスクされるのでy&31をyに、32-(y&31)を-yに省略。y=32のときx|xになるが問題ない
t = z & 1;
}
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X) | t; //Xは変化しない
}
} //irpXxlToRegLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ASL.W <ea> |-|012346|-|UUUUU|*****| M+-WXZ |1110_000_111_mmm_rrr
//
//ASL.W #<data>,Dr
//ASL.W Dq,Dr
//ASL.W <ea>
// 算術左シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタ0 アイ**ア Z=イウエオカキクケコサシスセソタ==0,V=アイ!=0/-1
// :
// 15 ................タ000000000000000 ソタ**ソ Z=タ==0,V=アイウエオカキクケコサシスセソタ!=0/-1
// 16 ................0000000000000000 タ01*タ V=アイウエオカキクケコサシスセソタ!=0
// 17 ................0000000000000000 001*0 V=アイウエオカキクケコサシスセソタ!=0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V ASRで元に戻せないときセット。他はクリア
// C countが0のときクリア。他は最後に押し出されたビット
public static void irpAslToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordSignData (a, XEiJ.regSRS);
int z = (short) (x << 1);
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = ((z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
(x ^ z) >>> 31 << 1 | //Vは最上位ビットが変化したときセット
x >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //XとCは最後に押し出されたビット
} //irpAslToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//LSR.W <ea> |-|012346|-|UUUUU|*0*0*| M+-WXZ |1110_001_011_mmm_rrr
//
//LSR.W #<data>,Dr
//LSR.W Dq,Dr
//LSR.W <ea>
// 論理右シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................0アイウエオカキクケコサシスセソ タ0*0タ Z=アイウエオカキクケコサシスセソ==0
// :
// 15 ................000000000000000ア イ0*0イ Z=ア==0
// 16 ................0000000000000000 ア010ア
// 17 ................0000000000000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
public static void irpLsrToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordZeroData (a, XEiJ.regSRS);
int z = x >>> 1;
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = ((z == 0 ? XEiJ.REG_CCR_Z : 0) |
-(x & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //XとCは最後に押し出されたビット
} //irpLsrToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//LSL.W <ea> |-|012346|-|UUUUU|***0*| M+-WXZ |1110_001_111_mmm_rrr
//
//LSL.W #<data>,Dr
//LSL.W Dq,Dr
//LSL.W <ea>
// 論理左シフトワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタ0 アイ*0ア Z=イウエオカキクケコサシスセソタ==0
// :
// 15 ................タ000000000000000 ソタ*0ソ Z=タ==0
// 16 ................0000000000000000 タ010タ
// 17 ................0000000000000000 00100
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は最後に押し出されたビット
public static void irpLslToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordSignData (a, XEiJ.regSRS);
int z = (short) (x << 1);
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = ((z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
x >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //XとCは最後に押し出されたビット
} //irpLslToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ROXR.W <ea> |-|012346|-|*UUUU|***0*| M+-WXZ |1110_010_011_mmm_rrr
//
//ROXR.W #<data>,Dr
//ROXR.W Dq,Dr
//ROXR.W <ea>
// 拡張右ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// 1 ................Xアイウエオカキクケコサシスセソ タX*0タ Z=アイウエオカキクケコサシスセソX==0
// 2 ................タXアイウエオカキクケコサシスセ ソタ*0ソ Z=アイウエオカキクケコサシスセタX==0
// :
// 15 ................ウエオカキクケコサシスセソタXア イウ*0イ Z=アウエオカキクケコサシスセソタX==0
// 16 ................イウエオカキクケコサシスセソタX アイ*0ア Z=イウエオカキクケコサシスセソタX==0
// 17 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpRoxrToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordZeroData (a, XEiJ.regSRS);
int z = -(XEiJ.regCCR & XEiJ.REG_CCR_X) << 15 - 4 | x >>> 1;
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = ((z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
-(x & 1) & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //XとCは最後に押し出されたビット
} //irpRoxrToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ROXL.W <ea> |-|012346|-|*UUUU|***0*| M+-WXZ |1110_010_111_mmm_rrr
//
//ROXL.W #<data>,Dr
//ROXL.W Dq,Dr
//ROXL.W <ea>
// 拡張左ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタX アイ*0ア Z=イウエオカキクケコサシスセソタX==0
// 2 ................ウエオカキクケコサシスセソタXア イウ*0イ Z=アウエオカキクケコサシスセソタX==0
// :
// 15 ................タXアイウエオカキクケコサシスセ ソタ*0ソ Z=アイウエオカキクケコサシスセタX==0
// 16 ................Xアイウエオカキクケコサシスセソ タX*0タ Z=アイウエオカキクケコサシスセソX==0
// 17 ................アイウエオカキクケコサシスセソタ Xア*0X Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X countが0のとき変化しない。他は最後に押し出されたビット
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときXのコピー。他は最後に押し出されたビット
public static void irpRoxlToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordSignData (a, XEiJ.regSRS);
int z = (short) (x << 1 | XEiJ.regCCR >> 4 & 1);
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = ((z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
x >> 15 & (XEiJ.REG_CCR_X | XEiJ.REG_CCR_C)); //XとCは最後に押し出されたビット
} //irpRoxlToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ROR.W <ea> |-|012346|-|-UUUU|-**0*| M+-WXZ |1110_011_011_mmm_rrr
//
//ROR.W #<data>,Dr
//ROR.W Dq,Dr
//ROR.W <ea>
// 右ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................タアイウエオカキクケコサシスセソ Xタ*0タ Z=アイウエオカキクケコサシスセソタ==0
// :
// 15 ................イウエオカキクケコサシスセソタア Xイ*0イ Z=アイウエオカキクケコサシスセソタ==0
// 16 ................アイウエオカキクケコサシスセソタ Xア*0ア Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最上位ビット
public static void irpRorToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordZeroData (a, XEiJ.regSRS);
int z = (short) (x << 15 | x >>> 1);
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = (XEiJ.regCCR & XEiJ.REG_CCR_X | //Xは変化しない
(z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
z >>> 31); //Cは結果の最上位ビット
} //irpRorToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//ROL.W <ea> |-|012346|-|-UUUU|-**0*| M+-WXZ |1110_011_111_mmm_rrr
//
//ROL.W #<data>,Dr
//ROL.W Dq,Dr
//ROL.W <ea>
// 左ローテートワード
// ................アイウエオカキクケコサシスセソタ XNZVC
// 0 ................アイウエオカキクケコサシスセソタ Xア*00 Z=アイウエオカキクケコサシスセソタ==0
// 1 ................イウエオカキクケコサシスセソタア Xイ*0ア Z=アイウエオカキクケコサシスセソタ==0
// :
// 15 ................タアイウエオカキクケコサシスセソ Xタ*0ソ Z=アイウエオカキクケコサシスセソタ==0
// 16 ................アイウエオカキクケコサシスセソタ Xア*0タ Z=アイウエオカキクケコサシスセソタ==0
// CCR
// X 常に変化しない
// N 結果の最上位ビット
// Z 結果が0のときセット。他はクリア
// V 常にクリア
// C countが0のときクリア。他は結果の最下位ビット
public static void irpRolToMem () throws M68kException {
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = efaMltWord (ea);
int x = mmuModifyWordZeroData (a, XEiJ.regSRS);
int z = (short) (x << 1 | x >>> 15);
mmuWriteWordData (a, z, XEiJ.regSRS);
XEiJ.regCCR = (XEiJ.regCCR & XEiJ.REG_CCR_X | //Xは変化しない
(z < 0 ? XEiJ.REG_CCR_N : 0) |
(z == 0 ? XEiJ.REG_CCR_Z : 0) |
z & 1); //Cは結果の最下位ビット
} //irpRolToMem
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFTST <ea>{#o:#w} |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_011_mmm_rrr-00000ooooo0wwwww
//BFTST <ea>{#o:Dw} |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_011_mmm_rrr-00000ooooo100www
//BFTST <ea>{Do:#w} |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_011_mmm_rrr-0000100ooo0wwwww
//BFTST <ea>{Do:Dw} |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_011_mmm_rrr-0000100ooo100www
public static void irpBftst () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0000_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 6;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFTST Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
} else { //BFTST <mem>{~}
int a = efaCntLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
o &= 7;
z = 31 - w + o >> 3; //フィールドが跨ぐバイト境界の数。0~4
z = (z == 0 ? mmuReadByteSignData (m60Address = a, XEiJ.regSRS) << 24 + o : //不要なバイトにアクセスしない
z == 1 ? mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 16 + o : //020以上なのでアドレスエラーは出ない
z == 2 ? (mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 8 | mmuReadByteZeroData (a + 2, XEiJ.regSRS)) << 8 + o :
z == 3 ? mmuReadLongData (m60Address = a, XEiJ.regSRS) << o :
mmuReadLongData (m60Address = a, XEiJ.regSRS) << o | mmuReadByteZeroData (m60Address = a + 4, XEiJ.regSRS) >>> 8 - o);
}
z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBftst
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFEXTU <ea>{#o:#w},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_111_mmm_rrr-0nnn0ooooo0wwwww
//BFEXTU <ea>{#o:Dw},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_111_mmm_rrr-0nnn0ooooo100www
//BFEXTU <ea>{Do:#w},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_111_mmm_rrr-0nnn100ooo0wwwww
//BFEXTU <ea>{Do:Dw},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_100_111_mmm_rrr-0nnn100ooo100www
public static void irpBfextu () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0111_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int n = w >> 12;
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 6;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFEXTU Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
} else { //BFEXTU <mem>{~}
int a = efaCntLong (ea) + (o >> 3);
o &= 7;
z = 31 - w + o >> 3;
z = (z == 0 ? mmuReadByteSignData (m60Address = a, XEiJ.regSRS) << 24 + o : //不要なバイトにアクセスしない
z == 1 ? mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 16 + o : //020以上なのでアドレスエラーは出ない
z == 2 ? (mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 8 | mmuReadByteZeroData (a + 2, XEiJ.regSRS)) << 8 + o :
z == 3 ? mmuReadLongData (m60Address = a, XEiJ.regSRS) << o :
mmuReadLongData (m60Address = a, XEiJ.regSRS) << o | mmuReadByteZeroData (m60Address = a + 4, XEiJ.regSRS) >>> 8 - o);
}
XEiJ.regRn[n] = z >>> w; //ゼロ拡張
z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfextu
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFCHG <ea>{#o:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_101_011_mmm_rrr-00000ooooo0wwwww
//BFCHG <ea>{#o:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_101_011_mmm_rrr-00000ooooo100www
//BFCHG <ea>{Do:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_101_011_mmm_rrr-0000100ooo0wwwww
//BFCHG <ea>{Do:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_101_011_mmm_rrr-0000100ooo100www
public static void irpBfchg () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0000_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 8;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFCHG Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
int t = z ^ -1 << w; //フィールドの幅だけ反転する
XEiJ.regRn[ea] = t << -o | t >>> o;
} else { //BFCHG <mem>{~}
int a = efaCltLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
o &= 7;
z = 31 - w + o >> 3; //フィールドが跨ぐバイト境界の数。0~4
if (z == 0) {
// <ea>{2,5} o=2,w=32-5=27 <ea> --abcde-
int t = mmuModifyByteSignData (a, XEiJ.regSRS) << 24; // t --abcde- 00000000 00000000 00000000 不要なバイトにアクセスしない
z = t << o; // z abcde-00 00000000 00000000 00000000
// // -1<<w 11111000 00000000 00000000 00000000
// // -1<<w>>>o 00111110 00000000 00000000 00000000
// //t^-1<<w>>>o --ABCDE- 00000000 00000000 00000000
mmuWriteByteData (a, (t ^ -1 << w >>> o) >>> 24, XEiJ.regSRS); // <ea> --ABCDE-
} else if (z == 1) {
// <ea>{7,5} o=7,w=32-5=27 <ea> -------a bcde----
int t = mmuModifyWordSignData (a, XEiJ.regSRS) << 16; // t -------a bcde---- 00000000 00000000 020以上なのでアドレスエラーは出ない
z = t << o; // z abcde--- -0000000 00000000 00000000
// // -1<<w 11111000 00000000 00000000 00000000
// // -1<<w>>>o 00000001 11110000 00000000 00000000
// //t^-1<<w>>>o -------A BCDE---- 00000000 00000000
mmuWriteWordData (a, (t ^ -1 << w >>> o) >>> 16, XEiJ.regSRS); // <ea> -------A BCDE----
} else if (z == 2) {
// <ea>{7,12} o=7,w=32-12=20 <ea> -------a bcdefghi jkl-----
int t = mmuModifyWordSignData (a, XEiJ.regSRS) << 16 | mmuModifyByteZeroData (a + 2, XEiJ.regSRS) << 8; // t -------a bcdefghi jkl----- 00000000
z = t << o; // z abcdefgh ijkl---- -0000000 00000000
// // -1<<w 11111111 11110000 00000000 00000000
// // -1<<w>>>o 00000001 11111111 11100000 00000000
t ^= -1 << w >>> o; // t -------A BCDEFGHI JKL----- 00000000
mmuWriteWordData (a, t >>> 16, XEiJ.regSRS); // <ea> -------A BCDEFGHI jkl-----
mmuWriteByteData (a + 2, t >>> 8, XEiJ.regSRS); // <ea> -------A BCDEFGHI JKL-----
} else if (z == 3) {
// <ea>{7,19} o=7,w=32-19=13 <ea> -------a bcdefghi jklmnopq rs------
int t = mmuModifyLongData (a, XEiJ.regSRS); // t -------a bcdefghi jklmnopq rs------
z = t << o; // z abcdefgh ijklmnop qrs----- -0000000
// // -1<<w 11111111 11111111 11100000 00000000
// // -1<<w>>>o 00000001 11111111 11111111 11000000
mmuWriteLongData (a, t ^ -1 << w >>> o, XEiJ.regSRS); // <ea> -------A BCDEFGHI JKLMNOPQ RS------
} else {
// <ea>{7,26} o=7,w=32-26=6 <ea> -------a bcdefghi jklmnopq rstuvwxy z-------
int t = mmuModifyLongData (a, XEiJ.regSRS); // t -------a bcdefghi jklmnopq rstuvwxy
z = t << o; // z abcdefgh ijklmnop qrstuvwx y0000000
// -1>>>o 00000001 11111111 11111111 11111111
mmuWriteLongData (a, t ^ -1 >>> o, XEiJ.regSRS); // <ea> -------A BCDEFGHI JKLMNOPQ RSTUVWXY
t = mmuModifyByteZeroData (a + 4, XEiJ.regSRS); // t 00000000 00000000 00000000 z-------
// // t>>>8-o 00000000 00000000 00000000 0z------
z |= t >>> 8 - o; // z abcdefgh ijklmnop qrstuvwx yz------
// // -1<<8-o+w 11111111 11111111 11111111 10000000
mmuWriteByteData (a + 4, t ^ -1 << 8 - o + w, XEiJ.regSRS); // <ea> -------A BCDEFGHI JKLMNOPQ RSTUVWXY Z-------
}
}
z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfchg
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFEXTS <ea>{#o:#w},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_101_111_mmm_rrr-0nnn0ooooo0wwwww
//BFEXTS <ea>{#o:Dw},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_101_111_mmm_rrr-0nnn0ooooo100www
//BFEXTS <ea>{Do:#w},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_101_111_mmm_rrr-0nnn100ooo0wwwww
//BFEXTS <ea>{Do:Dw},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_101_111_mmm_rrr-0nnn100ooo100www
public static void irpBfexts () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0111_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int n = w >> 12;
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 6;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFEXTS Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
} else { //BFEXTS <mem>{~}
int a = efaCntLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
o &= 7;
z = 31 - w + o >> 3; //フィールドが跨ぐバイト境界の数。0~4
z = (z == 0 ? mmuReadByteSignData (m60Address = a, XEiJ.regSRS) << 24 + o : //不要なバイトにアクセスしない
z == 1 ? mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 16 + o : //020以上なのでアドレスエラーは出ない
z == 2 ? (mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 8 | mmuReadByteZeroData (a + 2, XEiJ.regSRS)) << 8 + o :
z == 3 ? mmuReadLongData (m60Address = a, XEiJ.regSRS) << o :
mmuReadLongData (m60Address = a, XEiJ.regSRS) << o | mmuReadByteZeroData (m60Address = a + 4, XEiJ.regSRS) >>> 8 - o);
}
XEiJ.regRn[n] = z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfexts
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFCLR <ea>{#o:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_110_011_mmm_rrr-00000ooooo0wwwww
//BFCLR <ea>{#o:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_110_011_mmm_rrr-00000ooooo100www
//BFCLR <ea>{Do:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_110_011_mmm_rrr-0000100ooo0wwwww
//BFCLR <ea>{Do:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_110_011_mmm_rrr-0000100ooo100www
public static void irpBfclr () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0000_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 8;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFCLR Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
int t = z & ~(-1 << w); //フィールドの幅だけ0を並べる
XEiJ.regRn[ea] = t << -o | t >>> o;
} else { //BFCLR <mem>{~}
int a = efaCltLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
o &= 7;
z = 31 - w + o >> 3; //フィールドが跨ぐバイト境界の数。0~4
if (z == 0) {
// <ea>{2,5} o=2,w=32-5=27 <ea> --abcde-
int t = mmuModifyByteSignData (a, XEiJ.regSRS) << 24; // t --abcde- 00000000 00000000 00000000 不要なバイトにアクセスしない
z = t << o; // z abcde-00 00000000 00000000 00000000
// // -1<<w 11111000 00000000 00000000 00000000
// // -1<<w>>>o 00111110 00000000 00000000 00000000
// //~(-1<<w>>>o) 11000001 11111111 11111111 11111111
// //t&~(-1<<w>>>o) --00000- 00000000 00000000 00000000
mmuWriteByteData (a, (t & ~(-1 << w >>> o)) >>> 24, XEiJ.regSRS); // <ea> --00000-
} else if (z == 1) {
// <ea>{7,5} o=7,w=32-5=27 <ea> -------a bcde----
int t = mmuModifyWordSignData (a, XEiJ.regSRS) << 16; // t -------a bcde---- 00000000 00000000 020以上なのでアドレスエラーは出ない
z = t << o; // z abcde--- -0000000 00000000 00000000
// // -1<<w 11111000 00000000 00000000 00000000
// // -1<<w>>>o 00000001 11110000 00000000 00000000
// //~(-1<<w>>>o) 11111110 00001111 11111111 11111111
// //t&~(-1<<w>>>o) -------0 0000---- 00000000 00000000
mmuWriteWordData (a, (t & ~(-1 << w >>> o)) >>> 16, XEiJ.regSRS); // <ea> -------0 0000----
} else if (z == 2) {
// <ea>{7,12} o=7,w=32-12=20 <ea> -------a bcdefghi jkl-----
int t = mmuModifyWordSignData (a, XEiJ.regSRS) << 16 | mmuModifyByteZeroData (a + 2, XEiJ.regSRS) << 8; // t -------a bcdefghi jkl----- 00000000
z = t << o; // z abcdefgh ijkl---- -0000000 00000000
// // -1<<w 11111111 11110000 00000000 00000000
// // -1<<w>>>o 00000001 11111111 11100000 00000000
// //~(-1<<w>>>o) 11111110 00000000 00011111 11111111
t &= ~(-1 << w >>> o); // t -------0 00000000 000----- 00000000
mmuWriteWordData (a, t >>> 16, XEiJ.regSRS); // <ea> -------0 00000000 jkl-----
mmuWriteByteData (a + 2, t >>> 8, XEiJ.regSRS); // <ea> -------0 00000000 000-----
} else if (z == 3) {
// <ea>{7,19} o=7,w=32-19=13 <ea> -------a bcdefghi jklmnopq rs------
int t = mmuModifyLongData (a, XEiJ.regSRS); // t -------a bcdefghi jklmnopq rs------
z = t << o; // z abcdefgh ijklmnop qrs----- -0000000
// // -1<<w 11111111 11111111 11100000 00000000
// // -1<<w>>>o 00000001 11111111 11111111 11000000
// //~(-1<<w>>>o) 11111110 00000000 00000000 00111111
mmuWriteLongData (a, t & ~(-1 << w >>> o), XEiJ.regSRS); // <ea> -------0 00000000 00000000 00------
} else {
// <ea>{7,26} o=7,w=32-26=6 <ea> -------a bcdefghi jklmnopq rstuvwxy z-------
int t = mmuModifyLongData (a, XEiJ.regSRS); // t -------a bcdefghi jklmnopq rstuvwxy
z = t << o; // z abcdefgh ijklmnop qrstuvwx y0000000
// -1>>>o 00000001 11111111 11111111 11111111
// ~(-1>>>o) 11111110 00000000 00000000 00000000
mmuWriteLongData (a, t & ~(-1 >>> o), XEiJ.regSRS); // <ea> -------0 00000000 00000000 00000000
t = mmuModifyByteZeroData (a + 4, XEiJ.regSRS); // t 00000000 00000000 00000000 z-------
// // t>>>8-o 00000000 00000000 00000000 0z------
z |= t >>> 8 - o; // z abcdefgh ijklmnop qrstuvwx yz------
// // -1<<8-o+w 11111111 11111111 11111111 10000000
// //~(-1<<8-o+w) 00000000 00000000 00000000 01111111
mmuWriteByteData (a + 4, t & ~(-1 << 8 - o + w), XEiJ.regSRS); // <ea> -------0 00000000 00000000 00000000 0-------
}
}
z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfclr
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFFFO <ea>{#o:#w},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_110_111_mmm_rrr-0nnn0ooooo0wwwww
//BFFFO <ea>{#o:Dw},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_110_111_mmm_rrr-0nnn0ooooo100www
//BFFFO <ea>{Do:#w},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_110_111_mmm_rrr-0nnn100ooo0wwwww
//BFFFO <ea>{Do:Dw},Dn |-|--2346|-|-UUUU|-**00|D M WXZP |1110_110_111_mmm_rrr-0nnn100ooo100www
public static void irpBfffo () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0111_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int n = w >> 12;
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 9;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFFFO Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
} else { //BFFFO <mem>{~}
int a = efaCntLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
int o7 = o & 7;
z = 31 - w + o7 >> 3; //フィールドが跨ぐバイト境界の数。0~4
z = (z == 0 ? mmuReadByteSignData (m60Address = a, XEiJ.regSRS) << 24 + o7 : //不要なバイトにアクセスしない
z == 1 ? mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 16 + o7 : //020以上なのでアドレスエラーは出ない
z == 2 ? (mmuReadWordSignData (m60Address = a, XEiJ.regSRS) << 8 | mmuReadByteZeroData (a + 2, XEiJ.regSRS)) << 8 + o7 :
z == 3 ? mmuReadLongData (m60Address = a, XEiJ.regSRS) << o7 :
mmuReadLongData (m60Address = a, XEiJ.regSRS) << o7 | mmuReadByteZeroData (m60Address = a + 4, XEiJ.regSRS) >>> 8 - o7);
}
if (true) {
XEiJ.regRn[n] = Integer.numberOfLeadingZeros (z >>> w) - w + o; //ゼロ拡張してから1のビットを探す。見つからないときはoffset+widthになる
} else {
int t = z >>> w;
if (t == 0) {
XEiJ.regRn[n] = 32 - w + o;
} else {
int k = -(t >>> 16) >> 16 & 16;
k += -(t >>> k + 8) >> 8 & 8;
k += -(t >>> k + 4) >> 4 & 4;
// bit3 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
// bit2 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
// bit1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
// bit0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
XEiJ.regRn[n] = ((0b11_11_11_11_11_11_11_11_10_10_10_10_01_01_00_00 >>> (t >>> k << 1)) & 3) + k - w + o; //intのシフトカウントは下位5bitだけが使用される
}
}
z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfffo
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFSET <ea>{#o:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_011_mmm_rrr-00000ooooo0wwwww
//BFSET <ea>{#o:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_011_mmm_rrr-00000ooooo100www
//BFSET <ea>{Do:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_011_mmm_rrr-0000100ooo0wwwww
//BFSET <ea>{Do:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_011_mmm_rrr-0000100ooo100www
public static void irpBfset () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0000_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 8;
int ea = XEiJ.regOC & 63;
int z;
if (ea < XEiJ.EA_AR) { //BFSET Dr{~}
z = XEiJ.regRn[ea];
z = z << o | z >>> -o; //下位からはみ出したフィールドは上位に戻る
int t = z | -1 << w; //フィールドの幅だけ1を並べる
XEiJ.regRn[ea] = t << -o | t >>> o;
} else { //BFSET <mem>{~}
int a = efaCltLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
o &= 7;
z = 31 - w + o >> 3; //フィールドが跨ぐバイト境界の数。0~4
if (z == 0) {
// <ea>{2,5} o=2,w=32-5=27 <ea> --abcde-
int t = mmuModifyByteSignData (a, XEiJ.regSRS) << 24; // t --abcde- 00000000 00000000 00000000 不要なバイトにアクセスしない
z = t << o; // z abcde-00 00000000 00000000 00000000
// // -1<<w 11111000 00000000 00000000 00000000
// // -1<<w>>>o 00111110 00000000 00000000 00000000
// //t|-1<<w>>>o --11111- 00000000 00000000 00000000
mmuWriteByteData (a, (t | -1 << w >>> o) >>> 24, XEiJ.regSRS); // <ea> --11111-
} else if (z == 1) {
// <ea>{7,5} o=7,w=32-5=27 <ea> -------a bcde----
int t = mmuModifyWordSignData (a, XEiJ.regSRS) << 16; // t -------a bcde---- 00000000 00000000 020以上なのでアドレスエラーは出ない
z = t << o; // z abcde--- -0000000 00000000 00000000
// // -1<<w 11111000 00000000 00000000 00000000
// // -1<<w>>>o 00000001 11110000 00000000 00000000
// //t|-1<<w>>>o -------1 1111---- 00000000 00000000
mmuWriteWordData (a, (t | -1 << w >>> o) >>> 16, XEiJ.regSRS); // <ea> -------1 1111----
} else if (z == 2) {
// <ea>{7,12} o=7,w=32-12=20 <ea> -------a bcdefghi jkl-----
int t = mmuModifyWordSignData (a, XEiJ.regSRS) << 16 | mmuModifyByteZeroData (a + 2, XEiJ.regSRS) << 8; // t -------a bcdefghi jkl----- 00000000
z = t << o; // z abcdefgh ijkl---- -0000000 00000000
// // -1<<w 11111111 11110000 00000000 00000000
// // -1<<w>>>o 00000001 11111111 11100000 00000000
t |= -1 << w >>> o; // t -------1 11111111 111----- 00000000
mmuWriteWordData (a, t >>> 16, XEiJ.regSRS); // <ea> -------1 11111111 jkl-----
mmuWriteByteData (a + 2, t >>> 8, XEiJ.regSRS); // <ea> -------1 11111111 111-----
} else if (z == 3) {
// <ea>{7,19} o=7,w=32-19=13 <ea> -------a bcdefghi jklmnopq rs------
int t = mmuModifyLongData (a, XEiJ.regSRS); // t -------a bcdefghi jklmnopq rs------
z = t << o; // z abcdefgh ijklmnop qrs----- -0000000
// // -1<<w 11111111 11111111 11100000 00000000
// // -1<<w>>>o 00000001 11111111 11111111 11000000
mmuWriteLongData (a, t | -1 << w >>> o, XEiJ.regSRS); // <ea> -------1 11111111 11111111 11------
} else {
// <ea>{7,26} o=7,w=32-26=6 <ea> -------a bcdefghi jklmnopq rstuvwxy z-------
int t = mmuModifyLongData (a, XEiJ.regSRS); // t -------a bcdefghi jklmnopq rstuvwxy
z = t << o; // z abcdefgh ijklmnop qrstuvwx y0000000
// -1>>>o 00000001 11111111 11111111 11111111
mmuWriteLongData (a, t | -1 >>> o, XEiJ.regSRS); // <ea> -------1 11111111 11111111 11111111
t = mmuModifyByteZeroData (a + 4, XEiJ.regSRS); // t 00000000 00000000 00000000 z-------
// // t>>>8-o 00000000 00000000 00000000 0z------
z |= t >>> 8 - o; // z abcdefgh ijklmnop qrstuvwx yz------
// // -1<<8-o+w 11111111 11111111 11111111 10000000
mmuWriteByteData (a + 4, t | -1 << 8 - o + w, XEiJ.regSRS); // <ea> -------1 11111111 11111111 11111111 1-------
}
}
z >>= w; //符号拡張。下位のゴミを消す
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfset
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//BFINS Dn,<ea>{#o:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_111_mmm_rrr-0nnn0ooooo0wwwww
//BFINS Dn,<ea>{#o:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_111_mmm_rrr-0nnn0ooooo100www
//BFINS Dn,<ea>{Do:#w} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_111_mmm_rrr-0nnn100ooo0wwwww
//BFINS Dn,<ea>{Do:Dw} |-|--2346|-|-UUUU|-**00|D M WXZ |1110_111_111_mmm_rrr-0nnn100ooo100www
public static void irpBfins () throws M68kException {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & ~0b0111_111_111_111_111) != 0 ||
(w & 0b0000_111_111_000_000) > 0b0000_100_111_000_000 ||
(w & 0b0000_000_000_111_111) > 0b0000_000_000_100_111) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
int n = w >> 12;
int o = w << 31 - 11 >= 0 ? w >> 6 & 31 : XEiJ.regRn[w >> 6 & 7]; //o=offset
w = -(w << 31 - 5 >= 0 ? w : XEiJ.regRn[w & 7]) & 31; //w=32-width。1<=width<=32なので0<=32-width<=31
XEiJ.mpuCycleCount += 6;
int ea = XEiJ.regOC & 63;
int z = XEiJ.regRn[n] << w; //z=Dn<<-width
if (ea < XEiJ.EA_AR) { //BFINS Dn,Dr{~}
// Dr{30,5} o=30,w=32-5=27 t=Dr cde----- -------- -------- ------ab
// t<<o ab000000 00000000 00000000 00000000
// t>>>-o 00cde--- -------- -------- --------
// t<<o|t>>>-o abcde--- -------- -------- --------
// -1<<w 11111000 00000000 00000000 00000000
// ~(-1<<w) 00000111 11111111 11111111 11111111
// (t<<o|t>>>-o)&~(-1<<w) 00000--- -------- -------- --------
// r[n] -------- -------- -------- ---ABCDE
// z=r[n]<<w ABCDE000 00000000 00000000 00000000
// t=(t<<o|t>>>-o)&~(-1<<w)|z ABCDE--- -------- -------- --------
// t<<-o CDE----- -------- -------- ------00
// t>>>o 00000000 00000000 00000000 000000AB
// t<<-o|t>>>o CDE----- -------- -------- ------AB
int t = XEiJ.regRn[ea];
t = (t << o | t >>> -o) & ~(-1 << w) | z;
XEiJ.regRn[ea] = t << -o | t >>> o;
} else { //BFINS Dn,<mem>{~}
int a = efaCltLong (ea) + (o >> 3); //フィールドの最上位ビットを含むバイトのアドレス
o &= 7;
n = 31 - w + o >> 3; //フィールドが跨ぐバイト境界の数。0~4
if (n == 0) {
// <ea>{2,5} o=2,w=32-5=27 <ea> --abcde-
// XEiJ.busRbs(a)<<24 --abcde- 00000000 00000000 00000000
// -1<<w 11111000 00000000 00000000 00000000
// -1<<w>>>o 00111110 00000000 00000000 00000000
// ~(-1<<w>>>o) 11000001 11111111 11111111 11111111
// XEiJ.busRbs(a)<<24&~(-1<<w>>>o) --00000- 00000000 00000000 00000000
// r[n] -------- -------- -------- ---ABCDE
// z=r[n]<<w ABCDE000 00000000 00000000 00000000
// z>>>o 00ABCDE0 00000000 00000000 00000000
// XEiJ.busRbs(a)<<24&~(-1<<w>>>o)|z>>>o --ABCDE- 00000000 00000000 00000000
mmuWriteByteData (a, (mmuModifyByteSignData (a, XEiJ.regSRS) << 24 & ~(-1 << w >>> o) | z >>> o) >>> 24, XEiJ.regSRS);
} else if (n == 1) {
// <ea>{3,11} o=3,w=32-11=21 <ea> ---abcde fghijk--
// rws(a)<<16 ---abcde fghijk-- 00000000 00000000
// -1<<w 11111111 11100000 00000000 00000000
// -1<<w>>>o 00011111 11111100 00000000 00000000
// ~(-1<<w>>>o) 11100000 00000011 11111111 11111111
// rws(a)<<16&~(-1<<w>>>o) ---00000 000000-- 00000000 00000000
// r[n] -------- -------- -----ABC DEFGHIJK
// z=r[n]<<w ABCDEFGH IJK00000 00000000 00000000
// z>>>o 000ABCDE FGHIJK00 00000000 00000000
// rws(a)<<16&~(-1<<w>>>o)|z>>>o ---ABCDE FGHIJK-- 00000000 00000000
mmuWriteWordData (a, (mmuModifyWordSignData (a, XEiJ.regSRS) << 16 & ~(-1 << w >>> o) | z >>> o) >>> 16, XEiJ.regSRS);
} else if (n == 2) {
// <ea>{4,17} o=4,w=32-17=15 <ea> ----abcd efghijkl mnopq---
// rws(a)<<16|rbz(a+2)<<8 ----abcd efghijkl mnopq--- 00000000
// -1<<w 11111111 11111111 10000000 00000000
// -1<<w>>>o 00001111 11111111 11111000 00000000
// ~(-1<<w>>>o) 11110000 00000000 00000111 11111111
// (rws(a)<<16|rbz(a+2)<<8)&~(-1<<w>>>o) ----0000 00000000 00000--- 00000000
// r[n] -------- -------A BCDEFGHI JKLMNOPQ
// z=r[n]<<w ABCDEFGH IJKLMNOP Q0000000 00000000
// z>>>o 0000ABCD EFGHIJKL MNOPQ000 00000000
// (rws(a)<<16|rbz(a+2)<<8)&~(-1<<w>>>o)|z>>>o ----ABCD EFGHIJKL MNOPQ--- 00000000
int t = (mmuModifyWordSignData (a, XEiJ.regSRS) << 16 | mmuModifyByteZeroData (a + 2, XEiJ.regSRS) << 8) & ~(-1 << w >>> o) | z >>> o;
mmuWriteWordData (a, t >>> 16, XEiJ.regSRS);
mmuWriteByteData (a + 2, t >>> 8, XEiJ.regSRS);
} else if (n == 3) {
// <ea>{5,23} o=5,w=32-23=9 <ea> -----abc defghijk lmnopqrs tuvw----
// rls(a) -----abc defghijk lmnopqrs tuvw----
// -1<<w 11111111 11111111 11111110 00000000
// -1<<w>>>o 00000111 11111111 11111111 11110000
// ~(-1<<w>>>o) 11111000 00000000 00000000 00001111
// rls(a)&~(-1<<w>>>o) -----000 00000000 00000000 0000----
// r[n] -------- -ABCDEFG HIJKLMNO PQRSTUVW
// z=r[n]<<w ABCDEFGH IJKLMNOP QRSTUVW0 00000000
// z>>>o 00000ABC DEFGHIJK LMNOPQRS TUVW0000
// rls(a)&~(-1<<w>>>o)|z>>>o -----ABC DEFGHIJK LMNOPQRS TUVW----
mmuWriteLongData (a, mmuModifyLongData (a, XEiJ.regSRS) & ~(-1 << w >>> o) | z >>> o, XEiJ.regSRS);
} else {
// <ea>{6,29} o=6,w=32-29=3 <ea> ------ab cdefghij klmnopqr stuvwxyz abc-----
// rls(a) ------ab cdefghij klmnopqr stuvwxyz
// -1>>>o 00000011 11111111 11111111 11111111
// ~(-1>>>o) 11111100 00000000 00000000 00000000
// rls(a)&~(-1>>>o) ------00 00000000 00000000 00000000
// r[n] ---ABCDE FGHIJKLM NOPQRSTU VWXYZABC
// z=r[n]<<w ABCDEFGH IJKLMNOP QRSTUVWX YZABC000
// z>>>o 000000AB CDEFGHIJ KLMNOPQR STUVWXYZ
// rls(a)&~(-1>>>o)|z>>>o ------AB CDEFGHIJ KLMNOPQR STUVWXYZ
mmuWriteLongData (a, mmuModifyLongData (a, XEiJ.regSRS) & ~(-1 >>> o) | z >>> o, XEiJ.regSRS);
// rbz(a+4) 00000000 00000000 00000000 abc-----
// -1<<8-o+w 11111111 11111111 11111111 11100000
// ~(-1<<8-o+w) 00000000 00000000 00000000 00011111
// rbz(a+4)&~(-1<<8-o+w) 00000000 00000000 00000000 000-----
// z<<8-o CDEFGHIJ KLMNOPQR STUVWXYZ ABC00000
// rbz(a+4)&~(-1<<8-o+w)|z<<8-o CDEFGHIJ KLMNOPQR STUVWXYZ ABC-----
mmuWriteByteData (a + 4, mmuModifyByteZeroData (a + 4, XEiJ.regSRS) & ~(-1 << 8 - o + w) | z << 8 - o, XEiJ.regSRS);
}
}
//zは上位に寄ったままだが下位の空きは0なのでそのままテストする
XEiJ.regCCR = z >> 28 & XEiJ.REG_CCR_N | (z == 0 ? XEiJ.regCCR & XEiJ.REG_CCR_X | XEiJ.REG_CCR_Z : XEiJ.regCCR & XEiJ.REG_CCR_X); //ccr_tst
} //irpBfins
//浮動小数点例外
// 48 BSUN FP分岐または比較不能状態でのセット
// 49 INEX FP不正確な結果
// 50 DZ FPゼロによる除算
// 51 UNFL FPアンダーフロー
// 52 OPERR FPオペランドエラー
// 53 OVFL FPオーバーフロー
// 54 SNAN FPシグナリングNAN
// 55 FP未実装データ型
//FPSRのビットオフセット→例外ベクタ番号
/*
public static final int[] FP_OFFSET_TO_NUMBER = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48, //16 15 BSUN 48 BSUN FP分岐または比較不能状態でのセット
54, //17 14 SNAN 54 SNAN FPシグナリングNAN
52, //18 13 OPERR 52 OPERR FPオペランドエラー
53, //19 12 OVFL 53 OVFL FPオーバーフロー
51, //20 11 UNFL 51 UNFL FPアンダーフロー
50, //21 10 DZ 50 DZ FPゼロによる除算
49, //22 9 INEX2 49 INEX FP不正確な結果
49, //23 8 INEX1 49 INEX FP不正確な結果
0, 0, 0, 0, 0, 0, 0, 0,
};
*/
public static final byte[] FP_OFFSET_TO_NUMBER = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00006453211\0\0\0\0\0\0\0\0".getBytes (XEiJ.ISO_8859_1);
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FTST.X FPm |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmm0000111010
//FMOVE.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0000000
//FINT.X FPm,FPn |-|--CCS6|-|-----|-----| |1111_001_000_000_000-000mmmnnn0000001
//FSINH.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0000010
//FINTRZ.X FPm,FPn |-|--CCS6|-|-----|-----| |1111_001_000_000_000-000mmmnnn0000011
//FSQRT.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0000100
//FLOGNP1.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0000110
//FETOXM1.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001000
//FTANH.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001001
//FATAN.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001010
//FASIN.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001100
//FATANH.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001101
//FSIN.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001110
//FTAN.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0001111
//FETOX.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0010000
//FTWOTOX.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0010001
//FTENTOX.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0010010
//FLOGN.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0010100
//FLOG10.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0010101
//FLOG2.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0010110
//FABS.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011000
//FCOSH.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011001
//FNEG.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011010
//FACOS.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011100
//FCOS.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011101
//FGETEXP.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011110
//FGETMAN.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0011111
//FDIV.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100000
//FMOD.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100001
//FADD.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100010
//FMUL.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100011
//FSGLDIV.X FPm,FPn |-|--CCS6|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100100
//FREM.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100101
//FSCALE.X FPm,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100110
//FSGLMUL.X FPm,FPn |-|--CCS6|-|-----|-----| |1111_001_000_000_000-000mmmnnn0100111
//FSUB.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0101000
//FCMP.X FPm,FPn |-|--CC46|-|-----|-----| |1111_001_000_000_000-000mmmnnn0111000
//FSMOVE.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1000000
//FSSQRT.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1000001
//FDMOVE.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1000100
//FDSQRT.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1000101
//FSABS.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1011000
//FSNEG.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1011010
//FDABS.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1011100
//FDNEG.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1011110
//FSDIV.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1100000
//FSADD.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1100010
//FSMUL.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1100011
//FDDIV.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1100100
//FDADD.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1100110
//FDMUL.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1100111
//FSSUB.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1101000
//FDSUB.X FPm,FPn |-|----46|-|-----|-----| |1111_001_000_000_000-000mmmnnn1101100
//FSINCOS.X FPm,FPc:FPs |-|--CCSS|-|-----|-----| |1111_001_000_000_000-000mmmsss0110ccc
//FMOVECR.X #ccc,FPn |-|--CCSS|-|-----|-----| |1111_001_000_000_000-010111nnn0cccccc
//FMOVE.L FPn,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-011000nnn0000000
//FMOVE.S FPn,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-011001nnn0000000
//FMOVE.W FPn,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-011100nnn0000000
//FMOVE.B FPn,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-011110nnn0000000
//FMOVE.L FPIAR,<ea> |-|--CC46|-|-----|-----|DAM+-WXZ |1111_001_000_mmm_rrr-1010010000000000
//FMOVEM.L FPIAR,<ea> |-|--CC46|-|-----|-----|DAM+-WXZ |1111_001_000_mmm_rrr-1010010000000000
//FMOVE.L FPSR,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-1010100000000000
//FMOVEM.L FPSR,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-1010100000000000
//FMOVE.L FPCR,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-1011000000000000
//FMOVEM.L FPCR,<ea> |-|--CC46|-|-----|-----|D M+-WXZ |1111_001_000_mmm_rrr-1011000000000000
//FTST.L <ea> |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-0100000000111010
//FMOVE.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0000000
//FINT.L <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0000001
//FSINH.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0000010
//FINTRZ.L <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0000011
//FSQRT.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0000100
//FLOGNP1.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0000110
//FETOXM1.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001000
//FTANH.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001001
//FATAN.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001010
//FASIN.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001100
//FATANH.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001101
//FSIN.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001110
//FTAN.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0001111
//FETOX.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0010000
//FTWOTOX.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0010001
//FTENTOX.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0010010
//FLOGN.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0010100
//FLOG10.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0010101
//FLOG2.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0010110
//FABS.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011000
//FCOSH.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011001
//FNEG.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011010
//FACOS.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011100
//FCOS.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011101
//FGETEXP.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011110
//FGETMAN.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0011111
//FDIV.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100000
//FMOD.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100001
//FADD.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100010
//FMUL.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100011
//FSGLDIV.L <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100100
//FREM.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100101
//FSCALE.L <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100110
//FSGLMUL.L <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0100111
//FSUB.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0101000
//FCMP.L <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn0111000
//FSMOVE.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1000000
//FSSQRT.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1000001
//FDMOVE.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1000100
//FDSQRT.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1000101
//FSABS.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1011000
//FSNEG.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1011010
//FDABS.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1011100
//FDNEG.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1011110
//FSDIV.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1100000
//FSADD.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1100010
//FSMUL.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1100011
//FDDIV.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1100100
//FDADD.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1100110
//FDMUL.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1100111
//FSSUB.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1101000
//FDSUB.L <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000nnn1101100
//FSINCOS.L <ea>,FPc:FPs |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010000sss0110ccc
//FTST.S <ea> |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-0100010000111010
//FMOVE.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0000000
//FINT.S <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0000001
//FSINH.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0000010
//FINTRZ.S <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0000011
//FSQRT.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0000100
//FLOGNP1.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0000110
//FETOXM1.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001000
//FTANH.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001001
//FATAN.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001010
//FASIN.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001100
//FATANH.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001101
//FSIN.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001110
//FTAN.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0001111
//FETOX.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0010000
//FTWOTOX.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0010001
//FTENTOX.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0010010
//FLOGN.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0010100
//FLOG10.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0010101
//FLOG2.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0010110
//FABS.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011000
//FCOSH.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011001
//FNEG.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011010
//FACOS.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011100
//FCOS.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011101
//FGETEXP.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011110
//FGETMAN.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0011111
//FDIV.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100000
//FMOD.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100001
//FADD.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100010
//FMUL.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100011
//FSGLDIV.S <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100100
//FREM.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100101
//FSCALE.S <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100110
//FSGLMUL.S <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0100111
//FSUB.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0101000
//FCMP.S <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn0111000
//FSMOVE.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1000000
//FSSQRT.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1000001
//FDMOVE.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1000100
//FDSQRT.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1000101
//FSABS.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1011000
//FSNEG.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1011010
//FDABS.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1011100
//FDNEG.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1011110
//FSDIV.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1100000
//FSADD.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1100010
//FSMUL.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1100011
//FDDIV.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1100100
//FDADD.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1100110
//FDMUL.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1100111
//FSSUB.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1101000
//FDSUB.S <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001nnn1101100
//FSINCOS.S <ea>,FPc:FPs |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010001sss0110ccc
//FTST.W <ea> |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-0101000000111010
//FMOVE.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0000000
//FINT.W <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0000001
//FSINH.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0000010
//FINTRZ.W <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0000011
//FSQRT.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0000100
//FLOGNP1.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0000110
//FETOXM1.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001000
//FTANH.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001001
//FATAN.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001010
//FASIN.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001100
//FATANH.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001101
//FSIN.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001110
//FTAN.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0001111
//FETOX.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0010000
//FTWOTOX.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0010001
//FTENTOX.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0010010
//FLOGN.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0010100
//FLOG10.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0010101
//FLOG2.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0010110
//FABS.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011000
//FCOSH.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011001
//FNEG.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011010
//FACOS.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011100
//FCOS.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011101
//FGETEXP.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011110
//FGETMAN.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0011111
//FDIV.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100000
//FMOD.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100001
//FADD.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100010
//FMUL.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100011
//FSGLDIV.W <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100100
//FREM.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100101
//FSCALE.W <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100110
//FSGLMUL.W <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0100111
//FSUB.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0101000
//FCMP.W <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn0111000
//FSMOVE.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1000000
//FSSQRT.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1000001
//FDMOVE.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1000100
//FDSQRT.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1000101
//FSABS.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1011000
//FSNEG.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1011010
//FDABS.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1011100
//FDNEG.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1011110
//FSDIV.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1100000
//FSADD.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1100010
//FSMUL.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1100011
//FDDIV.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1100100
//FDADD.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1100110
//FDMUL.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1100111
//FSSUB.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1101000
//FDSUB.W <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100nnn1101100
//FSINCOS.W <ea>,FPc:FPs |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010100sss0110ccc
//FTST.B <ea> |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-0101100000111010
//FMOVE.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0000000
//FINT.B <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0000001
//FSINH.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0000010
//FINTRZ.B <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0000011
//FSQRT.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0000100
//FLOGNP1.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0000110
//FETOXM1.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001000
//FTANH.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001001
//FATAN.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001010
//FASIN.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001100
//FATANH.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001101
//FSIN.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001110
//FTAN.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0001111
//FETOX.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0010000
//FTWOTOX.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0010001
//FTENTOX.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0010010
//FLOGN.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0010100
//FLOG10.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0010101
//FLOG2.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0010110
//FABS.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011000
//FCOSH.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011001
//FNEG.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011010
//FACOS.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011100
//FCOS.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011101
//FGETEXP.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011110
//FGETMAN.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0011111
//FDIV.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100000
//FMOD.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100001
//FADD.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100010
//FMUL.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100011
//FSGLDIV.B <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100100
//FREM.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100101
//FSCALE.B <ea>,FPn |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100110
//FSGLMUL.B <ea>,FPn |-|--CCS6|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0100111
//FSUB.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0101000
//FCMP.B <ea>,FPn |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn0111000
//FSMOVE.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1000000
//FSSQRT.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1000001
//FDMOVE.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1000100
//FDSQRT.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1000101
//FSABS.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1011000
//FSNEG.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1011010
//FDABS.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1011100
//FDNEG.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1011110
//FSDIV.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1100000
//FSADD.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1100010
//FSMUL.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1100011
//FDDIV.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1100100
//FDADD.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1100110
//FDMUL.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1100111
//FSSUB.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1101000
//FDSUB.B <ea>,FPn |-|----46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110nnn1101100
//FSINCOS.B <ea>,FPc:FPs |-|--CCSS|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-010110sss0110ccc
//FMOVE.L <ea>,FPIAR |-|--CC46|-|-----|-----|DAM+-WXZPI|1111_001_000_mmm_rrr-1000010000000000
//FMOVEM.L <ea>,FPIAR |-|--CC46|-|-----|-----|DAM+-WXZPI|1111_001_000_mmm_rrr-1000010000000000
//FMOVE.L <ea>,FPSR |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-1000100000000000
//FMOVEM.L <ea>,FPSR |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-1000100000000000
//FMOVE.L <ea>,FPCR |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-1001000000000000
//FMOVEM.L <ea>,FPCR |-|--CC46|-|-----|-----|D M+-WXZPI|1111_001_000_mmm_rrr-1001000000000000
//FMOVE.X FPn,<ea> |-|--CC46|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-011010nnn0000000
//FMOVE.P FPn,<ea>{#k} |-|--CCSS|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-011011nnnkkkkkkk
//FMOVE.D FPn,<ea> |-|--CC46|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-011101nnn0000000
//FMOVE.P FPn,<ea>{Dk} |-|--CCSS|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-011111nnnkkk0000
//FMOVEM.L FPSR/FPIAR,<ea> |-|--CC46|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-1010110000000000
//FMOVEM.L FPCR/FPIAR,<ea> |-|--CC46|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-1011010000000000
//FMOVEM.L FPCR/FPSR,<ea> |-|--CC46|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-1011100000000000
//FMOVEM.L FPCR/FPSR/FPIAR,<ea> |-|--CC46|-|-----|-----| M+-WXZ |1111_001_000_mmm_rrr-1011110000000000
//FMOVEM.X #<data>,<ea> |-|--CC46|-|-----|-----| M WXZ |1111_001_000_mmm_rrr-11110000dddddddd
//FMOVEM.X <list>,<ea> |-|--CC46|-|-----|-----| M WXZ |1111_001_000_mmm_rrr-11110000llllllll
//FMOVEM.X Dl,<ea> |-|--CC4S|-|-----|-----| M WXZ |1111_001_000_mmm_rrr-111110000lll0000
//FMOVEM.L <ea>,FPSR/FPIAR |-|--CC46|-|-----|-----| M+-WXZP |1111_001_000_mmm_rrr-1000110000000000
//FMOVEM.L <ea>,FPCR/FPIAR |-|--CC46|-|-----|-----| M+-WXZP |1111_001_000_mmm_rrr-1001010000000000
//FMOVEM.L <ea>,FPCR/FPSR |-|--CC46|-|-----|-----| M+-WXZP |1111_001_000_mmm_rrr-1001100000000000
//FMOVEM.L <ea>,FPCR/FPSR/FPIAR |-|--CC46|-|-----|-----| M+-WXZP |1111_001_000_mmm_rrr-1001110000000000
//FMOVEM.X <ea>,#<data> |-|--CC46|-|-----|-----| M+ WXZP |1111_001_000_mmm_rrr-11010000dddddddd
//FMOVEM.X <ea>,<list> |-|--CC46|-|-----|-----| M+ WXZP |1111_001_000_mmm_rrr-11010000llllllll
//FMOVEM.X <ea>,Dl |-|--CC4S|-|-----|-----| M+ WXZP |1111_001_000_mmm_rrr-110110000lll0000
//FTST.X <ea> |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-0100100000111010
//FMOVE.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0000000
//FINT.X <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0000001
//FSINH.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0000010
//FINTRZ.X <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0000011
//FSQRT.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0000100
//FLOGNP1.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0000110
//FETOXM1.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001000
//FTANH.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001001
//FATAN.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001010
//FASIN.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001100
//FATANH.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001101
//FSIN.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001110
//FTAN.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0001111
//FETOX.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0010000
//FTWOTOX.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0010001
//FTENTOX.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0010010
//FLOGN.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0010100
//FLOG10.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0010101
//FLOG2.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0010110
//FABS.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011000
//FCOSH.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011001
//FNEG.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011010
//FACOS.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011100
//FCOS.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011101
//FGETEXP.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011110
//FGETMAN.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0011111
//FDIV.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100000
//FMOD.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100001
//FADD.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100010
//FMUL.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100011
//FSGLDIV.X <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100100
//FREM.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100101
//FSCALE.X <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100110
//FSGLMUL.X <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0100111
//FSUB.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0101000
//FCMP.X <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn0111000
//FSMOVE.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1000000
//FSSQRT.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1000001
//FDMOVE.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1000100
//FDSQRT.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1000101
//FSABS.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1011000
//FSNEG.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1011010
//FDABS.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1011100
//FDNEG.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1011110
//FSDIV.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1100000
//FSADD.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1100010
//FSMUL.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1100011
//FDDIV.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1100100
//FDADD.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1100110
//FDMUL.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1100111
//FSSUB.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1101000
//FDSUB.X <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010nnn1101100
//FSINCOS.X <ea>,FPc:FPs |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010010sss0110ccc
//FTST.P <ea> |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-0100110000111010
//FMOVE.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0000000
//FINT.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0000001
//FSINH.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0000010
//FINTRZ.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0000011
//FSQRT.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0000100
//FLOGNP1.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0000110
//FETOXM1.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001000
//FTANH.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001001
//FATAN.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001010
//FASIN.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001100
//FATANH.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001101
//FSIN.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001110
//FTAN.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0001111
//FETOX.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0010000
//FTWOTOX.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0010001
//FTENTOX.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0010010
//FLOGN.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0010100
//FLOG10.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0010101
//FLOG2.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0010110
//FABS.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011000
//FCOSH.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011001
//FNEG.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011010
//FACOS.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011100
//FCOS.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011101
//FGETEXP.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011110
//FGETMAN.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0011111
//FDIV.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100000
//FMOD.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100001
//FADD.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100010
//FMUL.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100011
//FSGLDIV.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100100
//FREM.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100101
//FSCALE.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100110
//FSGLMUL.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0100111
//FSUB.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0101000
//FCMP.P <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn0111000
//FSMOVE.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1000000
//FSSQRT.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1000001
//FDMOVE.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1000100
//FDSQRT.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1000101
//FSABS.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1011000
//FSNEG.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1011010
//FDABS.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1011100
//FDNEG.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1011110
//FSDIV.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1100000
//FSADD.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1100010
//FSMUL.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1100011
//FDDIV.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1100100
//FDADD.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1100110
//FDMUL.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1100111
//FSSUB.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1101000
//FDSUB.P <ea>,FPn |-|----SS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011nnn1101100
//FSINCOS.P <ea>,FPc:FPs |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010011sss0110ccc
//FTST.D <ea> |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-0101010000111010
//FMOVE.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0000000
//FINT.D <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0000001
//FSINH.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0000010
//FINTRZ.D <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0000011
//FSQRT.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0000100
//FLOGNP1.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0000110
//FETOXM1.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001000
//FTANH.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001001
//FATAN.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001010
//FASIN.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001100
//FATANH.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001101
//FSIN.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001110
//FTAN.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0001111
//FETOX.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0010000
//FTWOTOX.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0010001
//FTENTOX.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0010010
//FLOGN.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0010100
//FLOG10.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0010101
//FLOG2.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0010110
//FABS.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011000
//FCOSH.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011001
//FNEG.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011010
//FACOS.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011100
//FCOS.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011101
//FGETEXP.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011110
//FGETMAN.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0011111
//FDIV.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100000
//FMOD.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100001
//FADD.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100010
//FMUL.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100011
//FSGLDIV.D <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100100
//FREM.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100101
//FSCALE.D <ea>,FPn |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100110
//FSGLMUL.D <ea>,FPn |-|--CCS6|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0100111
//FSUB.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0101000
//FCMP.D <ea>,FPn |-|--CC46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn0111000
//FSMOVE.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1000000
//FSSQRT.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1000001
//FDMOVE.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1000100
//FDSQRT.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1000101
//FSABS.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1011000
//FSNEG.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1011010
//FDABS.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1011100
//FDNEG.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1011110
//FSDIV.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1100000
//FSADD.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1100010
//FSMUL.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1100011
//FDDIV.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1100100
//FDADD.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1100110
//FDMUL.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1100111
//FSSUB.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1101000
//FDSUB.D <ea>,FPn |-|----46|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101nnn1101100
//FSINCOS.D <ea>,FPc:FPs |-|--CCSS|-|-----|-----| M+-WXZPI|1111_001_000_mmm_rrr-010101sss0110ccc
//FMOVEM.X #<data>,-(Ar) |-|--CC46|-|-----|-----| - |1111_001_000_100_rrr-11100000dddddddd
//FMOVEM.X <list>,-(Ar) |-|--CC46|-|-----|-----| - |1111_001_000_100_rrr-11100000llllllll
//FMOVEM.X Dl,-(Ar) |-|--CC4S|-|-----|-----| - |1111_001_000_100_rrr-111010000lll0000
//FMOVEM.L #<data>,#<data>,FPSR/FPIAR |-|--CC4S|-|-----|-----| I|1111_001_000_111_100-1000110000000000-{data}
//FMOVEM.L #<data>,#<data>,FPCR/FPIAR |-|--CC4S|-|-----|-----| I|1111_001_000_111_100-1001010000000000-{data}
//FMOVEM.L #<data>,#<data>,FPCR/FPSR |-|--CC4S|-|-----|-----| I|1111_001_000_111_100-1001100000000000-{data}
//FMOVEM.L #<data>,#<data>,#<data>,FPCR/FPSR/FPIAR|-|--CC4S|-|-----|-----| I|1111_001_000_111_100-1001110000000000-{data}
@SuppressWarnings ("fallthrough") public static void irpFgen () throws M68kException {
fgen: {
if ((7 & XEiJ.currentOnchipFPU) == 0) {
irpFline ();
break fgen;
}
XEiJ.mpuCycleCount++;
int ea = XEiJ.regOC & 63;
int a = XEiJ.regPC;
XEiJ.regPC = a + 2;
int w = mmuReadWordZeroExword (a, XEiJ.regSRS); //pcwz。拡張ワード
int m = w >> 10 & 7;
int n = w >> 7 & 7;
int c = w & 0x7f;
XEiJ.fpuBox.epbSetRoundingPrec (XEiJ.fpuBox.epbFpcr >> 6 & 3); //丸め桁数
XEiJ.fpuBox.epbSetRoundingMode (XEiJ.fpuBox.epbFpcr >> 4 & 3); //丸めモード
a = 0; //実効アドレス
//XEiJ.fpuBox.epbExceptionStatusWord = 0;
switch (w >> 13) {
case 0b010: //$4xxx-$5xxx: Fop.* <ea>,FPn
XEiJ.fpuBox.epbFpsr &= 0x00ff00ff;
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
switch (m) {
case 0b000: //$40xx-$43xx: Fop.L <ea>,FPn
{
XEiJ.mpuCycleCount += 3;
int i;
if (ea < XEiJ.EA_AR) { //Dr
XEiJ.mpuCycleCount += 2;
//a = 0;
i = XEiJ.regRn[ea];
} else if (ea == XEiJ.EA_IM) { //#<data>
a = XEiJ.regPC;
XEiJ.regPC = a + 4;
i = mmuReadLongExword (a, XEiJ.regSRS); //pcls
} else { //Dr,#<data>以外
a = efaAnyLong (ea);
i = mmuReadLongData (a, XEiJ.regSRS);
}
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].seti (i);
}
break;
case 0b001: //$44xx-$47xx: Fop.S <ea>,FPn
{
int i;
if (ea < XEiJ.EA_AR) { //Dr
XEiJ.mpuCycleCount += 2;
//a = 0;
i = XEiJ.regRn[ea];
} else if (ea == XEiJ.EA_IM) { //#<data>
a = XEiJ.regPC;
XEiJ.regPC = a + 4;
i = mmuReadLongExword (a, XEiJ.regSRS); //pcls
} else { //Dr,#<data>以外
a = efaAnyLong (ea);
i = mmuReadLongData (a, XEiJ.regSRS);
}
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].setf0 (i);
}
break;
case 0b010: //$48xx-$4Bxx: Fop.X <ea>,FPn
{
int[] ib = new int[3];
if (ea == 074) { //#<data>
if (!XEiJ.fpuBox.epbIsFullSpec ()) { //12バイトのイミディエイト
irpExceptionFormat0 (M68kException.M6E_UNIMPLEMENTED_EFFECTIVE << 2, XEiJ.regPC0); //pcは命令の先頭
break fgen;
}
a = (XEiJ.regPC += 12) - 12;
ib[0] = mmuReadLongExword (a, XEiJ.regSRS);
ib[1] = mmuReadLongExword (a + 4, XEiJ.regSRS);
ib[2] = mmuReadLongExword (a + 8, XEiJ.regSRS);
} else { //#<data>以外
a = efaMemExtd (ea);
if ((ea & 070) == 040) { //-(Ar)
ib[2] = mmuReadLongData (m60Address = a + 8, XEiJ.regSRS);
ib[1] = mmuReadLongData (m60Address = a + 4, XEiJ.regSRS);
ib[0] = mmuReadLongData (m60Address = a, XEiJ.regSRS);
} else { //-(Ar)以外
ib[0] = mmuReadLongData (m60Address = a, XEiJ.regSRS);
ib[1] = mmuReadLongData (m60Address = a + 4, XEiJ.regSRS);
ib[2] = mmuReadLongData (m60Address = a + 8, XEiJ.regSRS);
}
}
if (XEiJ.fpuBox.epbIsTriple ()) { //三倍精度
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].sety012 (ib, 0);
} else { //拡張精度
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].setx012 (ib, 0);
}
}
break;
case 0b011: //$4Cxx-$4Fxx: Fop.P <ea>,FPn
{
int[] ib = new int[3];
if (ea == 074) { //#<data>
if (!XEiJ.fpuBox.epbIsFullSpec ()) { //12バイトのイミディエイト
irpExceptionFormat0 (M68kException.M6E_UNIMPLEMENTED_EFFECTIVE << 2, XEiJ.regPC0); //pcは命令の先頭
break fgen;
}
a = (XEiJ.regPC += 12) - 12;
ib[0] = mmuReadLongExword (a, XEiJ.regSRS);
ib[1] = mmuReadLongExword (a + 4, XEiJ.regSRS);
ib[2] = mmuReadLongExword (a + 8, XEiJ.regSRS);
} else { //#<data>以外
a = efaMemExtd (ea);
if ((ea & 070) == 040) { //-(Ar)
ib[2] = mmuReadLongData (m60Address = a + 8, XEiJ.regSRS);
ib[1] = mmuReadLongData (m60Address = a + 4, XEiJ.regSRS);
ib[0] = mmuReadLongData (m60Address = a, XEiJ.regSRS);
} else { //-(Ar)以外
ib[0] = mmuReadLongData (m60Address = a, XEiJ.regSRS);
ib[1] = mmuReadLongData (m60Address = a + 4, XEiJ.regSRS);
ib[2] = mmuReadLongData (m60Address = a + 8, XEiJ.regSRS);
}
}
if (!XEiJ.fpuBox.epbIsFullSpec ()) { //パックトデシマル
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | M68kException.M6E_FP_UNSUPPORTED_DATA_TYPE & 7;
irpExceptionFormat2 (M68kException.M6E_FP_UNSUPPORTED_DATA_TYPE << 2, XEiJ.regPC, a); //pcは次の命令,アドレスはソースオペランド
break fgen;
}
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].setp012 (ib, 0);
}
break;
case 0b100: //$50xx-$53xx: Fop.W <ea>,FPn
{
XEiJ.mpuCycleCount += 3;
int i;
if (ea < XEiJ.EA_AR) { //Dr
XEiJ.mpuCycleCount += 2;
//a = 0;
i = (short) XEiJ.regRn[ea];
} else if (ea == XEiJ.EA_IM) { //#<data>
a = XEiJ.regPC;
XEiJ.regPC = a + 2;
i = mmuReadWordSignExword (a, XEiJ.regSRS); //pcws
} else { //Dr,#<data>以外
a = efaAnyWord (ea);
i = mmuReadWordSignData (a, XEiJ.regSRS);
}
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].seti (i);
}
break;
case 0b101: //$54xx-$57xx: Fop.D <ea>,FPn
{
long l;
if (ea == XEiJ.EA_IM) { //#<data>
a = XEiJ.regPC;
XEiJ.regPC = a + 8;
l = mmuReadQuadExword (a, XEiJ.regSRS);
} else { //#<data>以外
a = efaAnyQuad (ea);
l = mmuReadQuadData (a, XEiJ.regSRS);
}
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].setd01 (l);
}
break;
case 0b110: //$58xx-$5Bxx: Fop.B <ea>,FPn
{
XEiJ.mpuCycleCount += 3;
int i;
if (ea < XEiJ.EA_AR) { //Dr
XEiJ.mpuCycleCount += 2;
//a = 0;
i = (byte) XEiJ.regRn[ea];
} else if (ea == XEiJ.EA_IM) { //#<data>
a = XEiJ.regPC;
XEiJ.regPC = a + 2;
i = mmuReadByteSignExword (a + 1, XEiJ.regSRS); //pcbs
} else { //Dr,#<data>以外
a = efaAnyByte (ea);
i = mmuReadByteSignData (a, XEiJ.regSRS);
}
XEiJ.fpuFPn[m = EFPBox.EPB_SRC_TMP].seti (i);
}
break;
case 0b111: //$5Cxx-$5Fxx: FMOVECR.X #ccc,FPn
default:
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2); //pcは次の命令,アドレスはベクタオフセット
break fgen;
}
if (0x40 <= c) {
//マニュアルにはFMOVECRの命令フォーマットのROMオフセットが7bitあるように書かれているが実際は6bit
//MC68882で0x40以上を指定すると命令実行前例外のF-Line Emulator(レスポンス$1C0B)が返る
XEiJ.regPC = XEiJ.regPC0 + 2; //拡張ワードを読まなかったことにする
irpFline ();
break fgen;
}
if (false) {
m = EFPBox.EPB_CONST_START + c; //定数
c = 0; //FMOVE
} else {
//FMOVECR
XEiJ.fpuBox.epbFmovecr (XEiJ.fpuFPn[n], c);
//FPSRのAEXCを設定する
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_TO_AEXC[XEiJ.fpuBox.epbFpsr >> 8 & 255];
//浮動小数点命令実行後例外 floating-point post-instruction exception
if (irpFPPostInstruction (a)) {
break fgen;
}
break fgen;
}
}
//浮動小数点命令実行前例外 floating-point pre-instruction exception
if (irpFPPreInstruction ()) {
break fgen;
}
//Fop.X <ea>,FPn → Fop.X FP[EFPBox.EPB_SRC_TMP],FPn
//FMOVECR.X #ccc,FPn → FMOVE.X FPc,FPn
//fallthrough
case 0b000: //$0xxx-$1xxx: Fop.X FPm,FPn
if (w >> 13 == 0) {
XEiJ.fpuBox.epbFpsr &= 0x00ff00ff;
}
//Fop.* <ea>,FPnのときFPIARは設定済み
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
switch (c) {
case 0b000_0000: //$xx00: FMOVE.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuFPn[n].sete (XEiJ.fpuFPn[m]).finish ();
break;
case 0b000_0001: //$xx01: FINT.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// 正規化数の最大値は整数なので丸めても大きくなることはない
// UNFL 常にクリア
// 結果は整数なので非正規化数にはならない
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
// FINTはsingleとdoubleの丸め処理を行わない
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_EXD);
XEiJ.fpuFPn[n].round (XEiJ.fpuFPn[m], XEiJ.fpuBox.epbRoundingMode);
break;
case 0b000_0010: //$xx02: FSINH.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].sinh (XEiJ.fpuFPn[m]);
break;
case 0b000_0011: //$xx03: FINTRZ.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 常にクリア
// 結果は整数なので非正規化数にはならない
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
// FINTRZはsingleとdoubleの丸め処理を行わない
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_EXD);
XEiJ.fpuFPn[n].trunc (XEiJ.fpuFPn[m]);
break;
case 0b000_0100: //$xx04: FSQRT.* *m,FPn
case 0b000_0101: //$xx05: FSQRT.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が-0を除く負数のときセット、それ以外はクリア
// OVFL 常にクリア
// 1よりも大きい数は小さくなるので溢れることはない
// UNFL 常にクリア
// 非正規化数の平方根は正規化数なので結果が非正規化数になることはない
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 67;
XEiJ.fpuFPn[n].sqrt (XEiJ.fpuFPn[m]);
break;
case 0b000_0110: //$xx06: FLOGNP1.* *m,FPn
case 0b000_0111: //$xx07: FLOGNP1.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が-1よりも小さいときセット、それ以外はクリア
// OVFL 常にクリア
// log(1+0)=0,log(1+x)<=xなので結果が引数よりも大きくなることはない
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 引数が-1のときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].log1p (XEiJ.fpuFPn[m]);
break;
case 0b000_1000: //$xx08: FETOXM1.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].expm1 (XEiJ.fpuFPn[m]);
break;
case 0b000_1001: //$xx09: FTANH.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].tanh (XEiJ.fpuFPn[m]);
break;
case 0b000_1010: //$xx0A: FATAN.* *m,FPn
case 0b000_1011: //$xx0B: FATAN.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].atan (XEiJ.fpuFPn[m]);
break;
case 0b000_1100: //$xx0C: FASIN.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の絶対値が1よりも大きいときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].asin (XEiJ.fpuFPn[m]);
break;
case 0b000_1101: //$xx0D: FATANH.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の絶対値が1よりも大きいときセット、それ以外はクリア
// OVFL 常にクリア
// 1のとき無限大なのだから1の近くでオーバーフローしそうに思えるがatanh(1-2^-80)≒28.07くらい
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 引数の絶対値が1のときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].atanh (XEiJ.fpuFPn[m]);
break;
case 0b000_1110: //$xx0E: FSIN.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].sin (XEiJ.fpuFPn[m]);
break;
case 0b000_1111: //$xx0F: FTAN.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// cos(x)=0を満たすxは正確に表現できないのだからsin(x)/cos(x)がゼロ除算になるのはおかしい
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].tan (XEiJ.fpuFPn[m]);
break;
case 0b001_0000: //$xx10: FETOX.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].exp (XEiJ.fpuFPn[m]);
break;
case 0b001_0001: //$xx11: FTWOTOX.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].exp2 (XEiJ.fpuFPn[m]);
break;
case 0b001_0010: //$xx12: FTENTOX.* *m,FPn
case 0b001_0011: //$xx13: FTENTOX.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].exp10 (XEiJ.fpuFPn[m]);
break;
case 0b001_0100: //$xx14: FLOGN.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が0よりも小さいときセット、それ以外はクリア
// OVFL 常にクリア
// log(1)=0,log(x)<=x-1なので結果が引数よりも大きくなることはない
// UNFL 常にクリア
// log(1+2^-80)≒2^-80
// DZ 引数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].log (XEiJ.fpuFPn[m]);
break;
case 0b001_0101: //$xx15: FLOG10.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が0よりも小さいときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 引数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].log10 (XEiJ.fpuFPn[m]);
break;
case 0b001_0110: //$xx16: FLOG2.* *m,FPn
case 0b001_0111: //$xx17: FLOG2.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が0よりも小さいときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 引数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].log2 (XEiJ.fpuFPn[m]);
break;
case 0b001_1000: //$xx18: FABS.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuFPn[n].abs (XEiJ.fpuFPn[m]);
break;
case 0b001_1001: //$xx19: FCOSH.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].cosh (XEiJ.fpuFPn[m]);
break;
case 0b001_1010: //$xx1A: FNEG.* *m,FPn
case 0b001_1011: //$xx1B: FNEG.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuFPn[n].neg (XEiJ.fpuFPn[m]);
break;
case 0b001_1100: //$xx1C: FACOS.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の絶対値が1よりも大きいときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// acos(1-ulp(1))はulp(1)よりも大きい
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// おそらくセットされないのはacos(1)=0だけ
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].acos (XEiJ.fpuFPn[m]);
break;
case 0b001_1101: //$xx1D: FCOS.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// cos(x)=0を満たすxは正確に表現できず、cos(pi/2)とcos(3*pi/2)が正規化数になってしまう
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].cos (XEiJ.fpuFPn[m]);
break;
case 0b001_1110: //$xx1E: FGETEXP.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].getexp (XEiJ.fpuFPn[m]);
break;
case 0b001_1111: //$xx1F: FGETMAN.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].getman (XEiJ.fpuFPn[m]);
break;
case 0b010_0000: //$xx20: FDIV.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方ゼロまたは両方無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 被除数がゼロ、無限大、NaN以外で除数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 36;
XEiJ.fpuFPn[n].div (XEiJ.fpuFPn[m]);
break;
case 0b010_0001: //$xx21: FMOD.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 除数がゼロまたは被除数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// 除数がゼロのとき結果は無限大ではなくNaNでありゼロ除算にはならない
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
// FPSRのquotient byteに符号付き商の下位7bitが入る
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].rem (XEiJ.fpuFPn[m]);
break;
case 0b010_0010: //$xx22: FADD.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方無限大で符号が異なるときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuFPn[n].add (XEiJ.fpuFPn[m]);
break;
case 0b010_0011: //$xx23: FMUL.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の一方がゼロで他方が無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuFPn[n].mul (XEiJ.fpuFPn[m]);
break;
case 0b010_0100: //$xx24: FSGLDIV.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方ゼロまたは両方無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 被除数がゼロ、無限大、NaN以外で除数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 36;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_XSG);
XEiJ.fpuFPn[n].div (XEiJ.fpuFPn[m]);
break;
case 0b010_0101: //$xx25: FREM.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 除数がゼロまたは被除数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// 除数がゼロのとき結果は無限大ではなくNaNでありゼロ除算にはならない
// INEX2 結果に誤差があるときセット、それ以外はクリア
// マニュアルにClearedと書いてあるのは間違い
// 除数が無限大で被除数をそのまま返す場合でもサイズが減ればアンダーフローや不正確な結果になることはマニュアルにも書かれている
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
// FPSRのquotient byteに符号付き商の下位7bitが入る
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
XEiJ.fpuFPn[n].ieeerem (XEiJ.fpuFPn[m]);
break;
case 0b010_0110: //$xx26: FSCALE.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
//! 本来はソースが整数のとき浮動小数点数を経由しないが、これは経由してしまっている。結果は同じだが効率が悪い
XEiJ.fpuFPn[n].scale (XEiJ.fpuFPn[m]);
break;
case 0b010_0111: //$xx27: FSGLMUL.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の一方がゼロで他方が無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
{
//引数を24bitに切り捨てるときX2をセットしない
int sr = XEiJ.fpuBox.epbFpsr;
XEiJ.fpuFPn[EFPBox.EPB_SRC_TMP].roundmanf (XEiJ.fpuFPn[m], EFPBox.EPB_MODE_RZ);
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].roundmanf (XEiJ.fpuFPn[n], EFPBox.EPB_MODE_RZ);
XEiJ.fpuBox.epbFpsr = sr;
}
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_XSG);
XEiJ.fpuFPn[n].mul (XEiJ.fpuFPn[EFPBox.EPB_DST_TMP], XEiJ.fpuFPn[EFPBox.EPB_SRC_TMP]);
break;
case 0b010_1000: //$xx28: FSUB.* *m,FPn
case 0b010_1001: //$xx29: FSUB.* *m,FPn (MC68882)
case 0b010_1010: //$xx2A: FSUB.* *m,FPn (MC68882)
case 0b010_1011: //$xx2B: FSUB.* *m,FPn (MC68882)
case 0b010_1100: //$xx2C: FSUB.* *m,FPn (MC68882)
case 0b010_1101: //$xx2D: FSUB.* *m,FPn (MC68882)
case 0b010_1110: //$xx2E: FSUB.* *m,FPn (MC68882)
case 0b010_1111: //$xx2F: FSUB.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方無限大で符号が同じときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuFPn[n].sub (XEiJ.fpuFPn[m]);
break;
case 0b011_0000: //$xx30: FSINCOS.* *m,FP0:FPn (c=0,s=n)
case 0b011_0001: //$xx31: FSINCOS.* *m,FP1:FPn (c=1,s=n)
case 0b011_0010: //$xx32: FSINCOS.* *m,FP2:FPn (c=2,s=n)
case 0b011_0011: //$xx33: FSINCOS.* *m,FP3:FPn (c=3,s=n)
case 0b011_0100: //$xx34: FSINCOS.* *m,FP4:FPn (c=4,s=n)
case 0b011_0101: //$xx35: FSINCOS.* *m,FP5:FPn (c=5,s=n)
case 0b011_0110: //$xx36: FSINCOS.* *m,FP6:FPn (c=6,s=n)
case 0b011_0111: //$xx37: FSINCOS.* *m,FP7:FPn (c=7,s=n)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が無限大のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL sin(x)の結果が非正規化数のときセット、それ以外はクリア
// cos(x)の結果は非正規化数にならない
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fgen;
}
c &= 7;
//m==EFPBox.EPB_SRC_TMP||m==n||m==cの場合があることに注意する
XEiJ.fpuFPn[EFPBox.EPB_SRC_TMP].sete (XEiJ.fpuFPn[m]);
XEiJ.fpuFPn[c].cos (XEiJ.fpuFPn[EFPBox.EPB_SRC_TMP]);
XEiJ.fpuFPn[n].sin (XEiJ.fpuFPn[EFPBox.EPB_SRC_TMP]);
break;
case 0b011_1000: //$xx38: FCMP.* *m,FPn
case 0b011_1001: //$xx39: FCMP.* *m,FPn (MC68882)
case 0b011_1100: //$xx3C: FCMP.* *m,FPn (MC68882) コマンドワードの不連続箇所に注意
case 0b011_1101: //$xx3D: FCMP.* *m,FPn (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
// FCMPはinfinityを常にクリアする
// efp.compareTo(x,y)を使う
// efp.compareTo(x,y)はefp.sub(x,y)よりも速い
// efp.sub(x,y)はINEX2をセットしてしまう
// efp.compareTo(x,y)は-0<+0だがFCMPは-0==+0なのでこれだけ調節する
{
int xf = XEiJ.fpuFPn[n].flg;
int yf = XEiJ.fpuFPn[m].flg;
if ((xf | yf) << 3 < 0) { //どちらかがNaN
//XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].setnan ();
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].flg = EFPBox.N;
} else {
int i = ((xf & yf) << 1 < 0 ? 0 : //両方±0
XEiJ.fpuFPn[n].compareTo (XEiJ.fpuFPn[m])); //-Inf==-Inf<-x<-0<+0<+x<+Inf==+Inf<NaN==NaN
if (i == 0) {
if (xf < 0) {
//XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].negset0 ();
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].flg = EFPBox.M | EFPBox.Z;
} else {
//XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].set0 ();
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].flg = EFPBox.P | EFPBox.Z;
}
} else if (i < 0) {
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].negset1 ();
} else {
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].set1 ();
}
}
n = EFPBox.EPB_DST_TMP;
}
break;
case 0b011_1010: //$xx3A: FTST.* *m
case 0b011_1011: //$xx3B: FTST.* *m (MC68882)
case 0b011_1110: //$xx3E: FTST.* *m (MC68882) コマンドワードの不連続箇所に注意
case 0b011_1111: //$xx3F: FTST.* *m (MC68882)
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
// ソースオペランドをダミーのデスティネーションオペランドにコピーしてテストする
// デスティネーションオペランドは変化しない
// デスティネーションオペランドにはFP0が指定される場合が多いがFP0である必要はない
XEiJ.fpuFPn[EFPBox.EPB_DST_TMP].sete (XEiJ.fpuFPn[m]);
n = EFPBox.EPB_DST_TMP;
break;
case 0b100_0000: //$xx40: FSMOVE.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].sete (XEiJ.fpuFPn[m]).finish ();
break;
case 0b100_0001: //$xx41: FSSQRT.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が-0を除く負数のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 67;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].sqrt (XEiJ.fpuFPn[m]);
break;
//case 0b100_0010: //$xx42:
//case 0b100_0011: //$xx43:
case 0b100_0100: //$xx44: FDMOVE.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].sete (XEiJ.fpuFPn[m]).finish ();
break;
case 0b100_0101: //$xx45: FDSQRT.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が-0を除く負数のときセット、それ以外はクリア
// OVFL 常にクリア
// UNFL 常にクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 67;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].sqrt (XEiJ.fpuFPn[m]);
break;
//case 0b100_0110: //$xx46:
//case 0b100_0111: //$xx47:
//case 0b100_1000: //$xx48:
//case 0b100_1001: //$xx49:
//case 0b100_1010: //$xx4A:
//case 0b100_1011: //$xx4B:
//case 0b100_1100: //$xx4C:
//case 0b100_1101: //$xx4D:
//case 0b100_1110: //$xx4E:
//case 0b100_1111: //$xx4F:
//case 0b101_0000: //$xx50:
//case 0b101_0001: //$xx51:
//case 0b101_0010: //$xx52:
//case 0b101_0011: //$xx53:
//case 0b101_0100: //$xx54:
//case 0b101_0101: //$xx55:
//case 0b101_0110: //$xx56:
//case 0b101_0111: //$xx57:
case 0b101_1000: //$xx58: FSABS.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].abs (XEiJ.fpuFPn[m]);
break;
//case 0b101_1001: //$xx59:
case 0b101_1010: //$xx5A: FSNEG.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].neg (XEiJ.fpuFPn[m]);
break;
//case 0b101_1011: //$xx5B:
case 0b101_1100: //$xx5C: FDABS.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].abs (XEiJ.fpuFPn[m]);
break;
//case 0b101_1101: //$xx5D:
case 0b101_1110: //$xx5E: FDNEG.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 常にクリア
// OVFL 常にクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 常にクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].neg (XEiJ.fpuFPn[m]);
break;
//case 0b101_1111: //$xx5F:
case 0b110_0000: //$xx60: FSDIV.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方ゼロまたは両方無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 被除数がゼロ、無限大、NaN以外で除数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 36;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].div (XEiJ.fpuFPn[m]);
break;
//case 0b110_0001: //$xx61:
case 0b110_0010: //$xx62: FSADD.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方無限大で符号が異なるときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].add (XEiJ.fpuFPn[m]);
break;
case 0b110_0011: //$xx63: FSMUL.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の一方がゼロで他方が無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].mul (XEiJ.fpuFPn[m]);
break;
case 0b110_0100: //$xx64: FDDIV.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方ゼロまたは両方無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 被除数がゼロ、無限大、NaN以外で除数がゼロのときセット、それ以外はクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 36;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].div (XEiJ.fpuFPn[m]);
break;
//case 0b110_0101: //$xx65:
case 0b110_0110: //$xx66: FDADD.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方無限大で符号が異なるときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].add (XEiJ.fpuFPn[m]);
break;
case 0b110_0111: //$xx67: FDMUL.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数の一方がゼロで他方が無限大のときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].mul (XEiJ.fpuFPn[m]);
break;
case 0b110_1000: //$xx68: FSSUB.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方無限大で符号が同じときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_SGL);
XEiJ.fpuFPn[n].sub (XEiJ.fpuFPn[m]);
break;
//case 0b110_1001: //$xx69:
//case 0b110_1010: //$xx6A:
//case 0b110_1011: //$xx6B:
case 0b110_1100: //$xx6C: FDSUB.* *m,FPn
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR 引数が両方無限大で符号が同じときセット、それ以外はクリア
// OVFL オーバーフローしたときセット、それ以外はクリア
// UNFL 結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 引数がpackedで正確に変換できないときセット、それ以外はクリア
XEiJ.mpuCycleCount += 2;
XEiJ.fpuBox.epbSetRoundingPrec (EFPBox.EPB_PREC_DBL);
XEiJ.fpuFPn[n].sub (XEiJ.fpuFPn[m]);
break;
//case 0b110_1101: //$xx6D:
//case 0b110_1110: //$xx6E:
//case 0b110_1111: //$xx6F:
case 0b111_0000: //$xx70: FLGAMMA *m,FPn
if (EFPBox.EPB_EXTRA_OPERATION) {
XEiJ.fpuFPn[n].lgamma (XEiJ.fpuFPn[m]);
break;
} else {
XEiJ.regPC = XEiJ.regPC0 + 2; //拡張ワードを読まなかったことにする
irpFline ();
break fgen;
}
case 0b111_0001: //$xx71: FTGAMMA *m,FPn
if (EFPBox.EPB_EXTRA_OPERATION) {
XEiJ.fpuFPn[n].tgamma (XEiJ.fpuFPn[m]);
break;
} else {
XEiJ.regPC = XEiJ.regPC0 + 2; //拡張ワードを読まなかったことにする
irpFline ();
break fgen;
}
//case 0b111_0010: //$xx72:
//case 0b111_0011: //$xx73:
//case 0b111_0100: //$xx74:
//case 0b111_0101: //$xx75:
//case 0b111_0110: //$xx76:
//case 0b111_0111: //$xx77:
//case 0b111_1000: //$xx78:
//case 0b111_1001: //$xx79:
//case 0b111_1010: //$xx7A:
//case 0b111_1011: //$xx7B:
//case 0b111_1100: //$xx7C:
//case 0b111_1101: //$xx7D:
//case 0b111_1110: //$xx7E:
//case 0b111_1111: //$xx7F:
default: //未定義
XEiJ.regPC = XEiJ.regPC0 + 2; //拡張ワードを読まなかったことにする
irpFline ();
break fgen;
}
//FPSRのFPCCを設定する
XEiJ.fpuBox.epbFpsr |= XEiJ.fpuFPn[n].flg >>> 4;
//FPSRのAEXCを設定する
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_TO_AEXC[XEiJ.fpuBox.epbFpsr >> 8 & 255];
//浮動小数点命令実行後例外 floating-point post-instruction exception
if (irpFPPostInstruction (a)) {
break fgen;
}
break fgen;
case 0b011: //$6xxx-$7xxx: FMOVE.* FPn,<ea>
// BSUN 常にクリア
// SNAN 引数がシグナリングNaNのときセット、それ以外はクリア
// OPERR byte,word,longで無限大または指定されたサイズに収まらないとき、packedでk-factorが17よりも大きいか指数部が3桁に収まらないときセット、それ以外はクリア
// OVFL packedではなくてオーバーフローしたときセット、それ以外はクリア
// UNFL packedではなくて結果が非正規化数のときセット、それ以外はクリア
// DZ 常にクリア
// INEX2 結果に誤差があるときセット、それ以外はクリア
// INEX1 常にクリア
XEiJ.fpuBox.epbFpsr &= 0xffff00ff; //FMOVE.* FPn,<ea>でFPSRのコンディションコードバイトは変化しない
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
switch (m) {
case 0b000: //$60xx-$63xx: FMOVE.L FPn,<ea>
{
int i = XEiJ.fpuFPn[n].geti (XEiJ.fpuBox.epbRoundingMode);
if (ea < XEiJ.EA_AR) { //Dr。Ar不可
XEiJ.regRn[ea] = i;
} else { //Dr以外
a = efaMltLong (ea);
mmuWriteLongData (a, i, XEiJ.regSRS);
}
}
break;
case 0b001: //$64xx-$67xx: FMOVE.S FPn,<ea>
{
int i = XEiJ.fpuFPn[n].getf0 (XEiJ.fpuBox.epbRoundingMode);
if (ea < XEiJ.EA_AR) { //Dr。Ar不可
XEiJ.regRn[ea] = i;
} else { //Dr以外
a = efaMltLong (ea);
mmuWriteLongData (a, i, XEiJ.regSRS);
}
}
break;
case 0b010: //$68xx-$6Bxx: FMOVE.X FPn,<ea>
{
int[] ib = new int[3];
if (XEiJ.fpuBox.epbIsTriple ()) { //三倍精度
XEiJ.fpuFPn[n].gety012 (ib, 0, XEiJ.fpuBox.epbRoundingMode);
} else { //拡張精度
XEiJ.fpuFPn[n].getx012 (ib, 0, XEiJ.fpuBox.epbRoundingMode);
}
a = efaMltExtd (ea);
if ((ea & 070) == 040) { //-(Ar)
mmuWriteLongData (m60Address = a + 8, ib[2], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 4, ib[1], XEiJ.regSRS);
mmuWriteLongData (m60Address = a, ib[0], XEiJ.regSRS);
} else { //-(Ar)以外
mmuWriteLongData (m60Address = a, ib[0], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 4, ib[1], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 8, ib[2], XEiJ.regSRS);
}
}
break;
case 0b011: //$6Cxx-$6Fxx: FMOVE.P FPn,<ea>{#k}
{
a = efaMltExtd (ea);
if (!XEiJ.fpuBox.epbIsFullSpec ()) { //パックトデシマル
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | M68kException.M6E_FP_UNSUPPORTED_DATA_TYPE & 7;
irpExceptionFormat3 (M68kException.M6E_FP_UNSUPPORTED_DATA_TYPE << 2, XEiJ.regPC, a); //pcは次の命令,アドレスはデスティネーションオペランド
break fgen;
}
int[] ib = new int[3];
XEiJ.fpuFPn[n].getp012 (ib, 0, w); //k-factor付き
if ((ea & 070) == 040) { //-(Ar)
mmuWriteLongData (m60Address = a + 8, ib[2], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 4, ib[1], XEiJ.regSRS);
mmuWriteLongData (m60Address = a, ib[0], XEiJ.regSRS);
} else { //-(Ar)以外
mmuWriteLongData (m60Address = a, ib[0], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 4, ib[1], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 8, ib[2], XEiJ.regSRS);
}
}
break;
case 0b100: //$70xx-$73xx: FMOVE.W FPn,<ea>
{
int i = XEiJ.fpuFPn[n].gets (XEiJ.fpuBox.epbRoundingMode);
if (ea < XEiJ.EA_AR) { //Dr。Ar不可
XEiJ.regRn[ea] = XEiJ.regRn[ea] & ~65535 | (char) i;
} else { //Dr以外
a = efaMltWord (ea);
mmuWriteWordData (a, i, XEiJ.regSRS);
}
}
break;
case 0b101: //$74xx-$77xx: FMOVE.D FPn,<ea>
{
long l = XEiJ.fpuFPn[n].getd01 (XEiJ.fpuBox.epbRoundingMode);
a = efaMltQuad (ea);
mmuWriteQuadData (a, l, XEiJ.regSRS);
}
break;
case 0b110: //$78xx-$7Bxx: FMOVE.B FPn,<ea>
{
int i = XEiJ.fpuFPn[n].getb (XEiJ.fpuBox.epbRoundingMode);
if (ea < XEiJ.EA_AR) { //Dr。Ar不可
XEiJ.regRn[ea] = XEiJ.regRn[ea] & ~255 | i & 255;
} else { //Dr以外
a = efaMltByte (ea);
mmuWriteByteData (a, i, XEiJ.regSRS);
}
}
break;
case 0b111: //$7Cxx-$7Fxx: FMOVE.P FPn,<ea>{Dl}
default:
{
a = efaMltExtd (ea);
if (!XEiJ.fpuBox.epbIsFullSpec ()) { //パックトデシマル
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | M68kException.M6E_FP_UNSUPPORTED_DATA_TYPE & 7;
irpExceptionFormat3 (M68kException.M6E_FP_UNSUPPORTED_DATA_TYPE << 2, XEiJ.regPC, a); //pcは次の命令,アドレスはデスティネーションオペランド
break fgen;
}
byte[] b = new byte[12];
XEiJ.fpuFPn[n].getp012 (b, 0, XEiJ.regRn[w >> 4 & 7]); //k-factor付き
if (ea >> 3 == XEiJ.MMM_MN) { //-(Ar)
mmuWriteByteArrayDecrement (a, b, 0, 12, XEiJ.regSRS);
} else { //-(Ar)
mmuWriteByteArray (a, b, 0, 12, XEiJ.regSRS);
}
}
}
//FPSRのAEXCを設定する
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_TO_AEXC[XEiJ.fpuBox.epbFpsr >> 8 & 255];
//浮動小数点命令実行後例外 floating-point post-instruction exception
if (irpFPPostInstruction (a)) {
break fgen;
}
break fgen;
case 0b100: //$8xxx-$9xxx: FMOVEM.L <ea>,FPCR/FPSR/FPIAR
XEiJ.mpuCycleCount += 6;
// FMOVEM命令は例外を発生させずFPCR/FPSR/FPIARも(デスティネーションに書かれたもの以外)変化しない
// 格納順序はFPCRが下位アドレス(連結したとき上位),FPIARが上位アドレス(連結したとき下位)
// レジスタリストは転送方向によらず4=FPCR,2=FPSR,1=FPIAR。0のとき1とみなす
// Dr,Arは単一レジスタのみ、ArはFPIARのみ、さもなくば不当命令
// (Ar)+は下位から転送した後にArをまとめて増やし、-(Ar)はArをまとめて減らした後に下位から転送する
// 68060のとき#<data>は単一レジスタのみ、さもなくば未実装実効アドレス
// 複数転送するときもFSLWのSIZEはLong
{
if (m == 0) { //レジスタリストが0のとき
m = 1; //FPIARとみなす
}
int s = m == 7 ? 12 : m == 6 || m == 5 || m == 3 ? 8 : 4; //転送サイズ
if ((ea & 070) == 000) { //Dr
if (4 < s) { //複数
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} else if ((ea & 070) == 010) { //Ar
if (m != 1) { //FPIAR以外
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} else if ((ea & 070) == 030) { //(Ar)+
a = XEiJ.regRn[ea - (030 - 8)];
} else if ((ea & 070) == 040) { //-(Ar)
m60Incremented -= (long) s << (ea << 3);
a = XEiJ.regRn[ea - (040 - 8)] -= s;
} else if (ea == 074) { //#<data>
if (4 < s && //複数
!XEiJ.fpuBox.epbIsFullSpec ()) { //フルスペック以外
irpExceptionFormat0 (M68kException.M6E_UNIMPLEMENTED_EFFECTIVE << 2, XEiJ.regPC0); //pcは命令の先頭
break fgen;
}
} else { //その他
a = efaMemLong (ea);
}
for (int t = 4; 1 <= t; t >>= 1) { //4,2,1
if ((m & t) == 0) {
continue;
}
int i = (ea < 020 ? XEiJ.regRn[ea] : //Dr,Ar
ea == 074 ? mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) : //#<data>
mmuReadLongData (m60Address = a, XEiJ.regSRS));
if (t == 4) { //FPCR
XEiJ.fpuBox.epbFpcr = i & EFPBox.EPB_FPCR_ALL;
} else if (t == 2) { //FPSR
XEiJ.fpuBox.epbFpsr = i & EFPBox.EPB_FPSR_ALL;
// fmove.lでfpsrのEXCに書き込んだだけではAEXCは更新されない
// fmove.lでfpsrに0x0000ff00を書き込んですぐに読み出しても0x0000ff00のまま
} else { //FPIAR
XEiJ.fpuBox.epbFpiar = i;
}
a += 4;
}
if ((ea & 070) == 030) { //(Ar)+
m60Incremented += (long) s << (ea << 3);
XEiJ.regRn[ea - (030 - 8)] += s;
}
}
break fgen;
case 0b101: //$Axxx-$Bxxx: FMOVEM.L FPCR/FPSR/FPIAR,<ea>
XEiJ.mpuCycleCount += 4;
{
if (m == 0) { //レジスタリストが0のとき
m = 1; //FPIARとみなす
}
int s = m == 7 ? 12 : m == 6 || m == 5 || m == 3 ? 8 : 4; //転送サイズ
if ((ea & 070) == 000) { //Dr
if (4 < s) { //複数
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} else if ((ea & 070) == 010) { //Ar
if (m != 1) { //FPIAR以外
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} else if ((ea & 070) == 030) { //(Ar)+
a = XEiJ.regRn[ea - (030 - 8)];
} else if ((ea & 070) == 040) { //-(Ar)
m60Incremented -= (long) s << (ea << 3);
a = XEiJ.regRn[ea - (040 - 8)] -= s;
} else { //その他
a = efaMltLong (ea);
}
for (int t = 4; 1 <= t; t >>= 1) { //4,2,1
if ((m & t) == 0) {
continue;
}
int i = (t == 4 ? XEiJ.fpuBox.epbFpcr : //FPCR
t == 2 ? XEiJ.fpuBox.epbFpsr : //FPSR
XEiJ.fpuBox.epbFpiar); //FPIAR
if (ea < 020) { //Dr,Ar
XEiJ.regRn[ea] = i;
} else {
mmuWriteLongData (m60Address = a, i, XEiJ.regSRS);
}
a += 4;
}
if ((ea & 070) == 030) { //(Ar)+
m60Incremented += (long) s << (ea << 3);
XEiJ.regRn[ea - (030 - 8)] += s;
}
}
break fgen;
case 0b110: //$Cxxx-$Dxxx: FMOVEM.X <ea>,<list>
// 0 <ea>,<list>
// 1 <list>,<ea>
// 0 -(Ar) 76543210
// 1 -(Ar)以外 01234567
// 0 static
// 1 dynamic 0rrr0000
// mmm
{
if ((m & 2) != 0 && !XEiJ.fpuBox.epbIsFullSpec ()) { //動的レジスタリスト
irpExceptionFormat0 (M68kException.M6E_UNIMPLEMENTED_EFFECTIVE << 2, XEiJ.regPC0); //pcは命令の先頭
break fgen;
}
int l = 0xff & ((m & 2) == 0 ? w : XEiJ.regRn[(0x0070 & w) >> 4]);
int[] ib = new int[3];
if ((ea & 070) == 030) { //(Ar)+
int arr = ea - (030 - 8);
a = XEiJ.regRn[arr];
for (n = 0; n <= 7; n++) {
if ((l & (0x80 >> n)) == 0) { //01234567
continue;
}
XEiJ.mpuCycleCount += 3;
ib[0] = mmuReadLongData (m60Address = a, XEiJ.regSRS);
ib[1] = mmuReadLongData (m60Address = a + 4, XEiJ.regSRS);
ib[2] = mmuReadLongData (m60Address = a + 8, XEiJ.regSRS);
if (XEiJ.fpuBox.epbIsTriple ()) { //三倍精度
XEiJ.fpuFPn[n].sety012 (ib, 0);
} else { //拡張精度
XEiJ.fpuFPn[n].setx012 (ib, 0);
}
a += 12;
}
m60Incremented += (long) (a - XEiJ.regRn[arr]) << (arr << 3);
XEiJ.regRn[arr] = a;
} else { //(Ar)+以外
a = efaCntLong (ea);
for (n = 0; n <= 7; n++) {
if ((l & (0x80 >> n)) == 0) { //01234567
continue;
}
XEiJ.mpuCycleCount += 3;
ib[0] = mmuReadLongData (m60Address = a, XEiJ.regSRS);
ib[1] = mmuReadLongData (m60Address = a + 4, XEiJ.regSRS);
ib[2] = mmuReadLongData (m60Address = a + 8, XEiJ.regSRS);
if (XEiJ.fpuBox.epbIsTriple ()) { //三倍精度
XEiJ.fpuFPn[n].sety012 (ib, 0);
} else { //拡張精度
XEiJ.fpuFPn[n].setx012 (ib, 0);
}
a += 12;
}
}
}
break fgen;
case 0b111: //$Exxx-$Fxxx: FMOVEM.X <list>,<ea>
{
if ((m & 2) != 0 && !XEiJ.fpuBox.epbIsFullSpec ()) { //動的レジスタリスト
irpExceptionFormat0 (M68kException.M6E_UNIMPLEMENTED_EFFECTIVE << 2, XEiJ.regPC0); //pcは命令の先頭
break fgen;
}
int l = 0xff & ((m & 2) == 0 ? w : XEiJ.regRn[(0x0070 & w) >> 4]);
int[] ib = new int[3];
if ((ea & 070) == 040) { //-(Ar)
int arr = ea - (040 - 8);
a = XEiJ.regRn[arr];
for (n = 7; 0 <= n; n--) {
if ((l & (0x01 << n)) == 0) { //76543210
continue;
}
XEiJ.mpuCycleCount += 3;
a -= 12;
if (XEiJ.fpuBox.epbIsTriple ()) { //三倍精度
XEiJ.fpuFPn[n].gety012 (ib, 0, XEiJ.fpuBox.epbRoundingMode);
} else { //拡張精度
XEiJ.fpuFPn[n].getx012 (ib, 0, XEiJ.fpuBox.epbRoundingMode);
}
mmuWriteLongData (m60Address = a + 8, ib[2], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 4, ib[1], XEiJ.regSRS);
mmuWriteLongData (m60Address = a, ib[0], XEiJ.regSRS);
}
m60Incremented -= (long) (XEiJ.regRn[arr] - a) << (arr << 3);
XEiJ.regRn[arr] = a;
} else { //-(Ar)以外
a = efaCntLong (ea);
for (n = 0; n <= 7; n++) {
if ((l & (0x80 >> n)) == 0) { //01234567
continue;
}
XEiJ.mpuCycleCount += 3;
if (XEiJ.fpuBox.epbIsTriple ()) { //三倍精度
XEiJ.fpuFPn[n].gety012 (ib, 0, XEiJ.fpuBox.epbRoundingMode);
} else { //拡張精度
XEiJ.fpuFPn[n].getx012 (ib, 0, XEiJ.fpuBox.epbRoundingMode);
}
mmuWriteLongData (m60Address = a, ib[0], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 4, ib[1], XEiJ.regSRS);
mmuWriteLongData (m60Address = a + 8, ib[2], XEiJ.regSRS);
a += 12;
}
}
}
break fgen;
case 0b001: //$2xxx-$3xxx: 未定義
default: //未定義
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
XEiJ.regPC = XEiJ.regPC0 + 2; //拡張ワードを読まなかったことにする
irpFline ();
break fgen;
}
} //fgen
} //irpFgen
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FSF.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000000
//FSEQ.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000001
//FSOGT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000010
//FSOGE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000011
//FSOLT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000100
//FSOLE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000101
//FSOGL.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000110
//FSOR.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000000111
//FSUN.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001000
//FSUEQ.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001001
//FSUGT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001010
//FSUGE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001011
//FSULT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001100
//FSULE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001101
//FSNE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001110
//FST.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000001111
//FSSF.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010000
//FSSEQ.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010001
//FSGT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010010
//FSGE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010011
//FSLT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010100
//FSLE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010101
//FSGL.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010110
//FSGLE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000010111
//FSNGLE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011000
//FSNGL.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011001
//FSNLE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011010
//FSNLT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011011
//FSNGE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011100
//FSNGT.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011101
//FSSNE.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011110
//FSST.B <ea> |-|--CC4S|-|-----|-----|D M+-WXZ |1111_001_001_mmm_rrr-0000000000011111
//FDBF Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000000-{offset}
//FDBRA Dr,<label> |A|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000000-{offset} [FDBF Dr,<label>]
//FDBEQ Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000001-{offset}
//FDBOGT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000010-{offset}
//FDBOGE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000011-{offset}
//FDBOLT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000100-{offset}
//FDBOLE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000101-{offset}
//FDBOGL Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000110-{offset}
//FDBOR Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000000111-{offset}
//FDBUN Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001000-{offset}
//FDBUEQ Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001001-{offset}
//FDBUGT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001010-{offset}
//FDBUGE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001011-{offset}
//FDBULT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001100-{offset}
//FDBULE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001101-{offset}
//FDBNE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001110-{offset}
//FDBT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000001111-{offset}
//FDBSF Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010000-{offset}
//FDBSEQ Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010001-{offset}
//FDBGT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010010-{offset}
//FDBGE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010011-{offset}
//FDBLT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010100-{offset}
//FDBLE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010101-{offset}
//FDBGL Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010110-{offset}
//FDBGLE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000010111-{offset}
//FDBNGLE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011000-{offset}
//FDBNGL Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011001-{offset}
//FDBNLE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011010-{offset}
//FDBNLT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011011-{offset}
//FDBNGE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011100-{offset}
//FDBNGT Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011101-{offset}
//FDBSNE Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011110-{offset}
//FDBST Dr,<label> |-|--CC4S|-|-----|-----| |1111_001_001_001_rrr-0000000000011111-{offset}
//FTRAPF.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000000-{data}
//FTRAPEQ.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000001-{data}
//FTRAPOGT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000010-{data}
//FTRAPOGE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000011-{data}
//FTRAPOLT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000100-{data}
//FTRAPOLE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000101-{data}
//FTRAPOGL.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000110-{data}
//FTRAPOR.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000000111-{data}
//FTRAPUN.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001000-{data}
//FTRAPUEQ.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001001-{data}
//FTRAPUGT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001010-{data}
//FTRAPUGE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001011-{data}
//FTRAPULT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001100-{data}
//FTRAPULE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001101-{data}
//FTRAPNE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001110-{data}
//FTRAPT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000001111-{data}
//FTRAPSF.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010000-{data}
//FTRAPSEQ.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010001-{data}
//FTRAPGT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010010-{data}
//FTRAPGE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010011-{data}
//FTRAPLT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010100-{data}
//FTRAPLE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010101-{data}
//FTRAPGL.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010110-{data}
//FTRAPGLE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000010111-{data}
//FTRAPNGLE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011000-{data}
//FTRAPNGL.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011001-{data}
//FTRAPNLE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011010-{data}
//FTRAPNLT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011011-{data}
//FTRAPNGE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011100-{data}
//FTRAPNGT.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011101-{data}
//FTRAPSNE.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011110-{data}
//FTRAPST.W #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_010-0000000000011111-{data}
//FTRAPF.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000000-{data}
//FTRAPEQ.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000001-{data}
//FTRAPOGT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000010-{data}
//FTRAPOGE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000011-{data}
//FTRAPOLT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000100-{data}
//FTRAPOLE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000101-{data}
//FTRAPOGL.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000110-{data}
//FTRAPOR.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000000111-{data}
//FTRAPUN.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001000-{data}
//FTRAPUEQ.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001001-{data}
//FTRAPUGT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001010-{data}
//FTRAPUGE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001011-{data}
//FTRAPULT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001100-{data}
//FTRAPULE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001101-{data}
//FTRAPNE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001110-{data}
//FTRAPT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000001111-{data}
//FTRAPSF.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010000-{data}
//FTRAPSEQ.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010001-{data}
//FTRAPGT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010010-{data}
//FTRAPGE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010011-{data}
//FTRAPLT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010100-{data}
//FTRAPLE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010101-{data}
//FTRAPGL.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010110-{data}
//FTRAPGLE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000010111-{data}
//FTRAPNGLE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011000-{data}
//FTRAPNGL.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011001-{data}
//FTRAPNLE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011010-{data}
//FTRAPNLT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011011-{data}
//FTRAPNGE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011100-{data}
//FTRAPNGT.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011101-{data}
//FTRAPSNE.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011110-{data}
//FTRAPST.L #<data> |-|--CC4S|-|-----|-----| |1111_001_001_111_011-0000000000011111-{data}
//FTRAPF |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000000
//FTRAPEQ |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000001
//FTRAPOGT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000010
//FTRAPOGE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000011
//FTRAPOLT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000100
//FTRAPOLE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000101
//FTRAPOGL |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000110
//FTRAPOR |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000000111
//FTRAPUN |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001000
//FTRAPUEQ |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001001
//FTRAPUGT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001010
//FTRAPUGE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001011
//FTRAPULT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001100
//FTRAPULE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001101
//FTRAPNE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001110
//FTRAPT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000001111
//FTRAPSF |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010000
//FTRAPSEQ |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010001
//FTRAPGT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010010
//FTRAPGE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010011
//FTRAPLT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010100
//FTRAPLE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010101
//FTRAPGL |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010110
//FTRAPGLE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000010111
//FTRAPNGLE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011000
//FTRAPNGL |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011001
//FTRAPNLE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011010
//FTRAPNLT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011011
//FTRAPNGE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011100
//FTRAPNGT |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011101
//FTRAPSNE |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011110
//FTRAPST |-|--CC4S|-|-----|-----| |1111_001_001_111_100-0000000000011111
public static void irpFscc () throws M68kException {
fscc: {
//XEiJ.fpuBox.epbExceptionStatusWord = 0;
if ((7 & XEiJ.currentOnchipFPU) == 0) {
irpFline ();
break fscc;
}
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz。拡張ワード
if ((w & 0b010000) != 0 && (XEiJ.fpuBox.epbFpsr & XEiJ.FPU_FPSR_NAN) != 0) { //IEEEノンアウェアテストでNANがセットされているとき
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_BSUN; //BSUNをセット
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_TO_AEXC[XEiJ.fpuBox.epbFpsr >> 8 & 255];
if ((XEiJ.fpuBox.epbFpcr & XEiJ.FPU_FPCR_BSUN) != 0) { //BSUN例外許可
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | M68kException.M6E_FP_BRANCH_SET_UNORDERED & 7;
irpExceptionFormat0 (M68kException.M6E_FP_BRANCH_SET_UNORDERED << 2, XEiJ.regPC0); //pcは命令の先頭
break fscc;
}
}
int ea = XEiJ.regOC & 63;
if (ea < XEiJ.EA_AR) { //FScc.B Dr
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, 0); //pcは次の命令,アドレスは実効アドレス
break fscc;
}
if (XEiJ.FPU_CCMAP_060[(w & 63) << 4 | XEiJ.fpuBox.epbFpsr >> 24 & 15]) { //セット
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] |= 0xff;
} else { //クリア
XEiJ.mpuCycleCount++;
XEiJ.regRn[ea] &= ~0xff;
}
} else if (ea < XEiJ.EA_MM) { //FDBcc Dr,<label>
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
XEiJ.regPC += 2; //オフセットを読み飛ばす
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, 0); //pcは次の命令,アドレスは実効アドレス
break fscc;
}
if (XEiJ.FPU_CCMAP_060[(w & 63) << 4 | XEiJ.fpuBox.epbFpsr >> 24 & 15]) { //条件が成立しているので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regPC += 2; //オフセットを読み飛ばす
} else {
int rrr = XEiJ.regOC & 7;
int t = XEiJ.regRn[rrr];
if ((short) t == 0) { //Drの下位16bitが0なので通過
XEiJ.mpuCycleCount += 2;
XEiJ.regRn[rrr] = t + 65535;
XEiJ.regPC += 2; //オフセットを読み飛ばす
} else { //Drの下位16bitが0でないのでジャンプ
XEiJ.mpuCycleCount++;
XEiJ.regRn[rrr] = t - 1; //下位16bitが0でないので上位16bitは変化しない
irpSetPC (XEiJ.regPC + mmuReadWordSignExword (XEiJ.regPC, XEiJ.regSRS)); //pc==pc0+2
}
}
} else if (ea < XEiJ.EA_PW) { //FScc.B <mem>
int a = efaMltByte (ea);
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, a); //pcは次の命令,アドレスは実効アドレス
break fscc;
}
XEiJ.mpuCycleCount++;
mmuWriteByteData (a, XEiJ.FPU_CCMAP_060[(w & 63) << 4 | XEiJ.fpuBox.epbFpsr >> 24 & 15] ? 0xff : 0x00, XEiJ.regSRS);
} else if (ea <= XEiJ.EA_IM) { //FTRAPcc.W/FTRAPcc.L/FTRAPcc
if (ea == 072) { //.W
mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
} else if (ea == 073) { //.L
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
}
if (!XEiJ.fpuBox.epbIsFullSpec ()) {
irpExceptionFormat2 (M68kException.M6E_FP_UNIMPLEMENTED_INSTRUCTION << 2, XEiJ.regPC, 0); //pcは次の命令,アドレスは実効アドレス
break fscc;
}
if (!XEiJ.FPU_CCMAP_060[(w & 63) << 4 | XEiJ.fpuBox.epbFpsr >> 24 & 15]) { //通過
XEiJ.mpuCycleCount += 2;
} else {
m60Address = XEiJ.regPC0; //アドレスは命令の先頭
M68kException.m6eNumber = M68kException.M6E_TRAPV_INSTRUCTION;
throw M68kException.m6eSignal;
}
} else {
XEiJ.regPC = XEiJ.regPC0 + 2; //拡張ワードを読まなかったことにする
irpFline ();
break fscc;
}
} //fscc
} //irpFscc
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FNOP |A|--CC46|-|-----|-----| |1111_001_010_000_000-0000000000000000 [FBF.W (*)+2]
//FBF.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_000-{offset}
//FBEQ.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_001-{offset}
//FBOGT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_010-{offset}
//FBOGE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_011-{offset}
//FBOLT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_100-{offset}
//FBOLE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_101-{offset}
//FBOGL.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_110-{offset}
//FBOR.W <label> |-|--CC46|-|-----|-----| |1111_001_010_000_111-{offset}
//FBUN.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_000-{offset}
//FBUEQ.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_001-{offset}
//FBUGT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_010-{offset}
//FBUGE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_011-{offset}
//FBULT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_100-{offset}
//FBULE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_101-{offset}
//FBNE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_110-{offset}
//FBT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_001_111-{offset}
//FBRA.W <label> |A|--CC46|-|-----|-----| |1111_001_010_001_111-{offset} [FBT.W <label>]
//FBSF.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_000-{offset}
//FBSEQ.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_001-{offset}
//FBGT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_010-{offset}
//FBGE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_011-{offset}
//FBLT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_100-{offset}
//FBLE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_101-{offset}
//FBGL.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_110-{offset}
//FBGLE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_010_111-{offset}
//FBNGLE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_000-{offset}
//FBNGL.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_001-{offset}
//FBNLE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_010-{offset}
//FBNLT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_011-{offset}
//FBNGE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_100-{offset}
//FBNGT.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_101-{offset}
//FBSNE.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_110-{offset}
//FBST.W <label> |-|--CC46|-|-----|-----| |1111_001_010_011_111-{offset}
public static void irpFbccWord () throws M68kException {
fbcc: {
//XEiJ.fpuBox.epbExceptionStatusWord = 0;
if ((7 & XEiJ.currentOnchipFPU) == 0) {
irpFline ();
break fbcc;
}
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
if ((XEiJ.regOC & 0b010000) != 0 && (XEiJ.fpuBox.epbFpsr & XEiJ.FPU_FPSR_NAN) != 0) { //IEEEノンアウェアテストでNANがセットされているとき
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_BSUN; //BSUNをセット
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_TO_AEXC[XEiJ.fpuBox.epbFpsr >> 8 & 255];
if ((XEiJ.fpuBox.epbFpcr & XEiJ.FPU_FPCR_BSUN) != 0) { //BSUN例外許可
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | M68kException.M6E_FP_BRANCH_SET_UNORDERED & 7;
irpExceptionFormat0 (M68kException.M6E_FP_BRANCH_SET_UNORDERED << 2, XEiJ.regPC0); //pcは命令の先頭
break fbcc;
}
}
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 2; //pc0+4
t += mmuReadWordSignExword (t, XEiJ.regSRS); //pc0+2+16bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.FPU_CCMAP_060[(XEiJ.regOC & 63) << 4 | XEiJ.fpuBox.epbFpsr >> 24 & 15]) { //分岐する
irpSetPC (t);
}
} //fbcc
} //irpFbccWord
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FBF.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_000-{offset}
//FBEQ.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_001-{offset}
//FBOGT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_010-{offset}
//FBOGE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_011-{offset}
//FBOLT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_100-{offset}
//FBOLE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_101-{offset}
//FBOGL.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_110-{offset}
//FBOR.L <label> |-|--CC46|-|-----|-----| |1111_001_011_000_111-{offset}
//FBUN.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_000-{offset}
//FBUEQ.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_001-{offset}
//FBUGT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_010-{offset}
//FBUGE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_011-{offset}
//FBULT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_100-{offset}
//FBULE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_101-{offset}
//FBNE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_110-{offset}
//FBT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_001_111-{offset}
//FBRA.L <label> |A|--CC46|-|-----|-----| |1111_001_011_001_111-{offset} [FBT.L <label>]
//FBSF.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_000-{offset}
//FBSEQ.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_001-{offset}
//FBGT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_010-{offset}
//FBGE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_011-{offset}
//FBLT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_100-{offset}
//FBLE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_101-{offset}
//FBGL.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_110-{offset}
//FBGLE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_010_111-{offset}
//FBNGLE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_000-{offset}
//FBNGL.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_001-{offset}
//FBNLE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_010-{offset}
//FBNLT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_011-{offset}
//FBNGE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_100-{offset}
//FBNGT.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_101-{offset}
//FBSNE.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_110-{offset}
//FBST.L <label> |-|--CC46|-|-----|-----| |1111_001_011_011_111-{offset}
public static void irpFbccLong () throws M68kException {
fbcc: {
//XEiJ.fpuBox.epbExceptionStatusWord = 0;
if ((7 & XEiJ.currentOnchipFPU) == 0) {
irpFline ();
break fbcc;
}
XEiJ.fpuBox.epbFpiar = XEiJ.regPC0; //FPIARはFMOVEM/FMOVE FPcr/FSAVE/FRESTORE以外の命令で例外が発生しなくても更新される
if ((XEiJ.regOC & 0b010000) != 0 && (XEiJ.fpuBox.epbFpsr & XEiJ.FPU_FPSR_NAN) != 0) { //IEEEノンアウェアテストでNANがセットされているとき
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_BSUN; //BSUNをセット
XEiJ.fpuBox.epbFpsr |= XEiJ.FPU_FPSR_EXC_TO_AEXC[XEiJ.fpuBox.epbFpsr >> 8 & 255];
if ((XEiJ.fpuBox.epbFpcr & XEiJ.FPU_FPCR_BSUN) != 0) { //BSUN例外許可
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | M68kException.M6E_FP_BRANCH_SET_UNORDERED & 7;
irpExceptionFormat0 (M68kException.M6E_FP_BRANCH_SET_UNORDERED << 2, XEiJ.regPC0); //pcは命令の先頭
break fbcc;
}
}
XEiJ.mpuCycleCount++;
int t = XEiJ.regPC; //pc0+2
XEiJ.regPC = t + 4; //pc0+6
t += mmuReadLongExword (t, XEiJ.regSRS); //pc0+2+32bitディスプレースメント
if ((t & 1) != 0) { //分岐先のアドレスが奇数
//MC68060のBcc/DBcc/FBccは分岐先のアドレスが奇数のとき分岐しなくてもアドレスエラーになる。FDBccは分岐するときだけ
irpBccAddressError (t);
}
if (XEiJ.FPU_CCMAP_060[(XEiJ.regOC & 63) << 4 | XEiJ.fpuBox.epbFpsr >> 24 & 15]) { //分岐する
irpSetPC (t);
}
} //fbcc
} //irpFbccLong
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FSAVE <ea> |-|--CC46|P|-----|-----| M -WXZ |1111_001_100_mmm_rrr
public static void irpFsave () throws M68kException {
if ((7 & XEiJ.currentOnchipFPU) == 0) {
irpFline ();
return;
}
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
XEiJ.mpuCycleCount += 3;
int ea = XEiJ.regOC & 63;
int a;
if (ea >> 3 == XEiJ.MMM_MN) { //-(Ar)
int arr = XEiJ.regOC & 7 | 8;
m60Incremented -= 12L << (arr << 3);
a = m60Address = XEiJ.regRn[arr] -= 12;
} else { //-(Ar)以外
a = efaCltWord (ea);
}
if (XEiJ.fpuBox.epbExceptionStatusWord == 0) { //例外なし
mmuWriteLongData (a, 0x00006000, 1); //アイドルフレーム
mmuWriteQuadSecond (a + 4, 0L, 1);
} else { //例外あり
mmuWriteLongData (a, XEiJ.fpuBox.epbExceptionOperandExponent | XEiJ.fpuBox.epbExceptionStatusWord, 1); //例外フレーム
mmuWriteQuadSecond (a + 4, XEiJ.fpuBox.epbExceptionOperandMantissa, 1);
XEiJ.fpuBox.epbExceptionStatusWord = 0;
}
} //irpFsave
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FRESTORE <ea> |-|--CC46|P|-----|-----| M+ WXZP |1111_001_101_mmm_rrr
public static void irpFrestore () throws M68kException {
if ((7 & XEiJ.currentOnchipFPU) == 0) {
irpFline ();
return;
}
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
XEiJ.mpuCycleCount += 6;
int ea = XEiJ.regOC & 63;
int a;
if (ea >> 3 == XEiJ.MMM_MP) { //(Ar)+
int arr = XEiJ.regOC & 7 | 8;
m60Incremented += 12L << (arr << 3);
a = m60Address = (XEiJ.regRn[arr] += 12) - 12;
} else { //(Ar)+以外
a = efaCntWord (ea);
}
int i = mmuReadLongData (a, 1);
long l = mmuReadQuadData (a + 4, 1);
if ((i & 0xff00) == 0xe000) { //例外フレーム
//例外ハンドラが0xe0xxを0x60xxに変更してFRESTOREする場合がある
XEiJ.fpuBox.epbExceptionStatusWord = (char) i;
XEiJ.fpuBox.epbExceptionOperandExponent = i & 0xffff0000;
XEiJ.fpuBox.epbExceptionOperandMantissa = l;
} else {
XEiJ.fpuBox.epbExceptionStatusWord = 0;
XEiJ.fpuBox.epbExceptionOperandExponent = 0;
XEiJ.fpuBox.epbExceptionOperandMantissa = 0x0000000000000000L;
}
//FPSRのAEXCをクリアする
XEiJ.fpuBox.epbFpsr = 0;
//FPIARをクリアする
XEiJ.fpuBox.epbFpiar = 0;
} //irpFrestore
//irpFPPreInstruction ()
// 浮動小数点命令実行前例外 floating-point pre-instruction exception
// 優先順位はBSUN>SNAN>OPERR>OVFL>UNFL>DZ>INEX2/INEX1
// 複数の例外が同時に発生したときは最上位の例外ハンドラだけが呼び出される
// 浮動小数点例外ハンドラは自分よりも下位の浮動小数点例外が発生していないか確認しなければならない
public static boolean irpFPPreInstruction () throws M68kException {
int mask = XEiJ.fpuBox.epbFpcr & XEiJ.fpuBox.epbFpsr & 0x0000ff00;
if (mask == 0) {
return false;
}
int number = FP_OFFSET_TO_NUMBER[Integer.numberOfLeadingZeros (mask)];
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | number & 7;
irpExceptionFormat0 (number << 2, XEiJ.regPC0); //pcは命令の先頭
return true;
} //irpFPPreInstruction()
//irpFPPostInstruction (a)
// 浮動小数点命令実行後例外 floating-point post-instruction exception
// 優先順位はBSUN>SNAN>OPERR>OVFL>UNFL>DZ>INEX2/INEX1
// 複数の例外が同時に発生したときは最上位の例外ハンドラだけが呼び出される
// 浮動小数点例外ハンドラは自分よりも下位の浮動小数点例外が発生していないか確認しなければならない
public static boolean irpFPPostInstruction (int a) throws M68kException {
int mask = XEiJ.fpuBox.epbFpcr & XEiJ.fpuBox.epbFpsr & 0x0000ff00;
if (mask == 0) {
return false;
}
int number = FP_OFFSET_TO_NUMBER[Integer.numberOfLeadingZeros (mask)];
XEiJ.fpuBox.epbExceptionStatusWord = 0xe000 | number & 7;
irpExceptionFormat3 (number << 2, XEiJ.regPC, a); //pcは次の命令,アドレスはデスティネーションオペランド
return true;
} //irpFPPostInstruction(int)
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CINVL NC,(Ar) |-|----46|P|-----|-----| |1111_010_000_001_rrr
//CINVP NC,(Ar) |-|----46|P|-----|-----| |1111_010_000_010_rrr
//CINVA NC |-|----46|P|-----|-----| |1111_010_000_011_000
//CPUSHL NC,(Ar) |-|----46|P|-----|-----| |1111_010_000_101_rrr
//CPUSHP NC,(Ar) |-|----46|P|-----|-----| |1111_010_000_110_rrr
//CPUSHA NC |-|----46|P|-----|-----| |1111_010_000_111_000
public static void irpCinvCpushNC () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
if (CAT_ON) {
int a = XEiJ.regRn[8 + (XEiJ.regOC & 0b000_111)];
switch (XEiJ.regOC & 0b111_000) {
case 0b001_000:
catInvL (0, a);
break;
case 0b010_000:
catInvP (0, a);
break;
case 0b011_000:
catInvA (0);
break;
case 0b101_000:
catPushL (0, a);
break;
case 0b110_000:
catPushP (0, a);
break;
case 0b111_000:
catPushA (0);
break;
}
} else {
XEiJ.mpuCycleCount++;
}
} //irpCinvCpushNC
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CINVL DC,(Ar) |-|----46|P|-----|-----| |1111_010_001_001_rrr
//CINVP DC,(Ar) |-|----46|P|-----|-----| |1111_010_001_010_rrr
//CINVA DC |-|----46|P|-----|-----| |1111_010_001_011_000
//CPUSHL DC,(Ar) |-|----46|P|-----|-----| |1111_010_001_101_rrr
//CPUSHP DC,(Ar) |-|----46|P|-----|-----| |1111_010_001_110_rrr
//CPUSHA DC |-|----46|P|-----|-----| |1111_010_001_111_000
public static void irpCinvCpushDC () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
if (CAT_ON) {
int a = XEiJ.regRn[8 + (XEiJ.regOC & 0b000_111)];
switch (XEiJ.regOC & 0b111_000) {
case 0b001_000:
catInvL (1, a);
break;
case 0b010_000:
catInvP (1, a);
break;
case 0b011_000:
catInvA (1);
break;
case 0b101_000:
catPushL (1, a);
break;
case 0b110_000:
catPushP (1, a);
break;
case 0b111_000:
catPushA (1);
break;
}
} else {
XEiJ.mpuCycleCount++;
}
} //irpCinvCpushDC
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CINVL IC,(Ar) |-|----46|P|-----|-----| |1111_010_010_001_rrr
//CINVP IC,(Ar) |-|----46|P|-----|-----| |1111_010_010_010_rrr
//CINVA IC |-|----46|P|-----|-----| |1111_010_010_011_000
//CPUSHL IC,(Ar) |-|----46|P|-----|-----| |1111_010_010_101_rrr
//CPUSHP IC,(Ar) |-|----46|P|-----|-----| |1111_010_010_110_rrr
//CPUSHA IC |-|----46|P|-----|-----| |1111_010_010_111_000
public static void irpCinvCpushIC () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
if (CAT_ON) {
int a = XEiJ.regRn[8 + (XEiJ.regOC & 0b000_111)];
switch (XEiJ.regOC & 0b111_000) {
case 0b001_000:
catInvL (2, a);
break;
case 0b010_000:
catInvP (2, a);
break;
case 0b011_000:
catInvA (2);
break;
case 0b101_000:
catPushL (2, a);
break;
case 0b110_000:
catPushP (2, a);
break;
case 0b111_000:
catPushA (2);
break;
}
} else {
XEiJ.mpuCycleCount++;
}
} //irpCinvCpushIC
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//CINVL BC,(Ar) |-|----46|P|-----|-----| |1111_010_011_001_rrr
//CINVP BC,(Ar) |-|----46|P|-----|-----| |1111_010_011_010_rrr
//CINVA BC |-|----46|P|-----|-----| |1111_010_011_011_000
//CPUSHL BC,(Ar) |-|----46|P|-----|-----| |1111_010_011_101_rrr
//CPUSHP BC,(Ar) |-|----46|P|-----|-----| |1111_010_011_110_rrr
//CPUSHA BC |-|----46|P|-----|-----| |1111_010_011_111_000
public static void irpCinvCpushBC () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
if (CAT_ON) {
int a = XEiJ.regRn[8 + (XEiJ.regOC & 0b000_111)];
switch (XEiJ.regOC & 0b111_000) {
case 0b001_000:
catInvL (3, a);
break;
case 0b010_000:
catInvP (3, a);
break;
case 0b011_000:
catInvA (3);
break;
case 0b101_000:
catPushL (3, a);
break;
case 0b110_000:
catPushP (3, a);
break;
case 0b111_000:
catPushA (3);
break;
}
} else {
XEiJ.mpuCycleCount++;
}
} //irpCinvCpushBC
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//PFLUSHN (Ar) |-|----46|P|-----|-----| |1111_010_100_000_rrr
//PFLUSH (Ar) |-|----46|P|-----|-----| |1111_010_100_001_rrr
//PFLUSHAN |-|----46|P|-----|-----| |1111_010_100_010_000
//PFLUSHA |-|----46|P|-----|-----| |1111_010_100_011_000
public static void irpPflush () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
if (XEiJ.regOC <= 0b1111_010_100_000_111) { //PFLUSHN (An)
XEiJ.mpuCycleCount += 18;
mmuInvalidateNonGlobalCache (XEiJ.regRn[XEiJ.regOC - (0b1111_010_100_000_000 - 8)]);
} else if (XEiJ.regOC <= 0b1111_010_100_001_111) { //PFLUSH (An)
XEiJ.mpuCycleCount += 18;
mmuInvalidateCache (XEiJ.regRn[XEiJ.regOC - (0b1111_010_100_001_000 - 8)]);
} else if (XEiJ.regOC == 0b1111_010_100_010_000) { //PFLUSHAN
XEiJ.mpuCycleCount += 33;
mmuInvalidateAllNonGlobalCache ();
} else if (XEiJ.regOC == 0b1111_010_100_011_000) { //PFLUSHA
XEiJ.mpuCycleCount += 33;
mmuInvalidateAllCache ();
} else {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} //irpPflush
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//PLPAW (Ar) |-|-----6|P|-----|-----| |1111_010_110_001_rrr
public static void irpPlpaw () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
XEiJ.mpuCycleCount += 15;
int ann = XEiJ.regOC - (0b1111_010_110_001_000 - 8); //8+nnn
XEiJ.regRn[ann] = mmuLoadPhysicalAddressWrite (XEiJ.regRn[ann]);
} //irpPlpaw
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//PLPAR (Ar) |-|-----6|P|-----|-----| |1111_010_111_001_rrr
//
//PLPAR (Ar)
// ReadだがSFCではなくDFCを使う
public static void irpPlpar () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
XEiJ.mpuCycleCount += 15;
int ann = XEiJ.regOC - (0b1111_010_111_001_000 - 8); //8+nnn
XEiJ.regRn[ann] = mmuLoadPhysicalAddressRead (XEiJ.regRn[ann]);
} //irpPlpar
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//MOVE16 (Ar)+,xxx.L |-|----46|-|-----|-----| |1111_011_000_000_rrr-{address}
//MOVE16 xxx.L,(Ar)+ |-|----46|-|-----|-----| |1111_011_000_001_rrr-{address}
//MOVE16 (Ar),xxx.L |-|----46|-|-----|-----| |1111_011_000_010_rrr-{address}
//MOVE16 xxx.L,(Ar) |-|----46|-|-----|-----| |1111_011_000_011_rrr-{address}
//MOVE16 (Ar)+,(An)+ |-|----46|-|-----|-----| |1111_011_000_100_rrr-1nnn000000000000
//
//MOVE16 (Ar)+,xxx.L
//MOVE16 xxx.L,(Ar)+
//MOVE16 (Ar),xxx.L
//MOVE16 xxx.L,(Ar)
//MOVE16 (Ar)+,(An)+
// アドレスの下位4bitは無視される
// ポストインクリメントで16増えるとき下位4bitは変化しない
// r==nのときMOVE16 (Ar)+,(Ar)+はMOVE16 (Ar),(Ar)+のような動作になる。データは動かずArは16だけ増える(M68060UM 1-21)
public static void irpMove16 () throws M68kException {
if (XEiJ.regOC <= 0b1111_011_000_011_111) { //どちらかがxxx.L
if (CAT_ON) {
catMove16Start ();
} else {
XEiJ.mpuCycleCount += 18;
}
int arr = XEiJ.regOC - (0b1111_011_000_000_000 - 8); //8+rrr
int a = XEiJ.regRn[arr] & -16;
int x = mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS) & -16; //pcls
if ((XEiJ.regOC & 0b001_000) == 0) { //(Ar)→xxx.L
long l = mmuReadQuadData (m60Address = a, XEiJ.regSRS);
long m = mmuReadQuadSecond (a + 8, XEiJ.regSRS);
mmuWriteQuadData (m60Address = x, l, XEiJ.regSRS);
mmuWriteQuadSecond (x + 8, m, XEiJ.regSRS);
} else { //xxx.L→(An)
long l = mmuReadQuadData (m60Address = x, XEiJ.regSRS);
long m = mmuReadQuadSecond (x + 8, XEiJ.regSRS);
mmuWriteQuadData (m60Address = a, l, XEiJ.regSRS);
mmuWriteQuadSecond (a + 8, m, XEiJ.regSRS);
}
if ((XEiJ.regOC & 0b010_000) == 0) { //(Ar)+
XEiJ.regRn[arr] += 16; //aはマスクされているのでa+16は不可
}
if (CAT_ON) {
catMove16End ();
}
} else if (XEiJ.regOC <= 0b1111_011_000_100_111) {
int w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //pcwz
if ((w & 0b1000111111111111) == 0b1000000000000000) { //MOVE16 (Ar)+,(As)+
if (CAT_ON) {
catMove16Start ();
} else {
XEiJ.mpuCycleCount += 18;
}
int arr = XEiJ.regOC - (0b1111_011_000_100_000 - 8); //8+rrr
int a = XEiJ.regRn[arr] & -16;
int ass = w >> 12; //8+sss
int x = XEiJ.regRn[ass] & -16;
long l = mmuReadQuadData (m60Address = a, XEiJ.regSRS);
long m = mmuReadQuadSecond (a + 8, XEiJ.regSRS);
mmuWriteQuadData (m60Address = x, l, XEiJ.regSRS);
mmuWriteQuadSecond (x + 8, m, XEiJ.regSRS);
XEiJ.regRn[arr] += 16; //aはマスクされているのでa+16は不可
if (arr != ass) {
XEiJ.regRn[ass] += 16; //xはマスクされているのでx+16は不可
}
if (CAT_ON) {
catMove16End ();
}
} else {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} else {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} //irpMove16
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//LPSTOP.W #<data> |-|-----6|P|-----|-----| |1111_100_000_000_000-0000000111000000-{data}
public static void irpLpstop () throws M68kException {
if (XEiJ.regSRS == 0) { //ユーザモードのとき
M68kException.m6eNumber = M68kException.M6E_PRIVILEGE_VIOLATION;
throw M68kException.m6eSignal;
}
//以下はスーパーバイザモード
//!!! 非対応
} //irpLpstop
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FPACK <data> |A|012346|-|UUUUU|*****| |1111_111_0dd_ddd_ddd [FLINE #<data>]
public static void irpFpack () throws M68kException {
if (!MainMemory.mmrFEfuncActivated) {
irpFline ();
return;
}
StringBuilder sb;
int a0;
if (FEFunction.FPK_DEBUG_TRACE) {
sb = new StringBuilder ();
String name = Disassembler.DIS_FPACK_NAME[XEiJ.regOC & 255];
if (name.length () == 0) {
XEiJ.fmtHex4 (sb.append ('$'), XEiJ.regOC);
} else {
sb.append (name);
}
sb.append ('\n');
XEiJ.fmtHex8 (XEiJ.fmtHex8 (XEiJ.fmtHex8 (XEiJ.fmtHex8 (sb.append (" D0="), XEiJ.regRn[0]).append (" D1="), XEiJ.regRn[1]).append (" D2="), XEiJ.regRn[2]).append (" D3="), XEiJ.regRn[3]);
a0 = XEiJ.regRn[8];
MainMemory.mmrRstr (sb.append (" (A0)=\""), a0, MainMemory.mmrStrlen (a0, 20)).append ("\"\n");
}
XEiJ.mpuCycleCount += FEFunction.FPK_CLOCK; //一律にFEFunction.FPK_CLOCKサイクルかかることにする
switch (XEiJ.regOC & 255) {
case 0x00: FEFunction.fpkLMUL (); break;
case 0x01: FEFunction.fpkLDIV (); break;
case 0x02: FEFunction.fpkLMOD (); break;
//case 0x03: break;
case 0x04: FEFunction.fpkUMUL (); break;
case 0x05: FEFunction.fpkUDIV (); break;
case 0x06: FEFunction.fpkUMOD (); break;
//case 0x07: break;
case 0x08: FEFunction.fpkIMUL (); break;
case 0x09: FEFunction.fpkIDIV (); break;
//case 0x0a: break;
//case 0x0b: break;
case 0x0c: FEFunction.fpkRANDOMIZE (); break;
case 0x0d: FEFunction.fpkSRAND (); break;
case 0x0e: FEFunction.fpkRAND (); break;
//case 0x0f: break;
case 0x10: fpkSTOL (); break;
case 0x11: fpkLTOS (); break;
case 0x12: fpkSTOH (); break;
case 0x13: fpkHTOS (); break;
case 0x14: fpkSTOO (); break;
case 0x15: fpkOTOS (); break;
case 0x16: fpkSTOB (); break;
case 0x17: fpkBTOS (); break;
case 0x18: fpkIUSING (); break;
//case 0x19: break;
case 0x1a: FEFunction.fpkLTOD (); break;
case 0x1b: FEFunction.fpkDTOL (); break;
case 0x1c: FEFunction.fpkLTOF (); break;
case 0x1d: FEFunction.fpkFTOL (); break;
case 0x1e: FEFunction.fpkFTOD (); break;
case 0x1f: FEFunction.fpkDTOF (); break;
case 0x20: fpkVAL (); break;
case 0x21: fpkUSING (); break;
case 0x22: fpkSTOD (); break;
case 0x23: fpkDTOS (); break;
case 0x24: fpkECVT (); break;
case 0x25: fpkFCVT (); break;
case 0x26: fpkGCVT (); break;
//case 0x27: break;
case 0x28: FEFunction.fpkDTST (); break;
case 0x29: FEFunction.fpkDCMP (); break;
case 0x2a: FEFunction.fpkDNEG (); break;
case 0x2b: FEFunction.fpkDADD (); break;
case 0x2c: FEFunction.fpkDSUB (); break;
case 0x2d: FEFunction.fpkDMUL (); break;
case 0x2e: FEFunction.fpkDDIV (); break;
case 0x2f: FEFunction.fpkDMOD (); break;
case 0x30: FEFunction.fpkDABS (); break;
case 0x31: FEFunction.fpkDCEIL (); break;
case 0x32: FEFunction.fpkDFIX (); break;
case 0x33: FEFunction.fpkDFLOOR (); break;
case 0x34: FEFunction.fpkDFRAC (); break;
case 0x35: FEFunction.fpkDSGN (); break;
case 0x36: FEFunction.fpkSIN (); break;
case 0x37: FEFunction.fpkCOS (); break;
case 0x38: FEFunction.fpkTAN (); break;
case 0x39: FEFunction.fpkATAN (); break;
case 0x3a: FEFunction.fpkLOG (); break;
case 0x3b: FEFunction.fpkEXP (); break;
case 0x3c: FEFunction.fpkSQR (); break;
case 0x3d: FEFunction.fpkPI (); break;
case 0x3e: FEFunction.fpkNPI (); break;
case 0x3f: FEFunction.fpkPOWER (); break;
case 0x40: FEFunction.fpkRND (); break;
case 0x41: FEFunction.fpkSINH (); break;
case 0x42: FEFunction.fpkCOSH (); break;
case 0x43: FEFunction.fpkTANH (); break;
case 0x44: FEFunction.fpkATANH (); break;
case 0x45: FEFunction.fpkASIN (); break;
case 0x46: FEFunction.fpkACOS (); break;
case 0x47: FEFunction.fpkLOG10 (); break;
case 0x48: FEFunction.fpkLOG2 (); break;
case 0x49: FEFunction.fpkDFREXP (); break;
case 0x4a: FEFunction.fpkDLDEXP (); break;
case 0x4b: FEFunction.fpkDADDONE (); break;
case 0x4c: FEFunction.fpkDSUBONE (); break;
case 0x4d: FEFunction.fpkDDIVTWO (); break;
case 0x4e: FEFunction.fpkDIEECNV (); break;
case 0x4f: FEFunction.fpkIEEDCNV (); break;
case 0x50: fpkFVAL (); break;
case 0x51: FEFunction.fpkFUSING (); break;
case 0x52: FEFunction.fpkSTOF (); break;
case 0x53: FEFunction.fpkFTOS (); break;
case 0x54: FEFunction.fpkFECVT (); break;
case 0x55: FEFunction.fpkFFCVT (); break;
case 0x56: FEFunction.fpkFGCVT (); break;
//case 0x57: break;
case 0x58: FEFunction.fpkFTST (); break;
case 0x59: FEFunction.fpkFCMP (); break;
case 0x5a: FEFunction.fpkFNEG (); break;
case 0x5b: FEFunction.fpkFADD (); break;
case 0x5c: FEFunction.fpkFSUB (); break;
case 0x5d: FEFunction.fpkFMUL (); break;
case 0x5e: FEFunction.fpkFDIV (); break;
case 0x5f: FEFunction.fpkFMOD (); break;
case 0x60: FEFunction.fpkFABS (); break;
case 0x61: FEFunction.fpkFCEIL (); break;
case 0x62: FEFunction.fpkFFIX (); break;
case 0x63: FEFunction.fpkFFLOOR (); break;
case 0x64: FEFunction.fpkFFRAC (); break;
case 0x65: FEFunction.fpkFSGN (); break;
case 0x66: FEFunction.fpkFSIN (); break;
case 0x67: FEFunction.fpkFCOS (); break;
case 0x68: FEFunction.fpkFTAN (); break;
case 0x69: FEFunction.fpkFATAN (); break;
case 0x6a: FEFunction.fpkFLOG (); break;
case 0x6b: FEFunction.fpkFEXP (); break;
case 0x6c: FEFunction.fpkFSQR (); break;
case 0x6d: FEFunction.fpkFPI (); break;
case 0x6e: FEFunction.fpkFNPI (); break;
case 0x6f: FEFunction.fpkFPOWER (); break;
case 0x70: FEFunction.fpkFRND (); break;
case 0x71: FEFunction.fpkFSINH (); break;
case 0x72: FEFunction.fpkFCOSH (); break;
case 0x73: FEFunction.fpkFTANH (); break;
case 0x74: FEFunction.fpkFATANH (); break;
case 0x75: FEFunction.fpkFASIN (); break;
case 0x76: FEFunction.fpkFACOS (); break;
case 0x77: FEFunction.fpkFLOG10 (); break;
case 0x78: FEFunction.fpkFLOG2 (); break;
case 0x79: FEFunction.fpkFFREXP (); break;
case 0x7a: FEFunction.fpkFLDEXP (); break;
case 0x7b: FEFunction.fpkFADDONE (); break;
case 0x7c: FEFunction.fpkFSUBONE (); break;
case 0x7d: FEFunction.fpkFDIVTWO (); break;
case 0x7e: FEFunction.fpkFIEECNV (); break;
case 0x7f: FEFunction.fpkIEEFCNV (); break;
//case 0x80: break;
//case 0x81: break;
//case 0x82: break;
//case 0x83: break;
//case 0x84: break;
//case 0x85: break;
//case 0x86: break;
//case 0x87: break;
//case 0x88: break;
//case 0x89: break;
//case 0x8a: break;
//case 0x8b: break;
//case 0x8c: break;
//case 0x8d: break;
//case 0x8e: break;
//case 0x8f: break;
//case 0x90: break;
//case 0x91: break;
//case 0x92: break;
//case 0x93: break;
//case 0x94: break;
//case 0x95: break;
//case 0x96: break;
//case 0x97: break;
//case 0x98: break;
//case 0x99: break;
//case 0x9a: break;
//case 0x9b: break;
//case 0x9c: break;
//case 0x9d: break;
//case 0x9e: break;
//case 0x9f: break;
//case 0xa0: break;
//case 0xa1: break;
//case 0xa2: break;
//case 0xa3: break;
//case 0xa4: break;
//case 0xa5: break;
//case 0xa6: break;
//case 0xa7: break;
//case 0xa8: break;
//case 0xa9: break;
//case 0xaa: break;
//case 0xab: break;
//case 0xac: break;
//case 0xad: break;
//case 0xae: break;
//case 0xaf: break;
//case 0xb0: break;
//case 0xb1: break;
//case 0xb2: break;
//case 0xb3: break;
//case 0xb4: break;
//case 0xb5: break;
//case 0xb6: break;
//case 0xb7: break;
//case 0xb8: break;
//case 0xb9: break;
//case 0xba: break;
//case 0xbb: break;
//case 0xbc: break;
//case 0xbd: break;
//case 0xbe: break;
//case 0xbf: break;
//case 0xc0: break;
//case 0xc1: break;
//case 0xc2: break;
//case 0xc3: break;
//case 0xc4: break;
//case 0xc5: break;
//case 0xc6: break;
//case 0xc7: break;
//case 0xc8: break;
//case 0xc9: break;
//case 0xca: break;
//case 0xcb: break;
//case 0xcc: break;
//case 0xcd: break;
//case 0xce: break;
//case 0xcf: break;
//case 0xd0: break;
//case 0xd1: break;
//case 0xd2: break;
//case 0xd3: break;
//case 0xd4: break;
//case 0xd5: break;
//case 0xd6: break;
//case 0xd7: break;
//case 0xd8: break;
//case 0xd9: break;
//case 0xda: break;
//case 0xdb: break;
//case 0xdc: break;
//case 0xdd: break;
//case 0xde: break;
//case 0xdf: break;
case 0xe0: fpkCLMUL (); break;
case 0xe1: fpkCLDIV (); break;
case 0xe2: fpkCLMOD (); break;
case 0xe3: fpkCUMUL (); break;
case 0xe4: fpkCUDIV (); break;
case 0xe5: fpkCUMOD (); break;
case 0xe6: fpkCLTOD (); break;
case 0xe7: fpkCDTOL (); break;
case 0xe8: fpkCLTOF (); break;
case 0xe9: fpkCFTOL (); break;
case 0xea: fpkCFTOD (); break;
case 0xeb: fpkCDTOF (); break;
case 0xec: fpkCDCMP (); break;
case 0xed: fpkCDADD (); break;
case 0xee: fpkCDSUB (); break;
case 0xef: fpkCDMUL (); break;
case 0xf0: fpkCDDIV (); break;
case 0xf1: fpkCDMOD (); break;
case 0xf2: fpkCFCMP (); break;
case 0xf3: fpkCFADD (); break;
case 0xf4: fpkCFSUB (); break;
case 0xf5: fpkCFMUL (); break;
case 0xf6: fpkCFDIV (); break;
case 0xf7: fpkCFMOD (); break;
case 0xf8: fpkCDTST (); break;
case 0xf9: fpkCFTST (); break;
case 0xfa: fpkCDINC (); break;
case 0xfb: fpkCFINC (); break;
case 0xfc: fpkCDDEC (); break;
case 0xfd: fpkCFDEC (); break;
case 0xfe: FEFunction.fpkFEVARG (); break;
//case 0xff: FEFunction.fpkFEVECS (); break; //FLOATn.Xに処理させる
default:
XEiJ.mpuCycleCount -= FEFunction.FPK_CLOCK; //戻す
irpFline ();
}
if (FEFunction.FPK_DEBUG_TRACE) {
int i = sb.length ();
XEiJ.fmtHex8 (XEiJ.fmtHex8 (XEiJ.fmtHex8 (XEiJ.fmtHex8 (sb.append (" D0="), XEiJ.regRn[0]).append (" D1="), XEiJ.regRn[1]).append (" D2="), XEiJ.regRn[2]).append (" D3="), XEiJ.regRn[3]);
int l = MainMemory.mmrStrlen (a0, 20);
sb.append (" (A0)=\"");
i = sb.length () - i;
MainMemory.mmrRstr (sb, a0, l).append ("\"\n");
if (a0 <= XEiJ.regRn[8] && XEiJ.regRn[8] <= a0 + l) {
for (i += sb.length () + XEiJ.regRn[8] - a0; sb.length () < i; ) {
sb.append (' ');
}
sb.append ('^');
}
System.out.println (sb.toString ());
}
} //irpFpack
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//DOS <data> |A|012346|-|UUUUU|UUUUU| |1111_111_1dd_ddd_ddd [FLINE #<data>]
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//FLINE #<data> |-|012346|-|UUUUU|UUUUU| |1111_ddd_ddd_ddd_ddd (line 1111 emulator)
public static void irpFline () throws M68kException {
irpExceptionFormat0 (M68kException.M6E_LINE_1111_EMULATOR << 2, XEiJ.regPC0); //pcは命令の先頭
} //irpFline
//irpIllegal ()
// オペコードの上位10bitで分類されなかった未実装命令
// 命令実行回数をカウントするために分けてある
// 0x4afcのILLEGAL命令はTASに分類されて未実装実効アドレスで処理されるのでここには来ない
public static void irpIllegal () throws M68kException {
if (true) {
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} //irpIllegal
//z = irpAbcd (x, y)
// ABCD
public static int irpAbcd (int x, int y) {
int c = XEiJ.regCCR >> 4;
int t = (x & 0xff) + (y & 0xff) + c; //仮の結果
int z = t; //結果
if (0x0a <= (x & 0x0f) + (y & 0x0f) + c) { //ハーフキャリー
z += 0x10 - 0x0a;
}
//XとCはキャリーがあるときセット、さもなくばクリア
if (0xa0 <= z) { //キャリー
z += 0x100 - 0xa0;
XEiJ.regCCR |= XEiJ.REG_CCR_X | XEiJ.REG_CCR_C;
} else {
XEiJ.regCCR &= ~(XEiJ.REG_CCR_X | XEiJ.REG_CCR_C);
}
//Zは結果が0でないときクリア、さもなくば変化しない
z &= 0xff;
if (z != 0x00) {
XEiJ.regCCR &= ~XEiJ.REG_CCR_Z;
}
if (false) {
//000/030のときNは結果の最上位ビット
if ((z & 0x80) != 0) {
XEiJ.regCCR |= XEiJ.REG_CCR_N;
} else {
XEiJ.regCCR &= ~XEiJ.REG_CCR_N;
}
//000のときVは補正値の加算でオーバーフローしたときセット、さもなくばクリア
int a = z - t; //補正値
if ((((t ^ z) & (a ^ z)) & 0x80) != 0) {
XEiJ.regCCR |= XEiJ.REG_CCR_V;
} else {
XEiJ.regCCR &= ~XEiJ.REG_CCR_V;
}
} else if (false) {
//000/030のときNは結果の最上位ビット
if ((z & 0x80) != 0) {
XEiJ.regCCR |= XEiJ.REG_CCR_N;
} else {
XEiJ.regCCR &= ~XEiJ.REG_CCR_N;
}
//030のときVはクリア
XEiJ.regCCR &= ~XEiJ.REG_CCR_V;
} else {
//060のときNとVは変化しない
}
return z;
} //irpAbcd
//z = irpSbcd (x, y)
// SBCD
public static int irpSbcd (int x, int y) {
int b = XEiJ.regCCR >> 4;
int t = (x & 0xff) - (y & 0xff) - b; //仮の結果
int z = t; //結果
if ((x & 0x0f) - (y & 0x0f) - b < 0) { //ハーフボロー
z -= 0x10 - 0x0a;
}
//XとCはボローがあるときセット、さもなくばクリア
if (z < 0) { //ボロー
if (t < 0) {
z -= 0x100 - 0xa0;
}
XEiJ.regCCR |= XEiJ.REG_CCR_X | XEiJ.REG_CCR_C;
} else {
XEiJ.regCCR &= ~(XEiJ.REG_CCR_X | XEiJ.REG_CCR_C);
}
//Zは結果が0でないときクリア、さもなくば変化しない
z &= 0xff;
if (z != 0x00) {
XEiJ.regCCR &= ~XEiJ.REG_CCR_Z;
}
if (false) {
//000/030のときNは結果の最上位ビット
if ((z & 0x80) != 0) {
XEiJ.regCCR |= XEiJ.REG_CCR_N;
} else {
XEiJ.regCCR &= ~XEiJ.REG_CCR_N;
}
//000のときVは補正値の加算でオーバーフローしたときセット、さもなくばクリア
int a = z - t; //補正値
if ((((t ^ z) & (a ^ z)) & 0x80) != 0) {
XEiJ.regCCR |= XEiJ.REG_CCR_V;
} else {
XEiJ.regCCR &= ~XEiJ.REG_CCR_V;
}
} else if (false) {
//000/030のときNは結果の最上位ビット
if ((z & 0x80) != 0) {
XEiJ.regCCR |= XEiJ.REG_CCR_N;
} else {
XEiJ.regCCR &= ~XEiJ.REG_CCR_N;
}
//030のときVはクリア
XEiJ.regCCR &= ~XEiJ.REG_CCR_V;
} else {
//060のときNとVは変化しない
}
return z;
} //irpSbcd
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
// | | MPU | |CCin |CCout|addressing| 1st opcode 2nd opcode
// A:alias P:privileged |A|012346|P|XNZVC|XNZVC|DAM+-WXZPI|bbbb_bbb_bbb_bbb_bbb-bbbbbbbbbbbbbbbb
//------------------------------------------------+-+------+-+-----+-----+----------+-------------------------------------
//HFSBOOT |-|012346|-|-----|-----| |0100_111_000_000_000
//HFSINST |-|012346|-|-----|-----| |0100_111_000_000_001
//HFSSTR |-|012346|-|-----|-----| |0100_111_000_000_010
//HFSINT |-|012346|-|-----|-----| |0100_111_000_000_011
//EMXNOP |-|012346|-|-----|-----| |0100_111_000_000_100
// エミュレータ拡張命令
public static void irpEmx () throws M68kException {
switch (XEiJ.regOC & 63) {
case XEiJ.EMX_OPCODE_HFSBOOT & 63:
XEiJ.mpuCycleCount += 19;
if (HFS.hfsIPLBoot ()) {
//JMP $6800.W
irpSetPC (0x00006800);
}
break;
case XEiJ.EMX_OPCODE_HFSINST & 63:
XEiJ.mpuCycleCount += 19;
HFS.hfsInstall ();
break;
case XEiJ.EMX_OPCODE_HFSSTR & 63:
XEiJ.mpuCycleCount += 19;
HFS.hfsStrategy ();
break;
case XEiJ.EMX_OPCODE_HFSINT & 63:
XEiJ.mpuCycleCount += 19;
//XEiJ.mpuClockTime += TMR_FREQ / 100000L; //0.01ms
if (HFS.hfsInterrupt ()) {
//WAIT
XEiJ.mpuTraceFlag = 0; //トレース例外を発生させない
XEiJ.regPC = XEiJ.regPC0; //ループ
XEiJ.mpuClockTime += XEiJ.TMR_FREQ * 4 / 1000000; //4μs。10MHzのとき40clk
XEiJ.mpuLastNano += 4000L;
}
break;
case XEiJ.EMX_OPCODE_EMXNOP & 63:
XEiJ.emxNop ();
break;
case XEiJ.EMX_OPCODE_EMXWAIT & 63:
WaitInstruction.execute (); //待機命令を実行する
break;
default:
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
}
} //irpEmx
//irpSetPC (a)
// pcへデータを書き込む
// 奇数のときはアドレスエラーが発生する
public static void irpSetPC (int a) throws M68kException {
if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
m60Address = a & -2; //アドレスを偶数にする
M68kException.m6eDirection = XEiJ.MPU_WR_READ;
M68kException.m6eSize = XEiJ.MPU_SS_LONG;
throw M68kException.m6eSignal;
}
if (BranchLog.BLG_ON) {
BranchLog.blgJump (a); //分岐ログに分岐レコードを追加する
} else {
XEiJ.regPC = a;
}
} //irpSetPC
//irpSetSR (newSr)
// srへデータを書き込む
// ori to sr/andi to sr/eori to sr/move to sr/stop/rteで使用される
// スーパーバイザモードになっていることを確認してから呼び出すこと
// rteではr[15]が指すアドレスからsrとpcを取り出してr[15]を更新してから呼び出すこと
// スーパーバイザモード→ユーザモードのときは移行のための処理を行う
// 新しい割り込みマスクレベルよりも高い割り込み処理の終了をデバイスに通知する
public static void irpSetSR (int newSr) {
XEiJ.regSRT1 = XEiJ.REG_SR_T1 & newSr;
XEiJ.regSRM = XEiJ.REG_SR_M & newSr;
if ((XEiJ.regSRS = XEiJ.REG_SR_S & newSr) == 0) { //スーパーバイザモード→ユーザモード
XEiJ.mpuISP = XEiJ.regRn[15]; //SSPを保存
XEiJ.regRn[15] = XEiJ.mpuUSP; //USPを復元
if (DataBreakPoint.DBP_ON) {
DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpUserMap; //ユーザメモリマップに切り替える
} else {
XEiJ.busMemoryMap = XEiJ.busUserMap; //ユーザメモリマップに切り替える
}
if (InstructionBreakPoint.IBP_ON) {
InstructionBreakPoint.ibpOp1MemoryMap = InstructionBreakPoint.ibpOp1UserMap;
}
}
int t = (XEiJ.mpuIMR = 0x7f >> ((XEiJ.regSRI = XEiJ.REG_SR_I & newSr) >> 8)) & XEiJ.mpuISR; //XEiJ.mpuISRで1→0とするビット
if (t != 0) { //終了する割り込みがあるとき
XEiJ.mpuISR ^= t;
//デバイスに割り込み処理の終了を通知する
if (t == XEiJ.MPU_MFP_INTERRUPT_MASK) { //MFPのみ
MC68901.mfpDone ();
} else if (t == XEiJ.MPU_DMA_INTERRUPT_MASK) { //DMAのみ
HD63450.dmaDone ();
} else if (t == XEiJ.MPU_SCC_INTERRUPT_MASK) { //SCCのみ
Z8530.sccDone ();
} else if (t == XEiJ.MPU_IOI_INTERRUPT_MASK) { //IOIのみ
IOInterrupt.ioiDone ();
} else if (t == XEiJ.MPU_EB2_INTERRUPT_MASK) { //EB2のみ
XEiJ.eb2Done ();
} else { //SYSのみまたは複数
if (XEiJ.TEST_BIT_1_SHIFT ? t << 24 + XEiJ.MPU_MFP_INTERRUPT_LEVEL < 0 : (t & XEiJ.MPU_MFP_INTERRUPT_MASK) != 0) {
MC68901.mfpDone ();
}
if (t << 24 + XEiJ.MPU_DMA_INTERRUPT_LEVEL < 0) { //(t & XEiJ.MPU_DMA_INTERRUPT_MASK) != 0
HD63450.dmaDone ();
}
if (XEiJ.TEST_BIT_2_SHIFT ? t << 24 + XEiJ.MPU_SCC_INTERRUPT_LEVEL < 0 : (t & XEiJ.MPU_SCC_INTERRUPT_MASK) != 0) {
Z8530.sccDone ();
}
if (t << 24 + XEiJ.MPU_IOI_INTERRUPT_LEVEL < 0) { //(t & XEiJ.MPU_IOI_INTERRUPT_MASK) != 0
IOInterrupt.ioiDone ();
}
if (t << 24 + XEiJ.MPU_EB2_INTERRUPT_LEVEL < 0) { //(t & XEiJ.MPU_EB2_INTERRUPT_MASK) != 0
XEiJ.eb2Done ();
}
if (XEiJ.TEST_BIT_0_SHIFT ? t << 24 + XEiJ.MPU_SYS_INTERRUPT_LEVEL < 0 : (t & XEiJ.MPU_SYS_INTERRUPT_MASK) != 0) {
XEiJ.sysDone ();
}
}
}
XEiJ.mpuIMR |= ~XEiJ.mpuISR & XEiJ.MPU_SYS_INTERRUPT_MASK; //割り込みマスクレベルが7のときレベル7割り込みの処理中でなければレベル7割り込みを許可する
XEiJ.regCCR = XEiJ.REG_CCR_MASK & newSr;
} //irpSetSR
//irpInterrupt (offset, level)
// 割り込み処理を開始する
public static void irpInterrupt (int offset, int level) throws M68kException {
if (XEiJ.regOC == 0b0100_111_001_110_010) { //最後に実行した命令はSTOP命令
XEiJ.regPC = XEiJ.regPC0 + 4; //次の命令に進む
}
XEiJ.mpuClockTime += XEiJ.mpuModifiedUnit * 19;
int save_sr = XEiJ.regSRT1 | XEiJ.regSRS | XEiJ.regSRM | XEiJ.regSRI | XEiJ.regCCR;
XEiJ.regSRI = level << 8; //割り込みマスクを要求されたレベルに変更する
XEiJ.mpuIMR = 0x7f >> level;
XEiJ.mpuISR |= 0x80 >> level;
XEiJ.regSRT1 = XEiJ.mpuTraceFlag = 0; //srのTビットを消す
int sp;
if (XEiJ.regSRS != 0) { //スーパーバイザモード
sp = XEiJ.regRn[15];
} else { //ユーザモード
XEiJ.regSRS = XEiJ.REG_SR_S; //スーパーバイザモードへ移行する
XEiJ.mpuUSP = XEiJ.regRn[15]; //USPを保存
sp = XEiJ.mpuISP; //SSPを復元
if (DataBreakPoint.DBP_ON) {
DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpSuperMap; //スーパーバイザメモリマップに切り替える
} else {
XEiJ.busMemoryMap = XEiJ.busSuperMap; //スーパーバイザメモリマップに切り替える
}
if (InstructionBreakPoint.IBP_ON) {
InstructionBreakPoint.ibpOp1MemoryMap = InstructionBreakPoint.ibpOp1SuperMap;
}
}
//以下はスーパーバイザモード
XEiJ.regRn[15] = sp -= 8;
mmuWriteWordData (sp + 6, offset, 1); //7-6:フォーマットとベクタオフセット
mmuWriteLongData (sp + 2, XEiJ.regPC, 1); //5-2:プログラムカウンタ
mmuWriteWordData (sp, save_sr, 1); //1-0:ステータスレジスタ
//if (XEiJ.regSRM != 0) { //マスタモードのとき
XEiJ.regSRM = 0; //割り込みモードへ移行する
//}
if (BranchLog.BLG_ON) {
XEiJ.regPC0 = XEiJ.regPC; //rteによる割り込み終了と同時に次の割り込みを受け付けたとき間でpc0を更新しないと2番目の分岐レコードの終了アドレスが1番目と同じになっておかしな分岐レコードができてしまう
}
irpSetPC (mmuReadLongFour (XEiJ.mpuVBR + offset, 1)); //例外ベクタを取り出してジャンプする
} //irpInterrupt
//irpExceptionFormat0 (offset, save_pc)
// 例外処理を開始する
// スタックへのプッシュ、ベクタの取り出し、ジャンプのいずれかでバスエラーまたはアドレスエラーが発生する場合がある
public static void irpExceptionFormat0 (int offset, int save_pc) throws M68kException {
XEiJ.mpuCycleCount += 19;
int save_sr = XEiJ.regSRT1 | XEiJ.regSRS | XEiJ.regSRM | XEiJ.regSRI | XEiJ.regCCR;
XEiJ.regSRT1 = XEiJ.mpuTraceFlag = 0; //srのTビットを消す
int sp;
if (XEiJ.regSRS != 0) { //スーパーバイザモード
sp = XEiJ.regRn[15];
} else { //ユーザモード
XEiJ.regSRS = XEiJ.REG_SR_S; //スーパーバイザモードへ移行する
XEiJ.mpuUSP = XEiJ.regRn[15]; //USPを保存
sp = XEiJ.mpuISP; //SSPを復元
if (DataBreakPoint.DBP_ON) {
DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpSuperMap; //スーパーバイザメモリマップに切り替える
} else {
XEiJ.busMemoryMap = XEiJ.busSuperMap; //スーパーバイザメモリマップに切り替える
}
if (InstructionBreakPoint.IBP_ON) {
InstructionBreakPoint.ibpOp1MemoryMap = InstructionBreakPoint.ibpOp1SuperMap;
}
}
//以下はスーパーバイザモード
XEiJ.regRn[15] = sp -= 8;
mmuWriteWordData (sp + 6, offset, 1); //7-6:フォーマットとベクタオフセット
mmuWriteLongData (sp + 2, save_pc, 1); //5-2:プログラムカウンタ
mmuWriteWordData (sp, save_sr, 1); //1-0:ステータスレジスタ
irpSetPC (mmuReadLongFour (XEiJ.mpuVBR + offset, 1)); //例外ベクタを取り出してジャンプする
} //irpExceptionFormat0
//irpExceptionFormat2 (offset, save_pc, address)
// 例外処理を開始する
// スタックへのプッシュ、ベクタの取り出し、ジャンプのいずれかでバスエラーまたはアドレスエラーが発生する場合がある
public static void irpExceptionFormat2 (int offset, int save_pc, int address) throws M68kException {
XEiJ.mpuCycleCount += 19;
int save_sr = XEiJ.regSRT1 | XEiJ.regSRS | XEiJ.regSRM | XEiJ.regSRI | XEiJ.regCCR;
XEiJ.regSRT1 = XEiJ.mpuTraceFlag = 0; //srのTビットを消す
int sp;
if (XEiJ.regSRS != 0) { //スーパーバイザモード
sp = XEiJ.regRn[15];
} else { //ユーザモード
XEiJ.regSRS = XEiJ.REG_SR_S; //スーパーバイザモードへ移行する
XEiJ.mpuUSP = XEiJ.regRn[15]; //USPを保存
sp = XEiJ.mpuISP; //SSPを復元
if (DataBreakPoint.DBP_ON) {
DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpSuperMap; //スーパーバイザメモリマップに切り替える
} else {
XEiJ.busMemoryMap = XEiJ.busSuperMap; //スーパーバイザメモリマップに切り替える
}
if (InstructionBreakPoint.IBP_ON) {
InstructionBreakPoint.ibpOp1MemoryMap = InstructionBreakPoint.ibpOp1SuperMap;
}
}
//以下はスーパーバイザモード
XEiJ.regRn[15] = sp -= 12;
mmuWriteLongData (sp + 8, address, 1); //11-8:アドレス
mmuWriteWordData (sp + 6, 0x2000 | offset, 1); //7-6:フォーマットとベクタオフセット
mmuWriteLongData (sp + 2, save_pc, 1); //5-2:プログラムカウンタ
mmuWriteWordData (sp, save_sr, 1); //1-0:ステータスレジスタ
irpSetPC (mmuReadLongFour (XEiJ.mpuVBR + offset, 1)); //例外ベクタを取り出してジャンプする
} //irpExceptionFormat2
//irpExceptionFormat3 (offset, save_pc, address)
// 例外処理を開始する
// スタックへのプッシュ、ベクタの取り出し、ジャンプのいずれかでバスエラーまたはアドレスエラーが発生する場合がある
public static void irpExceptionFormat3 (int offset, int save_pc, int address) throws M68kException {
XEiJ.mpuCycleCount += 19;
int save_sr = XEiJ.regSRT1 | XEiJ.regSRS | XEiJ.regSRM | XEiJ.regSRI | XEiJ.regCCR;
XEiJ.regSRT1 = XEiJ.mpuTraceFlag = 0; //srのTビットを消す
int sp;
if (XEiJ.regSRS != 0) { //スーパーバイザモード
sp = XEiJ.regRn[15];
} else { //ユーザモード
XEiJ.regSRS = XEiJ.REG_SR_S; //スーパーバイザモードへ移行する
XEiJ.mpuUSP = XEiJ.regRn[15]; //USPを保存
sp = XEiJ.mpuISP; //SSPを復元
if (DataBreakPoint.DBP_ON) {
DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpSuperMap; //スーパーバイザメモリマップに切り替える
} else {
XEiJ.busMemoryMap = XEiJ.busSuperMap; //スーパーバイザメモリマップに切り替える
}
if (InstructionBreakPoint.IBP_ON) {
InstructionBreakPoint.ibpOp1MemoryMap = InstructionBreakPoint.ibpOp1SuperMap;
}
}
//以下はスーパーバイザモード
XEiJ.regRn[15] = sp -= 12;
mmuWriteLongData (sp + 8, address, 1); //11-8:実効アドレス
mmuWriteWordData (sp + 6, 0x3000 | offset, 1); //7-6:フォーマットとベクタオフセット
mmuWriteLongData (sp + 2, save_pc, 1); //5-2:プログラムカウンタ
mmuWriteWordData (sp, save_sr, 1); //1-0:ステータスレジスタ
irpSetPC (mmuReadLongFour (XEiJ.mpuVBR + offset, 1)); //例外ベクタを取り出してジャンプする
} //irpExceptionFormat3
//
// (d8,Ar,Rn.wl)と(d8,PC,Rn.wl)の拡張ワード
// 0xf000 インデックスレジスタ
// 0=D0,1=D1,2=D2,3=D3,4=D4,5=D5,6=D6,7=D7,8=A0,9=A1,10=A2,11=A3,12=A4,13=A5,14=A6,15=A7
// 0x0800 インデックスサイズ
// 0=ワードインデックス,1=ロングインデックス
// 0x0600 スケールファクタ。ワードインデックスのとき符号拡張してから掛ける
// 0=*1,1=*2,2=*4,3=*8
// 0x0100 フォーマット
// 0=ブリーフフォーマット,1=フルフォーマット
// ブリーフフォーマット
// 0x00ff バイトディスプレースメント
// フルフォーマット
// 0x0080 1=ベースレジスタなし
// 0x0040 1=インデックスなし
// 0x0030 ベースディスプレースメントサイズ
// 1=ベースディスプレースメントなし,2=ワードベースディスプレースメント,3=ロングベースディスプレースメント
// 0x0008 0
// 0x0004 0=プリインデックス,1=ポストインデックス
// 0x0003 インダイレクトとアウタディスプレースメントサイズ
// 0=インダイレクトなし,1=アウタディスプレースメントなし,2=ワードアウタディスプレースメント,3=ロングアウタディスプレースメント
// ベースディスプレースメントとアウタディスプレースメントが続く
// MPUによる制限
// スケールファクタは68020以上。68000と68010では無視されて*1になる
// フルフォーマットは68020以上。68000と68010では不当命令になる
//
// (d16,PC)と(d8,PC,Rn.wl)のベースアドレス
// (d16,PC)と(d8,PC,Rn.wl)のベースアドレスは、Fライン命令以外では命令の先頭アドレス+2、Fライン命令では命令の先頭アドレス+4
// ベースアドレスの位置で実効アドレスを計算する
//
// #<data>の扱い
// #<data>をそれが書かれている場所を実効アドレスとみなす方法で処理するとデータアクセスになってしまう
// 命令アクセスにするためDr,Arと同様に呼び出し側で分離する
// バイト
// data = (ea < 020 ? (byte) XEiJ.regRn[ea] : //Dr,Ar
// ea < 074 ? mmuReadByteSignData (efaMemByte (ea)) :
// mmuReadByteSignExword ((XEiJ.regPC += 2) - 1, XEiJ.regSRS)); //#<data>
// ワード
// data = (ea < 020 ? (short) XEiJ.regRn[ea] : //Dr,Ar
// ea < 074 ? mmuReadWordSignData (efaMemWord (ea)) :
// mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS)); //#<data>
// ロング
// data = (ea < 020 ? XEiJ.regRn[ea] : //Dr,Ar
// ea < 074 ? mmuReadLongData (efaMemLong (ea)) :
// mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS)); //#<data>
//
//a = efaMemByte (ea)
//a = efaMemWord (ea)
//a = efaMemLong (ea)
//a = efaMemQuad (ea)
//a = efaMemExtd (ea)
// | M+-WXZP |
// メモリモードの実効アドレスを求める
// バイトのとき(A7)+と-(A7)はA7を奇偶に関わらず2変化させ、跨いだワードの上位バイト(アドレスの小さい方)を参照する
public static int efaMemByte (int ea) throws M68kException {
int t, w, x;
switch (ea) {
case 020: //(A0)
case 021: //(A1)
case 022: //(A2)
case 023: //(A3)
case 024: //(A4)
case 025: //(A5)
case 026: //(A6)
case 027: //(A7)
return m60Address = XEiJ.regRn[ea - (020 - 8)];
case 030: //(A0)+
case 031: //(A1)+
case 032: //(A1)+
case 033: //(A3)+
case 034: //(A4)+
case 035: //(A5)+
case 036: //(A6)+
m60Incremented += 1L << ((ea - 030) << 3);
return m60Address = XEiJ.regRn[ea - (030 - 8)]++;
case 037: //(A7)+
m60Incremented += 2L << (7 << 3);
return m60Address = (XEiJ.regRn[15] += 2) - 2;
case 040: //-(A0)
case 041: //-(A1)
case 042: //-(A2)
case 043: //-(A3)
case 044: //-(A4)
case 045: //-(A5)
case 046: //-(A6)
m60Incremented -= 1L << ((ea - 040) << 3);
return m60Address = --XEiJ.regRn[ea - (040 - 8)];
case 047: //-(A7)
m60Incremented -= 2L << (7 << 3);
return m60Address = XEiJ.regRn[15] -= 2;
case 050: //(d16,A0)
case 051: //(d16,A1)
case 052: //(d16,A2)
case 053: //(d16,A3)
case 054: //(d16,A4)
case 055: //(d16,A5)
case 056: //(d16,A6)
case 057: //(d16,A7)
case 072: //(d16,PC)
t = ea == 072 ? XEiJ.regPC : XEiJ.regRn[ea - (050 - 8)]; //ベースレジスタ
return m60Address = t + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //ワードディスプレースメント
case 060: //(d8,A0,Rn.wl)
case 061: //(d8,A1,Rn.wl)
case 062: //(d8,A2,Rn.wl)
case 063: //(d8,A3,Rn.wl)
case 064: //(d8,A4,Rn.wl)
case 065: //(d8,A5,Rn.wl)
case 066: //(d8,A6,Rn.wl)
case 067: //(d8,A7,Rn.wl)
case 073: //(d8,PC,Rn.wl)
t = ea == 073 ? XEiJ.regPC : XEiJ.regRn[ea - (060 - 8)]; //ベースレジスタ
w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //拡張ワード
if ((0x0100 & w) == 0) { //ブリーフフォーマット
return m60Address =
(t //ベースレジスタ
+ (byte) w //バイトディスプレースメント
+ (((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9))); //スケールファクタ
} else { //フルフォーマット
XEiJ.mpuCycleCount += ((0x0003 & w) == 0 ? 1 : //インダイレクトなし
3); //インダイレクトあり
t = (((0x0080 & w) != 0 ? 0 : //ベースレジスタなし
t) + //ベースレジスタあり
((0x0020 & w) == 0 ? 0 : //ベースディスプレースメントなし
(0x0010 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードベースディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS))); //ロングベースディスプレースメント
x = ((0x0040 & w) != 0 ? 0 : //インデックスなし
((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9)); //スケールファクタ
return m60Address =
((0x0003 & w) == 0 ? t + x : //インダイレクトなし
(((0x0004 & w) == 0 ? mmuReadLongData (m60Address = t + x, XEiJ.regSRS) : //プリインデックス
mmuReadLongData (m60Address = t, XEiJ.regSRS) + x) //ポストインデックス
+ ((0x0002 & w) == 0 ? 0 : //アウタディスプレースメントなし
(0x0001 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードアウタディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS)))); //ロングアウタディスプレースメント
}
case 070: //(xxx).W
return m60Address = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
case 071: //(xxx).L
return m60Address = mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
case 074:
Thread.dumpStack ();
break;
} //switch
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
} //efaMemByte
public static int efaMemWord (int ea) throws M68kException {
int t, w, x;
switch (ea) {
case 020: //(A0)
case 021: //(A1)
case 022: //(A2)
case 023: //(A3)
case 024: //(A4)
case 025: //(A5)
case 026: //(A6)
case 027: //(A7)
return m60Address = XEiJ.regRn[ea - (020 - 8)];
case 030: //(A0)+
case 031: //(A1)+
case 032: //(A1)+
case 033: //(A3)+
case 034: //(A4)+
case 035: //(A5)+
case 036: //(A6)+
case 037: //(A7)+
m60Incremented += 2L << ((ea - 030) << 3);
return m60Address = (XEiJ.regRn[ea - (030 - 8)] += 2) - 2;
case 040: //-(A0)
case 041: //-(A1)
case 042: //-(A2)
case 043: //-(A3)
case 044: //-(A4)
case 045: //-(A5)
case 046: //-(A6)
case 047: //-(A7)
m60Incremented -= 2L << ((ea - 040) << 3);
return m60Address = XEiJ.regRn[ea - (040 - 8)] -= 2;
case 050: //(d16,A0)
case 051: //(d16,A1)
case 052: //(d16,A2)
case 053: //(d16,A3)
case 054: //(d16,A4)
case 055: //(d16,A5)
case 056: //(d16,A6)
case 057: //(d16,A7)
case 072: //(d16,PC)
t = ea == 072 ? XEiJ.regPC : XEiJ.regRn[ea - (050 - 8)]; //ベースレジスタ
return m60Address = t + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //ワードディスプレースメント
case 060: //(d8,A0,Rn.wl)
case 061: //(d8,A1,Rn.wl)
case 062: //(d8,A2,Rn.wl)
case 063: //(d8,A3,Rn.wl)
case 064: //(d8,A4,Rn.wl)
case 065: //(d8,A5,Rn.wl)
case 066: //(d8,A6,Rn.wl)
case 067: //(d8,A7,Rn.wl)
case 073: //(d8,PC,Rn.wl)
t = ea == 073 ? XEiJ.regPC : XEiJ.regRn[ea - (060 - 8)]; //ベースレジスタ
w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //拡張ワード
if ((0x0100 & w) == 0) { //ブリーフフォーマット
return m60Address =
(t //ベースレジスタ
+ (byte) w //バイトディスプレースメント
+ (((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9))); //スケールファクタ
} else { //フルフォーマット
XEiJ.mpuCycleCount += ((0x0003 & w) == 0 ? 1 : //インダイレクトなし
3); //インダイレクトあり
t = (((0x0080 & w) != 0 ? 0 : //ベースレジスタなし
t) + //ベースレジスタあり
((0x0020 & w) == 0 ? 0 : //ベースディスプレースメントなし
(0x0010 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードベースディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS))); //ロングベースディスプレースメント
x = ((0x0040 & w) != 0 ? 0 : //インデックスなし
((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9)); //スケールファクタ
return m60Address =
((0x0003 & w) == 0 ? t + x : //インダイレクトなし
(((0x0004 & w) == 0 ? mmuReadLongData (m60Address = t + x, XEiJ.regSRS) : //プリインデックス
mmuReadLongData (m60Address = t, XEiJ.regSRS) + x) //ポストインデックス
+ ((0x0002 & w) == 0 ? 0 : //アウタディスプレースメントなし
(0x0001 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードアウタディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS)))); //ロングアウタディスプレースメント
}
case 070: //(xxx).W
return m60Address = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
case 071: //(xxx).L
return m60Address = mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
case 074:
Thread.dumpStack ();
break;
} //switch
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
} //efaMemWord
public static int efaMemLong (int ea) throws M68kException {
int t, w, x;
switch (ea) {
case 020: //(A0)
case 021: //(A1)
case 022: //(A2)
case 023: //(A3)
case 024: //(A4)
case 025: //(A5)
case 026: //(A6)
case 027: //(A7)
return m60Address = XEiJ.regRn[ea - (020 - 8)];
case 030: //(A0)+
case 031: //(A1)+
case 032: //(A1)+
case 033: //(A3)+
case 034: //(A4)+
case 035: //(A5)+
case 036: //(A6)+
case 037: //(A7)+
m60Incremented += 4L << ((ea - 030) << 3);
return m60Address = (XEiJ.regRn[ea - (030 - 8)] += 4) - 4;
case 040: //-(A0)
case 041: //-(A1)
case 042: //-(A2)
case 043: //-(A3)
case 044: //-(A4)
case 045: //-(A5)
case 046: //-(A6)
case 047: //-(A7)
m60Incremented -= 4L << ((ea - 040) << 3);
return m60Address = XEiJ.regRn[ea - (040 - 8)] -= 4;
case 050: //(d16,A0)
case 051: //(d16,A1)
case 052: //(d16,A2)
case 053: //(d16,A3)
case 054: //(d16,A4)
case 055: //(d16,A5)
case 056: //(d16,A6)
case 057: //(d16,A7)
case 072: //(d16,PC)
t = ea == 072 ? XEiJ.regPC : XEiJ.regRn[ea - (050 - 8)]; //ベースレジスタ
return m60Address = t + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //ワードディスプレースメント
case 060: //(d8,A0,Rn.wl)
case 061: //(d8,A1,Rn.wl)
case 062: //(d8,A2,Rn.wl)
case 063: //(d8,A3,Rn.wl)
case 064: //(d8,A4,Rn.wl)
case 065: //(d8,A5,Rn.wl)
case 066: //(d8,A6,Rn.wl)
case 067: //(d8,A7,Rn.wl)
case 073: //(d8,PC,Rn.wl)
t = ea == 073 ? XEiJ.regPC : XEiJ.regRn[ea - (060 - 8)]; //ベースレジスタ
w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //拡張ワード
if ((0x0100 & w) == 0) { //ブリーフフォーマット
return m60Address =
(t //ベースレジスタ
+ (byte) w //バイトディスプレースメント
+ (((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9))); //スケールファクタ
} else { //フルフォーマット
XEiJ.mpuCycleCount += ((0x0003 & w) == 0 ? 1 : //インダイレクトなし
3); //インダイレクトあり
t = (((0x0080 & w) != 0 ? 0 : //ベースレジスタなし
t) + //ベースレジスタあり
((0x0020 & w) == 0 ? 0 : //ベースディスプレースメントなし
(0x0010 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードベースディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS))); //ロングベースディスプレースメント
x = ((0x0040 & w) != 0 ? 0 : //インデックスなし
((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9)); //スケールファクタ
return m60Address =
((0x0003 & w) == 0 ? t + x : //インダイレクトなし
(((0x0004 & w) == 0 ? mmuReadLongData (m60Address = t + x, XEiJ.regSRS) : //プリインデックス
mmuReadLongData (m60Address = t, XEiJ.regSRS) + x) //ポストインデックス
+ ((0x0002 & w) == 0 ? 0 : //アウタディスプレースメントなし
(0x0001 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードアウタディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS)))); //ロングアウタディスプレースメント
}
case 070: //(xxx).W
return m60Address = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
case 071: //(xxx).L
return m60Address = mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
case 074:
Thread.dumpStack ();
break;
} //switch
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
} //efaMemLong
public static int efaMemQuad (int ea) throws M68kException {
int t, w, x;
switch (ea) {
case 020: //(A0)
case 021: //(A1)
case 022: //(A2)
case 023: //(A3)
case 024: //(A4)
case 025: //(A5)
case 026: //(A6)
case 027: //(A7)
return m60Address = XEiJ.regRn[ea - (020 - 8)];
case 030: //(A0)+
case 031: //(A1)+
case 032: //(A1)+
case 033: //(A3)+
case 034: //(A4)+
case 035: //(A5)+
case 036: //(A6)+
case 037: //(A7)+
m60Incremented += 8L << ((ea - 030) << 3);
return m60Address = (XEiJ.regRn[ea - (030 - 8)] += 8) - 8;
case 040: //-(A0)
case 041: //-(A1)
case 042: //-(A2)
case 043: //-(A3)
case 044: //-(A4)
case 045: //-(A5)
case 046: //-(A6)
case 047: //-(A7)
m60Incremented -= 8L << ((ea - 040) << 3);
return m60Address = XEiJ.regRn[ea - (040 - 8)] -= 8;
case 050: //(d16,A0)
case 051: //(d16,A1)
case 052: //(d16,A2)
case 053: //(d16,A3)
case 054: //(d16,A4)
case 055: //(d16,A5)
case 056: //(d16,A6)
case 057: //(d16,A7)
case 072: //(d16,PC)
t = ea == 072 ? XEiJ.regPC : XEiJ.regRn[ea - (050 - 8)]; //ベースレジスタ
return m60Address = t + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //ワードディスプレースメント
case 060: //(d8,A0,Rn.wl)
case 061: //(d8,A1,Rn.wl)
case 062: //(d8,A2,Rn.wl)
case 063: //(d8,A3,Rn.wl)
case 064: //(d8,A4,Rn.wl)
case 065: //(d8,A5,Rn.wl)
case 066: //(d8,A6,Rn.wl)
case 067: //(d8,A7,Rn.wl)
case 073: //(d8,PC,Rn.wl)
t = ea == 073 ? XEiJ.regPC : XEiJ.regRn[ea - (060 - 8)]; //ベースレジスタ
w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //拡張ワード
if ((0x0100 & w) == 0) { //ブリーフフォーマット
return m60Address =
(t //ベースレジスタ
+ (byte) w //バイトディスプレースメント
+ (((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9))); //スケールファクタ
} else { //フルフォーマット
XEiJ.mpuCycleCount += ((0x0003 & w) == 0 ? 1 : //インダイレクトなし
3); //インダイレクトあり
t = (((0x0080 & w) != 0 ? 0 : //ベースレジスタなし
t) + //ベースレジスタあり
((0x0020 & w) == 0 ? 0 : //ベースディスプレースメントなし
(0x0010 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードベースディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS))); //ロングベースディスプレースメント
x = ((0x0040 & w) != 0 ? 0 : //インデックスなし
((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9)); //スケールファクタ
return m60Address =
((0x0003 & w) == 0 ? t + x : //インダイレクトなし
(((0x0004 & w) == 0 ? mmuReadLongData (m60Address = t + x, XEiJ.regSRS) : //プリインデックス
mmuReadLongData (m60Address = t, XEiJ.regSRS) + x) //ポストインデックス
+ ((0x0002 & w) == 0 ? 0 : //アウタディスプレースメントなし
(0x0001 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードアウタディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS)))); //ロングアウタディスプレースメント
}
case 070: //(xxx).W
return m60Address = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
case 071: //(xxx).L
return m60Address = mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
case 074:
Thread.dumpStack ();
break;
} //switch
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
} //efaMemQuad
public static int efaMemExtd (int ea) throws M68kException {
int t, w, x;
switch (ea) {
case 020: //(A0)
case 021: //(A1)
case 022: //(A2)
case 023: //(A3)
case 024: //(A4)
case 025: //(A5)
case 026: //(A6)
case 027: //(A7)
return m60Address = XEiJ.regRn[ea - (020 - 8)];
case 030: //(A0)+
case 031: //(A1)+
case 032: //(A1)+
case 033: //(A3)+
case 034: //(A4)+
case 035: //(A5)+
case 036: //(A6)+
case 037: //(A7)+
m60Incremented += 12L << ((ea - 030) << 3);
return m60Address = (XEiJ.regRn[ea - (030 - 8)] += 12) - 12;
case 040: //-(A0)
case 041: //-(A1)
case 042: //-(A2)
case 043: //-(A3)
case 044: //-(A4)
case 045: //-(A5)
case 046: //-(A6)
case 047: //-(A7)
m60Incremented -= 12L << ((ea - 040) << 3);
return m60Address = XEiJ.regRn[ea - (040 - 8)] -= 12;
case 050: //(d16,A0)
case 051: //(d16,A1)
case 052: //(d16,A2)
case 053: //(d16,A3)
case 054: //(d16,A4)
case 055: //(d16,A5)
case 056: //(d16,A6)
case 057: //(d16,A7)
case 072: //(d16,PC)
t = ea == 072 ? XEiJ.regPC : XEiJ.regRn[ea - (050 - 8)]; //ベースレジスタ
return m60Address = t + mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //ワードディスプレースメント
case 060: //(d8,A0,Rn.wl)
case 061: //(d8,A1,Rn.wl)
case 062: //(d8,A2,Rn.wl)
case 063: //(d8,A3,Rn.wl)
case 064: //(d8,A4,Rn.wl)
case 065: //(d8,A5,Rn.wl)
case 066: //(d8,A6,Rn.wl)
case 067: //(d8,A7,Rn.wl)
case 073: //(d8,PC,Rn.wl)
t = ea == 073 ? XEiJ.regPC : XEiJ.regRn[ea - (060 - 8)]; //ベースレジスタ
w = mmuReadWordZeroExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS); //拡張ワード
if ((0x0100 & w) == 0) { //ブリーフフォーマット
return m60Address =
(t //ベースレジスタ
+ (byte) w //バイトディスプレースメント
+ (((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9))); //スケールファクタ
} else { //フルフォーマット
XEiJ.mpuCycleCount += ((0x0003 & w) == 0 ? 1 : //インダイレクトなし
3); //インダイレクトあり
t = (((0x0080 & w) != 0 ? 0 : //ベースレジスタなし
t) + //ベースレジスタあり
((0x0020 & w) == 0 ? 0 : //ベースディスプレースメントなし
(0x0010 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードベースディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS))); //ロングベースディスプレースメント
x = ((0x0040 & w) != 0 ? 0 : //インデックスなし
((0x0800 & w) == 0 ? (short) XEiJ.regRn[w >> 12] : //ワードインデックス
XEiJ.regRn[w >> 12]) //ロングインデックス
<< ((0x0600 & w) >> 9)); //スケールファクタ
return m60Address =
((0x0003 & w) == 0 ? t + x : //インダイレクトなし
(((0x0004 & w) == 0 ? mmuReadLongData (m60Address = t + x, XEiJ.regSRS) : //プリインデックス
mmuReadLongData (m60Address = t, XEiJ.regSRS) + x) //ポストインデックス
+ ((0x0002 & w) == 0 ? 0 : //アウタディスプレースメントなし
(0x0001 & w) == 0 ? mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS) : //ワードアウタディスプレースメント
mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS)))); //ロングアウタディスプレースメント
}
case 070: //(xxx).W
return m60Address = mmuReadWordSignExword ((XEiJ.regPC += 2) - 2, XEiJ.regSRS);
case 071: //(xxx).L
return m60Address = mmuReadLongExword ((XEiJ.regPC += 4) - 4, XEiJ.regSRS);
case 074:
Thread.dumpStack ();
break;
} //switch
M68kException.m6eNumber = M68kException.M6E_ILLEGAL_INSTRUCTION;
throw M68kException.m6eSignal;
} //efaMemExtd
// 7777777766666666555555554444444433333333222222221111111100000000 mmm
// 7654321076543210765432107654321076543210765432107654321076543210 rrr
// ...IPPZZXXXXXXXXWWWWWWWW--------++++++++MMMMMMMMAAAAAAAADDDDDDDD
static final long MEM_MASK = 0b0000111111111111111111111111111111111111111111110000000000000000L; //メモリモード
static final long MLT_MASK = 0b0000001111111111111111111111111111111111111111110000000000000000L; //メモリ可変モード
static final long CNT_MASK = 0b0000111111111111111111110000000000000000111111110000000000000000L; //制御モード
static final long CLT_MASK = 0b0000001111111111111111110000000000000000111111110000000000000000L; //制御可変モード
//a = efaMltByte (ea)
//a = efaMltWord (ea)
//a = efaMltLong (ea)
//a = efaMltQuad (ea)
//a = efaMltExtd (ea)
// | M+-WXZ |
// メモリ可変モードの実効アドレスを求める
// メモリモードとの違いは(d16,PC)と(d8,PC,Rn.wl)がないこと
public static int efaMltByte (int ea) throws M68kException {
return efaMemByte ((MLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaMltByte
public static int efaMltWord (int ea) throws M68kException {
return efaMemWord ((MLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaMltWord
public static int efaMltLong (int ea) throws M68kException {
return efaMemLong ((MLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaMltLong
public static int efaMltQuad (int ea) throws M68kException {
return efaMemQuad ((MLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaMltQuad
public static int efaMltExtd (int ea) throws M68kException {
return efaMemExtd ((MLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaMltExtd
//a = efaCntByte (ea)
//a = efaCntWord (ea)
//a = efaCntLong (ea)
//a = efaCntQuad (ea)
//a = efaCntExtd (ea)
// | M WXZP |
// 制御モードの実効アドレスを求める
// メモリモードとの違いは(Ar)+と-(Ar)がないこと
public static int efaCntByte (int ea) throws M68kException {
return efaMemByte ((CNT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCntByte
public static int efaCntWord (int ea) throws M68kException {
return efaMemWord ((CNT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCntWord
public static int efaCntLong (int ea) throws M68kException {
return efaMemLong ((CNT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCntLong
public static int efaCntQuad (int ea) throws M68kException {
return efaMemQuad ((CNT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCntQuad
public static int efaCntExtd (int ea) throws M68kException {
return efaMemExtd ((CNT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCntExtd
//a = efaCltByte (ea)
//a = efaCltWord (ea)
//a = efaCltLong (ea)
//a = efaCltQuad (ea)
//a = efaCltExtd (ea)
// | M WXZ |
// 制御可変モードの実効アドレスを求める
// メモリモードとの違いは(Ar)+と-(Ar)と(d16,PC)と(d8,PC,Rn.wl)がないこと
public static int efaCltByte (int ea) throws M68kException {
return efaMemByte ((CLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCltByte
public static int efaCltWord (int ea) throws M68kException {
return efaMemWord ((CLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCltWord
public static int efaCltLong (int ea) throws M68kException {
return efaMemLong ((CLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCltLong
public static int efaCltQuad (int ea) throws M68kException {
return efaMemQuad ((CLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCltQuad
public static int efaCltExtd (int ea) throws M68kException {
return efaMemExtd ((CLT_MASK & (1L << ea)) == 0 ? 0 : ea);
} //efaCltExtd
//以下廃止予定
// Any* → Mem* #<data>を分離できているか確認すること
// LeaPea → Cnt*
// JmpJsr → Cnt*
public static int efaAnyByte (int ea) throws M68kException {
return efaMemByte (ea);
} //efaAnyByte
public static int efaAnyWord (int ea) throws M68kException {
return efaMemWord (ea);
} //efaAnyWord
public static int efaAnyLong (int ea) throws M68kException {
return efaMemLong (ea);
} //efaAnyLong
public static int efaAnyQuad (int ea) throws M68kException {
return efaMemQuad (ea);
} //efaAnyQuad
public static int efaAnyExtd (int ea) throws M68kException {
return efaMemExtd (ea);
} //efaAnyExtd
public static int efaLeaPea (int ea) throws M68kException {
return efaCntLong (ea);
} //efaLeaPea
public static int efaJmpJsr (int ea) throws M68kException {
return efaCntLong (ea);
} //efaJmpJsr
//fpkSTOL ()
// $FE10 __STOL
// 10進数の文字列を32bit符号あり整数に変換する
// /^[ \t]*[-+]?[0-9]+/
// 先頭の'\t'と' 'を読み飛ばす
// <a0.l:10進数の文字列の先頭
// >d0.l:32bit符号あり整数
// >a0.l:10進数の文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkSTOL () throws M68kException {
int a = XEiJ.regRn[8]; //a0
int c = mmuReadByteZeroData (a, 1);
while (c == ' ' || c == '\t') {
c = mmuReadByteZeroData (++a, 1);
}
int n = '7'; //'7'=正,'8'=負
if (c == '-') { //負
n = '8';
c = mmuReadByteZeroData (++a, 1);
} else if (c == '+') { //正
c = mmuReadByteZeroData (++a, 1);
}
if (!('0' <= c && c <= '9')) { //数字が1つもない
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
return;
}
int x = c - '0'; //値
for (c = mmuReadByteZeroData (++a, 1); '0' <= c && c <= '9'; c = mmuReadByteZeroData (++a, 1)) {
if (214748364 < x || x == 214748364 && n < c) { //正のとき2147483647、負のとき2147483648より大きくなるときオーバーフロー
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
return;
}
x = x * 10 + (c - '0');
}
if (n != '7') { //負
x = -x;
}
XEiJ.regRn[0] = x; //d0
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = 0;
} //fpkSTOL()
//fpkLTOS ()
// $FE11 __LTOS
// 32bit符号あり整数を10進数の文字列に変換する
// /^-?[1-9][0-9]*$/
// <d0.l:32bit符号あり整数
// <a0.l:文字列バッファの先頭
// >a0.l:10進数の文字列の直後('\0'の位置)
public static void fpkLTOS () throws M68kException {
int x = XEiJ.regRn[0]; //d0
int a = XEiJ.regRn[8]; //a0
if (x < 0) { //負
mmuWriteByteData (a++, '-', 1);
x = -x;
}
long t = XEiJ.fmtBcd12 (0xffffffffL & x); //符号は取り除いてあるがx=0x80000000の場合があるので(long)xは不可
XEiJ.regRn[8] = a += Math.max (1, 67 - Long.numberOfLeadingZeros (t) >> 2); //a0
mmuWriteByteData (a, 0, 1);
do {
mmuWriteByteData (--a, '0' | (int) t & 15, 1);
} while ((t >>>= 4) != 0L);
} //fpkLTOS()
//fpkSTOH ()
// $FE12 __STOH
// 16進数の文字列を32bit符号なし整数に変換する
// /^[0-9A-Fa-f]+/
// <a0.l:16進数の文字列の先頭
// >d0.l:32bit符号なし整数
// >a0.l:16進数の文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkSTOH () throws M68kException {
int a = XEiJ.regRn[8]; //a0
int c = mmuReadByteZeroData (a, 1);
if (!('0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f')) { //数字が1つもない
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
return;
}
int x = c <= '9' ? c - '0' : c <= 'F' ? c - ('A' - 10) : c - ('a' - 10); //値
for (c = mmuReadByteZeroData (++a, 1); '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'; c = mmuReadByteZeroData (++a, 1)) {
if (0x0fffffff < x) { //0xffffffffより大きくなるときオーバーフロー
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
return;
}
x = x << 4 | (c <= '9' ? c - '0' : c <= 'F' ? c - ('A' - 10) : c - ('a' - 10));
}
XEiJ.regRn[0] = x; //d0
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = 0;
} //fpkSTOH()
//fpkHTOS ()
// $FE13 __HTOS
// 32bit符号なし整数を16進数の文字列に変換する
// /^[1-9A-F][0-9A-F]*$/
// <d0.l:32bit符号なし整数
// <a0.l:文字列バッファの先頭
// >a0.l:16進数の文字列の直後('\0'の位置)
public static void fpkHTOS () throws M68kException {
int x = XEiJ.regRn[0]; //d0
int a = XEiJ.regRn[8] += Math.max (1, 35 - Integer.numberOfLeadingZeros (x) >> 2); //a0
mmuWriteByteData (a, 0, 1);
do {
int t = x & 15;
// t 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
// 9-t 09 08 07 06 05 04 03 02 01 00 ff fe fd fc fb fa
// 9-t>>4 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff
// 9-t>>4&7 00 00 00 00 00 00 00 00 00 00 07 07 07 07 07 07
// 9-t>>4&7|48 30 30 30 30 30 30 30 30 30 30 37 37 37 37 37 37
// (9-t>>4&7|48)+t 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
mmuWriteByteData (--a, (9 - t >> 4 & 7 | 48) + t, 1);
} while ((x >>>= 4) != 0);
} //fpkHTOS()
//fpkSTOO ()
// $FE14 __STOO
// 8進数の文字列を32bit符号なし整数に変換する
// /^[0-7]+/
// <a0.l:8進数の文字列の先頭
// >d0.l:32bit符号なし整数
// >a0.l:8進数の文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkSTOO () throws M68kException {
int a = XEiJ.regRn[8]; //a0
int c = mmuReadByteZeroData (a, 1);
if (!('0' <= c && c <= '7')) { //数字が1つもない
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
return;
}
int x = c - '0'; //値
for (c = mmuReadByteZeroData (++a, 1); '0' <= c && c <= '7'; c = mmuReadByteZeroData (++a, 1)) {
if (0x1fffffff < x) { //0xffffffffより大きくなるときオーバーフロー
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
return;
}
x = x << 3 | c & 7;
}
XEiJ.regRn[0] = x; //d0
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = 0;
} //fpkSTOO()
//fpkOTOS ()
// $FE15 __OTOS
// 32bit符号なし整数を8進数の文字列に変換する
// /^[1-7][0-7]*$/
// <d0.l:32bit符号なし整数
// <a0.l:文字列バッファの先頭
// >a0.l:8進数の文字列の直後('\0'の位置)
public static void fpkOTOS () throws M68kException {
int x = XEiJ.regRn[0]; //d0
//perl optdiv.pl 34 3
// x/3==x*43>>>7 (0<=x<=127) [34*43==1462]
int a = XEiJ.regRn[8] += Math.max (1, (34 - Integer.numberOfLeadingZeros (x)) * 43 >>> 7); //a0
mmuWriteByteData (a, 0, 1);
do {
mmuWriteByteData (--a, '0' | x & 7, 1);
} while ((x >>>= 3) != 0);
} //fpkOTOS()
//fpkSTOB ()
// $FE16 __STOB
// 2進数の文字列を32bit符号なし整数に変換する
// /^[01]+/
// <a0.l:2進数の文字列の先頭
// >d0.l:32bit符号なし整数
// >a0.l:2進数の文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkSTOB () throws M68kException {
int a = XEiJ.regRn[8]; //a0
int c = mmuReadByteZeroData (a, 1);
if (!('0' <= c && c <= '1')) { //数字が1つもない
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
return;
}
int x = c - '0'; //値
for (c = mmuReadByteZeroData (++a, 1); '0' <= c && c <= '1'; c = mmuReadByteZeroData (++a, 1)) {
if (x < 0) { //オーバーフロー
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
return;
}
x = x << 1 | c & 1;
}
XEiJ.regRn[0] = x; //d0
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = 0;
} //fpkSTOB()
//fpkBTOS ()
// $FE17 __BTOS
// 32bit符号なし整数を2進数の文字列に変換する
// /^1[01]*$/
// <d0.l:32bit符号なし整数
// <a0.l:文字列バッファの先頭
// >a0.l:2進数の文字列の直後('\0'の位置)
public static void fpkBTOS () throws M68kException {
int x = XEiJ.regRn[0]; //d0
int a = XEiJ.regRn[8] += Math.max (1, 32 - Integer.numberOfLeadingZeros (x)); //a0
mmuWriteByteData (a, 0, 1);
do {
mmuWriteByteData (--a, '0' | x & 1, 1);
} while ((x >>>= 1) != 0);
} //fpkBTOS()
//fpkIUSING ()
// $FE18 __IUSING
// 32bit符号あり整数を文字数を指定して右詰めで10進数の文字列に変換する
// /^ *-?[1-9][0-9]*$/
// <d0.l:32bit符号あり整数
// <d1.b:文字数
// <a0.l:文字列バッファの先頭
// >a0.l:10進数の文字列の直後('\0'の位置)
public static void fpkIUSING () throws M68kException {
int x = XEiJ.regRn[0]; //d0
int n = 0; //符号の文字数
if (x < 0) { //負
n = 1;
x = -x;
}
long t = XEiJ.fmtBcd12 (0xffffffffL & x); //符号は取り除いてあるがx=0x80000000の場合があるので(long)xは不可
int l = n + Math.max (1, 67 - Long.numberOfLeadingZeros (t) >> 2); //符号を含めた文字数
int a = XEiJ.regRn[8]; //a0
for (int i = (XEiJ.regRn[1] & 255) - l; i > 0; i--) {
mmuWriteByteData (a++, ' ', 1);
}
XEiJ.regRn[8] = a += l; //a0
mmuWriteByteData (a, 0, 1);
do {
mmuWriteByteData (--a, '0' | (int) t & 15, 1);
} while ((t >>>= 4) != 0L);
if (n != 0) {
mmuWriteByteData (--a, '-', 1);
}
} //fpkIUSING()
//fpkVAL ()
// $FE20 __VAL
// 文字列を64bit浮動小数点数に変換する
// 先頭の'\t'と' 'を読み飛ばす
// "&B"または"&b"で始まっているときは続きを2進数とみなして__STOBで32bit符号なし整数に変換してから__LTODで64bit浮動小数点数に変換する
// "&O"または"&o"で始まっているときは続きを8進数とみなして__STOOで32bit符号なし整数に変換してから__LTODで64bit浮動小数点数に変換する
// "&H"または"&h"で始まっているときは続きを16進数とみなして__STOHで32bit符号なし整数に変換してから__LTODで64bit浮動小数点数に変換する
// それ以外は__STODと同じ
// <a0.l:文字列の先頭
// >d0d1.d:64bit浮動小数点数
// >d2.l:(先頭が'&'でないとき)65535=64bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
// >d3.l:(先頭が'&'でないとき)d2.l==65535のとき64bit浮動小数点数をintに変換した値
// >a0.l:変換された文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkVAL () throws M68kException {
int a = XEiJ.regRn[8]; //a0
//先頭の空白を読み飛ばす
int c = mmuReadByteSignData (a++, 1);
while (c == ' ' || c == '\t') {
c = mmuReadByteSignData (a++, 1);
}
if (c == '&') { //&B,&O,&H
c = mmuReadByteSignData (a++, 1) & 0xdf;
XEiJ.regRn[8] = a; //&?の直後
if (c == 'B') {
fpkSTOB ();
FEFunction.fpkLTOD ();
} else if (c == 'O') {
fpkSTOO ();
FEFunction.fpkLTOD ();
} else if (c == 'H') {
fpkSTOH ();
FEFunction.fpkLTOD ();
} else {
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C; //文法エラー
}
} else { //&B,&O,&H以外
fpkSTOD ();
}
} //fpkVAL()
//fpkUSING ()
// $FE21 __USING
// 64bit浮動小数点数をアトリビュートを指定して文字列に変換する
// メモ
// bit1の'\\'とbit4の'+'を両方指定したときは'\\'が右側。先頭に"+\\"を付ける
// bit1の'\\'とbit2の','とbit4の'+'は整数部の桁数が足りないとき数字を右にずらして押し込まれる
// bit3で指数形式を指示しなければ指数部が極端に大きくても極端に小さくても指数形式にならない
// bit3で指数形式を指定したときbit1の'\\'とbit2の','は無効
// bit4とbit5とbit6はbit4>bit5>bit6の順位で1つだけ有効
// 有効数字は14桁で15桁目以降はすべて0
// FLOAT2.Xは整数部の0でない最初の数字から256文字目までで打ち切られてしまう
// 整数部の桁数に余裕があれば左側の空白は出力されるので文字列の全体が常に256バイトに収まるわけではない
// using 1234.5 5 0 0 " 1235."
// using 1234.5 5 1 0 " 1234.5"
// using 1234.5 5 2 0 " 1234.50"
// using 1234.5 6 2 1 "**1234.50"
// using 1234.5 6 2 2 " \\1234.50"
// using 1234.5 6 2 3 "*\\1234.50"
// using 1234.5 6 2 4 " 1,234.50"
// using 1234.5 4 2 4 "1,234.50"
// using 1234.5 4 2 5 "1,234.50"
// using 1234.5 4 2 6 "\\1,234.50"
// using 1234.5 4 2 7 "\\1,234.50"
// using 1234.5 4 2 16 "+1234.50"
// using 1234.5 4 2 22 "+\\1,234.50"
// using 1234.5 4 2 32 "1234.50+"
// using 1234.5 4 2 48 "+1234.50"
// using 1234.5 4 2 64 "1234.50 "
// using 1234.5 4 2 80 "+1234.50"
// using 1234.5 4 2 96 "1234.50+"
// using 12345678901234567890 10 1 0 "12345678901235000000.0"
// using 12345678901234567890e+10 10 1 0 "123456789012350000000000000000.0"
// using 0.3333 0 0 0 "."
// using 0.6666 0 0 0 "1."
// using 0.6666 0 3 0 ".667"
// using 0.6666 3 0 0 " 1."
// using 0.3333 0 0 2 "\\."
// using 0.3333 0 0 16 "+."
// using 0.3333 0 0 18 "+\\."
// using 1e-10 3 3 0 " 0.000"
// 指数形式の出力は不可解で本来の動作ではないように思えるが、
// X-BASICのprint using命令が使っているのでFLOAT2.Xに合わせておいた方がよさそう
// print using "###.##";1.23 " 1.23" 整数部の桁数は3
// print using "+##.##";1.23 " +1.23" 整数部の桁数は3←
// print using "###.##^^^^^";1.23 " 12.30E-001" 整数部の桁数は3
// print using "+##.##^^^^^";1.23 "+12.30E-001" 整数部の桁数は2←
// FLOAT2.Xでは#NANと#INFは4桁の整数のように出力される。末尾に小数点が付くが小数部には何も出力されない
// using -#INF 7 3 23 "*-\\#,INF."
// FLOAT2.Xで#NANと#INFを指数形式にするとさらに不可解。これはバグと言ってよいと思う
// using #INF 10 10 8 " #INFE-005"
// ここでは#NANと#INFは整数部と小数点と小数部と指数部の全体を使って右寄せにする
// <d0d1.d:64bit浮動小数点数
// <d2.l:整数部の桁数
// <d3.l:小数部の桁数
// <d4.l:アトリビュート
// bit0 左側を'*'で埋める
// bit1 先頭に'\\'を付ける
// bit2 整数部を3桁毎に','で区切る
// bit3 指数形式
// bit4 先頭に符号('+'または'-')を付ける
// bit5 末尾に符号('+'または'-')を付ける
// bit6 末尾に符号(' 'または'-')を付ける
// <a0.l:文字列バッファの先頭
// a0は変化しない
public static void fpkUSING () throws M68kException {
fpkUSINGSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]); //64bit浮動小数点数
} //fpkUSING()
public static void fpkUSINGSub (long l) throws M68kException {
int len1 = Math.max (0, XEiJ.regRn[2]); //整数部の桁数
int len2 = Math.max (0, XEiJ.regRn[3]); //小数部の桁数
int attr = XEiJ.regRn[4]; //アトリビュート
int a = XEiJ.regRn[8]; //文字列バッファの先頭
boolean exp = (attr & 8) != 0; //true=指数形式
int spc = (attr & 1) != 0 ? '*' : ' '; //先頭の空白を充填する文字
int yen = (attr & 2) != 0 ? '\\' : 0; //先頭の'\\'
int cmm = !exp && (attr & 4) != 0 ? ',' : 0; //3桁毎に入れる','
//符号
int sgn1 = 0; //先頭の符号
int sgn2 = 0; //末尾の符号
if (l < 0L) { //負
if ((attr & 32 + 64) == 0) { //末尾に符号を付けない
sgn1 = '-'; //先頭の符号
} else { //末尾に符号を付ける
sgn2 = '-'; //末尾の符号
}
l &= 0x7fffffffffffffffL; //符号bitを消しておく
} else { //正
if ((attr & 16) != 0) { //先頭に符号('+'または'-')を付ける
sgn1 = '+';
} else if ((attr & 16 + 32) == 32) { //末尾に符号('+'または'-')を付ける
sgn2 = '+';
} else if ((attr & 16 + 32 + 64) == 64) { //末尾に符号(' 'または'-')を付ける
sgn2 = ' ';
}
}
double x = Double.longBitsToDouble (l); //絶対値
int e = (int) (l >>> 52) - 1023; //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
l &= 0x000fffffffffffffL; //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
//±0,±Inf,NaN
if (e == -1023) { //±0,非正規化数
if (l == 0L) { //±0
for (int i = len1 - ((sgn1 != 0 ? 1 : 0) + //先頭の符号
(yen != 0 ? 1 : 0) + //'\\'
1 //数字
); 0 < i; i--) {
mmuWriteByteData (a++, spc, 1); //空白
}
if (sgn1 != 0) {
mmuWriteByteData (a++, sgn1, 1); //先頭の符号
}
if (yen != 0) {
mmuWriteByteData (a++, yen, 1); //'\\'
}
if (0 < len1) {
mmuWriteByteData (a++, '0', 1); //整数部
}
mmuWriteByteData (a++, '.', 1); //小数点
for (; 0 < len2; len2--) {
mmuWriteByteData (a++, '0', 1); //小数部
}
mmuWriteByteData (a, '\0', 1);
return;
}
e -= Long.numberOfLeadingZeros (l) - 12; //非正規化数の指数部を補正する
} else if (e == 1024) { //±Inf,NaN
for (int i = len1 + 1 + len2 + (exp ? 5 : 0) - //整数部と小数点と小数部と指数部の全体を使って右寄せにする
((sgn1 != 0 ? 1 : 0) + //先頭の符号
(yen != 0 ? 1 : 0) + //'\\'
4 //文字
); 0 < i; i--) {
mmuWriteByteData (a++, spc, 1); //空白
}
if (sgn1 != 0) {
mmuWriteByteData (a++, sgn1, 1); //先頭の符号
}
if (yen != 0) {
mmuWriteByteData (a++, yen, 1); //'\\'
}
mmuWriteByteData (a++, '#', 1);
if (l == 0L) { //±Inf
mmuWriteByteData (a++, 'I', 1);
mmuWriteByteData (a++, 'N', 1);
mmuWriteByteData (a++, 'F', 1);
} else { //NaN
mmuWriteByteData (a++, 'N', 1);
mmuWriteByteData (a++, 'A', 1);
mmuWriteByteData (a++, 'N', 1);
}
mmuWriteByteData (a, '\0', 1);
return;
}
//10進数で表現したときの指数部を求める
// 10^e<=x<10^(e+1)となるeを求める
e = (int) Math.floor ((double) e * 0.30102999566398119521373889472); //log10(2)
//10^-eを掛けて1<=x<10にする
// 非正規化数の最小値から正規化数の最大値まで処理できなければならない
// 10^-eを計算してからまとめて掛ける方法はxが非正規化数のとき10^-eがオーバーフローしてしまうので不可
// doubleは非正規化数の逆数を表現できない
if (0 < e) { //10<=x
x *= FEFunction.FPK_TEN_M16QR[e & 15];
if (16 <= e) {
x *= FEFunction.FPK_TEN_M16QR[16 + (e >> 4 & 15)];
if (256 <= e) {
x *= FEFunction.FPK_TEN_M16QR[33]; //FEFunction.FPK_TEN_M16QR[32 + (e >> 8)]
}
}
} else if (e < 0) { //x<1
x *= FEFunction.FPK_TEN_P16QR[-e & 15];
if (e <= -16) {
x *= FEFunction.FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
if (e <= -256) {
x *= FEFunction.FPK_TEN_P16QR[33]; //FEFunction.FPK_TEN_P16QR[32 + (-e >> 8)]
}
}
}
//整数部2桁、小数部16桁の10進数に変換する
// 1<=x<10なのでw[1]が先頭になるはずだが誤差で前後にずれる可能性がある
int[] w = new int[18];
{
int d = (int) x;
int t = XEiJ.FMT_BCD4[d];
w[0] = t >> 4;
w[1] = t & 15;
for (int i = 2; i < 18; i += 4) {
//xを10000倍して整数部dを引くことで小数部を残すが、このとき情報落ちが発生して誤差が蓄積する
//Double-Doubleの乗算の要領で10000倍を正確に行い、誤差の蓄積を回避する
//x = (x - (double) d) * 10000.0;
double xh = x * 0x8000001p0;
xh += x - xh; //xの上半分
x = (xh - (double) d) * 10000.0 + (x - xh) * 10000.0;
d = (int) x;
t = XEiJ.FMT_BCD4[d];
w[i ] = t >> 12;
w[i + 1] = t >> 8 & 15;
w[i + 2] = t >> 4 & 15;
w[i + 3] = t & 15;
}
}
//先頭の位置を確認する
// w[h]が先頭(0でない最初の数字)の位置
int h = w[0] != 0 ? 0 : w[1] != 0 ? 1 : 2;
//14+1桁目を四捨五入する
int o = h + 14; //w[o]は四捨五入する桁の位置。w[]の範囲内
if (5 <= w[o]) {
int i = o;
while (10 <= ++w[--i]) {
w[i] = 0;
}
if (i < h) { //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
h--; //先頭を左にずらす
o--; //末尾を左にずらす
}
}
//先頭の位置に応じて指数部を更新する
// w[h]が整数部、w[h+1..13]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
e -= h - 1;
//整数部の桁数を調節する
int ee = !exp ? e : Math.max (0, sgn1 != 0 || sgn2 != 0 ? len1 : len1 - 1) - 1; //整数部の桁数-1。整数部の桁数はee+1桁。指数部はe-ee
//小数点以下len2+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
// あらかじめ14+1桁目で四捨五入しておかないと、
// 1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
int s = h + ee + 1 + len2; //w[s]は小数点以下len2+1桁目の位置。w.length<=sの場合があることに注意
if (s < o) {
o = s; //w[o]は四捨五入する桁の位置。o<0の場合があることに注意
if (0 <= o && 5 <= w[o]) {
int i = o;
while (10 <= ++w[--i]) {
w[i] = 0;
}
if (i < h) { //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
h--; //先頭を左にずらす
if (!exp) { //指数形式でないとき
ee++; //左に1桁伸ばす。全体の桁数が1桁増える
} else { //指数形式のとき
e++; //指数部を1増やす
o--; //末尾を左にずらす。全体の桁数は変わらない
}
}
}
}
//文字列に変換する
if (0 <= ee) { //1<=x
for (int i = len1 - ((sgn1 != 0 ? 1 : 0) + //先頭の符号
(yen != 0 ? 1 : 0) + //'\\'
(cmm != 0 ? ee / 3 : 0) + //','
ee + 1 //数字
); 0 < i; i--) {
mmuWriteByteData (a++, spc, 1); //空白
}
if (sgn1 != 0) {
mmuWriteByteData (a++, sgn1, 1); //先頭の符号
}
if (yen != 0) {
mmuWriteByteData (a++, yen, 1); //'\\'
}
for (int i = ee; 0 <= i; i--) {
mmuWriteByteData (a++, h < o ? '0' + w[h] : '0', 1); //整数部
h++;
if (cmm != 0 && 0 < i && i % 3 == 0) {
mmuWriteByteData (a++, cmm, 1); //','
}
}
mmuWriteByteData (a++, '.', 1); //小数点
for (; 0 < len2; len2--) {
mmuWriteByteData (a++, h < o ? '0' + w[h] : '0', 1); //小数部
h++;
}
} else { //x<1
for (int i = len1 - ((sgn1 != 0 ? 1 : 0) + //先頭の符号
(yen != 0 ? 1 : 0) + //'\\'
1 //数字
); 0 < i; i--) {
mmuWriteByteData (a++, spc, 1); //空白
}
if (sgn1 != 0) {
mmuWriteByteData (a++, sgn1, 1); //先頭の符号
}
if (yen != 0) {
mmuWriteByteData (a++, yen, 1); //'\\'
}
if (0 < len1) {
mmuWriteByteData (a++, '0', 1); //整数部
}
mmuWriteByteData (a++, '.', 1); //小数点
for (int i = -1 - ee; 0 < len2 && 0 < i; len2--, i--) {
mmuWriteByteData (a++, '0', 1); //小数部の先頭の0の並び
}
for (; 0 < len2; len2--) {
mmuWriteByteData (a++, h < o ? '0' + w[h] : '0', 1); //小数部
h++;
}
}
if (exp) {
e -= ee;
mmuWriteByteData (a++, 'E', 1); //指数部の始まり
if (0 <= e) {
mmuWriteByteData (a++, '+', 1); //指数部の正符号。省略しない
} else {
mmuWriteByteData (a++, '-', 1); //指数部の負符号
e = -e;
}
e = XEiJ.FMT_BCD4[e];
mmuWriteByteData (a++, '0' + (e >> 8 ), 1); //指数部の100の位。0でも省略しない
mmuWriteByteData (a++, '0' + (e >> 4 & 15), 1); //指数部の10の位
mmuWriteByteData (a++, '0' + (e & 15), 1); //指数部の1の位
}
if (sgn2 != 0) {
mmuWriteByteData (a++, sgn2, 1); //末尾の符号
}
mmuWriteByteData (a, '\0', 1);
} //fpkUSINGSub6(long)
//fpkSTOD ()
// $FE22 __STOD
// 文字列を64bit浮動小数点数に変換する
// 先頭の'\t'と' 'を読み飛ばす
// "#INF"は無限大、"#NAN"は非数とみなす
// バグ
// FLOAT2.X 2.02/2.03は誤差が大きい
// "1.7976931348623E+308"=0x7fefffffffffffb0が0x7fefffffffffffb3になる
// "1.5707963267949"=0x3ff921fb54442d28が0x3ff921fb54442d26になる
// "4.9406564584125E-324"(非正規化数の最小値よりもわずかに大きい)がエラーになる
// FLOAT2.X 2.02/2.03は"-0"が+0になる
// FLOAT4.X 1.02は"-0"が+0になる(実機で確認済み)
// FLOAT2.X 2.02/2.03は"-#INF"が+Infになる
// print val("-#INF")で再現できる
// '-'を符号として解釈しておきながら結果の無限大に符号を付けるのを忘れている
// FLOAT2.X 2.02/2.03は".#INF"が+Infになる
// print val(".#INF")で再現できる
// FLOAT4.X 1.02は"#NAN","#INF","-#INF"を読み取ったときa0が文字列の直後ではなく最後の文字を指している
// <a0.l:文字列の先頭
// >d0d1.d:64bit浮動小数点数
// >d2.l:65535=64bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
// >d3.l:d2.l==65535のとき64bit浮動小数点数をintに変換した値
// >a0.l:変換された文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkSTOD () throws M68kException {
long l = Double.doubleToLongBits (fpkSTODSub ());
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
XEiJ.regRn[0] = (int) (l >> 32); //d0
XEiJ.regRn[1] = (int) l; //d1
} //fpkSTOD()
public static double fpkSTODSub () throws M68kException {
int a = XEiJ.regRn[8]; //a0
//先頭の空白を読み飛ばす
int c = mmuReadByteSignData (a, 1);
while (c == ' ' || c == '\t') {
c = mmuReadByteSignData (++a, 1);
}
//符号を読み取る
double s = 1.0; //仮数部の符号
if (c == '+') {
c = mmuReadByteSignData (++a, 1);
} else if (c == '-') {
s = -s;
c = mmuReadByteSignData (++a, 1);
}
//#NANと#INFを処理する
if (c == '#') {
c = mmuReadByteSignData (a + 1, 1);
if (c == 'N' || c == 'I') { //小文字は不可
c = c << 8 | mmuReadByteZeroData (a + 2, 1);
if (c == ('N' << 8 | 'A') || c == ('I' << 8 | 'N')) {
c = c << 8 | mmuReadByteZeroData (a + 3, 1);
if (c == ('N' << 16 | 'A' << 8 | 'N') || c == ('I' << 16 | 'N' << 8 | 'F')) {
XEiJ.regRn[2] = 0; //d2
XEiJ.regRn[3] = 0; //d3
XEiJ.regRn[8] = a + 4; //a0。"#NAN"または"#INF"のときだけ直後まで進める。それ以外は'#'の位置で止める
XEiJ.regCCR = 0; //エラーなし。"#INF"はオーバーフローとみなされない
return c == ('N' << 16 | 'A' << 8 | 'N') ? Double.NaN : s * Double.POSITIVE_INFINITY;
}
}
}
XEiJ.regRn[8] = a; //a0。'#'の位置で止める
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C; //文法エラー
return 0.0;
} //if c=='#'
//仮数部を読み取る
// 数字を1000個並べてからe-1000などと書いてあるとき途中でオーバーフローすると困るので、
// 多すぎる数字の並びは先頭の有効数字だけ読み取って残りは桁数だけ数えて読み飛ばす
long u = 0L; //仮数部
int n = 0; //0以外の最初の数字から数えて何桁目か
int e = 1; //-小数部の桁数。1=整数部
if (c == '.') { //仮数部の先頭が小数点
e = 0; //小数部開始
c = mmuReadByteSignData (++a, 1);
}
if (c < '0' || '9' < c) { //仮数部に数字がない
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C; //文法エラー
return 0.0;
}
double x = 0.0;
do {
if (0 < n || '0' < c) { //0以外
n++; //0以外の最初の数字から数えて何桁目か
}
if (e <= 0 && n <= 18) { //小数部で18桁目まで
e--; //-小数部の桁数
}
if (0 < n && n <= 18) { //1桁目から18桁目まで
u = u * 10L + (long) (c - '0');
}
c = mmuReadByteSignData (++a, 1);
if (0 < e && c == '.') { //整数部で小数点が出てきた
e = 0; //小数部開始
c = mmuReadByteSignData (++a, 1);
}
} while ('0' <= c && c <= '9');
if (0 < e) { //小数点が出てこなかった
e = 18 < n ? n - 18 : 0; //整数部を読み飛ばした桁数が(-小数部の桁数)
}
// 1<=u<10^18 整数なので誤差はない
// 0<e 小数点がなくて整数部が19桁以上あって末尾を読み飛ばした
// e==0 小数点がなくて整数部が18桁以内で末尾を読み飛ばさなかった
// 小数点があって小数点で終わっていた
// e<0 小数点があって小数部が1桁以上あった
//指数部を読み取る
if (c == 'E' || c == 'e') {
c = mmuReadByteSignData (++a, 1);
int t = 1; //指数部の符号
if (c == '+') {
c = mmuReadByteSignData (++a, 1);
} else if (c == '-') {
t = -t;
c = mmuReadByteSignData (++a, 1);
}
if (c < '0' || '9' < c) { //指数部に数字がない
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C; //文法エラー
return 0.0;
}
while (c == '0') { //先頭の0を読み飛ばす
c = mmuReadByteSignData (++a, 1);
}
int p = 0;
for (int j = 0; '0' <= c && c <= '9' && j < 9; j++) { //0以外の数字が出てきてから最大で9桁目まで読み取る。Human68kの環境では数字を1GBも並べることはできないのでオーバーフローの判定には9桁あれば十分
p = p * 10 + (c - '0');
c = mmuReadByteSignData (++a, 1);
}
e += t * p;
}
//符号と仮数部と指数部を合わせる
// x=s*x*10^e
// 1<=u<10^18なのでeが範囲を大きく外れている場合を先に除外する
if (e < -350) {