xeij/MC68060.java (3/3)
1 2 3 XEiJ.regRn[2] = 65535; //d2。-1ではない
XEiJ.regRn[3] = 0; //d3
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = 0; //エラーなし。アンダーフローはエラーとみなされない
return s < 0.0 ? -0.0 : 0.0;
}
if (350 < e) {
XEiJ.regRn[2] = 0; //d2
XEiJ.regRn[3] = 0; //d3
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C; //オーバーフロー
return s * Double.POSITIVE_INFINITY;
}
if (true) {
QFP xx = new QFP (s < 0.0 ? -u : u); //符号と仮数部
if (0 < e) {
xx.mul (QFP.QFP_TEN_P16QR[e & 15]);
if (16 <= e) {
xx.mul (QFP.QFP_TEN_P16QR[16 + (e >> 4 & 15)]);
if (256 <= e) {
xx.mul (QFP.QFP_TEN_P16QR[33]);
}
}
} else if (e < 0) {
xx.mul (QFP.QFP_TEN_M16QR[-e & 15]);
if (e <= -16) {
xx.mul (QFP.QFP_TEN_M16QR[16 + (-e >> 4 & 15)]);
if (e <= -256) {
xx.mul (QFP.QFP_TEN_M16QR[33]);
}
}
}
x = xx.getd ();
} else {
x = s * (double) u; //符号と仮数部
if (0 < e) {
x *= FEFunction.FPK_TEN_P16QR[e & 15];
if (16 <= e) {
x *= FEFunction.FPK_TEN_P16QR[16 + (e >> 4 & 15)];
if (256 <= e) {
x *= FEFunction.FPK_TEN_P16QR[33]; //FEFunction.FPK_TEN_P16QR[32 + (e >> 8)]
}
}
} else if (e < 0) {
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)]
}
}
}
}
if (Double.isInfinite (x)) {
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C; //オーバーフロー
return x;
}
// アンダーフローで0になっている場合がある
if (x == (double) ((int) x)) { //intで表現できる。+0.0==-0.0==0なので±0.0を含む
XEiJ.regRn[2] = 65535; //d2。-1ではない
XEiJ.regRn[3] = (int) x; //d3
} else { //intで表現できない
XEiJ.regRn[2] = 0; //d2
XEiJ.regRn[3] = 0; //d3
}
XEiJ.regRn[8] = a; //a0
XEiJ.regCCR = 0; //エラーなし
return x;
} //fpkSTODSub()
//fpkDTOS ()
// $FE23 __DTOS
// 64bit浮動小数点数を文字列に変換する
// 無限大は"#INF"、非数は"#NAN"になる
// 指数形式の境目
// x<10^-4または10^14<=xのとき指数形式にする
// FLOAT2.X/FLOAT4.Xの場合
// 3f2fffffffffff47 2.4414062499999E-004
// 3f2fffffffffff48 0.000244140625
// 42d6bcc41e8fffdf 99999999999999
// 42d6bcc41e8fffe0 1E+014
// <d0d1.d:64bit浮動小数点数
// <a0.l:文字列バッファの先頭
// >a0.l:末尾の'\0'の位置
public static void fpkDTOS () throws M68kException {
fpkDTOSSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]); //64bit浮動小数点数
} //fpkDTOS()
public static void fpkDTOSSub (long l) throws M68kException {
final int len3 = 14;
int a = XEiJ.regRn[8]; //文字列バッファの先頭
//符号と指数部の処理
// ±0,±Inf,NaNはここで除外する
if (l < 0L) {
mmuWriteByteData (a++, '-', 1); //負符号
l &= 0x7fffffffffffffffL; //符号bitを消しておく
}
double x = Double.longBitsToDouble (l); //絶対値
int e = (int) (l >>> 52) - 1023; //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
l &= 0x000fffffffffffffL; //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
if (e == -1023) { //±0,非正規化数
if (l == 0L) { //±0
mmuWriteByteData (a++, '0', 1); //0
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[8] = a; //末尾の'\0'の位置
return;
}
e -= Long.numberOfLeadingZeros (l) - 12; //非正規化数の指数部を補正する
} else if (e == 1024) { //±Inf,NaN
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);
XEiJ.regRn[8] = a; //末尾の'\0'の位置
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..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
e -= h - 1;
//末尾の位置を確認する
// w[o-1]が末尾(0でない最後の数字)の位置
while (w[o - 1] == 0) { //全体は0ではないので必ず止まる。小数点よりも左側で止まる場合があることに注意
o--;
}
//指数形式にするかどうか選択して文字列に変換する
if (0 <= e && e < len3) { //1<=x<10^len3。指数形式にしない
do {
mmuWriteByteData (a++, '0' + w[h++], 1); //整数部。末尾の位置に関係なく1の位まで書く
} while (0 <= --e);
if (h < o) { //小数部がある
mmuWriteByteData (a++, '.', 1); //小数部があるときだけ小数点を書く
do {
mmuWriteByteData (a++, '0' + w[h++], 1); //小数部
} while (h < o);
}
} else if (-4 <= e && e < 0) { //10^-4<=x<1。指数形式にしない
mmuWriteByteData (a++, '0', 1); //整数部の0
mmuWriteByteData (a++, '.', 1); //小数点
while (++e < 0) {
mmuWriteByteData (a++, '0', 1); //小数部の先頭の0の並び
}
do {
mmuWriteByteData (a++, '0' + w[h++], 1); //小数部
} while (h < o);
} else { //x<10^-4または10^len3<=x。指数形式にする
mmuWriteByteData (a++, '0' + w[h++], 1); //整数部
if (h < o) { //小数部がある
mmuWriteByteData (a++, '.', 1); //小数部があるときだけ小数点を書く
do {
mmuWriteByteData (a++, '0' + w[h++], 1); //小数部
} while (h < o);
}
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の位
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[8] = a; //末尾の'\0'の位置
} //fpkDTOSSub6()
//fpkECVT ()
// $FE24 __ECVT
// 64bit浮動小数点数を全体の桁数を指定して文字列に変換する
// 文字列に書くのは仮数部の数字のみ
// 符号と小数点と指数部は文字列に書かず、小数点の位置と符号をレジスタに入れて返す
// 桁数は255桁まで指定できるが、有効桁数は14桁まで
// 有効桁数の次の桁で絶対値を四捨五入する
// 15桁以上を指定しても14桁に丸められ、15桁目以降はすべて'0'になる
// 無限大は"#INF"、非数は"#NAN"に変換する
// "#INF"と"#NAN"のとき小数点の位置は4になる
// "#INF"と"#NAN"で3桁以下のときは途中で打ち切る
// メモ
// FLOATn.Xは"#INF"と"#NAN"で1桁~3桁のとき文字列が"$","$0","$00"になってしまう
// 文字数が少なすぎて"#INF"や"#NAN"が入り切らないのは仕方がないが、
// 無意味な"$00"という文字列になるのは数字ではない文字列を四捨五入しようとするバグが原因
// 例えば3桁のときは4桁目の'F'または'N'が'5'以上なので繰り上げて上の位をインクリメントする
// 'N'+1='O'または'A'+1='B'が'9'よりも大きいので'0'を上書きして繰り上げて上の位をインクリメントする
// 'I'+1='J'または'N'+1='O'も'9'よりも大きいので'0'を上書きして繰り上げて上の位をインクリメントする
// '#'+1='$'は'9'以下なので"$00"になる
// X-BASICでint i2,i3:print ecvt(val("#INF"),3,i2,i3)とすると再現できる
// "#INF"と"#NAN"で5桁以上のときは5桁目以降はすべて'\0'になる
// メモ
// FLOATn.Xは"#NAN"と"#INF"で15桁以上のとき5桁目から14桁目までは'\0'だが15桁目以降に'0'が書き込まれる
// 通常は5桁目の'\0'で文字列は終了していると見なされるので実害はないが気持ち悪い
// メモ
// FLOAT2.X 2.02/2.03は0のとき小数点の位置が0になる
// FLOAT4.X 1.02は0のとき小数点の位置が1になる
// ここでは1にしている
// <d0d1.d:64bit浮動小数点数
// <d2.l:全体の桁数
// <a0.l:文字列バッファの先頭。末尾に'\0'を書き込むので桁数+1バイト必要
// >d0.l:先頭から小数点の位置までのオフセット
// >d1.l:符号(0=+,1=-)
// a0.lは変化しない
public static void fpkECVT () throws M68kException {
fpkECVTSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]); //64bit浮動小数点数
} //fpkECVT()
public static void fpkECVTSub (long l) throws M68kException {
int len3 = Math.max (0, XEiJ.regRn[2]); //全体の桁数
int a = XEiJ.regRn[8]; //文字列バッファの先頭
int b = a + len3; //文字列バッファの末尾+1。'\0'を書き込む位置
//符号と指数部の処理
// ±0,±Inf,NaNはここで除外する
if (0L <= l) {
XEiJ.regRn[1] = 0; //正符号
} else {
XEiJ.regRn[1] = 1; //負符号
l &= 0x7fffffffffffffffL; //符号bitを消しておく
}
double x = Double.longBitsToDouble (l); //絶対値
int e = (int) (l >>> 52) - 1023; //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
l &= 0x000fffffffffffffL; //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
if (e == -1023) { //±0,非正規化数
if (l == 0L) { //±0
//指定された全体の桁数だけ'0'を並べる
while (a < b) {
mmuWriteByteData (a++, '0', 1);
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[0] = 1; //小数点の位置
return;
}
e -= Long.numberOfLeadingZeros (l) - 12; //非正規化数の指数部を補正する
} else if (e == 1024) { //±Inf,NaN
for (int s = l != 0L ? '#' | 'N' << 8 | 'A' << 16 | 'N' << 24 : '#' | 'I' << 8 | 'N' << 16 | 'F' << 24; a < b && s != 0; s >>>= 8) {
mmuWriteByteData (a++, s, 1);
}
while (a < b) {
mmuWriteByteData (a++, '\0', 1); //残りは'\0'
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[0] = 4; //小数点の位置
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..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
e -= h - 1;
//先頭からlen3+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
// あらかじめ14+1桁目で四捨五入しておかないと、
// 1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
int s = h + len3; //w[s]は先頭からlen3+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--; //先頭を左にずらす
o--; //末尾を左にずらす
e++; //指数部を1増やす
}
}
}
//文字列に変換する
while (a < b && h < o) {
mmuWriteByteData (a++, '0' + w[h++], 1); //有効数字
}
while (a < b) {
mmuWriteByteData (a++, '0', 1); //残りは'0'
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[0] = e + 1; //小数点の位置
} //fpkECVTSub6()
//fpkFCVT ()
// $FE25 __FCVT
// 64bit浮動小数点数を小数点以下の桁数を指定して文字列に変換する
// メモ
// 小数点の位置がpのとき[p]の左側に小数点がある
// 全体の桁数が制限されないので指数部が大きいとき整数部が収まるサイズのバッファが必要
// 0または1以上のとき
// 整数部と小数点以下の指定された桁数までを小数部の0を省略せずに出力する
// 整数部と小数点以下の指定された桁数が合わせて14桁を超えるときは15桁目が四捨五入されて15桁目以降は0になる
// 小数点の位置は整数部の桁数に等しい
// print fcvt(0#,4,i2,i3),i2,i3
// 0000 0 0
// print fcvt(2e+12/3#,4,i2,i3),i2,i3
// 6666666666666700 12 0
// ↑
// 1未満のとき
// 小数点以下の桁数の範囲内を先頭の0を省略して出力する
// 小数点以下の桁数の範囲内がすべて0のときは""になる
// 小数点の位置は指数部+1に等しい
// print fcvt(0.01,3,i2,i3),i2,i3 0.010
// 10 -1 0 <~~
// print fcvt(0.001,3,i2,i3),i2,i3 0.001
// 1 -2 0 <<~
// print fcvt(0.0001,3,i2,i3),i2,i3 0.0001
// -3 0 <<<
// print fcvt(0.00001,3,i2,i3),i2,i3 0.00001
// -4 0 <<<<
// #INFと#NAN
// 小数点以下の桁数の指定に関係なく4文字出力して小数点の位置4を返す
// print fcvt(val("#INF"),2,i2,i3),i2,i3
// #INF 4 0
// print fcvt(val("#INF"),6,i2,i3),i2,i3
// #INF 4 0
// バグ
// FLOAT4.X 1.02は結果が整数部が大きいとき255文字で打ち切られる
// FLOAT4.X 1.02はFCVT(±0)の整数部が0桁ではなく1桁になる
// <d0d1.d:64bit浮動小数点数
// <d2.l:小数点以下の桁数
// <a0.l:文字列バッファの先頭
// >d0.l:先頭から小数点の位置までのオフセット
// >d1.l:符号(0=+,1=-)
public static void fpkFCVT () throws M68kException {
fpkFCVTSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]); //64bit浮動小数点数
} //fpkFCVT()
public static void fpkFCVTSub (long l) throws M68kException {
int len2 = Math.max (0, XEiJ.regRn[2]); //小数部の桁数
int a = XEiJ.regRn[8]; //文字列バッファの先頭
//符号と指数部の処理
// ±0,±Inf,NaNはここで除外する
if (0L <= l) {
XEiJ.regRn[1] = 0; //正符号
} else {
XEiJ.regRn[1] = 1; //負符号
l &= 0x7fffffffffffffffL; //符号bitを消しておく
}
double x = Double.longBitsToDouble (l); //絶対値
int e = (int) (l >>> 52) - 1023; //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
l &= 0x000fffffffffffffL; //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
if (e == -1023) { //±0,非正規化数
if (l == 0L) { //±0
//指定された小数点以下の桁数だけ'0'を並べる
while (len2-- > 0) {
mmuWriteByteData (a++, '0', 1);
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[0] = 0; //小数点の位置
return;
}
e -= Long.numberOfLeadingZeros (l) - 12; //非正規化数の指数部を補正する
} else if (e == 1024) { //±Inf,NaN
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);
XEiJ.regRn[0] = 4; //小数点の位置
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..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
e -= h - 1;
//小数点以下len2+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
// あらかじめ14+1桁目で四捨五入しておかないと、
// 1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
int s = h + e + 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--; //先頭を左にずらす
o--; //末尾を左にずらす
e++; //指数部を1増やす
}
}
}
//文字列に変換する
while (h < o) {
mmuWriteByteData (a++, '0' + w[h++], 1); //有効数字
}
while (h++ < s) {
mmuWriteByteData (a++, '0', 1); //残りは'0'
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[0] = e + 1; //小数点の位置
} //fpkFCVTSub6()
//fpkGCVT ()
// $FE26 __GCVT
// 64bit浮動小数点数を全体の桁数を指定して文字列に変換する
// 指定された桁数で表現できないときは指数表現になる
// メモ
// print gcvt(1e-1,10)
// 0.1
// print gcvt(1e-8,10)
// 0.00000001
// print gcvt(1.5e-8,10)
// 1.5E-008
// print gcvt(1e-9,10)
// 1.E-009 小数点はあるが小数部がない
// print gcvt(2e-1/3#,10)
// 6.666666667E-002
// print gcvt(2e+0/3#,10)
// 0.6666666667
// print gcvt(2e+1/3#,10)
// 6.666666667
// print gcvt(2e+9/3#,10)
// 666666666.7
// print gcvt(2e+10/3#,10)
// 6666666667
// print gcvt(2e+11/3#,10)
// 6.666666667E+010
// print gcvt(0#,4)
// 0.
// print gcvt(val("#INF"),4)
// #INF
// print gcvt(val("#INF"),3)
// $.E+003
// print gcvt(val("#INF"),2)
// $.E+003
// print gcvt(val("#INF"),1)
// $.E+003
// FLOAT2.XのGCVTは小数部がなくても桁数の範囲内であれば小数点を書く
// 桁数ちょうどのときは小数点も指数部も付かないので、整数でないことを明確にするために小数点を書いているとも言い難い
// ここでは#NANと#INF以外は小数部がなくても小数点を書くことにする
// バグ
// FLOAT2.X 2.02/2.03は#NANと#INFにも小数点を付ける
// FLOAT2.X 2.02/2.03は#NANと#INFのとき桁数が足りないと指数形式にしようとして文字列が壊れる
// FLOAT4.X 1.02は#NANと#INFにも小数点を付ける
// FLOAT4.X 1.02は桁数の少ない整数には小数点を付けて桁数ちょうどの整数には小数点も指数部も付けない
// <d0d1.d:64bit浮動小数点数
// <d2.b:全体の桁数
// <a0.l:文字列バッファの先頭
// >a0.l:末尾の'\0'の位置
public static void fpkGCVT () throws M68kException {
fpkGCVTSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]); //64bit浮動小数点数
} //fpkGCVT()
public static void fpkGCVTSub (long l) throws M68kException {
int len3 = Math.max (0, XEiJ.regRn[2]); //全体の桁数
int a = XEiJ.regRn[8]; //文字列バッファの先頭
//符号と指数部の処理
// ±0,±Inf,NaNはここで除外する
if (l < 0L) {
mmuWriteByteData (a++, '-', 1); //負符号
l &= 0x7fffffffffffffffL; //符号bitを消しておく
}
double x = Double.longBitsToDouble (l); //絶対値
int e = (int) (l >>> 52) - 1023; //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
l &= 0x000fffffffffffffL; //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
if (e == -1023) { //±0,非正規化数
if (l == 0L) { //±0
mmuWriteByteData (a++, '0', 1); //0
mmuWriteByteData (a++, '.', 1); //小数点
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[8] = a; //末尾の'\0'の位置
return;
}
e -= Long.numberOfLeadingZeros (l) - 12; //非正規化数の指数部を補正する
} else if (e == 1024) { //±Inf,NaN
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);
XEiJ.regRn[8] = a; //末尾の'\0'の位置
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..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
e -= h - 1;
//先頭からlen3+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
// あらかじめ14+1桁目で四捨五入しておかないと、
// 1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
int s = h + len3; //w[s]は先頭からlen3+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--; //先頭を左にずらす
o--; //末尾を左にずらす
e++; //指数部を1増やす
}
}
}
//末尾の位置を確認する
// w[o-1]が末尾(0でない最後の数字)の位置
while (w[o - 1] == 0) { //全体は0ではないので必ず止まる。小数点よりも左側で止まる場合があることに注意
o--;
}
//指数形式にするかどうか選択して文字列に変換する
if (0 <= e && e < len3) { //1<=x<10^len3。指数形式にしない
do {
mmuWriteByteData (a++, '0' + w[h++], 1); //整数部。末尾の位置に関係なく1の位まで書く
} while (0 <= --e);
mmuWriteByteData (a++, '.', 1); //小数部がなくても小数点を書く
while (h < o) {
mmuWriteByteData (a++, '0' + w[h++], 1); //小数部
}
} else if (-4 <= e && e < 0) { //10^-4<=x<1。指数形式にしない
mmuWriteByteData (a++, '0', 1); //整数部の0
mmuWriteByteData (a++, '.', 1); //小数点
while (++e < 0) {
mmuWriteByteData (a++, '0', 1); //小数部の先頭の0の並び
}
while (h < o) {
mmuWriteByteData (a++, '0' + w[h++], 1); //小数部
}
} else { //x<10^-4または10^len3<=x。指数形式にする
mmuWriteByteData (a++, '0' + w[h++], 1); //整数部
mmuWriteByteData (a++, '.', 1); //小数部がなくても小数点を書く
while (h < o) {
mmuWriteByteData (a++, '0' + w[h++], 1); //小数部
}
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の位
}
mmuWriteByteData (a, '\0', 1);
XEiJ.regRn[8] = a; //末尾の'\0'の位置
} //fpkGCVTSub6()
//fpkFVAL ()
// $FE50 __FVAL
// 文字列を32bit浮動小数点数に変換する
// __VALとほぼ同じ
// <a0.l:文字列の先頭
// >d0.s:32bit浮動小数点数
// >d2.l:(先頭が'&'でないとき)65535=32bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
// >d3.l:(先頭が'&'でないとき)d2.l==65535のとき32bit浮動小数点数をintに変換した値
// >a0.l:変換された文字列の直後('\0'とは限らない)
// >ccr:0=エラーなし,CCR_N|CCR_C=文法エラー,CCR_V|CCR_C=オーバーフロー
public static void fpkFVAL () 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.fpkLTOF ();
} else if (c == 'O') {
fpkSTOO ();
FEFunction.fpkLTOF ();
} else if (c == 'H') {
fpkSTOH ();
FEFunction.fpkLTOF ();
} else {
XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C; //文法エラー
}
} else { //&B,&O,&H以外
FEFunction.fpkSTOF ();
}
} //fpkFVAL()
//fpkCLMUL ()
// $FEE0 __CLMUL
// 32bit符号あり整数乗算
// <(a7).l:32bit符号あり整数。被乗数x
// <4(a7).l:32bit符号あり整数。乗数y
// >(a7).l:32bit符号あり整数。積x*y。オーバーフローのときは不定
// >ccr:cs=オーバーフロー。C以外は不定
public static void fpkCLMUL () throws M68kException {
int a7 = XEiJ.regRn[15];
long l = (long) mmuReadLongData (a7, 1) * (long) mmuReadLongData (a7 + 4, 1);
int h = (int) l;
mmuWriteLongData (a7, h, 1); //オーバーフローのときは積の下位32bit
XEiJ.regCCR = (long) h == l ? 0 : XEiJ.REG_CCR_C;
} //fpkCLMUL()
//fpkCLDIV ()
// $FEE1 __CLDIV
// 32bit符号あり整数除算
// <(a7).l:32bit符号あり整数。被除数x
// <4(a7).l:32bit符号あり整数。除数y
// >(a7).l:32bit符号あり整数。商x/y。ゼロ除算のときは不定
// >ccr:cs=ゼロ除算。C以外は不定
public static void fpkCLDIV () throws M68kException {
int a7 = XEiJ.regRn[15];
int h = mmuReadLongData (a7 + 4, 1);
if (h == 0) {
//(a7).lは変化しない
XEiJ.regCCR = XEiJ.REG_CCR_C;
} else {
mmuWriteLongData (a7, mmuReadLongData (a7, 1) / h, 1);
XEiJ.regCCR = 0;
}
} //fpkCLDIV()
//fpkCLMOD ()
// $FEE2 __CLMOD
// 32bit符号あり整数剰余算
// <(a7).l:32bit符号あり整数。被除数x
// <4(a7).l:32bit符号あり整数。除数y
// >(a7).l:32bit符号あり整数。余りx%y。ゼロ除算のときは不定
// >ccr:cs=ゼロ除算。C以外は不定
public static void fpkCLMOD () throws M68kException {
int a7 = XEiJ.regRn[15];
int h = mmuReadLongData (a7 + 4, 1);
if (h == 0) {
//(a7).lは変化しない
XEiJ.regCCR = XEiJ.REG_CCR_C;
} else {
mmuWriteLongData (a7, mmuReadLongData (a7, 1) % h, 1);
XEiJ.regCCR = 0;
}
} //fpkCLMOD()
//fpkCUMUL ()
// $FEE3 __CUMUL
// 32bit符号なし整数乗算
// <(a7).l:32bit符号なし整数。被乗数x
// <4(a7).l:32bit符号なし整数。乗数y
// >(a7).l:32bit符号なし整数。積x*y。オーバーフローのときは不定
// >ccr:cs=オーバーフロー。C以外は不定
public static void fpkCUMUL () throws M68kException {
int a7 = XEiJ.regRn[15];
long l = (0xffffffffL & mmuReadLongData (a7, 1)) * (0xffffffffL & mmuReadLongData (a7 + 4, 1));
int h = (int) l;
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (0xffffffffL & h) == l ? 0 : XEiJ.REG_CCR_C;
} //fpkCUMUL()
//fpkCUDIV ()
// $FEE4 __CUDIV
// 32bit符号なし整数除算
// <(a7).l:32bit符号なし整数。被除数x
// <4(a7).l:32bit符号なし整数。除数y
// >(a7).l:32bit符号なし整数。商x/y。ゼロ除算のときは不定
// >ccr:cs=ゼロ除算。C以外は不定
public static void fpkCUDIV () throws M68kException {
int a7 = XEiJ.regRn[15];
int h = mmuReadLongData (a7 + 4, 1);
if (h == 0) {
//(a7).lは変化しない
XEiJ.regCCR = XEiJ.REG_CCR_C;
} else {
mmuWriteLongData (a7, (int) ((0xffffffffL & mmuReadLongData (a7, 1)) / (0xffffffffL & h)), 1);
XEiJ.regCCR = 0;
}
} //fpkCUDIV()
//fpkCUMOD ()
// $FEE5 __CUMOD
// 32bit符号なし整数剰余算
// <(a7).l:32bit符号なし整数。被除数x
// <4(a7).l:32bit符号なし整数。除数y
// >(a7).l:32bit符号なし整数。余りx%y。ゼロ除算のときは不定
// >ccr:cs=ゼロ除算。C以外は不定
public static void fpkCUMOD () throws M68kException {
int a7 = XEiJ.regRn[15];
int h = mmuReadLongData (a7 + 4, 1);
if (h == 0) {
//(a7).lは変化しない
XEiJ.regCCR = XEiJ.REG_CCR_C;
} else {
mmuWriteLongData (a7, (int) ((0xffffffffL & mmuReadLongData (a7, 1)) % (0xffffffffL & h)), 1);
XEiJ.regCCR = 0;
}
} //fpkCUMOD()
//fpkCLTOD ()
// $FEE6 __CLTOD
// 32bit符号あり整数を64bit浮動小数点数に変換する
// <(a7).l:32bit符号あり整数。x
// >(a7).d:64bit浮動小数点数。(double)x
public static void fpkCLTOD () throws M68kException {
//int→double→[long]→[int,int]
int a7 = XEiJ.regRn[15];
long l = Double.doubleToLongBits ((double) mmuReadLongData (a7, 1));
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
} //fpkCLTOD()
//fpkCDTOL ()
// $FEE7 __CDTOL
// 64bit浮動小数点数を32bit符号あり整数に変換する
// <(a7).d:64bit浮動小数点数。x
// >(a7).l:32bit符号あり整数。(int)x
// >ccr:cs=オーバーフロー。C以外は不定
public static void fpkCDTOL () throws M68kException {
//[int,int]→[long]→double→int
int a7 = XEiJ.regRn[15];
double d = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
mmuWriteLongData (a7, (int) d, 1); //オーバーフローのときは最小値または最大値
XEiJ.regCCR = (double) Integer.MIN_VALUE - 1.0 < d && d < (double) Integer.MAX_VALUE + 1.0 ? 0 : XEiJ.REG_CCR_C; //NaN,±Infはエラー
} //fpkCDTOL()
//fpkCLTOF ()
// $FEE8 __CLTOF
// 32bit符号あり整数を32bit浮動小数点数に変換する
// <(a7).l:32bit符号あり整数。x
// >(a7).s:32bit浮動小数点数。(float)x
public static void fpkCLTOF () throws M68kException {
//int→float→[int]
int a7 = XEiJ.regRn[15];
mmuWriteLongData (a7, Float.floatToIntBits ((float) mmuReadLongData (a7, 1)), 1);
} //fpkCLTOF()
//fpkCFTOL ()
// $FEE9 __CFTOL
// 32bit浮動小数点数を32bit符号あり整数に変換する
// <(a7).s:32bit浮動小数点数。x
// >(a7).l:32bit符号あり整数。(int)x
// >ccr:cs=オーバーフロー。C以外は不定
public static void fpkCFTOL () throws M68kException {
//[int]→float→int
int a7 = XEiJ.regRn[15];
float f = Float.intBitsToFloat (mmuReadLongData (a7, 1));
mmuWriteLongData (a7, (int) f, 1);
XEiJ.regCCR = (float) Integer.MIN_VALUE - 1.0F < f && f < (float) Integer.MAX_VALUE + 1.0F ? 0 : XEiJ.REG_CCR_C; //NaN,±Infはエラー
} //fpkCFTOL()
//fpkCFTOD ()
// $FEEA __CFTOD
// 32bit浮動小数点数を64bit浮動小数点数に変換する
// <(a7).s:32bit浮動小数点数。x
// >(a7).d:64bit浮動小数点数。(double)x
public static void fpkCFTOD () throws M68kException {
//[int]→float→double→[long]→[int,int]
int a7 = XEiJ.regRn[15];
long l = Double.doubleToLongBits ((double) Float.intBitsToFloat (mmuReadLongData (a7, 1)));
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
} //fpkCFTOD()
//fpkCDTOF ()
// $FEEB __CDTOF
// 64bit浮動小数点数を32bit浮動小数点数に変換する
// <(a7).d:64bit浮動小数点数。x
// >(a7).s:32bit浮動小数点数。(float)x
// >ccr:cs=オーバーフロー。C以外は不定
public static void fpkCDTOF () throws M68kException {
//[int,int]→[long]→double→float→[int]
int a7 = XEiJ.regRn[15];
double d = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
int h = Float.floatToIntBits ((float) d);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (Double.isNaN (d) || Double.isInfinite (d) ||
Math.abs (d) < (double) Float.MAX_VALUE + 0.5 * (double) Math.ulp (Float.MAX_VALUE) ? 0 : XEiJ.REG_CCR_C); //アンダーフローはエラーなし
} //fpkCDTOF()
//fpkCDCMP ()
// $FEEC __CDCMP
// 64bit浮動小数点数の比較
// x<=>y
// <(a7).d:64bit浮動小数点数。x
// <8(a7).d:64bit浮動小数点数。y
// >ccr:lt=x<y,eq=x==y,gt=x>y
public static void fpkCDCMP () throws M68kException {
//([int,int]→[long]→double)<=>([int,int]→[long]→double)
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double yd = Double.longBitsToDouble ((long) mmuReadLongData (a7 + 8, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 12, 1));
XEiJ.regCCR = xd < yd ? XEiJ.REG_CCR_N | XEiJ.REG_CCR_C : xd == yd ? XEiJ.REG_CCR_Z : 0; //どちらかがNaNのときは0
} //fpkCDCMP()
//fpkCDADD ()
// $FEED __CDADD
// 64bit浮動小数点数の加算
// <(a7).d:64bit浮動小数点数。被加算数x
// <8(a7).d:64bit浮動小数点数。加算数y
// >(a7).d:64bit浮動小数点数。和x+y
// >ccr:0=エラーなし,CCR_C=アンダーフロー,CCR_V|CCR_C=オーバーフロー
public static void fpkCDADD () throws M68kException {
//([int,int]→[long]→double)+([int,int]→[long]→double)→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double yd = Double.longBitsToDouble ((long) mmuReadLongData (a7 + 8, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 12, 1));
double zd = xd + yd;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 : //引数がNaN
Double.isNaN (zd) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)+(-Inf)=NaN
Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 : //引数が±Inf
Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCDADD()
//fpkCDSUB ()
// $FEEE __CDSUB
// 64bit浮動小数点数の減算
// <(a7).d:64bit浮動小数点数。被減算数x
// <8(a7).d:64bit浮動小数点数。減算数y
// >(a7).d:64bit浮動小数点数。差x-y
// >ccr:cs=エラー,vs=オーバーフロー
public static void fpkCDSUB () throws M68kException {
//([int,int]→[long]→double)-([int,int]→[long]→double)→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double yd = Double.longBitsToDouble ((long) mmuReadLongData (a7 + 8, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 12, 1));
double zd = xd - yd;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 : //引数がNaN
Double.isNaN (zd) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)-(+Inf)=NaN
Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 : //引数が±Inf
Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCDSUB()
//fpkCDMUL ()
// $FEEF __CDMUL
// 64bit浮動小数点数の乗算
// <(a7).d:64bit浮動小数点数。被乗数x
// <8(a7).d:64bit浮動小数点数。乗数y
// >(a7).d:64bit浮動小数点数。積x*y
// >ccr:cs=エラー,vs=オーバーフロー
public static void fpkCDMUL () throws M68kException {
//([int,int]→[long]→double)*([int,int]→[long]→double)→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double yd = Double.longBitsToDouble ((long) mmuReadLongData (a7 + 8, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 12, 1));
double zd = xd * yd;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 : //引数がNaN
Double.isNaN (zd) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(±0)*(±Inf)=NaN
Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 : //引数が±Inf
Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCDMUL()
//fpkCDDIV ()
// $FEF0 __CDDIV
// 64bit浮動小数点数の除算
// <(a7).d:64bit浮動小数点数。被除数x
// <8(a7).d:64bit浮動小数点数。除数y
// >(a7).d:64bit浮動小数点数。商x/y。ゼロ除算のときは不定
// >ccr:cs=エラー,eq=ゼロ除算,vs=オーバーフロー
public static void fpkCDDIV () throws M68kException {
//([int,int]→[long]→double)/([int,int]→[long]→double)→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double yd = Double.longBitsToDouble ((long) mmuReadLongData (a7 + 8, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 12, 1));
double zd = xd / yd;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 : //引数がNaN
Double.isNaN (zd) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(±0)/(±0)=NaN
Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 : //引数が±Inf。(±Inf)/(±0)=(±Inf)
yd == 0.0 ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C : //除数が±0のときはゼロ除算
Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCDDIV()
//fpkCDMOD ()
// $FEF1 __CDMOD
// 64bit浮動小数点数の剰余算
// <(a7).d:64bit浮動小数点数。被除数x
// <8(a7).d:64bit浮動小数点数。除数y
// >(a7).d:64bit浮動小数点数。余りx%y。ゼロ除算のときは不定
// >ccr:cs=エラー,eq=ゼロ除算
public static void fpkCDMOD () throws M68kException {
//([int,int]→[long]→double)%([int,int]→[long]→double)→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double yd = Double.longBitsToDouble ((long) mmuReadLongData (a7 + 8, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 12, 1));
double zd = xd % yd;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 : //引数がNaN
yd == 0.0 ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C : //除数が0のときはゼロ除算。(±Inf)%(±0)=NaN, x%(±0)=(±Inf)
Double.isNaN (zd) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(±Inf)%y=NaN
Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 : //引数が±Inf
Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCDMOD()
//fpkCFCMP ()
// $FEF2 __CFCMP
// 32bit浮動小数点数の比較
// x<=>y
// <(a7).s:32bit浮動小数点数。x
// <(a7).s:32bit浮動小数点数。y
// >ccr:lt=x<y,eq=x==y,gt=x>y
public static void fpkCFCMP () throws M68kException {
//([int]→float)<=>([int]→float)
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float yf = Float.intBitsToFloat (mmuReadLongData (a7 + 4, 1));
XEiJ.regCCR = xf < yf ? XEiJ.REG_CCR_N | XEiJ.REG_CCR_C : xf == yf ? XEiJ.REG_CCR_Z : 0; //どちらかがNaNのときは0
} //fpkCFCMP()
//fpkCFADD ()
// $FEF3 __CFADD
// 32bit浮動小数点数の加算
// <(a7).s:32bit浮動小数点数。被加算数x
// <4(a7).s:32bit浮動小数点数。加算数y
// >(a7).s:32bit浮動小数点数。和x+y
// >ccr:cs=エラー,vs=オーバーフロー
public static void fpkCFADD () throws M68kException {
//([int]→float)+([int]→float)→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float yf = Float.intBitsToFloat (mmuReadLongData (a7 + 4, 1));
float zf = xf + yf;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 : //引数がNaN
Float.isNaN (zf) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)+(-Inf)=NaN
Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 : //引数が±Inf
Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCFADD()
//fpkCFSUB ()
// $FEF4 __CFSUB
// 32bit浮動小数点数の減算
// <(a7).s:32bit浮動小数点数。被減算数x
// <4(a7).s:32bit浮動小数点数。減算数y
// >(a7).s:32bit浮動小数点数。差x-y
// >ccr:cs=エラー,vs=オーバーフロー
public static void fpkCFSUB () throws M68kException {
//([int]→float)-([int]→float)→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float yf = Float.intBitsToFloat (mmuReadLongData (a7 + 4, 1));
float zf = xf - yf;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 : //引数がNaN
Float.isNaN (zf) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)-(+Inf)=NaN
Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 : //引数が±Inf
Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCFSUB()
//fpkCFMUL ()
// $FEF5 __CFMUL
// 32bit浮動小数点数の乗算
// <(a7).s:32bit浮動小数点数。被乗数x
// <4(a7).s:32bit浮動小数点数。乗数y
// >(a7).s:32bit浮動小数点数。積x*y
// >ccr:0=エラーなし,CCR_C=アンダーフロー,CCR_V|CCR_C=オーバーフロー
public static void fpkCFMUL () throws M68kException {
//([int]→float)*([int]→float)→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float yf = Float.intBitsToFloat (mmuReadLongData (a7 + 4, 1));
float zf = xf * yf;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 : //引数がNaN
Float.isNaN (zf) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(±0)*(±Inf)=NaN
Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 : //引数が±Inf
Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCFMUL()
//fpkCFDIV ()
// $FEF6 __CFDIV
// 32bit浮動小数点数の除算
// <(a7).s:32bit浮動小数点数。被除数x
// <4(a7).s:32bit浮動小数点数。除数y
// >(a7).s:32bit浮動小数点数。商x/y。ゼロ除算のときは不定
// >ccr:cs=エラー,eq=ゼロ除算,vs=オーバーフロー
public static void fpkCFDIV () throws M68kException {
//([int]→float)/([int]→float)→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float yf = Float.intBitsToFloat (mmuReadLongData (a7 + 4, 1));
float zf = xf / yf;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 : //引数がNaN
Float.isNaN (zf) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(±0)/(±0)=NaN
Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 : //引数が±Inf。(±Inf)/(±0)=(±Inf)
yf == 0.0F ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C : //除数が±0のときはゼロ除算
Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCFDIV()
//fpkCFMOD ()
// $FEF7 __CFMOD
// 32bit浮動小数点数の剰余算
// <(a7).s:32bit浮動小数点数。被除数x
// <4(a7).s:32bit浮動小数点数。除数y
// >(a7).s:32bit浮動小数点数。余りx%y。ゼロ除算のときは不定
// >ccr:cs=エラー,eq=ゼロ除算
public static void fpkCFMOD () throws M68kException {
//([int]→float)%([int]→float)→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float yf = Float.intBitsToFloat (mmuReadLongData (a7 + 4, 1));
float zf = xf % yf;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 : //引数がNaN
yf == 0.0F ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C : //除数が0のときはゼロ除算。(±Inf)%(±0)=NaN, x%(±0)=(±Inf)
Float.isNaN (zf) ? XEiJ.REG_CCR_C : //引数がNaNでないのに結果がNaNのときはエラー。(±Inf)%y=NaN
Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 : //引数が±Inf
Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : //引数が±Infでないのに結果が±Infのときはオーバーフロー
0);
} //fpkCFMOD()
//fpkCDTST ()
// $FEF8 __CDTST
// 64bit浮動小数点数と0の比較
// x<=>0
// <(a7).d:64bit浮動小数点数。x
// >ccr:lt=x<0,eq=x==0,gt=x>0
public static void fpkCDTST () throws M68kException {
if (true) {
int a7 = XEiJ.regRn[15];
long l = (long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1);
XEiJ.regCCR = l << 1 == 0L ? XEiJ.REG_CCR_Z : 0L <= l ? 0 : XEiJ.REG_CCR_N; //NaNのときは0
} else {
//[int,int]→[long]→double
int a7 = XEiJ.regRn[15];
double d = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
XEiJ.regCCR = d < 0.0 ? XEiJ.REG_CCR_N : d == 0.0 ? XEiJ.REG_CCR_Z : 0; //NaNのときは0
}
} //fpkCDTST()
//fpkCFTST ()
// $FEF9 __CFTST
// 32bit浮動小数点数と0の比較
// x<=>0
// <(a7).s:32bit浮動小数点数。x
// >ccr:lt=x<0,eq=x==0,gt=x>0
public static void fpkCFTST () throws M68kException {
//[int]→float
if (true) {
int h = mmuReadLongData (XEiJ.regRn[15], 1);
XEiJ.regCCR = h << 1 == 0 ? XEiJ.REG_CCR_Z : 0 <= h ? 0 : XEiJ.REG_CCR_N; //NaNのときは0
} else {
//([int]→float)<=>0
float f = Float.intBitsToFloat (mmuReadLongData (XEiJ.regRn[15], 1));
XEiJ.regCCR = f < 0.0F ? XEiJ.REG_CCR_N : f == 0.0F ? XEiJ.REG_CCR_Z : 0; //NaNのときは0
}
} //fpkCFTST()
//fpkCDINC ()
// $FEFA __CDINC
// 64bit浮動小数点数に1を加える
// <(a7).d:64bit浮動小数点数。x
// >(a7).d:64bit浮動小数点数。x+1
public static void fpkCDINC () throws M68kException {
//([int,int]→[long]→double)+1→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double zd = xd + 1.0;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = Double.isInfinite (zd) && !Double.isInfinite (xd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0; //結果が±Infだが引数が±Infでないときはオーバーフロー
} //fpkCDINC()
//fpkCFINC ()
// $FEFB __CFINC
// 32bit浮動小数点数に1を加える
// <(a7).s:32bit浮動小数点数。x
// >(a7).s:32bit浮動小数点数。x+1
public static void fpkCFINC () throws M68kException {
//([int]→float)+1→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float zf = xf + 1.0F;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = Double.isInfinite (zf) && !Float.isInfinite (xf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0; //結果が±Infだが引数が±Infでないときはオーバーフロー
} //fpkCFINC()
//fpkCDDEC ()
// $FEFC __CDDEC
// 64bit浮動小数点数から1を引く
// <(a7).d:64bit浮動小数点数。x
// >(a7).d:64bit浮動小数点数。x-1
public static void fpkCDDEC () throws M68kException {
//([int,int]→[long]→double)-1→[long]→[int,int]
int a7 = XEiJ.regRn[15];
double xd = Double.longBitsToDouble ((long) mmuReadLongData (a7, 1) << 32 | 0xffffffffL & mmuReadLongData (a7 + 4, 1));
double zd = xd - 1.0;
long l = Double.doubleToLongBits (zd);
if (FEFunction.FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
l = 0x7fffffffffffffffL;
}
mmuWriteLongData (a7, (int) (l >>> 32), 1);
mmuWriteLongData (a7 + 4, (int) l, 1);
XEiJ.regCCR = Double.isInfinite (zd) && !Double.isInfinite (xd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0; //結果が±Infだが引数が±Infでないときはオーバーフロー
} //fpkCDDEC()
//fpkCFDEC ()
// $FEFD __CFDEC
// 32bit浮動小数点数から1を引く
// <(a7).s:32bit浮動小数点数。x
// >(a7).s:32bit浮動小数点数。x-1
public static void fpkCFDEC () throws M68kException {
//([int]→float)-1→[int]
int a7 = XEiJ.regRn[15];
float xf = Float.intBitsToFloat (mmuReadLongData (a7, 1));
float zf = xf - 1.0F;
int h = Float.floatToIntBits (zf);
if (FEFunction.FPK_FPCP_NAN && h == 0x7fc00000) {
h = 0x7fffffff;
}
mmuWriteLongData (a7, h, 1);
XEiJ.regCCR = Double.isInfinite (zf) && !Float.isInfinite (xf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0; //結果が±Infだが引数が±Infでないときはオーバーフロー
} //fpkCFDEC()
//========================================================================================
//$$MMU メモリ管理ユニット
public static final boolean MMU_DEBUG_COMMAND = false;
public static final boolean MMU_DEBUG_TRANSLATION = false;
public static final boolean MMU_NOT_ALLOCATE_CACHE = false; //true=アドレス変換キャッシュをアロケートしない
//--------------------------------------------------------------------------------
//論理アドレスと物理アドレス
//
// ページサイズが4KBの場合
// ┌── 7 ──┬── 7 ──┬── 6──┬─────12─────┐
// 31 2524 1817 1211 0
// ┏━━━━━━┯━━━━━━┯━━━━━┯━━━━━━━━━━━┓
// 論理 ┃ ルート │ ポインタ │ ページ │ ページ ┃
// アドレス┃インデックス│インデックス インデックス オフセット ┃
// ┗━━↓━━━┷━━↓━━━┷━━↓━━┷━━━━━↓━━━━━┛
// ┌────┘ │ └────┐ └──────┐
// │ ルートテーブル │ ポインタテーブル │ ページテーブル │
// ┌┼→┏━━━━━━━┓┌┼→┏━━━━━━━┓┌┼→┏━━━━━━━┓│
// ││ 0┃ ┃││ 0┃ ┃││ 0┃ ┃│
// ││ ┃ ┃││ ┃ ┃│└→┠───────┨│
// │└→┠───────┨││ ┃ ┃│ ┃ ページ ┃│
// ルート ┃ ルート ┃│└→┠───────┨│┌─← デスクリプタ ┃│
// ポインタ ┃ デスクリプタ →┘ ┃ ポインタ ┃││ ┠───────┨│
// ┠───────┨ ┃ デスクリプタ →┘│63┃ ┃│
// ┃ ┃ ┠───────┨ │ ┗━━━━━━━┛│
// 127┃ ┃ 127┃ ┃ │ │
// ┗━━━━━━━┛ ┗━━━━━━━┛ │ │
// ┌───────────┘ ┌──────┘
// ┏━━━━━━━━━↓━━━━━━━━━┯━━━━━↓━━━━━┓
// 物理 ┃ 物理ページ │ ページ ┃
// アドレス┃ アドレス │ オフセット ┃
// ┗━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┛
// 31 1211 0
// └─────────20─────────┴─────12─────┘
//
// ページサイズが8KBの場合
// ┌── 7 ──┬── 7 ──┬─ 5 ─┬───── 13 ─────┐
// 31 2524 1817 1312 0
// ┏━━━━━━┯━━━━━━┯━━━━┯━━━━━━━━━━━━┓
// 論理 ┃ ルート │ ポインタ │ ページ │ ページ ┃
// アドレス┃インデックス│インデックスインデックス オフセット ┃
// ┗━━↓━━━┷━━↓━━━┷━━↓━┷━━━━━━↓━━━━━┛
// ┌────┘ │ └────┐ └──────┐
// │ ルートテーブル │ ポインタテーブル │ ページテーブル │
// ┌┼→┏━━━━━━━┓┌┼→┏━━━━━━━┓┌┼→┏━━━━━━━┓│
// ││ 0┃ ┃││ 0┃ ┃││ 0┃ ┃│
// ││ ┃ ┃││ ┃ ┃│└→┠───────┨│
// │└→┠───────┨││ ┃ ┃│ ┃ ページ ┃│
// ルート ┃ ルート ┃│└→┠───────┨│┌─← デスクリプタ ┃│
// ポインタ ┃ デスクリプタ →┘ ┃ ポインタ ┃││ ┠───────┨│
// ┠───────┨ ┃ デスクリプタ →┘│31┃ ┃│
// ┃ ┃ ┠───────┨ │ ┗━━━━━━━┛│
// 127┃ ┃ 127┃ ┃ │ │
// ┗━━━━━━━┛ ┗━━━━━━━┛ │ │
// ┌───────────┘ ┌──────┘
// ┏━━━━━━━━━↓━━━━━━━━┯━━━━━━↓━━━━━┓
// 物理 ┃ 物理ページ │ ページ ┃
// アドレス┃ アドレス │ オフセット ┃
// ┗━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┛
// 31 1312 0
// └──────── 19 ────────┴───── 13 ─────┘
//
public static final int MMU_ROOT_INDEX_BIT0 = 25;
public static final int MMU_POINTER_INDEX_BIT0 = 18;
public static final int MMU_PAGE_INDEX_BIT0_4KB = 12;
public static final int MMU_PAGE_INDEX_BIT0_8KB = 13;
public static final int MMU_PAGE_SIZE_4KB = 1 << MMU_PAGE_INDEX_BIT0_4KB;
public static final int MMU_PAGE_SIZE_8KB = 1 << MMU_PAGE_INDEX_BIT0_8KB;
// 33222222_22221111_111111
// 10987654_32109876_54321098_76543210
public static final int MMU_ROOT_INDEX_MASK = 0b11111110_00000000_00000000_00000000;
public static final int MMU_POINTER_INDEX_MASK = 0b00000001_11111100_00000000_00000000;
public static final int MMU_PAGE_INDEX_MASK_4KB = 0b00000000_00000011_11110000_00000000;
public static final int MMU_PAGE_INDEX_MASK_8KB = 0b00000000_00000011_11100000_00000000;
public static final int MMU_PAGE_OFFSET_MASK_4KB = 0b00000000_00000000_00001111_11111111;
public static final int MMU_PAGE_OFFSET_MASK_8KB = 0b00000000_00000000_00011111_11111111;
public static final int MMU_PAGE_ADDRESS_MASK_4KB = 0b11111111_11111111_11110000_00000000;
public static final int MMU_PAGE_ADDRESS_MASK_8KB = 0b11111111_11111111_11100000_00000000;
//--------------------------------------------------------------------------------
//透過変換レジスタ
//
// DTT0 データ透過変換レジスタ0
// DTT1 データ透過変換レジスタ1
// ITT0 命令透過変換レジスタ0
// ITT1 命令透過変換レジスタ1
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━┯━┯━┯━━━━━┯━┯━┯━┯━━━┯━━━┯━┯━━━┓
// ┃ 論理アドレスベース │ 論理アドレスマスク │ E│IS│US│ 0 │U1│U0│ 0│ CM │ 0 │ W│ 0 ┃
// ┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━┷━┷━┷━━━━━┷━┷━┷━┷━━━┷━━━┷━┷━━━┛
public static final int MMU_TTR_BASE = 255 << 24; //x Logical Address Base
public static final int MMU_TTR_MASK = 255 << 16; //x Logical Address Mask
public static final int MMU_TTR_ENABLE = 1 << 15; //x E Enable
public static final int MMU_TTR_IGNORE_FC2 = 1 << 14; //x IS Ignore FC2 when matching
public static final int MMU_TTR_USER_SUPERVISOR = 1 << 13; //x US User or Supervisor when IS=0
public static final int MMU_TTR_US_USER = 0 << 13; // Match only if FC2=0 (user mode access)
public static final int MMU_TTR_US_SUPERVISOR = 1 << 13; // Match only if FC2=1 (supervisor mode access)
public static final int MMU_TTR_CACHE_MODE = 3 << 5; //x CM Cache Mode
public static final int MMU_TTR_WRITE_PROTECT = 1 << 2; //x W Write Protect
public static int mmuDTT0; //DTT0
public static int mmuDTT1; //DTT1
public static int mmuITT0; //ITT0
public static int mmuITT1; //ITT1
// 透過変換マップ
// インデックス
// a >>> 24
// 値
// bit7 W 0 ライトプロテクトなし
// 1 ライトプロテクトあり。ライトのときアクセスフォルト
// bit6-5 CM 00 ライトスルー
// 01 コピーバック
// 10 プリサイズ
// 11 インプリサイズ
// bit0 E 0 透過変換なし。他のビットも0
// 1 透過変換あり
public static byte[] mmuTTUserData1; //ユーザデータ透過変換マップ
public static byte[] mmuTTUserCode1; //ユーザ命令透過変換マップ
public static byte[] mmuTTSuperData1; //スーパーバイザデータ透過変換マップ
public static byte[] mmuTTSuperCode1; //スーパーバイザ命令透過変換マップ
public static byte[] mmuTTUserData2;
public static byte[] mmuTTUserCode2;
public static byte[] mmuTTSuperData2;
public static byte[] mmuTTSuperCode2;
//d = mmuGetDTT0 ()
// DTT0を読む
public static int mmuGetDTT0 () {
return mmuDTT0;
} //mmuGetDTT0()
//d = mmuGetDTT1 ()
// DTT1を読む
public static int mmuGetDTT1 () {
return mmuDTT1;
} //mmuGetDTT1()
//d = mmuGetITT0 ()
// ITT0を読む
public static int mmuGetITT0 () {
return mmuITT0;
} //mmuGetITT0()
//d = mmuGetITT1 ()
// ITT1を読む
public static int mmuGetITT1 () {
return mmuITT1;
} //mmuGetITT1()
//mmuSetDTT0 (d)
// DTT0に書く
public static void mmuSetDTT0 (int d) {
mmuTTSetData (d, mmuDTT1);
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetDTT0(0x%08x)\n", XEiJ.regPC0, mmuDTT0);
}
} //mmuSetDTT0(int)
//mmuSetDTT1 (d)
// DTT1に書く
public static void mmuSetDTT1 (int d) {
mmuTTSetData (mmuDTT0, d);
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetDTT1(0x%08x)\n", XEiJ.regPC0, mmuDTT1);
}
} //mmuSetDTT1(int)
//mmuTTSetData (d0, d1)
// DTT0,DTT1に書く
// データ透過変換マップを更新する
public static void mmuTTSetData (int d0, int d1) {
mmuDTT0 = d0 & 0xffffe364;
mmuDTT1 = d1 & 0xffffe364;
//1と2を入れ換える
{
byte[] t = mmuTTUserData1;
mmuTTUserData1 = mmuTTUserData2;
mmuTTUserData2 = t;
t = mmuTTSuperData1;
mmuTTSuperData1 = mmuTTSuperData2;
mmuTTSuperData2 = t;
}
//1に構築する
// DTT0とDTT1の両方がヒットしたときDTT0を用いるため、DTT1→DTT0の順に書き込む
// DTT1でライトプロテクトされていてもDTT0でライトプロテクトされていなければ書き込める
Arrays.fill (mmuTTUserData1, (byte) 0); //透過変換なし
Arrays.fill (mmuTTSuperData1, (byte) 0); //透過変換なし
if ((short) mmuDTT1 < 0) { //MMU_TTR_ENABLE。DTT1が有効
int mask = ~mmuDTT1 >>> 16 & 255;
int base = mmuDTT1 >>> 24 & mask;
int flag = ((mmuDTT1 & MMU_TTR_WRITE_PROTECT) << (7 - 2) |
(mmuDTT1 & MMU_TTR_CACHE_MODE) |
1);
if ((mmuDTT1 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuDTT1 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_USER) { //ユーザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTUserData1[block] = (byte) flag;
}
}
}
if ((mmuDTT1 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuDTT1 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_SUPERVISOR) { //スーパーバイザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTSuperData1[block] = (byte) flag;
}
}
}
}
if ((short) mmuDTT0 < 0) { //MMU_TTR_ENABLE。DTT0が有効
int mask = ~mmuDTT0 >>> 16 & 255;
int base = mmuDTT0 >>> 24 & mask;
int flag = ((mmuDTT0 & MMU_TTR_WRITE_PROTECT) << (7 - 2) |
(mmuDTT0 & MMU_TTR_CACHE_MODE) |
1);
if ((mmuDTT0 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuDTT0 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_USER) { //ユーザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTUserData1[block] = (byte) flag;
}
}
}
if ((mmuDTT0 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuDTT0 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_SUPERVISOR) { //スーパーバイザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTSuperData1[block] = (byte) flag;
}
}
}
}
//状態が変化したブロックのアドレス変換キャッシュを無効化する
// 本来は透過変換はアドレス変換キャッシュより優先するので無効化する必要はないが、
// ここでは透過変換もアドレス変換キャッシュに乗せているため無効化する必要がある
if (!Arrays.equals (mmuTTUserData1, mmuTTUserData2)) {
for (int i = 0; i < 4 * MMU_CACHE_WAYS * MMU_HASH_SIZE; i += 4) {
int logicalPage = mmuUserDataCache[i];
if (logicalPage != 1) { //アドレス変換キャッシュが有効
int block = logicalPage >>> 24;
if (mmuTTUserData1[block] != mmuTTUserData2[block]) { //透過変換の状態が変化した
mmuUserDataCache[i] = mmuUserDataCache[i + 1] = mmuUserDataCache[i + 2] = mmuUserDataCache[i + 3] = 1; //アドレス変換キャッシュを無効化する
}
}
}
}
if (!Arrays.equals (mmuTTSuperData1, mmuTTSuperData2)) {
for (int i = 0; i < 4 * MMU_CACHE_WAYS * MMU_HASH_SIZE; i += 4) {
int logicalPage = mmuSuperDataCache[i];
if (logicalPage != 1) { //アドレス変換キャッシュが有効
int block = logicalPage >>> 24;
if (mmuTTSuperData1[block] != mmuTTSuperData2[block]) { //透過変換の状態が変化した
mmuSuperDataCache[i] = mmuSuperDataCache[i + 1] = mmuSuperDataCache[i + 2] = mmuSuperDataCache[i + 3] = 1; //アドレス変換キャッシュを無効化する
}
}
}
}
} //mmuTTSetData(int,int)
//mmuSetITT0 (d)
// ITT0に書く
public static void mmuSetITT0 (int d) {
mmuTTSetCode (d, mmuITT1);
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetITT0(0x%08x)\n", XEiJ.regPC0, mmuITT0);
}
} //mmuSetITT0(int)
//mmuSetITT1 (d)
// ITT1に書く
public static void mmuSetITT1 (int d) {
mmuTTSetCode (mmuITT0, d);
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetITT1(0x%08x)\n", XEiJ.regPC0, mmuITT1);
}
} //mmuSetITT1(int)
//mmuTTSetCode (d0, d1)
// ITT0,ITT1に書く
// 命令透過変換マップを更新する
public static void mmuTTSetCode (int d0, int d1) {
mmuITT0 = d0 & 0xffffe364;
mmuITT1 = d1 & 0xffffe364;
//1と2を入れ換える
{
byte[] t = mmuTTUserCode1;
mmuTTUserCode1 = mmuTTUserCode2;
mmuTTUserCode2 = t;
t = mmuTTSuperCode1;
mmuTTSuperCode1 = mmuTTSuperCode2;
mmuTTSuperCode2 = t;
}
//1に構築する
// ITT0とITT1の両方がヒットしたときITT0を用いるため、ITT1→ITT0の順に書き込む
Arrays.fill (mmuTTUserCode1, (byte) 0); //透過変換なし
Arrays.fill (mmuTTSuperCode1, (byte) 0); //透過変換なし
if ((short) mmuITT1 < 0) { //MMU_TTR_ENABLE。ITT1が有効
int mask = ~mmuITT1 >>> 16 & 255;
int base = mmuITT1 >>> 24 & mask;
int flag = ((mmuITT1 & MMU_TTR_WRITE_PROTECT) << (7 - 2) |
(mmuITT1 & MMU_TTR_CACHE_MODE) |
1);
if ((mmuITT1 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuITT1 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_USER) { //ユーザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTUserCode1[block] = (byte) flag;
}
}
}
if ((mmuITT1 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuITT1 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_SUPERVISOR) { //スーパーバイザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTSuperCode1[block] = (byte) flag;
}
}
}
}
if ((short) mmuITT0 < 0) { //MMU_TTR_ENABLE。ITT0が有効
int mask = ~mmuITT0 >>> 16 & 255;
int base = mmuITT0 >>> 24 & mask;
int flag = ((mmuITT0 & MMU_TTR_WRITE_PROTECT) << (7 - 2) |
(mmuITT0 & MMU_TTR_CACHE_MODE) |
1);
if ((mmuITT0 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuITT0 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_USER) { //ユーザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTUserCode1[block] = (byte) flag;
}
}
}
if ((mmuITT0 & MMU_TTR_IGNORE_FC2) != 0 ||
(mmuITT0 & MMU_TTR_USER_SUPERVISOR) == MMU_TTR_US_SUPERVISOR) { //スーパーバイザモードで有効
for (int block = 0; block < 256; block++) {
if ((block & mask) == base) {
mmuTTSuperCode1[block] = (byte) flag;
}
}
}
}
//状態が変化したブロックのアドレス変換キャッシュを無効化する
// 本来は透過変換はアドレス変換キャッシュより優先するので無効化する必要はないが、
// ここでは透過変換もアドレス変換キャッシュに乗せているため無効化する必要がある
if (!Arrays.equals (mmuTTUserCode1, mmuTTUserCode2)) {
for (int i = 0; i < 4 * MMU_CACHE_WAYS * MMU_HASH_SIZE; i += 4) {
int logicalPage = mmuUserCodeCache[i];
if (logicalPage != 1) { //アドレス変換キャッシュが有効
int block = logicalPage >>> 24;
if (mmuTTUserCode1[block] != mmuTTUserCode2[block]) { //透過変換の状態が変化した
mmuUserCodeCache[i] = mmuUserCodeCache[i + 1] = mmuUserCodeCache[i + 2] = mmuUserCodeCache[i + 3] = 1; //アドレス変換キャッシュを無効化する
}
}
}
}
if (!Arrays.equals (mmuTTSuperCode1, mmuTTSuperCode2)) {
for (int i = 0; i < 4 * MMU_CACHE_WAYS * MMU_HASH_SIZE; i += 4) {
int logicalPage = mmuSuperCodeCache[i];
if (logicalPage != 1) { //アドレス変換キャッシュが有効
int block = logicalPage >>> 24;
if (mmuTTSuperCode1[block] != mmuTTSuperCode2[block]) { //透過変換の状態が変化した
mmuSuperCodeCache[i] = mmuSuperCodeCache[i + 1] = mmuSuperCodeCache[i + 2] = mmuSuperCodeCache[i + 3] = 1; //アドレス変換キャッシュを無効化する
}
}
}
}
} //mmuTTSetCode(int,int)
//--------------------------------------------------------------------------------
//変換制御レジスタ
//
// TCR 変換制御レジスタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━┯━┯━┯━┯━┯━┯━━━┯━━━┯━┯━━━┯━━━┯━┓
// ┃ 0 │ E│ P NAD NAI FOTC FITC DCO │ DUO │DWO DCI │ DUI │ 0┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━┷━┷━┷━┷━┷━┷━━━┷━━━┷━┷━━━┷━━━┷━┛
public static final int MMU_TCR_ENABLE = 1 << 15; //x E Enable
public static final int MMU_TCR_PAGE_SIZE = 1 << 14; //x P Page Size
public static final int MMU_TCR_P_4KB = 0 << 14; // 4KB
public static final int MMU_TCR_P_8KB = 1 << 14; // 8KB
public static final int MMU_TCR_NAD = 1 << 13; //x NAD No Allocate Mode (Data ATC)。データATCはヒットするが更新されない
public static final int MMU_TCR_NAI = 1 << 12; //x NAI No Allocate Mode (Instruction ATC)。命令ATCはヒットするが更新されない
public static final int MMU_TCR_FOTC = 1 << 11; // FOTC 1/2-Cache Mode (Data ATC)。データATCは0=64エントリ,1=32エントリ
public static final int MMU_TCR_FITC = 1 << 10; // FITC 1/2-Cache Mode (Instruction ATC)。命令ATCは0=64エントリ,1=32エントリ
public static final int MMU_TCR_DCO = 3 << 8; // DCO Default Cache Mode (Data Cache)。デフォルトデータキャッシュモード
public static final int MMU_TCR_DUO = 3 << 6; // DUO Default UPA bits (Data Cache)。デフォルトデータUPA
public static final int MMU_TCR_DWO = 1 << 5; // DWO Default Write Protect (Data Cache)。デフォルトライトプロテクト
public static final int MMU_TCR_DCI = 3 << 3; // DCI Default Cache Mode (Instruction Cache)。デフォルト命令キャッシュモード
public static final int MMU_TCR_DUI = 3 << 1; // DUI Default UPA bits (Instruction Cache)。デフォルト命令UPA
public static int mmuTCR; //TCR
public static boolean mmuEnabled; //true=アドレス変換有効
public static boolean mmu4KB; //false=8KB,true=4KB
public static boolean mmuNotAllocateData; //true=データアドレス変換キャッシュをアロケートしない
public static boolean mmuNotAllocateCode; //true=命令アドレス変換キャッシュをアロケートしない
public static int mmuPageSize; //ページサイズ
public static int mmuPageAddressMask; //ページアドレスのマスク
public static int mmuPageOffsetMask; //ページオフセットのマスク
public static int mmuPageIndexMask; //ページインデックスのマスク
public static int mmuPageIndexBit2; //ページインデックスのbit番号-2
public static int mmuPageTableMask; //ページテーブルの先頭アドレスのマスク
//d = mmuGetTCR ()
// TCRを読む
public static int mmuGetTCR () {
return mmuTCR;
} //mmuGetTCR()
//mmuSetTCR (d)
// TCRに書く
public static void mmuSetTCR (int d) {
mmuInvalidateAllCache (); //高速化のためアドレス変換していないときもキャッシュに乗せているので、アドレス変換を有効にしたときキャッシュを初期化する必要がある
mmuTCR = d & 0x0000fffe;
mmuEnabled = (short) d < 0; //(d & MMU_TCR_ENABLE) != 0
mmu4KB = (d & MMU_TCR_PAGE_SIZE) == MMU_TCR_P_4KB;
mmuNotAllocateData = (d & MMU_TCR_NAD) != 0;
mmuNotAllocateCode = (d & MMU_TCR_NAI) != 0;
if (mmu4KB) { //4KB
mmuPageSize = MMU_PAGE_SIZE_4KB;
mmuPageAddressMask = MMU_PAGE_ADDRESS_MASK_4KB;
mmuPageOffsetMask = MMU_PAGE_OFFSET_MASK_4KB;
mmuPageIndexMask = MMU_PAGE_INDEX_MASK_4KB;
mmuPageIndexBit2 = MMU_PAGE_INDEX_BIT0_4KB - 2;
mmuPageTableMask = MMU_DESCRIPTOR_PAGE_TABLE_ADDRESS_4KB;
} else { //8KB
mmuPageSize = MMU_PAGE_SIZE_8KB;
mmuPageAddressMask = MMU_PAGE_ADDRESS_MASK_8KB;
mmuPageOffsetMask = MMU_PAGE_OFFSET_MASK_8KB;
mmuPageIndexMask = MMU_PAGE_INDEX_MASK_8KB;
mmuPageIndexBit2 = MMU_PAGE_INDEX_BIT0_8KB - 2;
mmuPageTableMask = MMU_DESCRIPTOR_PAGE_TABLE_ADDRESS_8KB;
}
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetTCR(0x%08x)\n", XEiJ.regPC0, mmuTCR);
System.out.printf (" mmuEnabled=%b\n", mmuEnabled);
System.out.printf (" mmu4KB=%b\n", mmu4KB);
System.out.printf (" mmuPageSize=0x%08x\n", mmuPageSize);
System.out.printf (" mmuPageAddressMask=0x%08x\n", mmuPageAddressMask);
System.out.printf (" mmuPageOffsetMask=0x%08x\n", mmuPageOffsetMask);
System.out.printf (" mmuPageIndexMask=0x%08x\n", mmuPageIndexMask);
System.out.printf (" mmuPageIndexBit2=%d\n", mmuPageIndexBit2);
System.out.printf (" mmuPageTableMask=%d\n", mmuPageTableMask);
}
} //mmuSetTCR(int)
//--------------------------------------------------------------------------------
//アドレス変換テーブル
// URP ユーザルートポインタ
// SRP スーパーバイザルートポインタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━┓
// ┃ ルートテーブルアドレス │ 0 ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━┛
public static int mmuURP; //URP
public static int mmuSRP; //SRP
//d = mmuGetURP ()
// URPを読む
public static int mmuGetURP () {
return mmuURP;
} //mmuGetURP()
//d = mmuGetSRP ()
// SRPを読む
public static int mmuGetSRP () {
return mmuSRP;
} //mmuGetSRP()
//mmuSetURP (d)
// URPに書く
public static void mmuSetURP (int d) throws M68kException {
mmuURP = d &= 0xfffffe00;
Arrays.fill (mmuUserDataCache, 1);
Arrays.fill (mmuUserCodeCache, 1);
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetURP(0x%08x)\n", XEiJ.regPC0, mmuURP);
}
if (RootPointerList.RTL_ON) {
RootPointerList.rtlSetRootPointer (d, false);
}
} //mmuSetURP(int)
//mmuSetSRP (d)
// SRPに書く
public static void mmuSetSRP (int d) {
mmuSRP = d &= 0xfffffe00;
Arrays.fill (mmuSuperDataCache, 1);
Arrays.fill (mmuSuperCodeCache, 1);
if (MMU_DEBUG_COMMAND) {
System.out.printf ("%08x mmuSetSRP(0x%08x)\n", XEiJ.regPC0, mmuSRP);
}
if (RootPointerList.RTL_ON) {
RootPointerList.rtlSetRootPointer (d, true);
}
} //mmuSetSRP(int)
// デスクリプタ
//
// ルートテーブルデスクリプタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━┯━┯━┯━━━┓
// ┃ ポインタテーブルアドレス │ X │ U│ W│ UDT ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━┷━┷━━━┛
//
// 4KBポインタテーブルデスクリプタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━┯━┯━┯━━━┓
// ┃ ページテーブルアドレス │ X │ U│ W│ UDT ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━┷━┷━┷━━━┛
//
// 8KBポインタテーブルデスクリプタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━┯━┯━┯━━━┓
// ┃ ページテーブルアドレス │ X│ U│ W│ UDT ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━┷━┷━┷━━━┛
//
// 4KBページテーブルデスクリプタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━┯━┯━┯━┯━┯━━━┯━┯━┯━┯━━━┓
// ┃ 物理ページアドレス │UR│ G│U1│U0│ S│ CM │ M│ U│ W│ PDT ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━┷━┷━┷━┷━┷━━━┷━┷━┷━┷━━━┛
//
// 8KBページテーブルデスクリプタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━┯━┯━┯━┯━┯━┯━━━┯━┯━┯━┯━━━┓
// ┃ 物理ページアドレス │UR│UR│ G│U1│U0│ S│ CM │ M│ U│ W│ PDT ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━┷━┷━┷━┷━┷━┷━━━┷━┷━┷━┷━━━┛
//
// 間接ページテーブルデスクリプタ
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━┓
// ┃ ページデスクリプタアドレス │ PDT ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━┛
public static final int MMU_DESCRIPTOR_POINTER_TABLE_ADDRESS = -1 << 9; //x Pointer Table Address
public static final int MMU_DESCRIPTOR_PAGE_TABLE_ADDRESS_4KB = -1 << 6; //x Page Table Address (4KB)
public static final int MMU_DESCRIPTOR_PAGE_TABLE_ADDRESS_8KB = -1 << 5; //x Page Table Address (8KB)
public static final int MMU_DESCRIPTOR_GLOBAL = 1 << 10; //x G Global
public static final int MMU_DESCRIPTOR_SUPERVISOR_PROTECTED = 1 << 7; //x S Supervisor Protected
public static final int MMU_DESCRIPTOR_CACHE_MODE = 3 << 5; //x CM Cache Mode
public static final int MMU_DESCRIPTOR_MODIFIED = 1 << 4; //x M Modified
public static final int MMU_DESCRIPTOR_USED = 1 << 3; //x U Used
public static final int MMU_DESCRIPTOR_WRITE_PROTECTED = 1 << 2; //x W Write Protected
public static final int MMU_DESCRIPTOR_UDT = 2 << 0; //x UDT Upper Level Descriptor Type
public static final int MMU_DESCRIPTOR_PDT = 3 << 0; //x PDT Page Descriptor Type
public static final int MMU_DESCRIPTOR_TYPE_INVALID = 0 << 0; // Invalid
public static final int MMU_DESCRIPTOR_TYPE_INDIRECT = 2 << 0; // Indirect
public static final int MMU_DESCRIPTOR_INDIRECT_ADDRESS = -1 << 2; //x Descriptor Address
//--------------------------------------------------------------------------------
//アドレス変換キャッシュ
//
// 構造
// ユーザモード
// ライン0
// エントリ0
// [0] 論理ページアドレス。リード用。1=無効
// [1] 論理ページアドレス。ライト用。修正済みかつライトプロテクトされていないときだけ有効。1=無効
// [2] 物理ページアドレス。1=無効
// [3] フラグ。bit10:グローバル,bit6-5:キャッシュモード,bit0:無効
// エントリ1
// エントリ2
// エントリ3
// ライン1
// :
// ライン63
// スーパーバイザモード
// ライン0
// エントリ0
// [0] 論理ページアドレス。リード用。1=無効
// [1] 論理ページアドレス。ライト用。修正済みかつライトプロテクトされていないときだけ有効。1=無効
// [2] 物理ページアドレス。1=無効
// [3] フラグ。bit10:グローバル,bit6-5:キャッシュモード,bit0:無効
// エントリ1
// エントリ2
// エントリ3
// ライン1
// :
// ライン63
//
// ハッシュ関数
// 次の関数で32bitの論理ページアドレスを6bitのライン番号に変換する
// a * 0x5efc103f >>> 26
// 32bitの中に幅6bit以内で6bitまでセットする組み合わせは1+1+2+4+8+16+32*27=896通りあるが、
// それらをa*x>>>26で0~63になるべく均一に分散させる係数を2^32通りの中から探して以下の24個を得た
// 0x5efbf041 0x5efc0fc1 0x5efc103f 0x5f03efc1 0x5f03f03f 0x5f040fbf
// 0x60fbf041 0x60fc0fc1 0x60fc103f 0x6103efc1 0x6103f03f 0x61040fbf
// 0x9efbf041 0x9efc0fc1 0x9efc103f 0x9f03efc1 0x9f03f03f 0x9f040fbf
// 0xa0fbf041 0xa0fc0fc1 0xa0fc103f 0xa103efc1 0xa103f03f 0xa1040fbf
// この中で(0..63)<<12と(0..63)<<13がそれぞれすべて分離するのは
// 0x5efc103f
// 0x60fc103f
// 0x9efc103f
// 0xa0fc103f
// この4個はほぼ同じパターンなので0x5efc103fを係数として用いることにする
// perl -e "for$x(0x5efc103f){printf' // 0x%x%c',$x,10;for$b(7..15){@c=(0)x64;for$n(0..63){$a=$n<<$b;$c[$a*$x>>26&63]++;}printf' // %2d %s%c',$b,join('',@c),10;}}"
// 0x5efc103f
// 7 2111111111111111111111111111111101111111111111111111111111111111
// 8 1111111111111111111111111111111111111111111111111111111111111111
// 9 1111111111111111111111111111111111111111111111111111111111111111
// 10 1111111111111111111111111111111111111111111111111111111111111111
// 11 1111111111111111111111111111111111111111111111111111111111111111
// 12 1111111111111111111111111111111111111111111111111111111111111111
// 13 1111111111111111111111111111111111111111111111111111111111111111
// 14 1111111111111111111111111111111111111111111111111111111111111111
// 15 2011111111111111111111111111111111111111111111111111111111111111
// ページサイズが2^8=256バイトから2^14=16384バイトまで、それぞれ先頭の64ページがすべて異なるハッシュ値を持つことがわかる
//
// 1wayセットアソシアティブ
// ハッシュ値が衝突したときの速度低下を抑えるため4waysにしてみたが効果がなさそうなので1wayに戻してある
// ハッシュ関数を工夫してあるので4waysにしてもほとんどの場合は1番目でヒットするか4番目まですべてミスするかのどちらかになる
// 1wayを4waysにするとミスしたときの条件分岐が1回から4回に増えてテーブルサーチの開始が遅れる
// 2ways以上では参照するときに1番目に比較するエントリとアロケートするときに押し出すエントリを適切に選択するための仕組みが必要
//
// LRU(least recently used)方式(2ways以上の場合)
// アロケートはラインの中で最も古いエントリを切り捨てて最も新しいエントリを追加する方法で行う
// アドレス変換キャッシュは最も新しいエントリが繰り返しアクセスされる場合が多く、ハッシュ関数で十分に分散させられているので、
// ここではエントリを常に新しい順にソートしておく方法を用いる
// 2番目以降のエントリがヒットしたときエントリを並べ替えなければならないので遅くなるが、1番目のヒット率が十分に高ければ問題ない
//
// グローバル
// 関連する命令
// PFLUSHA アドレス変換キャッシュのすべてのエントリを無効化する
// PFLUSHAN アドレス変換キャッシュのNonGlobalなエントリを無効化する
// PFLUSH (An) アドレス変換キャッシュの、DFC=1またはDFC=2ならばユーザモード、DFC=5またはDFC=6ならばスーパーバイザモードの、
// 論理ページアドレスがAnのエントリを無効化する
// PFLUSHN (An) アドレス変換キャッシュの、DFC=1またはDFC=2ならばユーザモード、DFC=5またはDFC=6ならばスーパーバイザモードの、
// 論理ページアドレスがAnかつNonGlobalのエントリを無効化する
// グローバルはこれらの命令の動作を変更する以外の機能を持たない
//
// キャッシュモード
//
public static final int MMU_HASH_BITS = 6;
public static final int MMU_HASH_SIZE = 1 << MMU_HASH_BITS;
public static final int MMU_HASH_COEFF = 0x5efc103f; //ハッシュ関数の係数
public static final int MMU_CACHE_WAYS = 1; //1=1way,4=4waysセットアソシアティブ
public static final int[] mmuUserDataCache = new int[4 * MMU_CACHE_WAYS * MMU_HASH_SIZE];
public static final int[] mmuUserCodeCache = new int[4 * MMU_CACHE_WAYS * MMU_HASH_SIZE];
public static final int[] mmuSuperDataCache = new int[4 * MMU_CACHE_WAYS * MMU_HASH_SIZE];
public static final int[] mmuSuperCodeCache = new int[4 * MMU_CACHE_WAYS * MMU_HASH_SIZE];
//mmuInvalidateAllCache ()
// PFLUSHA
// アドレス変換キャッシュのすべてのエントリを無効化する
public static void mmuInvalidateAllCache () {
Arrays.fill (mmuUserDataCache, 1);
Arrays.fill (mmuUserCodeCache, 1);
Arrays.fill (mmuSuperDataCache, 1);
Arrays.fill (mmuSuperCodeCache, 1);
} //mmuInvalidateAllCache()
//mmuInvalidateAllNonGlobalCache ()
// PFLUSHAN
// アドレス変換キャッシュのNonGlobalなエントリを無効化する
public static void mmuInvalidateAllNonGlobalCache () {
for (int i = 0; i < 4 * MMU_CACHE_WAYS * MMU_HASH_SIZE; i += 4) {
if ((mmuUserDataCache[i + 3] & (MMU_DESCRIPTOR_GLOBAL | 1)) == 0) { //エントリが有効かつNonGlobal
mmuUserDataCache[i] = mmuUserDataCache[i + 1] = mmuUserDataCache[i + 2] = mmuUserDataCache[i + 3] = 1;
}
if ((mmuUserCodeCache[i + 3] & (MMU_DESCRIPTOR_GLOBAL | 1)) == 0) { //エントリが有効かつNonGlobal
mmuUserCodeCache[i] = mmuUserCodeCache[i + 1] = mmuUserCodeCache[i + 2] = mmuUserCodeCache[i + 3] = 1;
}
if ((mmuSuperDataCache[i + 3] & (MMU_DESCRIPTOR_GLOBAL | 1)) == 0) { //エントリが有効かつNonGlobal
mmuSuperDataCache[i] = mmuSuperDataCache[i + 1] = mmuSuperDataCache[i + 2] = mmuSuperDataCache[i + 3] = 1;
}
if ((mmuSuperCodeCache[i + 3] & (MMU_DESCRIPTOR_GLOBAL | 1)) == 0) { //エントリが有効かつNonGlobal
mmuSuperCodeCache[i] = mmuSuperCodeCache[i + 1] = mmuSuperCodeCache[i + 2] = mmuSuperCodeCache[i + 3] = 1;
}
}
} //mmuInvalidateAllNonGlobalCache()
//mmuInvalidateCache (a)
// PFLUSH (An)
// アドレス変換キャッシュの、DFC=1またはDFC=2ならばユーザモード、DFC=5またはDFC=6ならばスーパーバイザモードの、
// 論理ページアドレスがAnのエントリを無効化する
public static void mmuInvalidateCache (int a) {
int logicalPage = a & mmuPageAddressMask;
boolean supervisor = (0b10011111 << 24 << XEiJ.mpuDFC) < 0;
boolean instruction = (0b00101010 << 24 << XEiJ.mpuDFC) < 0;
int[] cache = (supervisor ?
instruction ? mmuSuperCodeCache : mmuSuperDataCache :
instruction ? mmuUserCodeCache : mmuUserDataCache);
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (MMU_CACHE_WAYS == 1) { //1way
if (cache[head] == logicalPage) { //エントリが有効かつ論理ページアドレスがAn
cache[head] = cache[head + 1] = cache[head + 2] = cache[head + 3] = 1; //末尾を空ける
return;
}
} else { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head; i <= tail; i += 4) {
if (cache[i] == logicalPage) { //エントリが有効かつ論理ページアドレスがAn
for (int j = i; j < tail; j += 4) { //後ろを詰める
cache[j ] = cache[j + 4];
cache[j + 1] = cache[j + 5];
cache[j + 2] = cache[j + 6];
cache[j + 3] = cache[j + 7];
}
cache[tail] = cache[tail + 1] = cache[tail + 2] = cache[tail + 3] = 1; //末尾を空ける
return;
}
}
}
} //mmuInvalidateCache(int)
//mmuInvalidateNonGlobalCache (a)
// PFLUSHN (An)
// アドレス変換キャッシュの、DFC=1またはDFC=2ならばユーザモード、DFC=5またはDFC=6ならばスーパーバイザモードの、
// 論理ページアドレスがAnかつNonGlobalのエントリを無効化する
public static void mmuInvalidateNonGlobalCache (int a) {
int logicalPage = a & mmuPageAddressMask;
boolean supervisor = (0b10011111 << 24 << XEiJ.mpuDFC) < 0;
boolean instruction = (0b00101010 << 24 << XEiJ.mpuDFC) < 0;
int[] cache = (supervisor ?
instruction ? mmuSuperCodeCache : mmuSuperDataCache :
instruction ? mmuUserCodeCache : mmuUserDataCache);
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (MMU_CACHE_WAYS == 1) { //1way
if (cache[head] == logicalPage) { //エントリが有効かつ論理ページアドレスがAn
if ((cache[head + 3] & (MMU_DESCRIPTOR_GLOBAL | 1)) == 0) { //エントリが有効かつNonGlobal
cache[head] = cache[head + 1] = cache[head + 2] = cache[head + 3] = 1; //末尾を空ける
}
return; //論理ページアドレスがAnのエントリは1つだけなのでそれがNonGlobalでなければ何もしないで終了する
}
} else { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head; i <= tail; i += 4) {
if (cache[i] == logicalPage) { //エントリが有効かつ論理ページアドレスがAn
if ((cache[i + 3] & (MMU_DESCRIPTOR_GLOBAL | 1)) == 0) { //エントリが有効かつNonGlobal
for (int j = i; j < tail; j += 4) { //後ろを詰める
cache[j ] = cache[j + 4];
cache[j + 1] = cache[j + 5];
cache[j + 2] = cache[j + 6];
cache[j + 3] = cache[j + 7];
}
cache[tail] = cache[tail + 1] = cache[tail + 2] = cache[tail + 3] = 1; //末尾を空ける
}
return; //論理ページアドレスがAnのエントリは1つだけなのでそれがNonGlobalでなければ何もしないで終了する
}
}
}
} //mmuInvalidateNonGlobalCache(int)
//--------------------------------------------------------------------------------
//初期化
//mmuInit ()
// 初期化
public static void mmuInit () {
mmuTTUserData1 = new byte[256];
mmuTTUserCode1 = new byte[256];
mmuTTSuperData1 = new byte[256];
mmuTTSuperCode1 = new byte[256];
mmuTTUserData2 = new byte[256];
mmuTTUserCode2 = new byte[256];
mmuTTSuperData2 = new byte[256];
mmuTTSuperCode2 = new byte[256];
mmuReset ();
} //mmuInit()
//mmuReset ()
// リセット
public static void mmuReset () {
mmuTTSetData (0, 0);
mmuTTSetCode (0, 0);
mmuSetTCR (0);
} //mmuReset()
//--------------------------------------------------------------------------------
//バスアクセス
//
// ByteSign byte バイト符号拡張
// ByteZero int バイトゼロ拡張
// WordSign int ワード符号拡張
// WordZero int ワードゼロ拡張
// Long int ロング
// Quad long クワッド
//
// Data データ 1 先頭
// Second データ 1 2番目
// Even データ 2 先頭
// Four データ 4 先頭
// Code コード 2 先頭
// Opword コード 2 先頭(命令ワード)
// Exword コード 2 2番目(拡張ワード)
//
// バイト
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━┓
// ┃ B┃
// ┗━┛
// 0
//
// ワード
// 偶数
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━━━┓
// ┃ W ┃
// ┗━━━┛
// 0
// 奇数
// -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━┳━┓
// ┃ B┃ B┃
// ┗━┻━┛
// 8 0
//
// ロング
// 4の倍数
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━━━━━━━┓
// ┃ L ┃
// ┗━━━━━━━┛
// 0
// 4の倍数+1
// -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━┳━━━┳━┓
// ┃ B┃ W ┃ B┃
// ┗━┻━━━┻━┛
// 24 8 0
// 4の倍数+2
// -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━━━┳━━━┓
// ┃ W ┃ W ┃
// ┗━━━┻━━━┛
// 16 0
// 4の倍数+3
// -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━┳━━━┳━┓
// ┃ B┃ W ┃ B┃
// ┗━┻━━━┻━┛
// 24 8 0
//
// クワッド
// 4の倍数
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━━━━━━━┳━━━━━━━┓
// ┃ L ┃ L ┃
// ┗━━━━━━━┻━━━━━━━┛
// 32 0
// 4の倍数+1
// -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━┳━━━┳━━━━━━━┳━┓
// ┃ B┃ W ┃ L ┃ B┃
// ┗━┻━━━┻━━━━━━━┻━┛
// 56 40 8 0
// 4の倍数+2
// -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━━━┳━━━━━━━┳━━━┓
// ┃ W ┃ L ┃ W ┃
// ┗━━━┻━━━━━━━┻━━━┛
// 48 16 0
// 4の倍数+3
// -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
// ┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳━┯━┯━┯━┳
// ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃ │ │ │ ┃
// ┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻━┷━┷━┷━┻
// ┏━┳━━━━━━━┳━━━┳━┓
// ┃ B┃ L ┃ W ┃ B┃
// ┗━┻━━━━━━━┻━━━┻━┛
// 56 24 8 0
//
//--------------------------------------------------------------------------------
//ピーク
// デバッガ用
// エラーや副作用なしでリードする
// アドレス変換はピーク
// ページフォルトやバスエラーのときは-1をキャストした値を返す
//d = mmuPeekByteSign (a, f)
// ピークバイト符号拡張
public static byte mmuPeekByteSign (int a, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //SFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
return (a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0) : -1;
} else if (f != 7) { //SFC=0,3,4。アドレス変換なし
return mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a);
} else {
return -1;
}
} //mmuPeekByteSign(int,int)
//d = mmuPeekByteZero (a, f)
// ピークバイトゼロ拡張
public static int mmuPeekByteZero (int a, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //SFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
return (a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a0) : 0xff;
// ^ ^^^^
} else if (f != 7) { //SFC=0,3,4。アドレス変換なし
return mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a);
// ^
} else {
return 0xff;
// ^^^^
}
} //mmuPeekByteZero(int,int)
//d = mmuPeekByteSignData (a, supervisor)
// ピークバイト符号拡張(データ)
public static byte mmuPeekByteSignData (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0);
return (a ^ a0) == 1 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0);
} //mmuPeekByteSignData(int,int)
//d = mmuPeekByteSignCode (a, supervisor)
// ピークバイト符号拡張(コード)
public static byte mmuPeekByteSignCode (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 1);
return (a ^ a0) == 1 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0);
} //mmuPeekByteSignCode(int,int)
//d = mmuPeekByteZeroData (a, supervisor)
// ピークバイトゼロ拡張(データ)
public static int mmuPeekByteZeroData (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0);
return (a ^ a0) == 1 ? 255 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a0);
} //mmuPeekByteZeroData(int,int)
//d = mmuPeekByteZeroCode (a, supervisor)
// ピークバイトゼロ拡張(コード)
public static int mmuPeekByteZeroCode (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 1);
return (a ^ a0) == 1 ? 255 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a0);
} //mmuPeekByteZeroCode(int,int)
//d = mmuPeekWordSign (a, f)
// ピークワード符号拡張
public static int mmuPeekWordSign (int a, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //SFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
if ((a & 1) == 0) { //偶数
return (a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0) : -1;
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, f & 4, f & 2);
return (((a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0) : -1) << 8 |
((a + 1 ^ a1) != 1 ? mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a1) : 255));
}
} else if (f != 7) { //SFC=0,3,4。アドレス変換なし
if ((a & 1) == 0) { //偶数
return mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPws (a);
} else { //奇数
return (mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a ) << 8 |
mm[a + 1 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a + 1));
}
} else {
return -1;
}
} //mmuPeekWordSign(int,int)
//d = mmuPeekWordSignData (a, supervisor)
// ピークワード符号拡張(データ)
public static int mmuPeekWordSignData (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0);
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, supervisor, 0);
return (((a0 & 1) == 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0)) << 8 |
((a1 & 1) != 0 ? 255 : mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a1)));
}
} //mmuPeekWordSignData(int,int)
//d = mmuPeekWordSignEven (a, supervisor)
// ピークワード符号拡張(偶数)
public static int mmuPeekWordSignEven (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
a = mmuTranslatePeek (a, supervisor, 0);
return (a & 1) != 0 ? -1 : mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPws (a);
} //mmuPeekWordSignEven(int,int)
//d = mmuPeekWordSignCode (a, supervisor)
// ピークワード符号拡張(コード)
public static int mmuPeekWordSignCode (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
a = mmuTranslatePeek (a, supervisor, 1);
return (a & 1) != 0 ? -1 : mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPws (a);
} //mmuPeekWordSignCode(int,int)
//d = mmuPeekWordZeroData (a, supervisor)
// ピークワードゼロ拡張(データ)
public static int mmuPeekWordZeroData (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (a0 & 1) != 0 ? 65535 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a0);
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, supervisor, 0);
return (((a0 & 1) == 0 ? 255 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a0)) << 8 |
((a1 & 1) != 0 ? 255 : mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a1)));
}
} //mmuPeekWordZeroData(int,int)
//d = mmuPeekWordZeroEven (a, supervisor)
// ピークワードゼロ拡張(偶数)
public static int mmuPeekWordZeroEven (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
a = mmuTranslatePeek (a, supervisor, 0);
return (a & 1) != 0 ? 65535 : mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a);
} //mmuPeekWordZeroEven(int,int)
//d = mmuPeekWordZeroCode (a, supervisor)
// ピークワードゼロ拡張(コード)
public static int mmuPeekWordZeroCode (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
a = mmuTranslatePeek (a, supervisor, 1);
return (a & 1) != 0 ? 65535 : mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a);
} //mmuPeekWordZeroCode(int,int)
//d = mmuPeekLong (a, f)
// ピークロング
public static int mmuPeekLong (int a, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //SFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
if ((a & 3) == 0) { //4の倍数
return (a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0) : -1;
} else if ((a & 1) == 0) { //4の倍数ではない偶数
int a2 = mmuTranslatePeek (a + 2, f & 4, f & 2);
return (((a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0) : -1) << 16 |
((a + 2 ^ a2) != 1 ? mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a2) : 65535));
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, f & 4, f & 2);
int a3 = mmuTranslatePeek (a + 3, f & 4, f & 2);
return (((a ^ a0) != 1 ? mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0) : -1) << 24 |
((a + 1 ^ a1) != 1 ? mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a1) : 65535) << 8 |
((a + 3 ^ a3) != 1 ? mm[a3 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a3) : 255));
}
} else if (f != 7) { //SFC=0,3,4。アドレス変換なし
if ((a & 3) == 0) { //4の倍数
return mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPls (a);
} else if ((a & 1) == 0) { //4の倍数ではない偶数
return (mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPws (a ) << 16 |
mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a + 2));
} else { //奇数
return (mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a ) << 24 |
mm[a + 1 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a + 1) << 8 |
mm[a + 3 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a + 3));
}
} else {
return -1;
}
} //mmuPeekLong(int,int)
//d = mmuPeekLongData (a, supervisor)
// ピークロング(データ)
public static int mmuPeekLongData (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
return (a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0);
} else if ((a & 1) == 0) { //4の倍数+2
int a2 = mmuTranslatePeek (a + 2, supervisor, 0);
return (((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0)) << 16 |
((a2 & 1) != 0 ? 65535 : mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a2)));
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, supervisor, 0);
int a3 = mmuTranslatePeek (a + 3, supervisor, 0);
return (((a0 & 1) == 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0)) << 24 |
((a1 & 1) != 0 ? 65535 : mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a1)) << 16 |
((a3 & 1) != 0 ? 255 : mm[a3 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a3)));
}
} //mmuPeekLongData(int,int)
//d = mmuPeekLongEven (a, supervisor)
// ピークロング(偶数)
public static int mmuPeekLongEven (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0);
} else { //4の倍数+2
int a2 = mmuTranslatePeek (a + 2, supervisor, 0);
return (((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0)) << 16 |
((a2 & 1) != 0 ? 65535 : mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a2)));
}
} //mmuPeekLongEven(int,int)
//d = mmuPeekLongFour (a, supervisor)
// ピークロング(4の倍数)
public static int mmuPeekLongFour (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
a = mmuTranslatePeek (a, supervisor, 0);
return (a & 1) != 0 ? -1 : mm[a >>> XEiJ.BUS_PAGE_BITS].mmdPls (a);
} //mmuPeekLongFour(int,int)
//d = mmuPeekLongCode (a, supervisor)
// ピークロング(コード)
public static int mmuPeekLongCode (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 1); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0);
} else { //4の倍数+2
int a2 = mmuTranslatePeek (a + 2, supervisor, 1);
return (((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0)) << 16 |
((a2 & 1) != 0 ? 65535 : mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a2)));
}
} //mmuPeekLongCode(int,int)
//d = mmuPeekQuad (a, f)
// ピーククワッド
public static long mmuPeekQuad (int a, int f) {
return (long) mmuPeekLong (a, f) << 32 | mmuPeekLong (a + 4, f) & 0xffffffffL;
} //mmuPeekQuad(int,int)
//d = mmuPeekQuadData (a, supervisor)
// ピーククワッド(データ)
public static long mmuPeekQuadData (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0); //a+1,a+2,a+3,a+4,a+5,a+6,a+7が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
int a4 = mmuTranslatePeek (a + 4, supervisor, 0); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0)) << 32 |
(long) ((a4 & 1) != 0 ? -1 : mm[a4 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a4)) & 0x00000000ffffffffL);
} else if ((a & 1) == 0) { //4の倍数+2
int a2 = mmuTranslatePeek (a + 2, supervisor, 0); //4の倍数
int a6 = mmuTranslatePeek (a + 6, supervisor, 0); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0)) << 48 |
(long) ((a2 & 1) != 0 ? -1 : mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a2)) << 16 & 0x0000ffffffff0000L |
(long) ((a6 & 1) != 0 ? 65535 : mm[a6 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a6)));
} else if ((a & 3) == 1) { //4の倍数+1
int a1 = mmuTranslatePeek (a + 1, supervisor, 0); //4の倍数+2
int a3 = mmuTranslatePeek (a + 3, supervisor, 0); //4の倍数
int a7 = mmuTranslatePeek (a + 7, supervisor, 0); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0)) << 56 |
(long) ((a1 & 1) != 0 ? 65535 : mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a1)) << 40 |
(long) ((a3 & 1) != 0 ? -1 : mm[a3 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a3)) << 8 & 0x000000ffffffff00L |
(long) ((a7 & 1) != 0 ? 255 : mm[a7 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a7)));
} else { //4の倍数+3
int a1 = mmuTranslatePeek (a + 1, supervisor, 0); //4の倍数
int a5 = mmuTranslatePeek (a + 5, supervisor, 0); //4の倍数
int a7 = mmuTranslatePeek (a + 7, supervisor, 0); //4の倍数+2
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a0)) << 56 |
(long) ((a1 & 1) != 0 ? -1 : mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a1)) << 24 & 0x00ffffffff000000L |
(long) ((a5 & 1) != 0 ? 65535 : mm[a5 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a5)) << 8 |
(long) ((a7 & 1) != 0 ? 255 : mm[a7 >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a7)));
}
} //mmuPeekQuadData(int,int)
//d = mmuPeekQuadEven (a, supervisor)
// ピーククワッド(偶数)
public static long mmuPeekQuadEven (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0); //a+2,a+4,a+6が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
int a4 = mmuTranslatePeek (a + 4, supervisor, 0); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0)) << 32 |
(long) ((a4 & 1) != 0 ? -1 : mm[a4 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a4)) & 0x00000000ffffffffL);
} else { //4の倍数+2
int a2 = mmuTranslatePeek (a + 2, supervisor, 0); //4の倍数
int a6 = mmuTranslatePeek (a + 6, supervisor, 0); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0)) << 48 |
(long) ((a2 & 1) != 0 ? -1 : mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a2)) << 16 & 0x0000ffffffff0000L |
(long) ((a6 & 1) != 0 ? 65535 : mm[a6 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a6)));
}
} //mmuPeekQuadEven(int,int)
//d = mmuPeekQuadFour (a, supervisor)
// ピーククワッド(4の倍数)
public static long mmuPeekQuadFour (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a , supervisor, 0); //4の倍数。a+4が必要なので上書き不可
int a4 = mmuTranslatePeek (a + 4, supervisor, 0); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0)) << 32 |
(long) ((a4 & 1) != 0 ? -1 : mm[a4 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a4)) & 0x00000000ffffffffL);
} //mmuPeekQuadFour(int,int)
//d = mmuPeekQuadCode (a, supervisor)
// ピーククワッド(コード)
public static long mmuPeekQuadCode (int a, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 1); //a+2,a+4,a+6が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
int a4 = mmuTranslatePeek (a + 4, supervisor, 1);
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a0)) << 32 |
(long) ((a4 & 1) != 0 ? -1 : mm[a4 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a4)) & 0x00000000ffffffffL);
} else { //4の倍数+2
int a2 = mmuTranslatePeek (a + 2, supervisor, 1); //4の倍数
int a6 = mmuTranslatePeek (a + 6, supervisor, 1); //4の倍数
return ((long) ((a0 & 1) != 0 ? -1 : mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdPws (a0)) << 48 |
(long) ((a2 & 1) != 0 ? -1 : mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdPls (a2)) << 16 & 0x0000ffffffff0000L |
(long) ((a6 & 1) != 0 ? 65535 : mm[a6 >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a6)));
}
} //mmuPeekQuadCode(int,int)
//mmuPeekExtended (a, b, f)
// ピークエクステンデッド
public static void mmuPeekExtended (int a, byte[] b, int f) {
for (int i = 0; i < 12; i++) {
b[i] = mmuPeekByteSign (a + i, f);
}
} //mmuPeekExtended(int,int,byte[])
//len = mmuPeekStrlen (a, l)
public static int mmuPeekStrlen (int a, int l, int supervisor) {
for (int i = 0; i < l; i++) {
if (mmuPeekByteZeroData (a + i, supervisor) == 0) {
return i;
}
}
return l;
} //mmuPeekStrlen(int,int,int)
//bool = mmuPeekEquals (a, str)
// アドレスaから始まるSJISの文字列とstrをSJISに変換してエスケープシーケンスを展開した文字列を比較する
// 終端の\0まで比較するときはstrに\0を含めること
// \x??で任意のSJISの文字を書ける
// SJISに変換できない文字は'※'とみなす
// スーパーバイザモード比較する
public static boolean mmuPeekEquals (int a, String str) {
int len = str.length ();
for (int i = 0; i < len; i++) {
int c = str.charAt (i);
if (c == '\\') { //エスケープシーケンス。SJIS変換を省略する
int d = i + 1 < len ? str.charAt (i + 1) : -1; //2文字目
if ((d & -4) == '0') { // \[0-3][0-7]{0,2}
c = d & 7;
d = i + 2 < len ? str.charAt (i + 2) : -1; //3文字目
if ((d & -8) == '0') {
c = c << 3 | (d & 7);
d = i + 3 < len ? str.charAt (i + 3) : -1; //4文字目
if ((d & -8) == '0') {
c = c << 3 | (d & 7);
i++; //4文字
}
i++; //3文字
}
i++; //2文字
} else if ((d & -4) == '4') { // \[4-7][0-7]?
c = d & 7;
d = i + 2 < len ? str.charAt (i + 2) : -1; //3文字目
if ((d & -8) == '0') {
c = c << 3 | (d & 7);
i++; //3文字
}
i++; //2文字
} else if (d == 'b') { // \b
c = 0x08; //BS
i++; //2文字
} else if (d == 't') { // \t
c = 0x09; //HT
i++; //2文字
} else if (d == 'n') { // \n
c = 0x0a; //LF
i++; //2文字
} else if (d == 'v') { // \v
c = 0x0b; //VT
i++; //2文字
} else if (d == 'f') { // \f
c = 0x0c; //FF
i++; //2文字
} else if (d == 'r') { // \r
c = 0x0d; //CR
i++; //2文字
} else if (d == 'x' &&
i + 3 < len &&
CharacterCode.chrIsXdigit (str.charAt (i + 2)) &&
CharacterCode.chrIsXdigit (str.charAt (i + 3))) { // \x[0-9A-Fa-f]{2}
c = (CharacterCode.chrDigit (str.charAt (i + 2)) << 4 |
CharacterCode.chrDigit (str.charAt (i + 3)));
i += 3; //4文字
} else if ('!' <= d && d <= '~') {
c = d;
i++; //2文字
}
if (mmuPeekByteZeroData (a++, 1) != c) {
return false;
}
} else { //エスケープシーケンス以外
int s = CharacterCode.chrCharToSJIS[c];
if (s == 0 && c != 0) {
s = 0x81a6; //'※'
}
if (s >> 8 != 0) { //2バイトコード
if (mmuPeekByteZeroData (a++, 1) != s >> 8) {
return false;
}
}
if (mmuPeekByteZeroData (a++, 1) != (s & 0xff)) {
return false;
}
}
} //for
return true;
} //mmuPeekEquals
//s = mmuPeekStringL (a, l, supervisor)
//sb = mmuPeekStringL (sb, a, l, supervisor)
// ピークストリング(長さ指定)
// 文字列を読み出す
// 対応する文字がないときは'.'または'※'になる
// 制御コードは'.'になる
public static String mmuPeekStringL (int a, int l, int supervisor) {
return mmuPeekStringL (new StringBuilder (), a, l, supervisor).toString ();
} //mmuPeekStringL(int,int,int)
public static StringBuilder mmuPeekStringL (StringBuilder sb, int a, int l, int supervisor) {
for (int i = 0; i < l; i++) {
int s = mmuPeekByteZeroData (a + i, supervisor);
char c;
if (0x81 <= s && s <= 0x9f || 0xe0 <= s && s <= 0xef) { //SJISの2バイトコードの1バイト目
int t = i + 1 < l ? mmuPeekByteZeroData (a + i + 1, supervisor) : 0;
if (0x40 <= t && t != 0x7f && t <= 0xfc) { //SJISの2バイトコードの2バイト目
c = CharacterCode.chrSJISToChar[s << 8 | t]; //2バイトで変換する
if (c == 0) { //対応する文字がない
c = '※';
}
i++;
} else { //SJISの2バイトコードの2バイト目ではない
c = '.'; //SJISの2バイトコードの1バイト目ではなかった
}
} else { //SJISの2バイトコードの1バイト目ではない
c = CharacterCode.chrSJISToChar[s]; //1バイトで変換する
if (c < 0x20 || c == 0x7f) { //対応する文字がないまたは制御コード
c = '.';
}
}
sb.append (c);
}
return sb;
} //mmuPeekString(StringBuilder,int,int,int)
//s = mmuPeekStringZ (a, f)
//sb = mmuPeekStringZ (sb, a, f)
// ピークストリング
// 文字列をSJISからUTF-16に変換しながらメモリから読み出す
// '\0'の手前まで読み出す
// UTF-16に変換できない文字は'\ufffd'になる
public static String mmuPeekStringZ (int a, int f) {
return mmuPeekStringZ (new StringBuilder (), a, f).toString ();
} //mmuPeekStringZ(int,int)
public static StringBuilder mmuPeekStringZ (StringBuilder sb, int a, int f) {
for (;;) {
int s = mmuPeekByteSign (a++, f) & 255;
if (s == 0) {
break;
}
int u;
if (0x81 <= s && s <= 0x9f || 0xe0 <= s && s <= 0xef) { //SJISの2バイトコードの1バイト目
int t = mmuPeekByteSign (a++, f) & 255;
if (t == 0) {
sb.append ('\ufffd');
break;
}
if (0x40 <= t && t != 0x7f && t <= 0xfc) { //SJISの2バイトコードの2バイト目
t |= s << 8;
u = CharacterCode.chrSJISToChar[t]; //2バイトで変換する
if (u == 0) { //変換できない
u = 0xfffd;
}
} else { //SJISの2バイトコードの2バイト目ではない
u = 0xfffd;
}
} else { //SJISの2バイトコードの1バイト目ではない
u = CharacterCode.chrSJISToChar[s]; //1バイトで変換する
if (u == 0) { //変換できない
u = 0xfffd;
}
}
sb.append ((char) u);
}
return sb;
} //mmuPeekStringZ(StringBuilder,int,int)
//--------------------------------------------------------------------------------
//リード
// アドレス変換はリード
// FSLWのRead and WriteはRead
//d = mmuReadByteSignData (a, supervisor)
// リードバイト符号拡張(データ)
public static byte mmuReadByteSignData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateReadSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateReadUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
}
} //mmuReadByteSignData(int,int)
//d = mmuReadByteZeroData (a, supervisor)
// リードバイトゼロ拡張(データ)
public static int mmuReadByteZeroData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateReadSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateReadUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
}
} //mmuReadByteZeroData(int,int)
//d = mmuReadByteSignExword (a, supervisor)
// リードバイト符号拡張(拡張ワード)
public static byte mmuReadByteSignExword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_CODE;
int a0 = mmuTranslateReadSuperCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_CODE;
int a0 = mmuTranslateReadUserCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
}
} //mmuReadByteSignExword(int,int)
//d = mmuReadByteZeroExword (a, supervisor)
// リードバイトゼロ拡張(拡張ワード)
public static int mmuReadByteZeroExword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_CODE;
int a0 = mmuTranslateReadSuperCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_CODE;
int a0 = mmuTranslateReadUserCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
}
} //mmuReadByteZeroExword(int,int)
//d = mmuReadWordSignData (a, supervisor)
// リードワード符号拡張(データ)
public static int mmuReadWordSignData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateReadSuperData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateReadSuperData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateReadUserData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateReadUserData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
}
} //mmuReadWordSignData(int,int)
//d = mmuReadWordZeroData (a, supervisor)
// リードワードゼロ拡張(データ)
public static int mmuReadWordZeroData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateReadSuperData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateReadSuperData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateReadUserData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateReadUserData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
}
} //mmuReadWordZeroData(int,int)
//d = mmuReadWordSignEven (a, supervisor)
// リードワード符号拡張(偶数)
public static int mmuReadWordSignEven (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateReadSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
a = mmuTranslateReadUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
}
} //mmuReadWordSignEven(int,int)
//d = mmuReadWordZeroEven (a, supervisor)
// リードワードゼロ拡張(偶数)
public static int mmuReadWordZeroEven (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateReadSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
a = mmuTranslateReadUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
}
} //mmuReadWordZeroEven(int,int)
//d = mmuReadWordSignExword (a, supervisor)
// リードワード符号拡張(拡張ワード)
public static int mmuReadWordSignExword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_CODE;
a = mmuTranslateReadSuperCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_CODE;
a = mmuTranslateReadUserCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
}
} //mmuReadWordSignExword(int,int)
//d = mmuReadWordZeroExword (a, supervisor)
// リードワードゼロ拡張(拡張ワード)
public static int mmuReadWordZeroExword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_CODE;
a = mmuTranslateReadSuperCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_CODE;
a = mmuTranslateReadUserCode (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
}
} //mmuReadWordZeroExword(int,int)
//d = mmuReadWordSignOpword (a, supervisor)
// リードワード符号拡張(命令ワード)
public static int mmuReadWordSignOpword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_OPWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_CODE;
a = mmuTranslateReadSuperCode (a);
return (InstructionBreakPoint.IBP_ON ? InstructionBreakPoint.ibpOp1SuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_OPWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_CODE;
a = mmuTranslateReadUserCode (a);
return (InstructionBreakPoint.IBP_ON ? InstructionBreakPoint.ibpOp1UserMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
}
} //mmuReadWordSignOpword(int,int)
//d = mmuReadWordZeroOpword (a, supervisor)
// リードワードゼロ拡張(命令ワード)
public static int mmuReadWordZeroOpword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_OPWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_CODE;
a = mmuTranslateReadSuperCode (a);
return (InstructionBreakPoint.IBP_ON ? InstructionBreakPoint.ibpOp1SuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_OPWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_CODE;
a = mmuTranslateReadUserCode (a);
return (InstructionBreakPoint.IBP_ON ? InstructionBreakPoint.ibpOp1UserMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
}
} //mmuReadWordZeroOpword(int,int)
//d = mmuReadLongData (a, supervisor)
// リードロング(データ)
public static int mmuReadLongData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateReadSuperData (a); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else if ((a & 1) == 0) { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateReadSuperData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateReadSuperData (a + 1); //偶数
int a3 = mmuTranslateReadSuperData (a + 3); //偶数
return (d0 << 24 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a1) << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a3 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a3));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateReadUserData (a); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else if ((a & 1) == 0) { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateReadUserData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateReadUserData (a + 1); //偶数
int a3 = mmuTranslateReadUserData (a + 3); //偶数
return (d0 << 24 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a1) << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a3 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a3));
}
}
} //mmuReadLongData(int,int)
//d = mmuReadLongEven (a, supervisor)
// リードロング(偶数)
public static int mmuReadLongEven (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateReadSuperData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateReadSuperData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateReadUserData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateReadUserData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
}
}
} //mmuReadLongEven(int,int)
//d = mmuReadLongExword (a, supervisor)
// リードロング(拡張ワード)
public static int mmuReadLongExword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_CODE;
int a0 = mmuTranslateReadSuperData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else { //4の倍数+2
int a2 = mmuTranslateReadSuperData (a + 2); //偶数
return ((DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0) << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_CODE;
int a0 = mmuTranslateReadUserData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else { //4の倍数+2
int a2 = mmuTranslateReadUserData (a + 2); //偶数
return ((DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0) << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
}
}
} //mmuReadLongExword(int,int)
//d = mmuReadLongFour (a, supervisor)
// リードロング(4の倍数)
public static int mmuReadLongFour (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateReadSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRls (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
a = mmuTranslateReadUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRls (a);
}
} //mmuReadLongFour(int,int)
//l = mmuReadQuadData (a, supervisor)
// リードクワッド(データ)
public static long mmuReadQuadData (int a, int supervisor) throws M68kException {
long d;
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateReadSuperData (a);
if ((a & 3) == 0) { //4n
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 4);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
} else if ((a & 1) == 0) { //4n+2
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRws (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 2);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 6);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
} else if ((a & 3) == 1) { //4n+1
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 1);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 3);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
} else { // //4n+3
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 1);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 5);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
}
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateReadUserData (a);
if ((a & 3) == 0) { //4n
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 4);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
} else if ((a & 1) == 0) { //4n+2
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRws (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 2);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 6);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
} else if ((a & 3) == 1) { //4n+1
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 1);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 3);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
} else { // //4n+3
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 1);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 5);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
}
}
return d;
} //mmuReadQuadData(int,int)
//l = mmuReadQuadSecond (a, supervisor)
// リードクワッド(2番目)
// エクステンデッドとラインの2番目で使う
public static long mmuReadQuadSecond (int a, int supervisor) throws M68kException {
long d;
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateReadSuperData (a);
if ((a & 3) == 0) { //4n
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 4);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
} else if ((a & 1) == 0) { //4n+2
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRws (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 2);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 6);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
} else if ((a & 3) == 1) { //4n+1
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 1);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 3);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
} else { // //4n+3
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 1);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 5);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateReadSuperData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
}
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateReadUserData (a);
if ((a & 3) == 0) { //4n
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 4);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
} else if ((a & 1) == 0) { //4n+2
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRws (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 2);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 6);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
} else if ((a & 3) == 1) { //4n+1
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 1);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 3);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
} else { // //4n+3
d = (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbs (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 1);
d = d << 32 | (0xffffffffL & (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRls (t));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 5);
d = d << 16 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRwz (t);
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateReadUserData (a + 7);
d = d << 8 | (long) map[t >>> XEiJ.BUS_PAGE_BITS].mmdRbz (t);
}
}
return d;
} //mmuReadQuadSecond(int,int)
//l = mmuReadQuadExword (a, supervisor)
// リードクワッド(拡張ワード)
// イミディエイトで使う
public static long mmuReadQuadExword (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_CODE;
int a0 = mmuTranslateReadSuperData (a); //a+2,a+4,a+6が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
int a4 = mmuTranslateReadSuperData (a + 4); //4の倍数
return ((long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0) << 32 |
(long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a4 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a4) & 0x00000000ffffffffL);
} else { //4の倍数+2
int a2 = mmuTranslateReadSuperData (a + 2); //4の倍数
int a6 = mmuTranslateReadSuperData (a + 6); //4の倍数
return ((long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0) << 48 |
(long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a2) << 16 & 0x0000ffffffff0000L |
(long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a6 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a6));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_EXWORD | M60_FSLW_RW_READ | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_CODE;
int a0 = mmuTranslateReadUserData (a); //a+2,a+4,a+6が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
int a4 = mmuTranslateReadUserData (a + 4); //4の倍数
return ((long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0) << 32 |
(long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a4 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a4) & 0x00000000ffffffffL);
} else { //4の倍数+2
int a2 = mmuTranslateReadUserData (a + 2); //4の倍数
int a6 = mmuTranslateReadUserData (a + 6); //4の倍数
return ((long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0) << 48 |
(long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a2) << 16 & 0x0000ffffffff0000L |
(long) (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a6 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a6));
}
}
} //mmuReadQuadExword(int,int)
//--------------------------------------------------------------------------------
//リードモディファイライトのリード
// アドレス変換はライト
// FSLWのRead and WriteはRead-Modify-Write
//d = mmuModifyByteSignData (a, supervisor)
// リードモディファイライトのリードバイト符号拡張(データ)
public static byte mmuModifyByteSignData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateWriteSuperData (a);
return (a ^ a0) == 1 ? -1 : (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateWriteUserData (a);
return (a ^ a0) == 1 ? -1 : (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
}
} //mmuModifyByteSignData(int,int)
//d = mmuModifyByteZeroData (a, supervisor)
// リードモディファイライトのリードバイトゼロ拡張(データ)
public static int mmuModifyByteZeroData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateWriteSuperData (a);
return (a ^ a0) == 1 ? 255 : (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateWriteUserData (a);
return (a ^ a0) == 1 ? 255 : (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
}
} //mmuModifyByteZeroData(int,int)
//d = mmuModifyWordSignData (a, supervisor)
// リードモディファイライトのリードワード符号拡張(データ)
public static int mmuModifyWordSignData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateWriteSuperData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateWriteSuperData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateWriteUserData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateWriteUserData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
}
} //mmuModifyWordSignData(int,int)
//d = mmuModifyWordZeroData (a, supervisor)
// リードモディファイライトのリードワードゼロ拡張(データ)
public static int mmuModifyWordZeroData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateWriteSuperData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateWriteSuperData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateWriteUserData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a0);
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateWriteUserData (a + 1); //偶数
return (d0 << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a1));
}
}
} //mmuModifyWordZeroData(int,int)
//d = mmuModifyWordSignEven (a, supervisor)
// リードモディファイライトのリードワード符号拡張(偶数)
public static int mmuModifyWordSignEven (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateWriteSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
a = mmuTranslateWriteUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
}
} //mmuModifyWordSignEven(int,int)
//d = mmuModifyWordZeroEven (a, supervisor)
// リードモディファイライトのリードワードゼロ拡張(偶数)
public static int mmuModifyWordZeroEven (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateWriteSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
a = mmuTranslateWriteUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
}
} //mmuModifyWordZeroEven(int,int)
//d = mmuModifyLongData (a, supervisor)
// リードモディファイライトのリードロング(データ)
public static int mmuModifyLongData (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateWriteSuperData (a); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else if ((a & 1) == 0) { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateWriteSuperData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateWriteSuperData (a + 1); //偶数
int a3 = mmuTranslateWriteSuperData (a + 3); //偶数
return (d0 << 24 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a1) << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a3 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a3));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateWriteUserData (a); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else if ((a & 1) == 0) { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateWriteUserData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
} else { //奇数
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a1 = mmuTranslateWriteUserData (a + 1); //偶数
int a3 = mmuTranslateWriteUserData (a + 3); //偶数
return (d0 << 24 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a1 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a1) << 8 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a3 >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a3));
}
}
} //mmuModifyLongData(int,int)
//d = mmuModifyLongEven (a, supervisor)
// リードモディファイライトのリードロング(偶数)
public static int mmuModifyLongEven (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
int a0 = mmuTranslateWriteSuperData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateWriteSuperData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
int a0 = mmuTranslateWriteUserData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRls (a0);
} else { //4の倍数+2
int d0 = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a0 >>> XEiJ.BUS_PAGE_BITS].mmdRws (a0);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
int a2 = mmuTranslateWriteUserData (a + 2); //偶数
return (d0 << 16 |
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a2 >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a2));
}
}
} //mmuModifyLongEven(int,int)
//d = mmuModifyLongFour (a, supervisor)
// リードモディファイライトのリードロング(4の倍数)
public static int mmuModifyLongFour (int a, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateWriteSuperData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRls (a);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_MODIFY | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
a = mmuTranslateWriteUserData (a);
return (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRls (a);
}
} //mmuModifyLongFour(int,int)
//--------------------------------------------------------------------------------
//ポーク
// デバッガ用
// エラーや副作用なしでライトする
//mmuPokeByte (a, x, f)
// ポークバイト
public static void mmuPokeByte (int a, int x, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //DFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
if ((a ^ a0) != 1) {
mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a0, x);
}
} else if (f != 7) { //DFC=0,3,4。アドレス変換なし
mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVb (a, x);
}
} //mmuPokeByte(int,int,int)
//mmuPokeByteData (a, d, supervisor)
// ポークバイト(データ)
public static void mmuPokeByteData (int a, int d, int supervisor) {
MemoryMappedDevice[] mm = supervisor != 0 ? DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap : DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int a0 = mmuTranslatePeek (a, supervisor, 0);
if ((a ^ a0) != 1) {
//mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVb (a0, d);
XEiJ.busVb (a0, d);
}
} //mmuPokeByteData(int,int,int)
//mmuPokeWord (a, x, f)
// ポークワード
public static void mmuPokeWord (int a, int x, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //DFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
if ((a & 1) == 0) { //偶数
if ((a ^ a0) != 1) {
mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdVw (a0, x);
}
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, f & 4, f & 2);
if ((a ^ a0) != 1) {
mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a0, x >> 8);
}
if ((a + 1 ^ a1) != 1) {
mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a1, x );
}
}
} else if (f != 7) { //DFC=0,3,4。アドレス変換なし
if ((a & 1) == 0) { //偶数
mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVw (a, x);
} else { //奇数
mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVb (a , x >> 8);
mm[a + 1 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a + 1, x );
}
}
} //mmuPokeWord(int,int,int)
//mmuPokeWordData (a, d, supervisor)
// ポークワード(データ)
public static void mmuPokeWordData (int a, int d, int supervisor) {
mmuPokeByteData (a, d >> 8, supervisor);
mmuPokeByteData (a + 1, d, supervisor);
} //mmuPokeWordData(int,int,int)
//mmuPokeLong (a, x, f)
// ポークロング
public static void mmuPokeLong (int a, int x, int f) {
f = f == -1 ? XEiJ.regSRS != 0 ? 5 : 1 : f & 7;
MemoryMappedDevice[] mm = (DataBreakPoint.DBP_ON ?
(f & 4) != 0 ? DataBreakPoint.dbpSuperMap : DataBreakPoint.dbpUserMap :
(f & 4) != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap);
// 01234567
if (0b01100110 << 24 << f < 0) { //DFC=1,2,5,6。アドレス変換あり
int a0 = mmuTranslatePeek (a, f & 4, f & 2);
if ((a & 3) == 0) { //4の倍数
if ((a ^ a0) != 1) {
mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdVl (a0, x);
}
} else if ((a & 1) == 0) { //4の倍数ではない偶数
int a2 = mmuTranslatePeek (a + 2, f & 4, f & 2);
if ((a ^ a0) != 1) {
mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdVw (a0, x >> 16);
}
if ((a + 2 ^ a2) != 1) {
mm[a2 >>> XEiJ.BUS_PAGE_BITS].mmdVw (a2, x);
}
} else { //奇数
int a1 = mmuTranslatePeek (a + 1, f & 4, f & 2);
int a3 = mmuTranslatePeek (a + 3, f & 4, f & 2);
if ((a ^ a0) != 1) {
mm[a0 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a0, x >> 24);
}
if ((a + 1 ^ a1) != 1) {
mm[a1 >>> XEiJ.BUS_PAGE_BITS].mmdVw (a1, x >> 8);
}
if ((a + 3 ^ a3) != 1) {
mm[a3 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a3, x);
}
}
} else if (f != 7) { //DFC=0,3,4。アドレス変換なし
if ((a & 3) == 0) { //4の倍数
mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVl (a, x);
} else if ((a & 1) == 0) { //4の倍数ではない偶数
mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVw (a , x >> 16);
mm[a + 2 >>> XEiJ.BUS_PAGE_BITS].mmdVw (a + 2, x );
} else { //奇数
mm[a >>> XEiJ.BUS_PAGE_BITS].mmdVb (a, x >> 24);
mm[a + 1 >>> XEiJ.BUS_PAGE_BITS].mmdVw (a + 1, x >> 8);
mm[a + 3 >>> XEiJ.BUS_PAGE_BITS].mmdVb (a + 3, x );
}
}
} //mmuPokeLong(int,int,int)
//mmuPokeLongData (a, d, supervisor)
// ポークロング(データ)
public static void mmuPokeLongData (int a, int d, int supervisor) {
mmuPokeByteData (a, d >> 24, supervisor);
mmuPokeByteData (a + 1, d >> 16, supervisor);
mmuPokeByteData (a + 2, d >> 8, supervisor);
mmuPokeByteData (a + 3, d, supervisor);
} //mmuPokeLongData(int,int,int)
//mmuPokeQuad (a, x, f)
// ポーククワッド
public static void mmuPokeQuad (int a, long x, int f) {
mmuPokeLong (a , (int) (x >> 32), f);
mmuPokeLong (a + 4, (int) x , f);
} //mmuPokeQuad(int,long,int)
//mmuPokeExtended (a, b, f)
public static void mmuPokeExtended (int a, byte[] b, int f) {
for (int i = 0; i < 12; i++) {
mmuPokeByte (a + i, b[i], f);
}
} //mmuPokeQuad(int,long,int)
//a = mmuPokeStringZ (a, str, f)
// ポークストリング
// 文字列をUTF-16からSJISに変換しながらメモリに書き込む
// 文字列に'\0'が含まれるときはその手前まで書き込む
// SJISに変換できない文字は'※'になる
// 最後に'\0'を書き込む
// '\0'を含まない書き込んだ文字列を返す
public static String mmuPokeStringZ (int a, String str, int f) {
StringBuilder sb = new StringBuilder ();
int l = str.length ();
for (int i = 0; i < l; i++) {
int u = str.charAt (i);
if (u == '\0') {
break;
}
int s = CharacterCode.chrCharToSJIS[u]; //SJISに変換する
if (s == 0) { //変換できない
s = 0x81a6; //'※'
}
if (s >> 8 != 0) {
mmuPokeByte (a++, s >> 8, f);
}
mmuPokeByte (a++, s, f);
u = CharacterCode.chrSJISToChar[s]; //UTF-16に変換する
if (u == 0) { //変換できない
u = 0xfffd;
}
sb.append ((char) u);
}
mmuPokeByte (a, 0, f); //'\0'
return sb.toString ();
} //mmuPokeStringZ(int,String,int)
//--------------------------------------------------------------------------------
//ライト
// アドレス変換はライト
// FSLWのRead and WriteはWrite
//mmuWriteByteData (a, d, supervisor)
// ライトバイト符号拡張(データ)
public static void mmuWriteByteData (int a, int d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateWriteSuperData (a);
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_BYTE | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateWriteUserData (a);
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d);
}
} //mmuWriteByteData(int,int,int)
//mmuWriteWordData (a, d, supervisor)
// ライトワード符号拡張(データ)
public static void mmuWriteWordData (int a, int d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateWriteSuperData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d);
} else { //奇数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d >> 8);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteSuperData (a + 1); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d);
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateWriteUserData (a); //a+1が必要なので上書き不可
if ((a & 1) == 0) { //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d);
} else { //奇数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d >> 8);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteUserData (a + 1); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d);
}
}
} //mmuWriteWordData(int,int,int)
//mmuWriteWordEven (a, d, supervisor)
// ライトワード符号拡張(偶数)
public static void mmuWriteWordEven (int a, int d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_WORD | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateWriteSuperData (a);
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, d);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_WORD | M60_FSLW_TM_USER_DATA;
a = mmuTranslateWriteUserData (a);
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, d);
}
} //mmuWriteWordEven(int,int,int)
//mmuWriteLongData (a, d, supervisor)
// ライトロング(データ)
public static void mmuWriteLongData (int a, int d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateWriteSuperData (a); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, d);
} else if ((a & 1) == 0) { //4の倍数+2
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d >> 16);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteSuperData (a + 2); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d);
} else { //奇数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d >> 24);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteSuperData (a + 1); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d >> 8);
t = mmuTranslateWriteSuperData (a + 3); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d);
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateWriteUserData (a); //a+1,a+2,a+3が必要なので上書き不可
if ((a & 3) == 0) { //4の倍数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, d);
} else if ((a & 1) == 0) { //4の倍数+2
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d >> 16);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteUserData (a + 2); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d);
} else { //奇数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d >> 24);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteUserData (a + 1); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d >> 8);
t = mmuTranslateWriteUserData (a + 3); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, d);
}
}
} //mmuWriteLongData(int,int,int)
//mmuWriteLongEven (a, d, supervisor)
// ライトロング(偶数)
public static void mmuWriteLongEven (int a, int d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateWriteSuperData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, d);
} else { //4の倍数+2
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d >> 16);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteSuperData (a + 2); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d);
}
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateWriteUserData (a); //a+2が必要なので上書き不可
if ((a & 2) == 0) { //4の倍数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, d);
} else { //4の倍数+2
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d >> 16);
m60FSLW ^= M60_FSLW_IOMA_FIRST ^ M60_FSLW_IOMA_SECOND;
t = mmuTranslateWriteUserData (a + 2); //偶数
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, d);
}
}
} //mmuWriteLongEven(int,int,int)
//mmuWriteLongFour (a, d, supervisor)
// ライトロング(4の倍数)
public static void mmuWriteLongFour (int a, int d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_LONG | M60_FSLW_TM_SUPER_DATA;
a = mmuTranslateWriteSuperData (a);
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWl (a, d);
} else { //ユーザモード
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_LONG | M60_FSLW_TM_USER_DATA;
a = mmuTranslateWriteUserData (a);
(DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWl (a, d);
}
} //mmuWriteLongFour(int,int,int)
//mmuWriteQuadData (a, d, supervisor)
// ライトクワッド(データ)
public static void mmuWriteQuadData (int a, long d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateWriteSuperData (a);
if ((a & 3) == 0) { //4n
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 32));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 4);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) d);
} else if ((a & 1) == 0) { //4n+2
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 48));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 2);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 16));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 6);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) d);
} else if ((a & 3) == 1) { //4n+1
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 40));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 3);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
} else { //4n+3
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 24));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 5);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
}
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateWriteUserData (a);
if ((a & 3) == 0) { //4n
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 32));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 4);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) d);
} else if ((a & 1) == 0) { //4n+2
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 48));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 2);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 16));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 6);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) d);
} else if ((a & 3) == 1) { //4n+1
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 40));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 3);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
} else { //4n+3
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 24));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 5);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
}
}
} //mmuWriteQuadData(int,long,int)
//mmuWriteQuadSecond (a, d, supervisor)
// ライトクワッド(2番目)
// エクステンデッドとラインの2番目で使う
public static void mmuWriteQuadSecond (int a, long d, int supervisor) throws M68kException {
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
int t = mmuTranslateWriteSuperData (a);
if ((a & 3) == 0) { //4n
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 32));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 4);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) d);
} else if ((a & 1) == 0) { //4n+2
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 48));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 2);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 16));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 6);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) d);
} else if ((a & 3) == 1) { //4n+1
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 40));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 3);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
} else { //4n+3
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 24));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 5);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_SUPER_DATA;
t = mmuTranslateWriteSuperData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
}
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
int t = mmuTranslateWriteUserData (a);
if ((a & 3) == 0) { //4n
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 32));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 4);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) d);
} else if ((a & 1) == 0) { //4n+2
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 48));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 2);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 16));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 6);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) d);
} else if ((a & 3) == 1) { //4n+1
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 40));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 3);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
} else { //4n+3
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) (d >> 56));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 1);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWl (t, (int) (d >> 24));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 5);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWw (t, (int) (d >> 8));
m60FSLW = M60_FSLW_IOMA_SECOND | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_QUAD | M60_FSLW_TM_USER_DATA;
t = mmuTranslateWriteUserData (a + 7);
map[t >>> XEiJ.BUS_PAGE_BITS].mmdWb (t, (int) d);
}
}
} //mmuWriteQuadSecond(int,int,int)
//mmuReadByteArray (address, array, offset, length, supervisor)
// リードバイト配列。先頭から読み出す
// address 先頭アドレス
// array バイト配列
// offset 先頭オフセット
// length バイト数
public static void mmuReadByteArray (int address, byte[] array, int offset, int length, int supervisor) throws M68kException {
if (false) { //1バイトずつmmuReadByteSignDataを呼び出す
for (int index = 0; index < length; index++) {
array[offset + index] = mmuReadByteSignData (address + index, supervisor);
}
} else {
// 変換後アドレスは0
// デバイスはnull
// while 残りが1バイト以上
// if ページの先頭
// デバイスはnull
// if アドレスが4nかつ残りが4バイト以上
// FSLWはリードロング
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// リードロング
// elif アドレスが2nかつ残りが2バイト以上
// FSLWはリードワード
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// リードワード
// else
// FSLWはリードバイト
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// リードバイト
// endwhile
length += offset; //lengthはoffsetの上限
final int mask = Math.min (XEiJ.BUS_PAGE_SIZE, mmuPageSize) - 1;
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
int translated = 0; //変換後アドレスは0
MemoryMappedDevice device = null; //デバイスはnull
while (offset < length) { //残りが1バイト以上
if ((address & mask) == 0) { //ページの先頭
device = null; //デバイスはnull
}
if ((address & 3) == 0 && offset + 4 <= length) { //アドレスが4nかつ残りが4バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_READ |
M60_FSLW_SIZE_LONG |
M60_FSLW_TM_SUPER_DATA); //FSLWはリードロング
if (device == null) { //デバイスがnull
translated = mmuTranslateReadSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
int data = device.mmdRls (translated); //リードロング
array[offset] = (byte) (data >> 24);
array[offset + 1] = (byte) (data >> 16);
array[offset + 2] = (byte) (data >> 8);
array[offset + 3] = (byte) data;
address += 4;
translated += 4;
offset += 4;
} else if ((address & 1) == 0 && offset + 2 <= length) { //アドレスが2nかつ残りが2バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_READ |
M60_FSLW_SIZE_WORD |
M60_FSLW_TM_SUPER_DATA); //FSLWはリードワード
if (device == null) { //デバイスがnull
translated = mmuTranslateReadSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
int data = device.mmdRws (translated); //リードワード
array[offset] = (byte) (data >> 8);
array[offset + 1] = (byte) data;
address += 2;
translated += 2;
offset += 2;
} else {
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_READ |
M60_FSLW_SIZE_BYTE |
M60_FSLW_TM_SUPER_DATA); //FSLWはリードバイト
if (device == null) { //デバイスがnull
translated = mmuTranslateReadSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
array[offset] = device.mmdRbs (translated); //リードバイト
address++;
translated++;
offset++;
}
} //while
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int translated = 0; //変換後アドレスは0
MemoryMappedDevice device = null; //デバイスはnull
while (offset < length) { //残りが1バイト以上
if ((address & mask) == 0) { //ページの先頭
device = null; //デバイスはnull
}
if ((address & 3) == 0 && offset + 4 <= length) { //アドレスが4nかつ残りが4バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_READ |
M60_FSLW_SIZE_LONG |
M60_FSLW_TM_USER_DATA); //FSLWはリードロング
if (device == null) { //デバイスがnull
translated = mmuTranslateReadUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
int data = device.mmdRls (translated); //リードロング
array[offset] = (byte) (data >> 24);
array[offset + 1] = (byte) (data >> 16);
array[offset + 2] = (byte) (data >> 8);
array[offset + 3] = (byte) data;
address += 4;
translated += 4;
offset += 4;
} else if ((address & 1) == 0 && offset + 2 <= length) { //アドレスが2nかつ残りが2バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_READ |
M60_FSLW_SIZE_WORD |
M60_FSLW_TM_USER_DATA); //FSLWはリードワード
if (device == null) { //デバイスがnull
translated = mmuTranslateReadUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
int data = device.mmdRws (translated); //リードワード
array[offset] = (byte) (data >> 8);
array[offset + 1] = (byte) data;
address += 2;
translated += 2;
offset += 2;
} else {
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_READ |
M60_FSLW_SIZE_BYTE |
M60_FSLW_TM_USER_DATA); //FSLWはリードバイト
if (device == null) { //デバイスがnull
translated = mmuTranslateReadUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
array[offset] = device.mmdRbs (translated); //リードバイト
address++;
translated++;
offset++;
}
} //while
}
}
} //mmuReadByteArray
//mmuWriteByteArray (address, array, offset, length, supervisor)
// ライトバイト配列。先頭から書き込む
// address 先頭アドレス
// array バイト配列
// offset 先頭オフセット
// length バイト数
public static void mmuWriteByteArray (int address, byte[] array, int offset, int length, int supervisor) throws M68kException {
if (false) { //1バイトずつmmuWriteByteDataを呼び出す
for (int index = 0; index < length; index++) {
mmuWriteByteData (address + index, array[offset + index], supervisor);
}
} else {
// 変換後アドレスは0
// デバイスはnull
// while 残りが1バイト以上
// if ページの先頭
// デバイスはnull
// if アドレスが4nかつ残りが4バイト以上
// FSLWはライトロング
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// ライトロング
// elif アドレスが2nかつ残りが2バイト以上
// FSLWはライトワード
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// ライトワード
// else
// FSLWはライトバイト
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// ライトバイト
// endwhile
length += offset; //lengthはoffsetの上限
final int mask = Math.min (XEiJ.BUS_PAGE_SIZE, mmuPageSize) - 1;
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
int translated = 0; //変換後アドレスは0
MemoryMappedDevice device = null; //デバイスはnull
while (offset < length) { //残りが1バイト以上
if ((address & mask) == 0) { //ページの先頭
device = null; //デバイスはnull
}
if ((address & 3) == 0 && offset + 4 <= length) { //アドレスが4nかつ残りが4バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_LONG |
M60_FSLW_TM_SUPER_DATA); //FSLWはライトロング
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWl (translated,
array[offset] << 24 |
(0xff & array[offset + 1]) << 16 |
(0xff & array[offset + 2]) << 8 |
(0xff & array[offset + 3])); //ライトロング
address += 4;
translated += 4;
offset += 4;
} else if ((address & 1) == 0 && offset + 2 <= length) { //アドレスが2nかつ残りが2バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_WORD |
M60_FSLW_TM_SUPER_DATA); //FSLWはライトワード
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWw (translated,
array[offset] << 8 |
(0xff & array[offset + 1])); //ライトワード
address += 2;
translated += 2;
offset += 2;
} else {
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_BYTE |
M60_FSLW_TM_SUPER_DATA); //FSLWはライトバイト
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWb (translated, array[offset]); //ライトバイト
address++;
translated++;
offset++;
}
} //while
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int translated = 0; //変換後アドレスは0
MemoryMappedDevice device = null; //デバイスはnull
while (offset < length) { //残りが1バイト以上
if ((address & mask) == 0) { //ページの先頭
device = null; //デバイスはnull
}
if ((address & 3) == 0 && offset + 4 <= length) { //アドレスが4nかつ残りが4バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_LONG |
M60_FSLW_TM_USER_DATA); //FSLWはライトロング
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWl (translated,
array[offset] << 24 |
(0xff & array[offset + 1]) << 16 |
(0xff & array[offset + 2]) << 8 |
(0xff & array[offset + 3])); //ライトロング
address += 4;
translated += 4;
offset += 4;
} else if ((address & 1) == 0 && offset + 2 <= length) { //アドレスが2nかつ残りが2バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_WORD |
M60_FSLW_TM_USER_DATA); //FSLWはライトワード
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWw (translated,
array[offset] << 8 |
(0xff & array[offset + 1])); //ライトワード
address += 2;
translated += 2;
offset += 2;
} else {
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_BYTE |
M60_FSLW_TM_USER_DATA); //FSLWはライトバイト
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWb (translated, array[offset]); //ライトバイト
address++;
translated++;
offset++;
}
} //while
}
}
} //mmuWriteByteArray
//mmuWriteByteArrayDecrement (address, array, offset, length, supervisor)
// ライトバイト配列デクリメント。末尾から書き込む
// address 先頭アドレス
// array バイト配列
// offset 先頭オフセット
// length バイト数
public static void mmuWriteByteArrayDecrement (int address, byte[] array, int offset, int length, int supervisor) throws M68kException {
if (false) { //1バイトずつmmuWriteByteDataを呼び出す
for (int index = length - 1; 0 <= index; index--) {
mmuWriteByteData (address + index, array[offset + index], supervisor);
}
} else {
// 変換後アドレスは0
// デバイスはnull
// while 残りが1バイト以上
// if ページの先頭
// デバイスはnull
// if アドレスが4nかつ残りが4バイト以上
// FSLWはライトロング
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// ライトロング
// elif アドレスが2nかつ残りが2バイト以上
// FSLWはライトワード
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// ライトワード
// else
// FSLWはライトバイト
// if デバイスがnull
// 変換後アドレスを求める
// デバイスを求める
// ライトバイト
// endwhile
address += length; //addressはaddressの上限
offset += length; //offsetはoffsetの上限
length = offset - length; //lengthはoffsetの下限
final int mask = Math.min (XEiJ.BUS_PAGE_SIZE, mmuPageSize) - 1;
if (supervisor != 0) { //スーパーバイザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap;
int translated = 0; //変換後アドレスは0
MemoryMappedDevice device = null; //デバイスはnull
while (length < offset) { //残りが1バイト以上
if ((address & mask) == 0) { //ページの先頭
device = null; //デバイスはnull
}
if ((address & 3) == 0 && length <= offset - 4) { //アドレスが4nかつ残りが4バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_LONG |
M60_FSLW_TM_SUPER_DATA); //FSLWはライトロング
address -= 4;
translated -= 4;
offset -= 4;
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWl (translated,
array[offset] << 24 |
(0xff & array[offset + 1]) << 16 |
(0xff & array[offset + 2]) << 8 |
(0xff & array[offset + 3])); //ライトロング
} else if ((address & 1) == 0 && length <= offset - 2) { //アドレスが2nかつ残りが2バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_WORD |
M60_FSLW_TM_SUPER_DATA); //FSLWはライトワード
address -= 2;
translated -= 2;
offset -= 2;
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWw (translated,
array[offset] << 8 |
(0xff & array[offset + 1])); //ライトワード
} else {
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_BYTE |
M60_FSLW_TM_SUPER_DATA); //FSLWはライトバイト
address--;
translated--;
offset--;
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteSuperData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWb (translated, array[offset]); //ライトバイト
}
} //while
} else { //ユーザモード
final MemoryMappedDevice[] map = DataBreakPoint.DBP_ON ? DataBreakPoint.dbpUserMap : XEiJ.busUserMap;
int translated = 0; //変換後アドレスは0
MemoryMappedDevice device = null; //デバイスはnull
while (length < offset) { //残りが1バイト以上
if ((address & mask) == 0) { //ページの先頭
device = null; //デバイスはnull
}
if ((address & 3) == 0 && length <= offset - 4) { //アドレスが4nかつ残りが4バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_LONG |
M60_FSLW_TM_USER_DATA); //FSLWはライトロング
address -= 4;
translated -= 4;
offset -= 4;
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWl (translated,
array[offset] << 24 |
(0xff & array[offset + 1]) << 16 |
(0xff & array[offset + 2]) << 8 |
(0xff & array[offset + 3])); //ライトロング
} else if ((address & 1) == 0 && length <= offset - 2) { //アドレスが2nかつ残りが2バイト以上
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_WORD |
M60_FSLW_TM_USER_DATA); //FSLWはライトワード
address -= 2;
translated -= 2;
offset -= 2;
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWw (translated,
array[offset] << 8 |
(0xff & array[offset + 1])); //ライトワード
} else {
m60FSLW = (M60_FSLW_IOMA_FIRST |
M60_FSLW_RW_WRITE |
M60_FSLW_SIZE_BYTE |
M60_FSLW_TM_USER_DATA); //FSLWはライトバイト
address--;
translated--;
offset--;
if (device == null) { //デバイスがnull
translated = mmuTranslateWriteUserData (address); //変換後アドレスを求める
device = map[translated >>> XEiJ.BUS_PAGE_BITS]; //デバイスを求める
}
device.mmdWb (translated, array[offset]); //ライトバイト
}
} //while
}
}
} //mmuWriteByteArrayDecrement
//--------------------------------------------------------------------------------
//アドレス変換
//pa = mmuLoadPhysicalAddressRead (a)
// PLPAR (An)
// DFCに従って論理アドレスを物理アドレスに変換する(リードアクセス)
// DFC 1=ユーザデータ,2=ユーザ命令,5=スーパーバイザデータ,6=スーパーバイザ命令
// pa 物理アドレス
// a 論理アドレス
public static int mmuLoadPhysicalAddressRead (int a) throws M68kException {
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_READ | M60_FSLW_SIZE_BYTE | XEiJ.mpuDFC << 16;
return ((0b10011111 << 24 << XEiJ.mpuDFC) < 0 ?
(0b00101010 << 24 << XEiJ.mpuDFC) < 0 ? mmuTranslateReadSuperCode (a) : mmuTranslateReadSuperData (a) :
(0b00101010 << 24 << XEiJ.mpuDFC) < 0 ? mmuTranslateReadUserCode (a) : mmuTranslateReadUserData (a));
} //mmuLoadPhysicalAddressRead(int)
//pa = mmuLoadPhysicalAddressWrite (a)
// PLPAW (An)
// DFCに従って論理アドレスを物理アドレスに変換する(ライトアクセス)
// DFC 1=ユーザデータ,2=ユーザ命令,5=スーパーバイザデータ,6=スーパーバイザ命令
// pa 物理アドレス
// a 論理アドレス
public static int mmuLoadPhysicalAddressWrite (int a) throws M68kException {
m60FSLW = M60_FSLW_IOMA_FIRST | M60_FSLW_RW_WRITE | M60_FSLW_SIZE_BYTE | XEiJ.mpuDFC << 16;
return ((0b10011111 << 24 << XEiJ.mpuDFC) < 0 ?
(0b00101010 << 24 << XEiJ.mpuDFC) < 0 ? mmuTranslateWriteSuperCode (a) : mmuTranslateWriteSuperData (a) :
(0b00101010 << 24 << XEiJ.mpuDFC) < 0 ? mmuTranslateWriteUserCode (a) : mmuTranslateWriteUserData (a));
} //mmuLoadPhysicalAddressWrite(int)
//pa = mmuTranslateReadUserData (a)
// アドレス変換を行う(リードユーザデータ)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateReadUserData (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuUserDataCache[head] == logicalPage) { //リード用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuUserDataCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuUserDataCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuUserDataCache[i] == logicalPage) { //リード用の論理ページアドレスと一致した
//int logicalRead = mmuUserDataCache[i ];
int logicalWrite = mmuUserDataCache[i + 1];
int physicalPage = mmuUserDataCache[i + 2];
int flag = mmuUserDataCache[i + 3];
for (; i > head; i -= 4) {
mmuUserDataCache[i ] = mmuUserDataCache[i - 4];
mmuUserDataCache[i + 1] = mmuUserDataCache[i - 3];
mmuUserDataCache[i + 2] = mmuUserDataCache[i - 2];
mmuUserDataCache[i + 3] = mmuUserDataCache[i - 1];
}
mmuUserDataCache[i ] = logicalPage; //logicalRead
mmuUserDataCache[i + 1] = logicalWrite;
mmuUserDataCache[i + 2] = physicalPage;
mmuUserDataCache[i + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, false, false, false);
} //mmuTranslateReadUserData(int)
//pa = mmuTranslateReadUserCode (a)
// アドレス変換を行う(リードユーザコード)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateReadUserCode (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuUserCodeCache[head] == logicalPage) { //リード用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuUserCodeCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuUserCodeCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuUserCodeCache[i] == logicalPage) { //リード用の論理ページアドレスと一致した
//int logicalRead = mmuUserCodeCache[i ];
int logicalWrite = mmuUserCodeCache[i + 1];
int physicalPage = mmuUserCodeCache[i + 2];
int flag = mmuUserCodeCache[i + 3];
for (; i > head; i -= 4) {
mmuUserCodeCache[i ] = mmuUserCodeCache[i - 4];
mmuUserCodeCache[i + 1] = mmuUserCodeCache[i - 3];
mmuUserCodeCache[i + 2] = mmuUserCodeCache[i - 2];
mmuUserCodeCache[i + 3] = mmuUserCodeCache[i - 1];
}
mmuUserCodeCache[head ] = logicalPage; //logicalRead
mmuUserCodeCache[head + 1] = logicalWrite;
mmuUserCodeCache[head + 2] = physicalPage;
mmuUserCodeCache[head + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, false, false, true);
} //mmuTranslateReadUserCode(int)
//pa = mmuTranslateReadSuperData (a)
// アドレス変換を行う(リードスーパーバイザデータ)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateReadSuperData (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuSuperDataCache[head] == logicalPage) { //リード用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuSuperDataCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuSuperDataCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuSuperDataCache[i] == logicalPage) { //リード用の論理ページアドレスと一致した
//int logicalRead = mmuSuperDataCache[i ];
int logicalWrite = mmuSuperDataCache[i + 1];
int physicalPage = mmuSuperDataCache[i + 2];
int flag = mmuSuperDataCache[i + 3];
for (; i > head; i -= 4) {
mmuSuperDataCache[i ] = mmuSuperDataCache[i - 4];
mmuSuperDataCache[i + 1] = mmuSuperDataCache[i - 3];
mmuSuperDataCache[i + 2] = mmuSuperDataCache[i - 2];
mmuSuperDataCache[i + 3] = mmuSuperDataCache[i - 1];
}
mmuSuperDataCache[i ] = logicalPage; //logicalRead
mmuSuperDataCache[i + 1] = logicalWrite;
mmuSuperDataCache[i + 2] = physicalPage;
mmuSuperDataCache[i + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, false, true, false);
} //mmuTranslateReadSuperData(int)
//pa = mmuTranslateReadSuperCode (a)
// アドレス変換を行う(リードスーパーバイザコード)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateReadSuperCode (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuSuperCodeCache[head] == logicalPage) { //リード用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuSuperCodeCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuSuperCodeCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuSuperCodeCache[i] == logicalPage) { //リード用の論理ページアドレスと一致した
//int logicalRead = mmuSuperCodeCache[i ];
int logicalWrite = mmuSuperCodeCache[i + 1];
int physicalPage = mmuSuperCodeCache[i + 2];
int flag = mmuSuperCodeCache[i + 3];
for (; i > head; i -= 4) {
mmuSuperCodeCache[i ] = mmuSuperCodeCache[i - 4];
mmuSuperCodeCache[i + 1] = mmuSuperCodeCache[i - 3];
mmuSuperCodeCache[i + 2] = mmuSuperCodeCache[i - 2];
mmuSuperCodeCache[i + 3] = mmuSuperCodeCache[i - 1];
}
mmuSuperCodeCache[head ] = logicalPage; //logicalRead
mmuSuperCodeCache[head + 1] = logicalWrite;
mmuSuperCodeCache[head + 2] = physicalPage;
mmuSuperCodeCache[head + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, false, true, true);
} //mmuTranslateReadSuperCode(int)
//pa = mmuTranslateWriteUserData (a)
// アドレス変換を行う(ライトユーザデータ)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateWriteUserData (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuUserDataCache[head + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuUserDataCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuUserDataCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuUserDataCache[i + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
int logicalRead = mmuUserDataCache[i ];
//int logicalWrite = mmuUserDataCache[i + 1];
int physicalPage = mmuUserDataCache[i + 2];
int flag = mmuUserDataCache[i + 3];
for (; i > head; i -= 4) {
mmuUserDataCache[i ] = mmuUserDataCache[i - 4];
mmuUserDataCache[i + 1] = mmuUserDataCache[i - 3];
mmuUserDataCache[i + 2] = mmuUserDataCache[i - 2];
mmuUserDataCache[i + 3] = mmuUserDataCache[i - 1];
}
mmuUserDataCache[i ] = logicalRead;
mmuUserDataCache[i + 1] = logicalPage; //logicalWrite
mmuUserDataCache[i + 2] = physicalPage;
mmuUserDataCache[i + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, true, false, false);
} //mmuTranslateWriteUserData(int)
//pa = mmuTranslateWriteUserCode (a)
// アドレス変換を行う(ライトユーザコード)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateWriteUserCode (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuUserCodeCache[head + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuUserCodeCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuUserCodeCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuUserCodeCache[i + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
int logicalRead = mmuUserCodeCache[i ];
//int logicalWrite = mmuUserCodeCache[i + 1];
int physicalPage = mmuUserCodeCache[i + 2];
int flag = mmuUserCodeCache[i + 3];
for (; i > head; i -= 4) {
mmuUserCodeCache[i ] = mmuUserCodeCache[i - 4];
mmuUserCodeCache[i + 1] = mmuUserCodeCache[i - 3];
mmuUserCodeCache[i + 2] = mmuUserCodeCache[i - 2];
mmuUserCodeCache[i + 3] = mmuUserCodeCache[i - 1];
}
mmuUserCodeCache[head ] = logicalRead;
mmuUserCodeCache[head + 1] = logicalPage; //logicalWrite
mmuUserCodeCache[head + 2] = physicalPage;
mmuUserCodeCache[head + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, true, false, true);
} //mmuTranslateWriteUserCode(int)
//pa = mmuTranslateWriteSuperData (a)
// アドレス変換を行う(ライトスーパーバイザデータ)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateWriteSuperData (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuSuperDataCache[head + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuSuperDataCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuSuperDataCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuSuperDataCache[i + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
int logicalRead = mmuSuperDataCache[i ];
//int logicalWrite = mmuSuperDataCache[i + 1];
int physicalPage = mmuSuperDataCache[i + 2];
int flag = mmuSuperDataCache[i + 3];
for (; i > head; i -= 4) {
mmuSuperDataCache[i ] = mmuSuperDataCache[i - 4];
mmuSuperDataCache[i + 1] = mmuSuperDataCache[i - 3];
mmuSuperDataCache[i + 2] = mmuSuperDataCache[i - 2];
mmuSuperDataCache[i + 3] = mmuSuperDataCache[i - 1];
}
mmuSuperDataCache[i ] = logicalRead;
mmuSuperDataCache[i + 1] = logicalPage; //logicalWrite
mmuSuperDataCache[i + 2] = physicalPage;
mmuSuperDataCache[i + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, true, true, false);
} //mmuTranslateWriteSuperData(int)
//pa = mmuTranslateWriteSuperCode (a)
// アドレス変換を行う(ライトスーパーバイザコード)
// pa 物理アドレス
// a 論理アドレス
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateWriteSuperCode (int a) throws M68kException {
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (mmuSuperCodeCache[head + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
if (CAT_ON) {
catCM = (mmuSuperCodeCache[head + 3] >> 5) & 3; //キャッシュモード
}
return mmuSuperCodeCache[head + 2] | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
if (MMU_CACHE_WAYS >= 2) { //2ways以上
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ
for (int i = head + 4; i <= tail; i += 4) {
if (mmuSuperCodeCache[i + 1] == logicalPage) { //ライト用の論理ページアドレスと一致した
int logicalRead = mmuSuperCodeCache[i ];
//int logicalWrite = mmuSuperCodeCache[i + 1];
int physicalPage = mmuSuperCodeCache[i + 2];
int flag = mmuSuperCodeCache[i + 3];
for (; i > head; i -= 4) {
mmuSuperCodeCache[i ] = mmuSuperCodeCache[i - 4];
mmuSuperCodeCache[i + 1] = mmuSuperCodeCache[i - 3];
mmuSuperCodeCache[i + 2] = mmuSuperCodeCache[i - 2];
mmuSuperCodeCache[i + 3] = mmuSuperCodeCache[i - 1];
}
mmuSuperCodeCache[head ] = logicalRead;
mmuSuperCodeCache[head + 1] = logicalPage; //logicalWrite
mmuSuperCodeCache[head + 2] = physicalPage;
mmuSuperCodeCache[head + 3] = flag;
return physicalPage | (a & mmuPageOffsetMask); //物理ページアドレスとページオフセットを連結する
}
} //for i
}
return mmuTranslateCommon (a, true, true, true);
} //mmuTranslateWriteSuperCode(int)
//pa = mmuTranslateCommon (a, write, supervisor, instruction)
// 透過変換とテーブルサーチを行い、アドレス変換キャッシュ更新する
// アドレス変換キャッシュがミスしたときに呼び出す
// pa 物理アドレス
// a 論理アドレス
// write true=ライト,false=リード
// supervisor true=スーパーバイザ,false=ユーザ。通常はXEiJ.regSRS!=0、PLPAR/PLPAWでは(XEiJ.mpuDFC&4)!=0
// instruction true=命令,false=データ。通常は命令フェッチまたは拡張ワードのときtrue、PLPAR/PLPAWでは(XEiJ.mpuDFC&2)!=0
// m60FSLWのMA,RW,SIZE,TM,IOをセットしてから呼び出すこと
public static int mmuTranslateCommon (int a, boolean write, boolean supervisor, boolean instruction) throws M68kException {
if (MMU_DEBUG_TRANSLATION) {
System.out.printf ("%08x mmuTranslateCommon(0x%08x,%b,%b,%b)", XEiJ.regPC0, a, write, supervisor, instruction);
}
int logicalPage = a & mmuPageAddressMask; //リード用の論理ページアドレス
int logicalWrite; //ライト用の論理ページアドレス
int physicalPage; //物理ページアドレス
int flag; //フラグ。bit10:グローバル,bit6-5:キャッシュモード
int pa; //物理アドレス
//透過変換
// 透過変換はスーパーバイザモードかどうかを条件にすることができる(しないこともできる)
// 条件が合わなければヒットしないだけで、スーパーバイザプロテクトのアクセスフォルトになならない
// 透過変換をアドレス変換キャッシュに乗せる場合
// アドレス変換キャッシュがヒットしてバスエラーが発生したとき
// 透過変換かどうかを再確認してFSLWのTTRをセットしなければならない
// 透過変換レジスタが操作されたとき
// OFF→ONの領域だけでなくON→OFFの領域もフラッシュしなければならない
// 透過変換レジスタを頻繁に操作されると重くなるかも知れない
int tt = (supervisor ?
instruction ? mmuTTSuperCode1 : mmuTTSuperData1 :
instruction ? mmuTTUserCode1 : mmuTTUserData1)[a >>> 24];
if (tt != 0) { //透過変換あり
m60FSLW |= M60_FSLW_TRANSPARENT;
if (write && //ライトで
tt < 0) { //透過変換によるライトプロテクト
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" write protected by transparent translation\n", a);
}
m60FSLW |= M60_FSLW_WRITE_PROTECT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
logicalWrite = logicalPage; //ライト用の論理ページアドレス
physicalPage = logicalPage; //物理ページアドレス
flag = MMU_DESCRIPTOR_GLOBAL | (tt & MMU_TTR_CACHE_MODE); //グローバル、キャッシュモード
pa = a;
if (MMU_DEBUG_TRANSLATION) {
System.out.printf ("=0x%08x (transparent translation)\n", pa);
}
} else if (mmuEnabled) { //透過変換なし、アドレス変換あり
//テーブルサーチ
// スーパーバイザプロテクトまたはライトプロテクトで停止したときデスクリプタの使用済みフラグはセットされない
// リードモディファイライトはライトでアロケートするのでリードする前にライトプロテクトに引っかかる
// 例えばROMの内容をインクリメントしようとしたときライトだけでなくリードも行われない
m60FSLW |= M60_FSLW_TABLE_SEARCH; //これはbus error on table searchなのでそれ以外は消すこと
//TMを保存して書き換える
int xorTM = ((m60FSLW & M60_FSLW_TRANSFER_MODIFIER) ^
(instruction ? M60_FSLW_TM_MMU_CODE : M60_FSLW_TM_MMU_DATA));
m60FSLW ^= xorTM;
//ルートテーブル
int rootDescriptorAddress = (supervisor ? mmuSRP : mmuURP) + ((a & MMU_ROOT_INDEX_MASK) >>> MMU_ROOT_INDEX_BIT0 - 2); //ルートテーブルデスクリプタのアドレス
MemoryMappedDevice rootDescriptorDevice = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[rootDescriptorAddress >>> XEiJ.BUS_PAGE_BITS];
int rootDescriptor = rootDescriptorDevice.mmdRls (rootDescriptorAddress); //ルートテーブルデスクリプタ
if ((rootDescriptor & MMU_DESCRIPTOR_UDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" invalid root descriptor 0x%08x at 0x%08x\n", rootDescriptor, rootDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_ROOT_DESCRIPTOR;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if (write && //ライトで
(rootDescriptor & MMU_DESCRIPTOR_WRITE_PROTECTED) != 0) { //ライトプロテクトされているとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" write protected by root descriptor 0x%08x at 0x%08x\n", rootDescriptor, rootDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_WRITE_PROTECT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if ((rootDescriptor & MMU_DESCRIPTOR_USED) == 0) { //デスクリプタが未使用のとき
rootDescriptor |= MMU_DESCRIPTOR_USED; //使用済み
rootDescriptorDevice.mmdWl (rootDescriptorAddress, rootDescriptor);
}
//ポインタテーブル
int pointerDescriptorAddress = (rootDescriptor & MMU_DESCRIPTOR_POINTER_TABLE_ADDRESS) + ((a & MMU_POINTER_INDEX_MASK) >>> MMU_POINTER_INDEX_BIT0 - 2); //ポインタテーブルデスクリプタのアドレス
MemoryMappedDevice pointerDescriptorDevice = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[pointerDescriptorAddress >>> XEiJ.BUS_PAGE_BITS];
int pointerDescriptor = pointerDescriptorDevice.mmdRls (pointerDescriptorAddress); //ポインタテーブルデスクリプタ
if ((pointerDescriptor & MMU_DESCRIPTOR_UDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" invalid pointer descriptor 0x%08x at 0x%08x\n", pointerDescriptor, pointerDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_POINTER_DESCRIPTOR;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if (write && //ライトで
(pointerDescriptor & MMU_DESCRIPTOR_WRITE_PROTECTED) != 0) { //ライトプロテクトされているとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" write protected by pointer descriptor 0x%08x at 0x%08x\n", pointerDescriptor, pointerDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_WRITE_PROTECT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if ((pointerDescriptor & MMU_DESCRIPTOR_USED) == 0) { //デスクリプタが未使用のとき
pointerDescriptor |= MMU_DESCRIPTOR_USED; //使用済み
pointerDescriptorDevice.mmdWl (pointerDescriptorAddress, pointerDescriptor);
}
//ページテーブル
int pageDescriptorAddress = (pointerDescriptor & mmuPageTableMask) + ((a & mmuPageIndexMask) >>> mmuPageIndexBit2); //ページテーブルデスクリプタのアドレス
MemoryMappedDevice pageDescriptorDevice = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[pageDescriptorAddress >>> XEiJ.BUS_PAGE_BITS];
int pageDescriptor = pageDescriptorDevice.mmdRls (pageDescriptorAddress); //ページテーブルデスクリプタ
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" invalid page descriptor 0x%08x at 0x%08x\n", pageDescriptor, pageDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_PAGE_FAULT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INDIRECT) { //デスクリプタが間接のとき
pageDescriptorAddress = pageDescriptor & MMU_DESCRIPTOR_INDIRECT_ADDRESS; //ページテーブルデスクリプタのアドレス
pageDescriptorDevice = (DataBreakPoint.DBP_ON ? DataBreakPoint.dbpSuperMap : XEiJ.busSuperMap)[pageDescriptorAddress >>> XEiJ.BUS_PAGE_BITS];
pageDescriptor = pageDescriptorDevice.mmdRls (pageDescriptorAddress); //ページテーブルデスクリプタ
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" invalid page descriptor 0x%08x at 0x%08x\n", pageDescriptor, pageDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_PAGE_FAULT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INDIRECT) { //デスクリプタが二重間接のとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" indirect page descriptor 0x%08x at 0x%08x\n", pageDescriptor, pageDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_INDIRECT_LEVEL;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
}
if (!supervisor && //ユーザモードで
(pageDescriptor & MMU_DESCRIPTOR_SUPERVISOR_PROTECTED) != 0) { //スーパーバイザプロテクトされているとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" supervisor protected by page descriptor 0x%08x at 0x%08x\n", pageDescriptor, pageDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_SUPERVISOR_PROTECT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
if (write && //ライトで
(pageDescriptor & MMU_DESCRIPTOR_WRITE_PROTECTED) != 0) { //ライトプロテクトされているとき
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" write protected by page descriptor 0x%08x at 0x%08x\n", pageDescriptor, pageDescriptorAddress);
}
m60FSLW ^= M60_FSLW_TABLE_SEARCH ^ M60_FSLW_WRITE_PROTECT;
M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
//m60Address = a;
throw M68kException.m6eSignal;
}
{
int t = pageDescriptor;
if ((pageDescriptor & MMU_DESCRIPTOR_USED) == 0) { //デスクリプタが未使用のとき
pageDescriptor |= MMU_DESCRIPTOR_USED; //使用済みにする
}
if (write && //ライトで
(pageDescriptor & MMU_DESCRIPTOR_MODIFIED) == 0) { //修正済みでないとき
pageDescriptor |= MMU_DESCRIPTOR_MODIFIED; //修正済みにする
}
if (t != pageDescriptor) {
pageDescriptorDevice.mmdWl (pageDescriptorAddress, pageDescriptor);
}
}
//テーブルサーチ終了
m60FSLW &= ~M60_FSLW_TABLE_SEARCH;
//TMを復元する
m60FSLW ^= xorTM;
//logicalWrite = (pageDescriptor & (MMU_DESCRIPTOR_MODIFIED | MMU_DESCRIPTOR_WRITE_PROTECTED)) == MMU_DESCRIPTOR_MODIFIED ? logicalPage : 1; //ライト用の論理ページアドレス。修正済みかつライトプロテクトされていないときだけ有効
logicalWrite = (pageDescriptor & MMU_DESCRIPTOR_WRITE_PROTECTED) == 0 ? logicalPage : 1; //ライト用の論理ページアドレス。ライトプロテクトされていないときだけ有効
physicalPage = pageDescriptor & mmuPageAddressMask; //物理ページアドレス
flag = pageDescriptor & (MMU_DESCRIPTOR_GLOBAL | //グローバル
MMU_DESCRIPTOR_CACHE_MODE); //キャッシュモード
pa = physicalPage | a & mmuPageOffsetMask; //物理ページアドレスとページオフセットを連結する
if (MMU_DEBUG_TRANSLATION) {
System.out.printf ("=0x%08x (table search)\n", pa);
System.out.printf (" rootTable=0x%08x\n", supervisor ? mmuSRP : mmuURP);
System.out.printf (" rootIndex=0x%08x\n", (a & MMU_ROOT_INDEX_MASK) >>> MMU_ROOT_INDEX_BIT0);
System.out.printf (" rootDescriptorAddress=0x%08x\n", rootDescriptorAddress);
System.out.printf (" rootDescriptor=0x%08x\n", rootDescriptor);
System.out.printf (" pointerTable=0x%08x\n", rootDescriptor & MMU_DESCRIPTOR_POINTER_TABLE_ADDRESS);
System.out.printf (" pointerIndex=0x%08x\n", (a & MMU_POINTER_INDEX_MASK) >>> MMU_POINTER_INDEX_BIT0);
System.out.printf (" pointerDescriptorAddress=0x%08x\n", pointerDescriptorAddress);
System.out.printf (" pointerDescriptor=0x%08x\n", pointerDescriptor);
System.out.printf (" pageTable=0x%08x\n", pointerDescriptor & mmuPageTableMask);
System.out.printf (" pageIndex=0x%08x\n", (a & mmuPageIndexMask) >>> mmuPageIndexBit2 + 2);
System.out.printf (" pageDescriptorAddress=0x%08x\n", pageDescriptorAddress);
System.out.printf (" pageDescriptor=0x%08x\n", pageDescriptor);
}
} else { //透過変換なし、アドレス変換なし
logicalWrite = logicalPage; //ライト用の論理ページアドレス
physicalPage = logicalPage; //物理ページアドレス
flag = MMU_DESCRIPTOR_GLOBAL | ((mmuTCR >> (instruction ? 4 : 8)) & 3); //グローバル、デフォルトキャッシュモード。DCOまたはDCI
pa = a;
if (MMU_DEBUG_TRANSLATION) {
System.out.printf ("=0x%08x (no translation)\n", pa);
}
}
if (!(MMU_NOT_ALLOCATE_CACHE ||
(instruction ? mmuNotAllocateCode : mmuNotAllocateData))) {
//アドレス変換キャッシュを更新する
// 同じ論理ページアドレスのエントリが存在する場合
// (リードでアロケートしたとき修正済みでなかったためライトでアロケートしなかった場合)
// 同じ論理ページアドレスのエントリよりも前にあるエントリを後ろにずらす
// 空いた先頭のエントリに上書きする
// 同じ論理ページアドレスのエントリが存在しない場合
// 末尾以外のエントリを後ろにずらす
// 空いた先頭のエントリに上書きする
int[] cache = (supervisor ?
instruction ? mmuSuperCodeCache : mmuSuperDataCache :
instruction ? mmuUserCodeCache : mmuUserDataCache);
int head = (logicalPage * MMU_HASH_COEFF >>> -MMU_HASH_BITS) * (4 * MMU_CACHE_WAYS); //先頭のエントリ
if (MMU_CACHE_WAYS >= 2) { //2ways以上のとき
int tail = head + (4 * MMU_CACHE_WAYS - 4); //末尾のエントリ→捨てるエントリ
if (write) { //ライトのとき
for (int i = head; i < tail; i += 4) {
if (cache[i] == logicalPage) { //リードでアロケートされていた
tail = i;
break;
}
}
}
// 捨てるエントリよりも前にあるエントリを後ろにずらす
for (; tail > head; tail -= 4) {
cache[tail ] = cache[tail - 4];
cache[tail + 1] = cache[tail - 3];
cache[tail + 2] = cache[tail - 2];
cache[tail + 3] = cache[tail - 1];
}
}
// 先頭のエントリに上書きする
cache[head ] = logicalPage; //リード用の論理ページアドレス
cache[head + 1] = logicalWrite; //ライト用の論理ページアドレス
cache[head + 2] = physicalPage; //物理ページアドレス
cache[head + 3] = flag; //フラグ
if (MMU_DEBUG_TRANSLATION) {
System.out.printf (" ATC[%d]={0x%08x,0x%08x,0x%08x,0x%08x}\n",
head / (4 * MMU_CACHE_WAYS), logicalPage, logicalWrite, physicalPage, flag);
}
}
if (CAT_ON) {
catCM = (flag >> 5) & 3; //キャッシュモード
}
return pa;
} //mmuTranslateCommon(int,boolean,boolean,boolean)
public static int mmuPeekFlags;
//pa = mmuTranslatePeek (a, supervisor, instruction) {
// アドレス変換を行う(デバッガ用、例外なし、テーブル更新なし)
// pa 物理アドレス。a^1=エラー
// a 論理アドレス
// supervisor 0=ユーザ,0以外=スーパーバイザ。通常はXEiJ.regSRS、PLPAR/PLPAWではXEiJ.mpuDFC&4
// instruction 0=データ,0以外=命令。通常は命令フェッチまたは拡張ワードのとき1、PLPAR/PLPAWではXEiJ.mpuDFC&2
public static int mmuTranslatePeek (int a, int supervisor, int instruction) {
//透過変換の確認
// 透過変換はスーパーバイザモードかどうかを条件にすることができる(しないこともできる)
// 透過変換にスーパーバイザプロテクトの機能はない
{
int[] tta = new int[2];
if (instruction != 0) {
tta[0] = mmuITT0;
tta[1] = mmuITT1;
} else {
tta[0] = mmuDTT0;
tta[1] = mmuDTT1;
}
for (int i = 0; i < 2; i++) {
int ttr = tta[i];
if ((ttr & 0x8000) != 0 && //Enable
((ttr & 0x4000) != 0 || ((ttr & 0x2000) != 0) == (supervisor != 0)) &&
((a ^ ttr) & ~ttr << 8) >>> 24 == 0) {
mmuPeekFlags = ttr & MMU_TTR_WRITE_PROTECT;
return a;
}
}
}
//透過変換なし
if (!mmuEnabled) { //アドレス変換なし
mmuPeekFlags = 0;
return a;
}
//アドレス変換あり
int logicalPage = a & mmuPageAddressMask; //論理ページアドレス
//テーブルサーチ開始
// スーパーバイザプロテクトまたはライトプロテクトで停止したときデスクリプタの使用済みフラグはセットされない
// リードモディファイライトはライトでアロケートするのでリードする前にライトプロテクトに引っかかる
// 例えばROMの内容をインクリメントしようとしたときライトだけでなくリードも行われない
//ルートテーブル
int rootDescriptorAddress = (supervisor != 0 ? mmuSRP : mmuURP) + ((a & MMU_ROOT_INDEX_MASK) >>> MMU_ROOT_INDEX_BIT0 - 2); //ルートテーブルデスクリプタのアドレス
int rootDescriptor = XEiJ.busPlsf (rootDescriptorAddress); //ルートテーブルデスクリプタ
if ((rootDescriptor & MMU_DESCRIPTOR_UDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
return a ^ 1;
}
//ポインタテーブル
int pointerDescriptorAddress = (rootDescriptor & MMU_DESCRIPTOR_POINTER_TABLE_ADDRESS) + ((a & MMU_POINTER_INDEX_MASK) >>> MMU_POINTER_INDEX_BIT0 - 2); //ポインタテーブルデスクリプタのアドレス
int pointerDescriptor = XEiJ.busPlsf (pointerDescriptorAddress); //ポインタテーブルデスクリプタ
if ((pointerDescriptor & MMU_DESCRIPTOR_UDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
return a ^ 1;
}
//ページテーブル
int pageDescriptorAddress = (pointerDescriptor & mmuPageTableMask) + ((a & mmuPageIndexMask) >>> mmuPageIndexBit2); //ページテーブルデスクリプタのアドレス
int pageDescriptor = XEiJ.busPlsf (pageDescriptorAddress); //ページテーブルデスクリプタ
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
return a ^ 1;
}
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INDIRECT) { //デスクリプタが間接のとき
pageDescriptorAddress = pageDescriptor & MMU_DESCRIPTOR_INDIRECT_ADDRESS; //ページテーブルデスクリプタのアドレス
pageDescriptor = XEiJ.busPlsf (pageDescriptorAddress); //ページテーブルデスクリプタ
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INVALID) { //デスクリプタが無効のとき
return a ^ 1;
}
if ((pageDescriptor & MMU_DESCRIPTOR_PDT) == MMU_DESCRIPTOR_TYPE_INDIRECT) { //デスクリプタが二重間接のとき
return a ^ 1;
}
}
if (supervisor == 0 && //ユーザモードで
(pageDescriptor & MMU_DESCRIPTOR_SUPERVISOR_PROTECTED) != 0) { //スーパーバイザプロテクトされているとき
return a ^ 1;
}
int physicalPage = pageDescriptor & mmuPageAddressMask; //物理ページアドレス
//テーブルサーチ終了
mmuPeekFlags = pageDescriptor & (MMU_DESCRIPTOR_SUPERVISOR_PROTECTED |
MMU_DESCRIPTOR_MODIFIED |
MMU_DESCRIPTOR_USED |
MMU_DESCRIPTOR_WRITE_PROTECTED);
return physicalPage | a & mmuPageOffsetMask; //物理ページアドレスとページオフセットを連結する
} //mmuTranslatePeek(int,int,int)
//実効アドレス
// FIRSTのアドレス
// SECONDでアクセスフォルトが発生した場合でも、FORMAT $4の例外スタックフレームにはFIRSTのアドレスが書き込まれる
// M68kException.m6eAddressは実際にバスエラーが発生したアドレスを示しており、これはSECONDの場合がある
private static int m60Address;
// MC68060のページフォルトに関する考察
// ページフォルトが発生すると、プレデクリメントとポストインクリメントによるアドレスレジスタの変化がすべてキャンセルされる
// MOVE.B (A0)+,(A0)+またはMOVE.B -(A0),-(A0)でソースまたはデスティネーションでページフォルトが発生したとき、
// どの組み合わせでもA0は命令開始時の値のままアクセスフォルトハンドラに移行する
// RTEでページフォルトを発生させた命令に復帰すると、ソースをリードするところからやり直す
// MOVE.B <mem>,<mem>のデスティネーションのライトでページフォルトが発生したとき、ソースのリードが2回行われる
// これはMC68060ユーザーズマニュアルの7.10 BUS SYNCHRONIZATIONに書かれており、
// 060turboでも、ページフォルトのハンドラでソースを書き換えると結果に反映されることから、リードが再実行されていることを確認できる
// リードすると値が変化する可能性のあるデバイスから非常駐の可能性のあるページに転送するとき、MOVE.B <mem>,<mem>を使ってはいけない
//アドレスレジスタの増分
// 実効アドレスの計算でポストインクリメントまたはプレデクリメントのとき、
// アドレスレジスタを更新してそのままにするとページフォルトを起こした命令を再実行することができない
// MOVE.L (A0)+,(d16,A0)などでデスティネーションの実効アドレスの計算にソースの結果を反映させる必要があるので、
// アドレスレジスタは更新しておいてページフォルトのときだけ命令開始時の値に巻き戻す
// CMPM.L (A0)+,(A1)+やSUBX.L -(A0),-(A1)などでは複数の増分を並べるかまたは積まなければならない
// m60Incremented += (long) offset << (r << 3);
// で積むことにする
// 巻き戻すとき負数に注意する
private static long m60Incremented;
// FSLW Fault Status Long Word
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// ┏━━━━━━━┯━┯━┯━┯━━━┯━━━┯━━━┯━━━━━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━┓
// ┃ │MA│ │LK│ RW │ SIZE │ TT │ TM │IO│PBE SBE PTA PTB IL│PF│SP│WP│TWE RE│WE│TTR BPE SEE┃
// ┗━━━━━━━┷━┷━┷━┷━━━┷━━━┷━━━┷━━━━━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━┛
private static final int M60_FSLW_MISALIGNED = 1 << 27; //MA Misaligned Access
private static final int M60_FSLW_LOCKED = 1 << 25; //LK Locked Transfer
private static final int M60_FSLW_READ_AND_WRITE = 3 << 23; //RW Read and Write
private static final int M60_FSLW_RW_WRITE = 1 << 23; // Write
private static final int M60_FSLW_RW_READ = 2 << 23; // Read
private static final int M60_FSLW_RW_MODIFY = 3 << 23; // Read-Modify-Write
private static final int M60_FSLW_TRANSFER_SIZE = 3 << 21; //SIZE Transfer Size
private static final int M60_FSLW_SIZE_LONG = 0 << 21; // Long マニュアルが間違っているので注意
private static final int M60_FSLW_SIZE_BYTE = 1 << 21; // Byte マニュアルが間違っているので注意
private static final int M60_FSLW_SIZE_WORD = 2 << 21; // Word マニュアルが間違っているので注意
private static final int M60_FSLW_SIZE_QUAD = 3 << 21; // Double Precision or MOVE16
private static final int M60_FSLW_TRANSFER_TYPE = 3 << 19; //TT Transfer Type
private static final int M60_FSLW_TT_NORMAL = 0 << 19; // Normal Access
private static final int M60_FSLW_TT_MOVE16 = 1 << 19; // MOVE16 Access
private static final int M60_FSLW_TT_ALTERNATE = 2 << 19; // Alternate Logical Function Code Access, Debug Access
private static final int M60_FSLW_TT_ACKNOWLEDGE = 3 << 19; // Acknowledge Access, Low-Power Stop Broadcast
private static final int M60_FSLW_TRANSFER_MODIFIER = 7 << 16; //TM Transfer Modifier
private static final int M60_FSLW_TM_CACHE_PUSH = 0 << 16; // Data Cache Push Access
private static final int M60_FSLW_TM_USER_DATA = 1 << 16; // User Data Access
private static final int M60_FSLW_TM_USER_CODE = 2 << 16; // User Code Access
private static final int M60_FSLW_TM_MMU_DATA = 3 << 16; // MMU Table Search Data Access
private static final int M60_FSLW_TM_MMU_CODE = 4 << 16; // MMU Table Search Code Access
private static final int M60_FSLW_TM_SUPER_DATA = 5 << 16; // Supervisor Data Access
private static final int M60_FSLW_TM_SUPER_CODE = 6 << 16; // Supervisor Code Access
private static final int M60_FSLW_TM_DATA = 1 << 16; // Data Access
private static final int M60_FSLW_TM_CODE = 2 << 16; // Code Access
private static final int M60_FSLW_TM_SUPERVISOR = 4 << 16; // Supervisor Access
private static final int M60_FSLW_INSTRUCTION = 1 << 15; //IO Instruction or Operand
private static final int M60_FSLW_IOMA_FIRST = 0 << 15 | 0 << 27; //Fault occurred on the first access of a misaligned transfer, or to the only access of an aligned transfer
private static final int M60_FSLW_IOMA_SECOND = 0 << 15 | 1 << 27; //Fault occurred on the second or later access of a misaligned transfer
private static final int M60_FSLW_IOMA_OPWORD = 1 << 15 | 0 << 27; //Fault occurred on an instruction opword fetch
private static final int M60_FSLW_IOMA_EXWORD = 1 << 15 | 1 << 27; //Fault occurred on a fetch of an extension word
private static final int M60_FSLW_PUSH_BUFFER = 1 << 14; //PBE Push Buffer Bus Error
private static final int M60_FSLW_STORE_BUFFER = 1 << 13; //SBE Store Buffer Bus Error
private static final int M60_FSLW_ROOT_DESCRIPTOR = 1 << 12; //PTA Pointer A Fault
private static final int M60_FSLW_POINTER_DESCRIPTOR = 1 << 11; //PTB Pointer B Fault
private static final int M60_FSLW_INDIRECT_LEVEL = 1 << 10; //IL Indirect Level Fault
private static final int M60_FSLW_PAGE_FAULT = 1 << 9; //PF Page Fault
private static final int M60_FSLW_SUPERVISOR_PROTECT = 1 << 8; //SP Supervisor Protect
private static final int M60_FSLW_WRITE_PROTECT = 1 << 7; //WP Write Protect
private static final int M60_FSLW_TABLE_SEARCH = 1 << 6; //TWE Bus Error on Table Search
private static final int M60_FSLW_BUS_ERROR_ON_READ = 1 << 5; //RE Bus Error on Read
private static final int M60_FSLW_BUS_ERROR_ON_WRITE = 1 << 4; //WE Bus Error on Write
private static final int M60_FSLW_TRANSPARENT = 1 << 3; //TTR TTR Hit
private static final int M60_FSLW_BRANCH_PREDICTION = 1 << 2; //BPE Branch Prediction Error
private static final int M60_FSLW_SOFTWARE_EMULATION = 1 << 0; //SEE Software Emulation Error
private static int m60FSLW;
public static void m60BusErrorOnRead () {
m60FSLW |= M60_FSLW_BUS_ERROR_ON_READ;
}
public static void m60BusErrorOnWrite () {
m60FSLW |= M60_FSLW_BUS_ERROR_ON_WRITE;
}
private static final String[] M60_FSLW_TEXT_IOMA = {
"IO=0,MA=0 First access of a misaligned transfer or only access of an aligned transfer",
"IO=0,MA=1 Second or later access of a misaligned transfer",
"IO=1,MA=0 Instruction opword fetch",
"IO=1,MA=1 Fetch of an extension word",
};
private static final String[] M60_FSLW_TEXT_LK = {
"LK=0 Not locked",
"LK=1 Locked",
};
private static final String[] M60_FSLW_TEXT_RW = {
"RW=0 Undefined, reserved",
"RW=1 Write",
"RW=2 Read",
"RW=3 Read-Modify-Write",
};
private static final String[] M60_FSLW_TEXT_SIZE = {
"SIZE=0 Byte",
"SIZE=1 Word",
"SIZE=2 Long",
"SIZE=3 Double precision or MOVE16",
};
private static final String[] M60_FSLW_TEXT_TT = {
"TT=0 Normal access",
"TT=1 MOVE16 access",
"TT=2 Alternate or debug access",
"TT=3 Acknowledge or LPSTOP broadcast",
};
private static final String[] M60_FSLW_TEXT_TM = {
"TM=0 Data cache push access",
"TM=1 User data or MOVE16 access",
"TM=2 User code access",
"TM=3 MMU table search data access",
"TM=4 MMU table search code access",
"TM=5 Supervisor data access",
"TM=6 Supervisor code access",
"TM=7 Reserved",
//"TM=0 Logical function code 0",
//"TM=1 Debug access",
//"TM=2 Reserved",
//"TM=3 Logical function code 3",
//"TM=4 Logical function code 4",
//"TM=5 Debug pipe control mode access",
//"TM=6 Debug pipe control mode access",
//"TM=7 Logical function code 7",
};
private static final String[] M60_FSLW_TEXT_CAUSE = {
"SEE=1 Software emulation error", //0
"", //1
"BPE=1 Branch prediction error", //2
"TTR=1 TTR hit", //3
"WE=1 Bus error on write", //4
"RE=1 Bus error on read", //5
"TWE=1 Bus error on table search", //6
"WP=1 Write protect", //7
"SP=1 Supervisor protect", //8
"PF=1 Page fault", //9
"IL=1 Indirect level fault", //10
"PTB=1 Pointer B fault", //11
"PTA=1 Pointer A fault", //12
"SBE=1 Store buffer bus error", //13
"PBE=1 Push buffer bus error", //14
};
private static String m60ErrorToString () {
StringBuilder sb = new StringBuilder ();
int supervisor = m60FSLW & M60_FSLW_TM_SUPERVISOR;
int instruction = m60FSLW & M60_FSLW_TM_CODE;
if (0 <= M68kException.m6eNumber && M68kException.m6eNumber < M68kException.M6E_ERROR_NAME.length) {
sb.append (M68kException.M6E_ERROR_NAME[M68kException.m6eNumber]);
} else {
sb.append ("undefined exception #").append (M68kException.m6eNumber);
}
XEiJ.fmtHex8 (sb.append (" at PC=$"), XEiJ.regPC0).append ("($");
int pa = mmuTranslatePeek (XEiJ.regPC0, supervisor, 1);
if ((XEiJ.regPC0 ^ pa) == 1) {
sb.append ("????????");
} else {
XEiJ.fmtHex8 (sb, pa);
}
XEiJ.fmtHex4 (sb.append ("), SR=$"), XEiJ.regSRT1 | XEiJ.regSRS | XEiJ.regSRI | XEiJ.regCCR);
// 111111111122222222223333333333444444444455555555556666
// 0123456789012345678901234567890123456789012345678901234567890123
if (0b0011011101000000000000000000000000000000000000000000000000000000L << M68kException.m6eNumber < 0L) { //FORMAT $2,$4
XEiJ.fmtHex8 (sb.append ("\n Fault or effective address is EA=$"), m60Address).append ("($");
pa = mmuTranslatePeek (m60Address, supervisor, instruction);
if ((m60Address ^ pa) == 1) {
sb.append ("????????");
} else {
XEiJ.fmtHex8 (sb, pa);
}
sb.append (')');
}
if (M68kException.m6eNumber == M68kException.M6E_ACCESS_FAULT) { //FORMAT $4
XEiJ.fmtHex8 (sb.append ("\n Fault status long word is FSLW=$"), m60FSLW);
sb.append ("\n Fault was caused by:");
for (int i = 14; i >= 0; i--) {
if ((m60FSLW & (1 << i)) != 0) {
sb.append ("\n ").append (M60_FSLW_TEXT_CAUSE[i]);
}
}
sb.append ("\n Fault occured on:\n ")
.append (M60_FSLW_TEXT_IOMA[(m60FSLW & M60_FSLW_INSTRUCTION) >>> 15 - 1 | (m60FSLW & M60_FSLW_MISALIGNED) >>> 27])
.append ("\n ").append (M60_FSLW_TEXT_LK[(m60FSLW & M60_FSLW_LOCKED) >>> 25])
.append ("\n ").append (M60_FSLW_TEXT_RW[(m60FSLW & M60_FSLW_READ_AND_WRITE) >>> 23])
.append ("\n ").append (M60_FSLW_TEXT_SIZE[(m60FSLW & M60_FSLW_TRANSFER_SIZE) >>> 21])
.append ("\n ").append (M60_FSLW_TEXT_TT[(m60FSLW & M60_FSLW_TRANSFER_TYPE) >>> 19])
.append ("\n ").append (M60_FSLW_TEXT_TM[(m60FSLW & M60_FSLW_TRANSFER_MODIFIER) >>> 16]);
}
return sb.toString ();
} //m60ErrorToString()
//キャッシュアクセス時間
// キャッシュONのとき、全領域でキャッシュがヒットしたことにすると速くなりすぎる
// キャッシュの実体は設けないが、キャッシュミスペナルティの時間を加算する
// メインメモリ、ROM、ハイメモリのリードまたはライトに以下の処理を追加する
// (TMは通常のアクセス、MOVESのアクセス、MMUのテーブルサーチでFSLWに設定する)
// TMが1,2,5,6(キャッシュあり)
// TMが1,5(データ)
// CACRのEDCが1(データキャッシュ有効)
// TMが2,6(命令)
// CACRのEICが1(命令キャッシュ有効)
// (CMはアドレス変換時にTTR、PD、TCRから取得しATCに保存したものをアクセス時にコピーする)
// CMが0,1(キャッシュ許可)
// キャッシュミスペナルティを加算する
// ライト
// CMが0(ライトスルー)
// キャッシュがヒットしたかどうかに関係なくロング時間を加算する
// その他
// リード、ライトともにロング時間を加算する
public static final boolean CAT_ON = true;
//キャッシュの配列
// bit31-11 アドレス
// bit1 有効
// bit0 ダーティ(データのみ)
private static final int[] catData = new int[4 * 128]; //データ
private static final int[] catInst = new int[4 * 128]; //命令
private static int catLine = 0; //ラウンドロビンで使うライン
//ウェイト時間
// mpuSetWaitが設定する
public static long catMainLongTime = 0; //メインメモリとROM、ロング
public static long catMainLineTime = 0; //メインメモリとROM、ライン
public static long catHighLongTime = 0; //ハイメモリ、ロング
public static long catHighLineTime = 0; //ハイメモリ、ライン
//キャッシュモード
public static int catCM; //キャッシュモード
//catReset ()
// リセット
public static void catReset () {
Arrays.fill (catData, 0); //無効
Arrays.fill (catInst, 0); //無効
catLine = 0;
} //catReset
//catReadMainROM (a)
// リードメインメモリ、リードROM
public static void catReadMainROM (int a) {
if (!XEiJ.busWaitCycles) { //ウェイトサイクルなし
return;
}
int tm = m60FSLW & M60_FSLW_TRANSFER_MODIFIER;
if (tm == M60_FSLW_TM_USER_DATA ||
tm == M60_FSLW_TM_SUPER_DATA) { //データ
if (0 <= XEiJ.mpuCACR || //データキャッシュ禁止
2 <= catCM) { //プリサイズまたはインプリサイズ
XEiJ.mpuClockTime += catMainLongTime;
return;
}
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
if ((catData[i ] & -2) == t ||
(catData[i + 1] & -2) == t ||
(catData[i + 2] & -2) == t ||
(catData[i + 3] & -2) == t) { //ヒット
return;
}
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & 2) == 0) { //無効
catData[i + l] = t; //アロケート
XEiJ.mpuClockTime += catMainLineTime; //充填
return;
}
}
if ((catData[i + catLine] & 1) != 0) { //ダーティ
XEiJ.mpuClockTime += catMainLineTime; //排出
}
catData[i + catLine] = t; //アロケート
XEiJ.mpuClockTime += catMainLineTime; //充填
catLine = (catLine + 1) & 3; //ラウンドロビン
} else if (tm == M60_FSLW_TM_USER_CODE ||
tm == M60_FSLW_TM_SUPER_CODE) { //命令
if (0 <= (short) XEiJ.mpuCACR || //命令キャッシュ禁止
2 <= catCM) { //プリサイズまたはインプリサイズ
XEiJ.mpuClockTime += catMainLongTime;
return;
}
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
if ((catInst[i ] & -2) == t ||
(catInst[i + 1] & -2) == t ||
(catInst[i + 2] & -2) == t ||
(catInst[i + 3] & -2) == t) { //ヒット
return;
}
for (int l = 0; l < 4; l++) {
if ((catInst[i + l] & 2) == 0) { //無効
catInst[i + l] = t; //アロケート
XEiJ.mpuClockTime += catMainLineTime; //充填
return;
}
}
catInst[i + catLine] = t; //アロケート
XEiJ.mpuClockTime += catMainLineTime; //充填
catLine = (catLine + 1) & 3; //ラウンドロビン
} else { //データでも命令でもない
XEiJ.mpuClockTime += catMainLongTime;
}
} //catReadMainROM
//catReadHigh (a)
// リードハイメモリ
public static void catReadHigh (int a) {
if (!XEiJ.busWaitCycles) { //ウェイトサイクルなし
return;
}
int tm = m60FSLW & M60_FSLW_TRANSFER_MODIFIER;
if (tm == M60_FSLW_TM_USER_DATA ||
tm == M60_FSLW_TM_SUPER_DATA) { //データ
if (0 <= XEiJ.mpuCACR || //データキャッシュ禁止
2 <= catCM) { //プリサイズまたはインプリサイズ
XEiJ.mpuClockTime += catHighLongTime;
return;
}
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
if ((catData[i ] & -2) == t ||
(catData[i + 1] & -2) == t ||
(catData[i + 2] & -2) == t ||
(catData[i + 3] & -2) == t) { //ヒット
return;
}
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & 2) == 0) { //無効
catData[i + l] = t; //アロケート
XEiJ.mpuClockTime += catHighLineTime; //充填
return;
}
}
if ((catData[i + catLine] & 1) != 0) { //ダーティ
XEiJ.mpuClockTime += catHighLineTime; //排出
}
catData[i + catLine] = t; //アロケート
XEiJ.mpuClockTime += catHighLineTime; //充填
catLine = (catLine + 1) & 3; //ラウンドロビン
} else if (tm == M60_FSLW_TM_USER_CODE ||
tm == M60_FSLW_TM_SUPER_CODE) { //命令
if (0 <= (short) XEiJ.mpuCACR || //命令キャッシュ禁止
2 <= catCM) { //プリサイズまたはインプリサイズ
XEiJ.mpuClockTime += catHighLineTime;
return;
}
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
if ((catInst[i ] & -2) == t ||
(catInst[i + 1] & -2) == t ||
(catInst[i + 2] & -2) == t ||
(catInst[i + 3] & -2) == t) { //ヒット
return;
}
for (int l = 0; l < 4; l++) {
if ((catInst[i + l] & 2) == 0) { //無効
catInst[i + l] = t; //アロケート
XEiJ.mpuClockTime += catHighLineTime; //充填
return;
}
}
catInst[i + catLine] = t; //アロケート
XEiJ.mpuClockTime += catHighLineTime; //充填
catLine = (catLine + 1) & 3; //ラウンドロビン
} else { //データでも命令でもない
XEiJ.mpuClockTime += catHighLongTime;
}
} //catReadHigh
//catWriteMain (a)
// ライトメインメモリ
public static void catWriteMain (int a) {
if (!XEiJ.busWaitCycles) { //ウェイトサイクルなし
return;
}
int tm = m60FSLW & M60_FSLW_TRANSFER_MODIFIER;
if (tm == M60_FSLW_TM_USER_DATA ||
tm == M60_FSLW_TM_SUPER_DATA) { //データ
if (0 <= XEiJ.mpuCACR || //データキャッシュ禁止
2 <= catCM) { //プリサイズまたはインプリサイズ
XEiJ.mpuClockTime += catMainLongTime;
return;
}
if (catCM == 2) { //ライトスルー
XEiJ.mpuClockTime += catMainLongTime;
}
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & -2) == t) { //ヒット
catData[i + l] |= 1; //ダーティ
return;
}
}
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & 2) == 0) { //無効
catData[i + l] = t | 1; //アロケート、ダーティ
XEiJ.mpuClockTime += catMainLineTime; //充填
return;
}
}
if ((catData[i + catLine] & 1) != 0) { //ダーティ
XEiJ.mpuClockTime += catMainLineTime; //排出
}
catData[i + catLine] = t | 1; //アロケート、ダーティ
XEiJ.mpuClockTime += catMainLineTime; //充填
catLine = (catLine + 1) & 3; //ラウンドロビン
} else { //データでない
XEiJ.mpuClockTime += catMainLongTime;
}
} //catWriteMain
//catWriteHigh (a)
// ライトハイメモリ
public static void catWriteHigh (int a) {
if (!XEiJ.busWaitCycles) { //ウェイトサイクルなし
return;
}
int tm = m60FSLW & M60_FSLW_TRANSFER_MODIFIER;
if (tm == M60_FSLW_TM_USER_DATA ||
tm == M60_FSLW_TM_SUPER_DATA) { //データ
if (0 <= XEiJ.mpuCACR || //データキャッシュ禁止
2 <= catCM) { //プリサイズまたはインプリサイズ
XEiJ.mpuClockTime += catHighLongTime;
return;
}
if (catCM == 2) { //ライトスルー
XEiJ.mpuClockTime += catHighLongTime;
}
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & -2) == t) { //ヒット
catData[i + l] |= 1; //ダーティ
return;
}
}
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & 2) == 0) { //無効
catData[i + l] = t | 1; //アロケート、ダーティ
XEiJ.mpuClockTime += catHighLineTime; //充填
return;
}
}
if ((catData[i + catLine] & 1) != 0) { //ダーティ
XEiJ.mpuClockTime += catHighLineTime; //排出
}
catData[i + catLine] = t | 1; //アロケート、ダーティ
XEiJ.mpuClockTime += catHighLineTime; //充填
catLine = (catLine + 1) & 3; //ラウンドロビン
} else { //データでない
XEiJ.mpuClockTime += catHighLongTime;
}
} //catWriteHigh
private static boolean catMove16InProgress; //MOVE16実行中
private static int catSavedEDC; //保存されたEDC
private static long catSavedMainLongTime; //保存されたメインメモリのロング時間
private static long catSavedHighLongTime; //保存されたハイメモリのロング時間
//catMove16Start ()
// MOVE16開始
// EDCを保存
// EDCをクリア
// ロングの時間を保存
// ロングの時間をラインの時間の1/4に変更
// MOVE16はEDCに関係なく常にラインの時間がかかる
private static void catMove16Start () {
if (!XEiJ.busWaitCycles) { //ウェイトサイクルなし
return;
}
XEiJ.mpuCycleCount += 11;
catMove16InProgress = true;
//EDCを保存
catSavedEDC = XEiJ.mpuCACR & 0x80000000;
//EDCをクリア
XEiJ.mpuCACR &= 0x7FFFFFFF;
//ロングの時間を保存
catSavedMainLongTime = catMainLongTime;
catSavedHighLongTime = catHighLongTime;
//ロングの時間をラインの時間の1/4に変更
catMainLongTime = catMainLineTime >> 2;
catHighLongTime = catHighLineTime >> 2;
} //catMove16Start
//catMove16End ()
// MOVE16終了
// EDCを復元
// ロングの時間を復元
private static void catMove16End () {
if (!catMove16InProgress) {
return;
}
catMove16InProgress = false;
//EDCを復元
XEiJ.mpuCACR |= catSavedEDC;
//ロングの時間を復元
catMainLongTime = catSavedMainLongTime;
catHighLongTime = catSavedHighLongTime;
} //catMove16End
//catInvL (id, a)
// ライン無効
private static void catInvL (int id, int a) {
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
if ((id & 1) != 0) { //データ
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & -2) == t) { //ヒット
catData[i + l] = 0; //無効
break;
}
}
}
if ((id & 2) != 0) { //命令
for (int l = 0; l < 4; l++) {
if ((catInst[i + l] & -2) == t) { //ヒット
catInst[i + l] = 0; //無効
break;
}
}
}
XEiJ.mpuClockTime += XEiJ.mpuCycleUnit * 18; //<=18
} //catInvL
//catInvP (id, a)
// ページ無効
private static void catInvP (int id, int a) {
int t = (a & -0x800) | 2; //タグ、有効
if ((id & 1) != 0) { //データ
for (int i = 0; i < 512; i++) {
if ((catData[i] & -2) == t) { //ヒット
catData[i] = 0; //無効
}
}
}
if ((id & 2) != 0) { //命令
for (int i = 0; i < 512; i++) {
if ((catInst[i] & -2) == t) { //ヒット
catInst[i] = 0; //無効
}
}
}
XEiJ.mpuClockTime += XEiJ.mpuCycleUnit * (18 + 256); //<=274
} //catInvP
//catInvA (id)
// 全無効
private static void catInvA (int id) {
if ((id & 1) != 0) { //データ
Arrays.fill (catData, 0); //無効
}
if ((id & 2) != 0) { //命令
Arrays.fill (catInst, 0); //無効
}
XEiJ.mpuClockTime += XEiJ.mpuCycleUnit * 18; //<=17
} //catInvA
//catPushL (id, a)
// ラインプッシュ
private static void catPushL (int id, int a) {
int k = 0;
int t = (a & -0x800) | 2; //タグ、有効
int i = (a & 0x7f0) >>> 2; //4*(0~127)
if ((id & 1) != 0) { //データ
for (int l = 0; l < 4; l++) {
if ((catData[i + l] & -2) == t) { //ヒット
if ((catData[i + l] & 1) == 1) { //ダーティ
k++; //ライトライン
}
catData[i + l] = 0; //無効
break;
}
}
}
if ((id & 2) != 0) { //命令
for (int l = 0; l < 4; l++) {
if ((catInst[i + l] & -2) == t) { //ヒット
catInst[i + l] = 0; //無効
break;
}
}
}
long lineTime = (XEiJ.busExMemoryStart <= a && a < XEiJ.busExMemoryStart + XEiJ.busExMemorySize
? catHighLineTime : catMainLineTime);
XEiJ.mpuClockTime += XEiJ.mpuCycleUnit * 18 + lineTime * k; //<=26
} //catPushL
//catPushP (id, a)
// ページプッシュ
private static void catPushP (int id, int a) {
int k = 0;
int t = (a & -0x800) | 2; //タグ、有効
if ((id & 1) != 0) { //データ
for (int i = 0; i < 512; i++) {
if ((catData[i] & -2) == t) { //ヒット
if ((catData[i] & 1) == 1) { //ダーティ
k++; //ライトライン
}
catData[i] = 0; //無効
}
}
}
if ((id & 2) != 0) { //命令
for (int i = 0; i < 512; i++) {
if ((catInst[i] & -2) == t) { //ヒット
catInst[i] = 0; //無効
}
}
}
long lineTime = (XEiJ.busExMemoryStart <= a && a < XEiJ.busExMemoryStart + XEiJ.busExMemorySize
? catHighLineTime : catMainLineTime);
XEiJ.mpuClockTime += XEiJ.mpuCycleUnit * (18 + 256) + lineTime * k; //<=2838
} //catPushP
//catPushA (id)
// 全プッシュ
private static void catPushA (int id) {
int km = 0, kh = 0;
if ((id & 1) != 0) { //データ
for (int i = 0; i < 512; i++) {
if ((catData[i] & 3) == 3) { //有効、ダーティ
int a = catData[i] & -4;
if (XEiJ.busExMemoryStart <= a && a < XEiJ.busExMemoryStart + XEiJ.busExMemorySize) {
kh++;
} else {
km++;
}
}
}
Arrays.fill (catData, 0); //無効
}
if ((id & 2) != 0) { //命令
Arrays.fill (catInst, 0); //無効
}
XEiJ.mpuClockTime += XEiJ.mpuCycleUnit * (18 + 256) + catMainLineTime * km + catHighLineTime * kh; //<=5394
} //catPushA
} //class MC68060