|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2022 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: #include "m68030bitfield.h" ! 8: ! 9: // コンストラクタ ! 10: // 呼び出し側でここまでに ir2 へのフェッチはしておくこと。 ! 11: acc_bf::acc_bf(MPU680x0Device *cpu_) ! 12: { ! 13: cpu = cpu_; ! 14: ! 15: // F E D C B A 9 8 7 6 5 4 3 2 1 0 ! 16: // 0 0 0 0 DO <-- offset --> DW <-- width ---> ! 17: ! 18: offset = (cpu->GetIR2() >> 6) & 0x1f; ! 19: if ((cpu->GetIR2() & 0x0800)) { ! 20: offset = (int32)cpu->reg.D[offset & 7]; ! 21: local_offset = offset & 0x1f; ! 22: } else { ! 23: local_offset = offset; ! 24: } ! 25: ! 26: width = cpu->GetIR2(); ! 27: if ((cpu->GetIR2() & 0x0020)) { ! 28: width = cpu->reg.D[width & 7]; ! 29: } ! 30: // モジュロ 32 を取り、0 なら 32 を表す ! 31: width = ((width - 1) & 31) + 1; ! 32: // mask は32ビットの上位から width ビット 1 が並んだもの ! 33: mask = 0xffffffff << (32 - width); ! 34: } ! 35: ! 36: // データレジスタから値を読み込む。n はデータレジスタの番号。 ! 37: void ! 38: acc_bf::LoadReg(uint n) ! 39: { ! 40: data = cpu->reg.D[n]; ! 41: data = ROL32(data, local_offset); ! 42: data &= mask; ! 43: } ! 44: ! 45: // メモリから値を読み込む。 ! 46: void ! 47: acc_bf::LoadMem(uint32 addr) ! 48: { ! 49: // EA の計算 ! 50: ea = addr + offset / 8; ! 51: local_offset = offset % 8; ! 52: if (local_offset < 0) { ! 53: local_offset += 8; ! 54: ea--; ! 55: } ! 56: ! 57: // アクセスするバイト数 ! 58: bytes = (local_offset + width + 7) / 8; ! 59: ! 60: // 40ビットバッファに読み込む ! 61: // read_NN() はミスアラインドでもアクセスできる ! 62: switch (bytes) { ! 63: case 1: ! 64: buf = ((uint64)cpu->read_8(ea)) << 32; ! 65: break; ! 66: case 2: ! 67: buf = ((uint64)cpu->read_16(ea)) << 24; ! 68: break; ! 69: case 3: ! 70: if ((ea & 1) == 0) { ! 71: // 偶数アドレスから3バイト ! 72: buf = ((uint64)cpu->read_16(ea)) << 24; ! 73: buf |= ((uint64)cpu->read_8(ea + 2)) << 16; ! 74: } else { ! 75: // 奇数アドレスから3バイト ! 76: buf = ((uint64)cpu->read_8(ea)) << 32; ! 77: buf |= (uint64)cpu->read_16(ea + 1) << 16; ! 78: } ! 79: break; ! 80: case 4: ! 81: buf = ((uint64)cpu->read_32(ea)) << 8; ! 82: break; ! 83: case 5: ! 84: if ((ea & 1) == 0) { ! 85: // 偶数アドレスから5バイト ! 86: buf = ((uint64)cpu->read_32(ea)) << 8; ! 87: buf |= ((uint64)cpu->read_8(ea + 4)); ! 88: } else { ! 89: // 奇数アドレスから5バイト ! 90: buf = ((uint64)cpu->read_8(ea)) << 32; ! 91: buf |= ((uint64)cpu->read_32(ea + 1)); ! 92: } ! 93: break; ! 94: default: ! 95: PANIC("corrupted bytes=%d", bytes); ! 96: } ! 97: ! 98: // 32ビット左詰めにする ! 99: data = (buf >> (8 - local_offset)) & mask; ! 100: } ! 101: ! 102: // データレジスタに値を書き出す。 ! 103: void ! 104: acc_bf::StoreReg(uint n) ! 105: { ! 106: uint32 m = ROR32(mask, local_offset); ! 107: uint32 d = ROR32(data, local_offset); ! 108: ! 109: cpu->reg.D[n] = (cpu->reg.D[n] & ~m) | (d & m); ! 110: } ! 111: ! 112: // メモリに値を書き出す ! 113: void ! 114: acc_bf::StoreMem() ! 115: { ! 116: // 32ビット左詰めデータを 40ビットバッファにマージ ! 117: uint64 m = (uint64)mask << (8 - local_offset); ! 118: uint64 d = (uint64)data << (8 - local_offset); ! 119: buf = (buf & ~m) | (d & m); ! 120: ! 121: // 40ビットバッファを書き戻す ! 122: // write_NN() はミスアラインドでもアクセスできる ! 123: switch (bytes) { ! 124: case 1: ! 125: cpu->write_8(ea, buf >> 32); ! 126: break; ! 127: case 2: ! 128: cpu->write_16(ea, buf >> 24); ! 129: break; ! 130: case 3: ! 131: if ((ea & 1) == 0) { ! 132: // 偶数アドレスから3バイト ! 133: cpu->write_16(ea, buf >> 24); ! 134: cpu->write_8(ea + 2, buf >> 16); ! 135: } else { ! 136: // 奇数アドレスから3バイト ! 137: cpu->write_8(ea, buf >> 32); ! 138: cpu->write_16(ea + 1, buf >> 16); ! 139: } ! 140: break; ! 141: case 4: ! 142: cpu->write_32(ea, buf >> 8); ! 143: break; ! 144: case 5: ! 145: if ((ea & 1) == 0) { ! 146: // 偶数アドレスから5バイト ! 147: cpu->write_32(ea, buf >> 8); ! 148: cpu->write_8(ea + 4, buf); ! 149: } else { ! 150: // 奇数アドレスから5バイト ! 151: cpu->write_8(ea, buf >> 32); ! 152: cpu->write_32(ea + 1, buf); ! 153: } ! 154: break; ! 155: default: ! 156: PANIC("corrupted bytes=%d", bytes); ! 157: } ! 158: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.