/*******************************************************************************
* openDLX - A DLX/MIPS processor simulator.
* Copyright (C) 2013 The openDLX project, University of Augsburg, Germany
* Project URL: <https://sourceforge.net/projects/opendlx>
* Development branch: <https://github.com/smetzlaff/openDLX>
*
*
* This program 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
* any later version.
*
* This program 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 this program, see <LICENSE>. If not, see
* <http://www.gnu.org/licenses/>.
******************************************************************************/
package openDLX.util;
import openDLX.PipelineConstants;
import openDLX.memory.MainMemory;
import openDLX.datatypes.*;
import openDLX.exception.DLXTrapException;
import openDLX.exception.MemoryException;
import openDLX.gui.dialog.Input;
import org.apache.log4j.Logger;
public class DLXTrapHandler {
public static final char LINE_END = '\0';
public static final char FORMAT_DELIMITER = '%';
public static final char FORMAT_INTEGER = 'd';
public static final char FORMAT_HEX = 'x';
public static final char INPUT_END = 10;
private static Logger logger = Logger.getLogger("PrintHandler");
private static final DLXTrapHandler instance = new DLXTrapHandler();
private TrapObservable oOutput = null;
private TrapObservable oInput = null;
private Input input = null;
private MainMemory mem=null;
private DLXTrapHandler()
{
}
public static DLXTrapHandler getInstance()
{
return instance;
}
public void setTrapObserverOutput(TrapObservable to)
{
oOutput = to;
}
public void setTrapObserverInput(TrapObservable to)
{
oInput = to;
}
public void setInput(Input input)
{
this.input = input;
}
public void open(int parameter) throws DLXTrapException, MemoryException
{
logger.error("TRAP " + PipelineConstants.DLX_TRAP_OPEN + " not implemented. Parameter: " + parameter + " mem");
mem.dumpMemory(new uint32(parameter), new uint32(parameter+32));
throw new DLXTrapException("TRAP " + PipelineConstants.DLX_TRAP_OPEN + " not implemented. Parameter: " + parameter);
}
public void close(int parameter) throws DLXTrapException, MemoryException
{
logger.error("TRAP " + PipelineConstants.DLX_TRAP_CLOSE + " not implemented. Parameter: " + parameter + " mem");
mem.dumpMemory(new uint32(parameter), new uint32(parameter+32));
throw new DLXTrapException("TRAP " + PipelineConstants.DLX_TRAP_OPEN + " not implemented. Parameter: " + parameter);
}
public uint32 read(int parameter) throws MemoryException
{
String user_input = null;
// uint32 unknown = new uint32(parameter);
uint32 write_addr = mem.read_u32(new uint32(parameter+4));
int input_length = mem.read_u32(new uint32(parameter+8)).getValue();
uint32 return_value = new uint32(-1);
if((oInput != null) && (input != null))
{
oInput.notifyObservers("Input string...");
user_input = input.getInput();
}
if(user_input != null)
{
System.out.println("Input: " + user_input);
logger.info("Input: " + user_input + " @" + write_addr.getValueAsHexString());
byte[] raw = user_input.getBytes();
for(int i = 0; ((i < user_input.length()) && (i < input_length-1)); i++)
{
mem.write_u8(write_addr, new uint8(raw[i]));
write_addr.setValue(write_addr.getValue()+1);
}
return_value.setValue(raw.length);
}
mem.write_u8(write_addr, new uint8(INPUT_END));
return return_value;
}
public void write(int parameter) throws DLXTrapException, MemoryException
{
logger.error("TRAP " + PipelineConstants.DLX_TRAP_WRITE + " not implemented. Parameter: " + parameter + " mem");
mem.dumpMemory(new uint32(parameter), new uint32(parameter+32));
throw new DLXTrapException("TRAP " + PipelineConstants.DLX_TRAP_WRITE + " not implemented. Parameter: " + parameter + " mem");
}
public void printf(int parameter) throws MemoryException, DLXTrapException
{
uint32 format_addr = mem.read_u32(new uint32(parameter));
String format_string = new String("");
uint32 parameter_list_pointer = new uint32(parameter + 4);
logger.debug("TRAP " + PipelineConstants.DLX_TRAP_PRINTF + " catched. Printf format string is at: " + format_addr.getValueAsHexString() + " Parameter list begins at: " + parameter_list_pointer.getValueAsHexString());
// logger.debug("Format string dump:");
// mem.dumpMemory(format_addr, new uint32(format_addr.getValue() + 20));
// logger.debug("Parameter list dump:");
// mem.dumpMemory(parameter_list_pointer, new uint32(parameter_list_pointer.getValue() + 20));
char read_char = 0xFF;
// read the format string from memory
while(read_char != LINE_END)
{
// logger.debug("Read addr: " + format_addr.getHex() + " char: " + (char)mem.read_u8(format_addr).getValue() + "("+ mem.read_u8(format_addr).getHex() +")");
read_char = (char)(mem.read_u8(format_addr).getValue());
String read_s = String.valueOf(read_char);
format_string += read_s;
// logger.debug("Added :" + read_s + " to: " + format_string);
format_addr.setValue(format_addr.getValue()+1);
}
int format_string_index = 0;
String print_string = new String("");
// replace the format parameters with values
while(format_string_index != -1)
{
int format_descr_pos = format_string.indexOf(FORMAT_DELIMITER, format_string_index);
// found format delimiter "%"
if(format_descr_pos != -1)
{
// logger.debug("Found format delimiter: " + format_string.substring(format_descr_pos, format_descr_pos+1) + " reading from: " + parameter_list_pointer.toString());
// add the format string before the format delimiter to the print string
print_string += format_string.substring(format_string_index, format_descr_pos);
// replace the format delimiter with value from memory
switch(format_string.charAt(format_descr_pos+1))
{
case FORMAT_INTEGER:
print_string += mem.read_u32(parameter_list_pointer).getValue();
// set pointer to next addr in the parameter list
parameter_list_pointer.setValue(parameter_list_pointer.getValue()+4);
// skip two characters: the "%" and the format descriptor
format_descr_pos+=2;
break;
case FORMAT_HEX:
print_string += mem.read_u32(parameter_list_pointer).getValueAsHexString();
// set pointer to next addr in the parameter list
parameter_list_pointer.setValue(parameter_list_pointer.getValue()+4);
// skip two characters: the "%" and the format descriptor
format_descr_pos+=2;
break;
default:
throw new DLXTrapException("Unknown format identifier for printf: " + format_string.charAt(format_descr_pos+1));
}
}
else
{
// logger.debug("End of format string. start: " + format_string_index + " end: " + format_string.length());
// end of string, add the rest of the format string
print_string += format_string.substring(format_string_index, format_string.length()-1);
}
format_string_index = format_descr_pos;
}
System.out.println(print_string);
logger.info("Printf out: " + print_string);
if (oOutput != null)
{
oOutput.notifyObservers(print_string);
}
// TODO return the number of printed bytes to be written to R1
}
public void setMemory(MainMemory mainMem)
{
mem = mainMem;
}
}