/* 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; import static jpcsp.Allegrex.Common._a0; import static jpcsp.Allegrex.Common._f0; import static jpcsp.Allegrex.Common._f12; import jpcsp.Allegrex.CpuState; public class ParameterReader { private CpuState cpu; final private Memory memory; private int parameterIndex = 0; private int parameterIndexFloat = 0; protected static final int maxParameterInGprRegisters = 8; protected static final int maxParameterInFprRegisters = 8; protected static final int firstParameterInGpr = _a0; protected static final int firstParameterInFpr = _f12; public ParameterReader(CpuState cpu, Memory memory) { this.cpu = cpu; this.memory = memory; } public void setCpu(CpuState cpu) { this.cpu = cpu; } public void resetReading() { parameterIndex = 0; parameterIndexFloat = 0; } private int getParameterIntAt(int index) { if (index >= maxParameterInGprRegisters) { return memory.read32(cpu._sp + (index - maxParameterInGprRegisters) * 4); } return cpu.getRegister(firstParameterInGpr + index); } private float getParameterFloatAt(int index) { if (index >= maxParameterInFprRegisters) { throw(new UnsupportedOperationException()); } return cpu.fpr[firstParameterInFpr + index]; } private long getParameterLongAt(int index) { if ((index % 2) != 0) { throw(new RuntimeException("Parameter misalignment")); } return (long)getParameterIntAt(index) + (long)getParameterIntAt(index + 1) << 32; } protected int moveParameterIndex(int size) { while (size > 0 && (parameterIndex % size) != 0) { parameterIndex++; } int retParameterIndex = parameterIndex; parameterIndex += size; return retParameterIndex; } protected int moveParameterIndexFloat(int size) { while ((parameterIndexFloat % size) != 0) { parameterIndexFloat++; } int retParameterIndexFloat = parameterIndexFloat; parameterIndexFloat += size; return retParameterIndexFloat; } public int getNextInt() { return getParameterIntAt(moveParameterIndex(1)); } public long getNextLong() { return getParameterLongAt(moveParameterIndex(2)); } public float getNextFloat() { return getParameterFloatAt(moveParameterIndexFloat(1)); } public void setReturnValueInt(int value) { cpu._v0 = value; } public void setReturnValueFloat(float value) { // Float value is returned in $f0 register cpu.fpr[_f0] = value; } public void setReturnValueLong(long value) { cpu._v0 = (int)((value ) & 0xFFFFFFFF); cpu._v1 = (int)((value >> 32) & 0xFFFFFFFF); } }