/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.Allegrex;
import jpcsp.Emulator;
import jpcsp.Memory;
/**
* Load Store Unit, handles memory operations.
*
* @author hli
*/
public class LsuState extends MduState {
public static final Memory memory = Memory.getInstance();
protected static final boolean CHECK_ALIGNMENT = true;
@Override
public void reset() {
}
@Override
public void resetAll() {
super.resetAll();
}
public LsuState() {
}
public void copy(LsuState that) {
super.copy(that);
}
public LsuState(LsuState that) {
super(that);
}
public void doLB(int rt, int rs, int simm16) {
int word = (byte)memory.read8(getRegister(rs) + simm16);
if (rt != 0) {
setRegister(rt, word);
}
}
public void doLBU(int rt, int rs, int simm16) {
int word = memory.read8(getRegister(rs) + simm16) & 0xff;
if (rt != 0) {
setRegister(rt, word);
}
}
public void doLH(int rt, int rs, int simm16) {
if (CHECK_ALIGNMENT) {
CpuState cpu = Emulator.getProcessor().cpu;
int address = getRegister(rs) + simm16;
if ((address & 1) != 0) {
Memory.log.error(String.format("LH unaligned addr:0x%08x pc:0x%08x", address, cpu.pc));
}
}
int word = (short)memory.read16(getRegister(rs) + simm16);
if (rt != 0) {
setRegister(rt, word);
}
}
public void doLHU(int rt, int rs, int simm16) {
if (CHECK_ALIGNMENT) {
CpuState cpu = Emulator.getProcessor().cpu;
int address = getRegister(rs) + simm16;
if ((address & 1) != 0) {
Memory.log.error(String.format("LHU unaligned addr:0x%08x pc:0x%08x", address, cpu.pc));
}
}
int word = memory.read16(getRegister(rs) + simm16) & 0xffff;
if (rt != 0) {
setRegister(rt, word);
}
}
private static final int[] lwlMask = { 0xffffff, 0xffff, 0xff, 0 };
private static final int[] lwlShift = { 24, 16, 8, 0 };
public void doLWL(int rt, int rs, int simm16) {
int address = getRegister(rs) + simm16;
int offset = address & 0x3;
int value = getRegister(rt);
int data = memory.read32(address & 0xfffffffc);
if (rt != 0) {
setRegister(rt, (data << lwlShift[offset]) | (value & lwlMask[offset]));
}
}
public void doLW(int rt, int rs, int simm16) {
if (CHECK_ALIGNMENT) {
CpuState cpu = Emulator.getProcessor().cpu;
int address = getRegister(rs) + simm16;
if ((address & 3) != 0) {
Memory.log.error(String.format("LW unaligned addr:0x%08x pc:0x%08x", address, cpu.pc));
}
}
int word = memory.read32(getRegister(rs) + simm16);
if (rt != 0) {
setRegister(rt, word);
}
}
private static final int[] lwrMask = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
private static final int[] lwrShift = { 0, 8, 16, 24 };
public void doLWR(int rt, int rs, int simm16) {
int address = getRegister(rs) + simm16;
int offset = address & 0x3;
int value = getRegister(rt);
int data = memory.read32(address & 0xfffffffc);
if (rt != 0) {
setRegister(rt, (data >>> lwrShift[offset]) | (value & lwrMask[offset]));
}
}
public void doSB(int rt, int rs, int simm16) {
memory.write8(getRegister(rs) + simm16, (byte) (getRegister(rt) & 0xFF));
}
public void doSH(int rt, int rs, int simm16) {
if (CHECK_ALIGNMENT) {
CpuState cpu = Emulator.getProcessor().cpu;
int address = getRegister(rs) + simm16;
if ((address & 1) != 0) {
Memory.log.error(String.format("SH unaligned addr:0x%08x pc:0x%08x", address, cpu.pc));
}
}
memory.write16(getRegister(rs) + simm16, (short) (getRegister(rt) & 0xFFFF));
}
private static final int[] swlMask = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
private static final int[] swlShift = { 24, 16, 8, 0 };
public void doSWL(int rt, int rs, int simm16) {
int address = getRegister(rs) + simm16;
int offset = address & 0x3;
int value = getRegister(rt);
int data = memory.read32(address & 0xfffffffc);
data = (value >>> swlShift[offset]) | (data & swlMask[offset]);
memory.write32(address & 0xfffffffc, data);
}
public void doSW(int rt, int rs, int simm16) {
if (CHECK_ALIGNMENT) {
CpuState cpu = Emulator.getProcessor().cpu;
int address = getRegister(rs) + simm16;
if ((address & 3) != 0) {
Memory.log.error(String.format("SW unaligned addr:0x%08x pc:0x%08x", address, cpu.pc));
}
}
memory.write32(getRegister(rs) + simm16, getRegister(rt));
}
private static final int[] swrMask = { 0, 0xff, 0xffff, 0xffffff };
private static final int[] swrShift = { 0, 8, 16, 24 };
public void doSWR(int rt, int rs, int simm16) {
int address = getRegister(rs) + simm16;
int offset = address & 0x3;
int value = getRegister(rt);
int data = memory.read32(address & 0xfffffffc);
data = (value << swrShift[offset]) | (data & swrMask[offset]);
memory.write32(address & 0xfffffffc, data);
}
public void doLL(int rt, int rs, int simm16) {
int word = memory.read32(getRegister(rs) + simm16);
if (rt != 0) {
setRegister(rt, word);
}
//ll_bit = 1;
}
public void doSC(int rt, int rs, int simm16) {
memory.write32(getRegister(rs) + simm16, getRegister(rt));
if (rt != 0) {
setRegister(rt, 1); // = ll_bit;
}
}
}