summaryrefslogtreecommitdiffstats
path: root/zpu/sw/simulator/com/zylin
diff options
context:
space:
mode:
authorBert Lange <b.lange@hzdr.de>2015-04-15 13:36:55 +0200
committerBert Lange <b.lange@hzdr.de>2015-04-15 13:36:55 +0200
commita1c964908b51599bf624bd2d253419c7e629f195 (patch)
tree06125d59e83b7dde82d1bb57bc0e09ca83451b98 /zpu/sw/simulator/com/zylin
parentbbfe29a15f11548eb7c9fa71dcb4d2d18c164a53 (diff)
parent8679e4f91dcae05aef40f96629f33f0f4161f14a (diff)
downloadzpu-a1c964908b51599bf624bd2d253419c7e629f195.zip
zpu-a1c964908b51599bf624bd2d253419c7e629f195.tar.gz
Merge branch 'master' of https://github.com/zylin/zpu
Diffstat (limited to 'zpu/sw/simulator/com/zylin')
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Abel.java109
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java285
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Host.java46
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Machine.java17
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Phi.java126
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/PhiFeeble.java34
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Sim.java62
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/SimApp.java177
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/SimFactory.java8
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Simulator.java2065
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/State.java9
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/Tracer.java21
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/ZPU.java14
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/applet/ZPUApplet.java281
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/BadPacketException.java22
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/CPUException.java23
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/DebuggerBreakpointException.java10
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/EndSessionException.java46
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/GDBServerException.java25
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/HardwareWatchPointException.java12
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/IllegalInstructionException.java23
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/InterruptException.java23
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/MemoryAccessException.java23
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/NoAckException.java22
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/TraceException.java22
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnknownPacketException.java10
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnsupportedSyscallException.java12
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java364
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java472
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeDRAM.java39
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeRam.java39
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/stats/CountSequences.java94
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/stats/DumpIt.java17
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/stats/Instruction.java62
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/stats/StatKeeper.java52
35 files changed, 4666 insertions, 0 deletions
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Abel.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Abel.java
new file mode 100644
index 0000000..8d8667c
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Abel.java
@@ -0,0 +1,109 @@
+
+package com.zylin.zpu.simulator;
+
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+
+public class Abel extends Simulator
+{
+
+ protected int getIO()
+ {
+ return 0x8000;
+ }
+
+
+
+ protected int ioRead(int addr) throws CPUException
+ {
+ switch (addr)
+ {
+ case 0xc000:
+ return syscall.readUART();
+
+ /* FIFO empty? bit 0, FIFO full bit 1(never the case) */
+ case 0xc004:
+ return syscall.readFIFO();
+
+ case 0x9000:
+ case 0x9004:
+ case 0x9008:
+ case 0x900c:
+
+ case 0x9010:
+ case 0x9014:
+ case 0x9018:
+ case 0x901c:
+ return readSampledTimer(addr, 0x9000);
+
+ case 0x8800:
+ return readMHz();
+
+ default:
+ throw new MemoryAccessException();
+ }
+ }
+
+ /*
+ ; Read/write are on different addresses
+ ; The registers are 8 bits and mapped to bit[7:0]
+ ;
+ ; 0xC000 Write: Writes to UART TX FIFO (4 byte FIFO)
+ ; Read : Reads from UART RX FIFO (4 byte FIFO)
+ ; 0xC004 Read : UART status register
+ ; Bit 0 = RX FIFO empty
+ ; Bit 1 = TX FIFO full
+ ; 0xA000 Write: 8 LED's
+ */
+
+ /*
+ 0x9000 Write: bit 0: 1= reset counter
+ 0= counter running
+ bit 1: 1= sample counter (when set to 1)
+ 0=not used
+ Read : counter bit[7:0]
+ 0x9004 Read: counter bit [15:8]
+ 0x9008 Read: counter bit [23:16]
+ 0x900C Read: counter bit [31:24]
+ 0x9010 Read: counter bit [39:32]
+ 0x9014 Read: counter bit [47:40]
+ 0x9018 Read: counter bit [55:48]
+ 0x901C Read: counter bit [63:56]
+
+ 0x8800 Read: unsigned 8-bit integer with FPGA frequency (in MHz)
+ */
+
+ protected void ioWrite(int addr, int val) throws MemoryAccessException
+ {
+ switch (addr)
+ {
+ case 0x9000:
+ writeTimerSampleReg(val);
+ case 0xc000:
+ syscall.writeUART(val);
+ break;
+ default:
+ throw new MemoryAccessException();
+ }
+ }
+
+ Abel() throws CPUException
+ {
+ }
+
+ protected boolean emulateConfig()
+ {
+ return true;
+ }
+
+ protected int getStartStack()
+ {
+ return getRAMSIZE()-8;
+ }
+
+ protected int getRAMSIZE()
+ {
+ return 32768;
+ }
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java b/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java
new file mode 100644
index 0000000..6ccca24
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java
@@ -0,0 +1,285 @@
+
+package com.zylin.zpu.simulator;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.LineNumberReader;
+
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.GDBServerException;
+import com.zylin.zpu.simulator.exceptions.TraceException;
+
+public class FileTracer implements Tracer
+{
+ private LineNumberReader file;
+ private boolean trigger;
+ private boolean resync;
+ private Simulator simulator;
+ private String line;
+ private boolean ignore;
+
+ static class Trace
+ {
+ int pc;
+ int opcode;
+ int sp;
+ int stackA;
+ int stackB;
+ int intSp;
+ long cycle;
+ public boolean undefinedStackA;
+ public boolean undefinedStackB;
+ public boolean undefinedIntSp;
+ public void print()
+ {
+ System.err.println(Integer.toHexString(pc)+ " " +
+ Integer.toHexString(opcode) + " " +
+ Integer.toHexString(sp) + " " +
+ Integer.toHexString(stackA) + " " +
+ Integer.toHexString(stackB) + " " +
+ intSp + " " +
+ cycle);
+
+ }
+ };
+ private Trace[] trace= new Trace[100];
+ private int current;
+ private String fileName;
+ private boolean metEnd;
+
+
+ public FileTracer(Simulator sim, String string)
+ {
+ simulator=sim;
+ fileName=string;
+
+ resync=true;
+
+
+ for (int i=0; i<trace.length; i++)
+ {
+ trace[i]=new Trace();
+ }
+ findNextTrigger();
+ }
+
+ LineNumberReader getFile()
+ {
+ if (file==null)
+ {
+ try
+ {
+ file=new LineNumberReader(new java.io.FileReader(fileName));
+ } catch (FileNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ return file;
+ }
+
+
+ private void findNextTrigger() throws TraceException
+ {
+ trigger=false;
+ try
+ {
+ for (;;)
+ {
+ line=getFile().readLine();
+ if (line==null)
+ {
+ metEnd=true;
+ System.err.println("================== End of trace file ======================");
+ break;
+ }
+ if (line.matches("^\\s*\\#.*$"))
+ {
+ /* this was a comment*/
+ continue;
+ }
+ if (line.matches("^\\s*$"))
+ {
+ /* all whitespace */
+ continue;
+ }
+ String[] val=line.split(" ");
+
+ try
+ {
+ Trace t=trace[current];
+ t.pc=(int) parseInt(val[0]);
+ t.opcode=(int) parseInt(val[1]);
+ t.sp=(int) parseInt(val[2]);
+ try
+ {
+ t.undefinedStackA=false;
+ t.stackA=(int) parseInt(val[3]);
+ } catch (NumberFormatException e)
+ {
+ t.undefinedStackA=true;
+ t.stackB=0;
+ }
+
+ try
+ {
+ t.undefinedStackB=false;
+ t.stackB=(int) parseInt(val[4]);
+ } catch (NumberFormatException e)
+ {
+ t.undefinedStackB=true;
+ t.stackB=0;
+ }
+ try
+ {
+ t.undefinedIntSp=false;
+ t.intSp=(int) parseInt(val[5]);
+ } catch (NumberFormatException e)
+ {
+ t.undefinedIntSp=true;
+ t.intSp=0;
+ }
+ t.cycle=parseInt(val[6]);
+ trigger=true;
+ break;
+ } catch (NumberFormatException e)
+ {
+ /* skip this line. */
+ e.printStackTrace();
+ }
+ }
+ } catch (IOException e)
+ {
+ throw new TraceException(e);
+ }
+
+ }
+
+ private long parseInt(String string2) throws TraceException
+ {
+ String string = string2;
+ if (!string.startsWith("0x"))
+ {
+ throw new TraceException(new Exception("Trace file pasing error line " + getFile().getLineNumber()));
+ }
+ return Long.parseLong(string.substring(2), 16);
+ }
+
+ public void instructionEvent() throws GDBServerException
+ {
+ if (metEnd)
+ {
+ metEnd=false;
+ throw new TraceException();
+ }
+ if (resync&&trigger)
+ {
+ if (match())
+ {
+ /* we have to wait for the first instruction in the trace to be matched */
+ System.out.println("First matching instruction found!");
+ resync=false;
+ }
+ }
+
+ if (!resync&&trigger)
+ {
+
+ boolean m=match();
+ recordCurrent();
+ current=(current+1)%trace.length;
+
+ if (!m)
+ {
+ System.err.println("Trace file mismatch");
+ dumpTraceBack();
+ System.err.print("Expected by Java simulator: \n");
+ simulator.printState(this);
+ System.err.print("Actual from ModelSim: ");
+ System.err.println(line);
+ // we now have to ignore this match.
+ ignore=true;
+ throw new TraceException();
+ }
+ } else
+ {
+ recordCurrent();
+ current=(current+1)%trace.length;
+ }
+ }
+
+ public void dumpTraceBack()
+ {
+ System.err.println("Expected");
+ System.err.println("PC SP topOfStack");
+ for (int i=0; i<trace.length; i++)
+ {
+ trace[(i+current)%trace.length].print();
+ }
+ }
+
+ private void recordCurrent()
+ {
+ recordState(trace[current]);
+ }
+
+ private void recordState(Trace trace3)
+ {
+ trace3.pc=simulator.getPc();
+ trace3.sp=simulator.getSp();
+ trace3.opcode=simulator.getOpcode();
+ try
+ {
+ trace3.stackA=simulator.cpuReadLong(simulator.getSp());
+ trace3.stackB=simulator.cpuReadLong(simulator.getSp()+4);
+ trace3.intSp=simulator.getIntSp();
+ // trace[current].cycle=expectetdCycle();
+ } catch (CPUException e1)
+ {
+ e1.printStackTrace();
+ }
+ }
+
+
+
+ boolean match() throws GDBServerException
+ {
+ if (ignore)
+ return true;
+
+ return simulator.checkMatch(trace[current]);
+ }
+
+ public void commit()
+ {
+ try
+ {
+ if (!resync&&trigger)
+ {
+ ignore=false;
+ findNextTrigger();
+ }
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSp(int sp)
+ {
+ }
+
+ public boolean onInterrupt()
+ {
+ if (trace[current].pc==0x20)
+ return true;
+ else
+ return false;
+ }
+
+ public boolean simInterrupt()
+ {
+ return true;
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Host.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Host.java
new file mode 100644
index 0000000..c1daa9f
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Host.java
@@ -0,0 +1,46 @@
+
+package com.zylin.zpu.simulator;
+
+import com.zylin.zpu.simulator.exceptions.CPUException;
+
+public interface Host
+{
+ /** generic file io error */
+ public final static int EIO = 5;
+
+ public final static int SYS_read= 4;
+ public final static int SYS_write= 5;
+ public final static int SYS_argv = 13;
+ public final static int SYS_exit=1;
+ public final static int SYS_open= 2;
+ public final static int SYS_close= 3;
+ public final static int SYS_lseek = 6;
+ public final static int SYS_unlink = 7;
+ public final static int SYS_getpid = 8;
+ public final static int SYS_kill = 9;
+ public final static int SYS_fstat = 10;
+ /*final static int SYS_sbrk 11 - not currently a system call, but reserved. */
+ /* ARGV support. */
+ public final static int SYS_argvlen= 12;
+ /* These are extras added for one reason or another. */
+ public final static int SYS_chdir = 14;
+ public final static int SYS_stat = 15;
+ public final static int SYS_chmod = 16;
+ public final static int SYS_utime = 17;
+ public final static int SYS_time = 18;
+ public final static int SYS_gettimeofday =19;
+ public final static int SYS_times = 20;
+ public final static int SYS_link = 21;
+ public final static int SYS_ftruncate=3000;
+ public final static int SYS_isatty=3001;
+ public void syscall(Sim s) throws CPUException;
+ boolean doneContinue();
+ public void writeUART(int val);
+ public int readUART() throws CPUException;
+ public int readFIFO();
+ /** notification that the CPU is halted */
+ public void halted();
+ /** notification that the CPU is running */
+ public void running();
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Machine.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Machine.java
new file mode 100644
index 0000000..3827378
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Machine.java
@@ -0,0 +1,17 @@
+
+package com.zylin.zpu.simulator;
+
+/**
+ * @author oyvind
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface Machine
+{
+
+ long getPrevCycles();
+
+ long getCycles();
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Phi.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Phi.java
new file mode 100644
index 0000000..663e68f
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Phi.java
@@ -0,0 +1,126 @@
+
+package com.zylin.zpu.simulator;
+
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+
+public class Phi extends Simulator
+{
+ @Override
+ protected long getSampleOffset()
+ {
+
+ return super.getSampleOffset()-(0x5e7b2-0x0005E7C0);
+ }
+
+
+ public static void main(String[] args)
+ {
+ new SimApp(new SimFactory()
+ {
+ public Simulator create()
+ {
+ return new Phi();
+ }
+ }).run(args);
+ }
+
+
+ protected int getIO()
+ {
+ return 0x08000000;
+ }
+
+
+
+ protected int ioRead(int addr) throws CPUException
+ {
+ switch (addr)
+ {
+
+ case 0x080a0020:
+ return interrupt?0:1; // interrupt mask
+
+
+
+ /* FIFO empty? bit 0, FIFO full bit 1(never the case) */
+ case 0x080a000c:
+ return 0x100; // buffer ready.
+
+ case 0x080a0014:
+ case 0x080a0018:
+ return readSampledTimer(addr, 0x080a0014);
+
+ case 0x080a0030:
+ return timerPending?1:0;
+ case 0x080a0038:
+ return (int)(timerInterval-1-((cycles-lastTimer)%timerInterval));
+
+
+ default:
+ throw new MemoryAccessException();
+ }
+ }
+
+
+
+ protected void ioWrite(int addr, int val) throws MemoryAccessException
+ {
+ switch (addr)
+ {
+ case 0x080a0020:
+ interrupt=(val&1)==0;
+ return;
+ case 0x080a002c:
+ timer=(val&0x1)!=0;
+ break;
+ case 0x080a0030:
+ if ((val&0x1)!=0)
+ {
+ timerPending=false;
+ }
+ if ((val&0x2)!=0)
+ {
+ lastTimer=cycles;
+ }
+ break;
+ case 0x080a0034:
+ timerInterval=val;
+ return;
+
+ case 0x080a0014:
+ writeTimerSampleReg(val);
+ case 0x080a000c:
+ syscall.writeUART(val);
+ break;
+ default:
+ throw new MemoryAccessException();
+ }
+ }
+
+ public Phi() throws CPUException
+ {
+ }
+
+ protected boolean emulateConfig()
+ {
+ return true;
+ }
+
+ protected int getStartStack()
+ {
+ return getRAMSIZE()-8;
+ }
+
+ protected int getRAMSIZE()
+ {
+ return 2*1024*1024;
+ }
+
+
+ protected int getIOSIZE()
+ {
+ return 0x100000;
+ }
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/PhiFeeble.java b/zpu/sw/simulator/com/zylin/zpu/simulator/PhiFeeble.java
new file mode 100644
index 0000000..79d3a38
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/PhiFeeble.java
@@ -0,0 +1,34 @@
+package com.zylin.zpu.simulator;
+
+public class PhiFeeble extends Phi
+{
+ public static void main(String[] args)
+ {
+ new SimApp(new SimFactory()
+ {
+ public Simulator create()
+ {
+ return new PhiFeeble();
+ }
+ }).run(args);
+ }
+ protected void setFeeble()
+ {
+// feeble[NEQBRANCH] = false;
+// feeble[EQ] = false;
+// feeble[LOADB] = false;
+// feeble[LESSTHAN] = false;
+// feeble[ULESSTHAN] = false;
+// feeble[STOREB] = false;
+// feeble[MULT] = false;
+// feeble[CALL] = true;
+// feeble[POPPCREL] = true;
+// feeble[LESSTHANOREQUAL] = true;
+// feeble[ULESSTHANOREQUAL] = true;
+//
+// feeble[PUSHSPADD] = false;
+// feeble[CALLPCREL] = false;
+// feeble[SUB] = false;
+ }
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Sim.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Sim.java
new file mode 100644
index 0000000..21450f7
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Sim.java
@@ -0,0 +1,62 @@
+
+package com.zylin.zpu.simulator;
+
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+
+public interface Sim
+{
+/**
+ * halts the CPU.
+ */
+ void suspend();
+ void writeByte(int i, int val) throws CPUException;
+ /**
+ * synchronous method that returns when simulator enters the halt state.
+ **/
+ void cont();
+ /**
+ * synchronous method that returns when simulator finishes step or otherwise enters
+ * the halt state.
+ **/
+ void step();
+
+ int getReg(int i) throws CPUException;
+
+ int getREGNUM();
+ int readByte(int addr) throws CPUException;
+
+ /**
+ * @param sp The sp to set.
+ * @throws CPUException
+ */
+ void setSp(int sp) throws CPUException;
+
+ /**
+ * @return Returns the sp.
+ */
+ int getSp();
+
+ /**
+ * @param pc The pc to set.
+ * @throws MemoryAccessException
+ */
+ void setPc(int pc) throws MemoryAccessException;
+
+ /**
+ * @return Returns the pc.
+ */
+ int getPc();
+
+ void enableAccessWatchPoint(int address, int length) throws CPUException;
+
+ void disableAccessWatchPoint(int address, int length) throws CPUException;
+
+ int cpuReadLong(int i) throws CPUException;
+
+ void cpuWriteLong(int i, int retval) throws MemoryAccessException;
+
+ int getArg(int num) throws CPUException;
+ void sessionStarted();
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/SimApp.java b/zpu/sw/simulator/com/zylin/zpu/simulator/SimApp.java
new file mode 100644
index 0000000..3f6e1a9
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/SimApp.java
@@ -0,0 +1,177 @@
+package com.zylin.zpu.simulator;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.channels.ServerSocketChannel;
+
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.gdb.GDBServer;
+
+public class SimApp
+{
+ private static Simulator simulator;
+ private String[] args;
+ private int portNumber;
+ private SimFactory simFactory;
+
+ public SimApp(SimFactory factory)
+ {
+ simFactory=factory;
+ }
+
+ public void parseArgs()
+ {
+ portNumber = 4444;
+ if (args.length>=1)
+ {
+ portNumber=Integer.parseInt(args[0]);
+ }
+ }
+
+ private void moreParse()
+ {
+ if (args.length>=2)
+ {
+ simulator.setTraceFile(args[1]);
+ }
+ }
+
+ void run(String[] args)
+ {
+ this.args=args;
+ createSimulator();
+ parseArgs();
+ moreParse();
+ runSimAndGDB();
+ }
+ Object launched=new Object();
+ private boolean doneLaunching;
+ private boolean manyGDBSessions;
+ public ServerSocket serverSocket;
+ public void runSimAndGDB()
+ {
+ try
+ {
+ serverSocket = new ServerSocket(portNumber);
+ try
+ {
+ serverSocket.setReuseAddress(true);
+ System.out.println("Listening on port " + portNumber);
+ setLaunchedFlag();
+ do
+ {
+ try
+ {
+ runGDBServer();
+ } catch (CPUException e)
+ {
+ e.printStackTrace();
+ }
+ } while (manyGDBSessions);
+ } finally
+ {
+ serverSocket.close();
+ }
+ } catch (IOException e1)
+ {
+ e1.printStackTrace();
+ } finally
+ {
+ setLaunchedFlag();
+ }
+
+ }
+
+ private void setLaunchedFlag()
+ {
+ synchronized(launched)
+ {
+ doneLaunching=true;
+ launched.notify();
+ }
+ }
+
+ public void createSimulator()
+ {
+ simulator=simFactory.create();
+ simulator.suspend();
+ }
+
+ private void runGDBServer() throws CPUException
+ {
+ final GDBServer gdbServer=new GDBServer(simulator, this);
+ simulator.setSyscall(gdbServer);
+ Thread thread = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ gdbServer.gdbServer();
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
+ simulator.shutdown();
+ }
+ });
+ thread.start();
+ try
+ {
+ simulator.run();
+ }
+ finally
+ {
+ try
+ {
+ thread.join();
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ public Simulator getSimulator()
+ {
+ return simulator;
+ }
+
+ public void setPort(int i)
+ {
+ portNumber=i;
+ }
+
+ /** synchronous launch of GDB server */
+ public void launchGDBServer()
+ {
+ Thread t=new Thread(new Runnable()
+ {
+
+ public void run()
+ {
+ runSimAndGDB();
+ }
+ });
+ t.start();
+ synchronized (launched)
+ {
+ while (!doneLaunching)
+ {
+ try
+ {
+ launched.wait(2000);
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/SimFactory.java b/zpu/sw/simulator/com/zylin/zpu/simulator/SimFactory.java
new file mode 100644
index 0000000..4db85d7
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/SimFactory.java
@@ -0,0 +1,8 @@
+package com.zylin.zpu.simulator;
+
+public interface SimFactory
+{
+
+ Simulator create();
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Simulator.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Simulator.java
new file mode 100644
index 0000000..cf6cf41
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Simulator.java
@@ -0,0 +1,2065 @@
+package com.zylin.zpu.simulator;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.zylin.zpu.simulator.FileTracer.Trace;
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.DebuggerBreakpointException;
+import com.zylin.zpu.simulator.exceptions.EndSessionException;
+import com.zylin.zpu.simulator.exceptions.GDBServerException;
+import com.zylin.zpu.simulator.exceptions.HardwareWatchPointException;
+import com.zylin.zpu.simulator.exceptions.IllegalInstructionException;
+import com.zylin.zpu.simulator.exceptions.InterruptException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+
+public class Simulator implements ZPU, Machine, Sim
+{
+
+ int minStack;
+
+ /**
+ * the feeble version of the CPU, e.g. only implements
+ * 11 instructions.
+ *
+ * For debugging purposes it is useful to enable/disable
+ * each instruction
+ */
+ boolean feeble[]=new boolean[256];
+
+ private long opcodeHistogram[]=new long[256];
+ private long opcodeHistogramCycles[]=new long[256];
+ private long opcodePairHistogram[]=new long[256*256];
+ private long opcodePairHistogramCycles[]=new long[256*256];
+
+ /** weee! constants are 32 bit by default, so we need to assign a 64 bit
+ * integer in this matter.
+ */
+ private static final long INTMASK = Long.parseLong("ffffffff", 16);
+
+ final static int PUSHPC=59;
+ final static int OR=7;
+ final static int NOT=9;
+ final static int LOAD=8;
+ final static int STORE=12;
+ final static int POPPC=4;
+ final static int FLIP=10;
+
+ final static int ADD=5;
+ final static int PUSHSP=2;
+ final static int POPSP=13;
+ final static int NOP=11;
+ final static int AND=6;
+ final static int ADDSP=16;
+
+ final static int EMULATE=32;
+ final static int LOADH=34;
+ final static int STOREH=35;
+ final static int LESSTHAN=36;
+ final static int LESSTHANOREQUAL=37;
+ final static int ULESSTHAN=38;
+ final static int ULESSTHANOREQUAL=39;
+ final static int SWAP=40;
+ final static int MULT=41;
+ final static int LSHIFTRIGHT=42;
+ final static int ASHIFTLEFT=43;
+ final static int ASHIFTRIGHT=44;
+ final static int CALL=45;
+ final static int EQ=46;
+ final static int NEQ=47;
+ final static int NEG=48;
+ final static int SUB=49;
+ final static int XOR=50;
+ final static int LOADB=51;
+ final static int STOREB=52;
+ final static int DIV=53;
+ final static int MOD=54;
+ final static int EQBRANCH=55;
+ final static int NEQBRANCH=56;
+ final static int POPPCREL=57;
+ final static int CONFIG=58;
+ final static int SYSCALL=60;
+ final static int PUSHSPADD=61;
+ final static int MULT16X16=62;
+ final static int CALLPCREL=63;
+ final static int STORESP=64;
+ final static int LOADSP=64+32;
+
+ int[] memory;
+ boolean[] validMemory;
+ protected long cycles;
+ protected int instructionCount;
+ private int sp;
+ private int pc;
+ protected boolean breakNext;
+
+ /* halting synchronization object */
+ protected Object halt = new Object();
+
+ private int IOSIZE=getIOSIZE();
+ protected int getIOSIZE()
+ {
+ return 32768;
+ }
+ long prevCycles;
+ private static final int VECTORSIZE = 0x20;
+ private static final int VECTOR_RESET = 0;
+ private static final int VECTOR_INTERRUPT = 1;
+ private boolean hitVector;
+ private static final int VECTORBASE = 0x0;
+ private int nextVector;
+ protected long lastTimer;
+ protected boolean timer;
+ private boolean powerdown;
+ private boolean decodeMask;
+
+ private static final int ZETA = 1;
+
+ private static final int ABEL = 0;
+
+ private int startStack;
+
+ protected Host syscall;
+
+ private long[] emulateOpcodeHistogram= new long[256];
+
+ private long[] emulateOpcodeHistogramCycles=new long[256];
+
+ private long emulateCycles;;
+
+ public Simulator() throws CPUException
+ {
+ }
+
+
+ public void run() throws CPUException
+ {
+ syscall.running();
+
+ try
+ {
+
+ instructionLoop();
+
+
+ } catch (EndSessionException e)
+ {
+ /* done */
+ } finally
+ {
+ }
+ dumpInfo();
+
+ System.err.println("Stack usage: " + (startStack-minStack));
+ }
+
+ private void dumpInfo()
+ {
+ dumpOpcodeHistogram();
+
+ //printMemoryHistorgram();
+ }
+
+
+ private void dumpOpcodeHistogram()
+ {
+ System.out.println("Opcode histogram");
+ dumpHistogram(opcodeHistogram, opcodeHistogramCycles);
+ System.out.println("Emulate histogram");
+ dumpHistogram(emulateOpcodeHistogram, emulateOpcodeHistogramCycles);
+ System.out.println("Pair histogram");
+ dumpHistogram(opcodePairHistogram, opcodePairHistogramCycles);
+
+
+ dumpGmon();
+
+ System.out.println("Grouping of LOADSP/STORESP/IM");
+ printRange(64, 96);
+ printRange(96, 128);
+ printRange(128, 256);
+// printRange(64, 65);
+// printRange(65, 66);
+// printRange(66, 64+32);
+// printRange(96, 97);
+// printRange(97, 98);
+// printRange(98, 96+32);
+// printRange(128, 129);
+// printRange(129, 130);
+// printRange(130, 131);
+// printRange(131, 132);
+// printRange(132, 133);
+// printRange(252, 253);
+// printRange(253, 254);
+// printRange(254, 255);
+// printRange(255, 256);
+ }
+
+
+
+// #define GMON_MAGIC "gmon" /* magic cookie */
+// #define GMON_VERSION 1 /* version number */
+//
+// /*
+// * Raw header as it appears on file (without padding):
+// */
+// struct gmon_hdr
+// {
+// char cookie[4];
+// char version[4]; // a cyg_uint32, target-side endianness
+// char spare[3 * 4];
+// };
+//
+// /* types of records in this file: */
+// typedef enum
+// {
+// GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2
+// }
+// GMON_Record_Tag;
+//
+// /* The histogram tag is followed by this header, and then an array of */
+// /* cyg_uint16's for the actual counts. */
+//
+// struct gmon_hist_hdr
+// {
+// /* host-side gprof adapts to sizeof(void*) and endianness. */
+// /* It is assumed that the compiler does not insert padding around the */
+// /* cyg_uint32's or the char arrays. */
+// void* low_pc; /* base pc address of sample buffer */
+// void* high_pc; /* max pc address of sampled buffer */
+// cyg_uint32 hist_size; /* size of sample buffer */
+// cyg_uint32 prof_rate; /* profiling clock rate */
+// char dimen[15]; /* phys. dim., usually "seconds" */
+// char dimen_abbrev; /* usually 's' for "seconds" */
+// };
+//
+// /* An arc tag is followed by a single arc record. self_pc corresponds to */
+// /* the location of an mcount() call, at the start of a function. from_pc */
+// /* corresponds to the return address, i.e. where the function was called */
+// /* from. count is the number of calls. */
+//
+// struct gmon_cg_arc_record
+// {
+// void* from_pc; /* address within caller's body */
+// void* self_pc; /* address within callee's body */
+// cyg_uint32 count; /* number of arc traversals */
+// };
+//
+// /* In theory gprof can also process basic block counts, as per the */
+// /* compiler's -fprofile-arcs flag. The compiler-generated basic block */
+// /* structure should contain a table of addresses and a table of counts, */
+// /* and the compiled code updates those counts. Current versions of the */
+// /* compiler (~3.2.1) do not output the table of addresses, and without */
+// /* that table gprof cannot process the counts. Possibly gprof should read */
+// /* in the .bb and .bbg files generated for gcov processing, but that does */
+// /* not happen at the moment. */
+// /* */
+// /* So for now gmon.out does not contain basic block counts and gprof */
+// /* operations that depend on it, e.g. --annotated-source, won't work. */
+
+ /**
+ * Write gmon.out file.
+ **/
+ private void dumpGmon()
+ {
+ if (memory==null)
+ return;
+ try
+ {
+ ByteArrayOutputStream b=new ByteArrayOutputStream();
+
+
+// /*
+// * Raw header as it appears on file (without padding):
+// */
+// struct gmon_hdr
+// {
+// char cookie[4];
+// char version[4]; // a cyg_uint32, target-side endianness
+// char spare[3 * 4];
+// };
+// #define GMON_MAGIC "gmon" /* magic cookie */
+// #define GMON_VERSION 1 /* version number */
+
+// dump binary memory gmon.out &profile_gmon_hdr ((char*)&profile_gmon_hdr + sizeof(struct gmon_hdr))
+ b.write("gmon".getBytes());
+ writeLong(b, 1); // version
+ b.write(new byte[3*4]); // spare
+
+// GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2
+
+// append binary memory gmon.out &profile_tags[0] &profile_tags[1]
+ b.write(new byte[]{0}); // GMON_TAG_TIME_HIST
+
+
+//
+// // The gprof documentation claims that this should be the size in
+// // bytes. The implementation treats it as a count.
+// profile_hist_hdr.hist_size = (cyg_uint32) ((text_size + bucket_size - 1) / bucket_size);
+// profile_hist_hdr.low_pc = _start;
+// profile_hist_hdr.high_pc = (void*)((cyg_uint8*)_end - 1);
+// // The prof_rate is the frequency in hz. The resolution argument is
+// // an interval in microseconds.
+// profile_hist_hdr.prof_rate = 1000000 / resolution;
+//
+// // Now allocate a buffer for the histogram data.
+// profile_hist_data = (cyg_uint16*) malloc(profile_hist_hdr.hist_size * sizeof(cyg_uint16));
+// if ((cyg_uint16*)0 == profile_hist_data) {
+// diag_printf("profile_on(): cannot allocate histogram buffer - ignored\n");
+// return;
+// }
+// memset(profile_hist_data, 0, profile_hist_hdr.hist_size * sizeof(cyg_uint16));
+
+
+
+// struct gmon_hist_hdr
+// {
+// /* host-side gprof adapts to sizeof(void*) and endianness. */
+// /* It is assumed that the compiler does not insert padding around the */
+// /* cyg_uint32's or the char arrays. */
+// void* low_pc; /* base pc address of sample buffer */
+// void* high_pc; /* max pc address of sampled buffer */
+// cyg_uint32 hist_size; /* size of sample buffer */
+// cyg_uint32 prof_rate; /* profiling clock rate */
+// char dimen[15]; /* phys. dim., usually "seconds" */
+// char dimen_abbrev; /* usually 's' for "seconds" */
+// };
+
+
+ // maximum 65536 buckets.
+ int length=memory.length*4;
+ if (length > 60000)
+ {
+ length=60000;
+ }
+ int buckets[]=new int[length];
+ for (long i=0; i<profile.length;i++)
+ {
+ buckets[(int)((i*(((long)buckets.length)-1))/(((long)profile.length)-1))]+=profile[(int)i];
+ }
+
+
+
+ // append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr))
+ writeLong(b, 0); // low_pc
+ writeLong(b, memory.length*4); // high_pc
+ writeLong(b, buckets.length); // # of samples
+ writeLong(b, 64000000); // 64MHz
+ b.write("seconds".getBytes());
+ b.write(new byte[15-"seconds".length()]);
+ b.write("s".getBytes());
+
+
+
+// append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size)
+ for (int i=0; i<buckets.length;i++)
+ {
+ int val;
+ val=buckets[i];
+ if (val>65535)
+ {
+ val=65535;
+ }
+ writeShort(b, val);
+ }
+
+ OutputStream o=new FileOutputStream("gmon.out");
+ b.writeTo(o);
+ o.flush();
+ o.close();
+
+ } catch (IOException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+
+ }
+
+
+ private void writeLong(ByteArrayOutputStream b, int i) throws IOException
+ {
+ int val=i;
+ b.write(new byte[]{(byte)((val>>24)&0xff),
+ (byte)((val>>16)&0xff),
+ (byte)((val>>8)&0xff),
+ (byte)((val>>0)&0xff)});
+ }
+
+
+ private void writeShort(ByteArrayOutputStream b, int i) throws IOException
+ {
+ int val=i;
+ b.write(new byte[]{ (byte)((val>>8)&0xff),
+ (byte)((val>>0)&0xff)});
+ }
+
+
+ private void dumpHistogram(long[] ms, long[] ms2)
+ {
+ List<OpcodeSample> l=new LinkedList();
+
+ totalCycles = 0;
+ for (int i=0; i<256; i++)
+ {
+ totalCycles+=opcodeHistogramCycles[i];
+ }
+ for (int i=0; i<ms.length; i++)
+ {
+ final int j=i;
+ l.add(new OpcodeSample(j, ms2[j]));
+ }
+ Collections.sort(l, new Comparator()
+ {
+
+ public int compare(Object arg0, Object arg1)
+ {
+ OpcodeSample a=(OpcodeSample) arg0, b=(OpcodeSample) arg1;
+ if (a.count<b.count)
+ {
+ return 1;
+ } else if (a.count==b.count)
+ {
+ return 0;
+ } else
+ {
+ return -1;
+ }
+ }
+ });
+
+ for (int i=0; i<ms.length; i++)
+ {
+ if (totalCycles==0)
+ break;
+ double d = ((double)l.get(i).count/((double)totalCycles));
+ if (d<0.005)
+ break;
+ double cycPerIns = ((double)ms2[l.get(i).j]/((double)ms[l.get(i).j]));
+ System.out.println("0x"+ Integer.toHexString(l.get(i).j) + " " + d + " " + l.get(i).count + " " + cycPerIns );
+ }
+ }
+
+
+ private void printRange(int from, int to)
+ {
+ int totalLoadSP=0;
+ for (int i=from; i<to; i++)
+ {
+ totalLoadSP+=opcodeHistogram[i];
+ }
+
+ double d = ((double)totalLoadSP/((double)totalCycles));
+
+ System.out.println(""+ from + " " + d + " " + totalLoadSP);
+ }
+
+
+// private void printMemoryHistorgram()
+// {
+// Arrays.sort(profile, new Comparator()
+// {
+// public int compare(Object o1, Object o2)
+// {
+// return (int)(((Profile)o2).counter-
+// ((Profile)o1).counter);
+// }
+// });
+// System.err.println("Profiling information");
+// for (int i=0; i<1000; i++)
+// {
+// if (profile[i].counter==0)
+// {
+// break;
+// }
+// System.err.println("0x"+Integer.toHexString(profile[i].address)+ " " + profile[i].counter);
+// }
+// }
+
+
+ /**
+ * notify everybody that we are powering down
+ */
+ public void shutdown()
+ {
+ powerdown=true;
+ /* wake up */
+ synchronized(halt)
+ {
+ halt.notify();
+ }
+ }
+
+
+ /**
+ * This method can be invoked in two cases:
+ *
+ * a) while the CPU is running on the simulator thread
+ * b) while the CPU is halted from other threads
+ */
+ protected void resetHardwareInternal() throws CPUException
+ {
+ interrupt=false;
+ timer=false;
+ lastTimer=0;
+ hitVector=false;
+ instructionCount=0;
+ for (int i=0; i<memory.length; i++)
+ {
+ memory[i]=0;
+ }
+
+ setPcToVector(VECTOR_RESET); // starting address
+ startStack=getStartStack();
+ minStack=startStack;
+ changeSp(startStack);
+
+ intSp=0;
+
+ }
+
+
+ private void instructionLoop() throws EndSessionException, CPUException
+ {
+ /* wait for connection.... */
+ for (;;)
+ {
+ try
+ {
+
+ /*
+ * execute an instruction.
+ *
+ * If an exception happens while executing the instruction,
+ * invoke the approperiate exception vector.
+ *
+ * If a second exception occurs while invoking the
+ * exception(i.e. before the first instruction of the vector
+ * is executed), invoke the reboot exception.
+ */
+ executeInstruction();
+ } catch (DebuggerBreakpointException e1)
+ {
+ suspend();
+ } catch (InterruptException e1)
+ {
+ armVector(VECTOR_INTERRUPT);
+ } catch (IllegalInstructionException e1)
+ {
+ suspend();
+ } catch (MemoryAccessException e1)
+ {
+ suspend();
+ } catch (CPUException e)
+ {
+ suspend();
+ } catch (GDBServerException e)
+ {
+ suspend();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ suspend();
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ suspend();
+ } finally
+ {
+ checkCommit();
+ }
+ }
+ }
+
+
+ private void armVector(int vector)
+ {
+ // for now we always break as soon as we hit a vector
+ if (vector!=VECTOR_INTERRUPT)
+ {
+ // print(MINIMAL, "Vector " + vector + " armed at PC: " + formatHex(pc, "00000000"));
+ suspend();
+ }
+ hitVector=true;
+ nextVector=vector;
+ }
+
+ private void checkVector() throws CPUException
+ {
+ if (hitVector)
+ {
+ hitVector=false;
+ invokeVector(nextVector);
+ }
+ }
+
+
+ private void invokeVector(int vector) throws CPUException
+ {
+ push(pc);
+ setPcToVector(vector);
+ }
+
+ private void setPcToVector(int vector) throws MemoryAccessException
+ {
+ setPc(VECTORSIZE*vector+VECTORBASE);
+ }
+
+ private void executeInstruction() throws CPUException, EndSessionException, GDBServerException, IOException
+ {
+ for (;;)
+ {
+ checkHalt();
+
+ /* jump to any armed vector */
+ checkVector();
+
+ checkInterrupts();
+
+ tracer.instructionEvent();
+
+
+
+
+
+ commit = false;
+ savedSp=getSp();
+ savedPc=pc;
+ savedDecodeMask=decodeMask;
+ touchedPc=false;
+
+ instruction=cpuReadByte(pc);
+ // electrons perish each time we attempt an instruction
+ tick();
+
+ if (((instruction&0x80)!=0))
+ {
+ int t=((instruction<<(32-7)))>>(32-7);
+
+ if (decodeMask)
+ {
+ int a;
+ a=(popIntStack()<<7)|(t&0x7f);
+ pushIntStack(a);
+ } else
+ {
+ pushIntStack(t);
+ }
+ decodeMask=true;
+ } else
+ {
+ decodeMask = false;
+ if (isAddSP(instruction))
+ {
+ int offset=instruction - ADDSP;
+ int valAddr=sp+offset*4;
+ int a = popIntStack();
+ pushIntStack(cpuReadLong(valAddr) + a);
+ } else if ((instruction >= LOADSP) && (instruction < LOADSP + 32))
+ {
+ int addr;
+ addr = getSp();
+ int offset=(instruction - LOADSP)^0x10;
+ addr += 4 * offset;
+ pushIntStack(cpuReadLong(addr));
+ } else if (isStoreSP(instruction))
+ {
+ int addr;
+ addr = getSp();
+ int offset=(instruction - STORESP)^0x10;
+ addr += 4 * offset;
+
+ cpuWriteLong(addr, popIntStack());
+ } else
+ {
+ int addr;
+ int val;
+ switch (instruction)
+ {
+ case 0:
+ throw new DebuggerBreakpointException();
+
+ case PUSHPC:
+ pushIntStack(pc);
+ break;
+ case OR:
+ pushIntStack(popIntStack() | popIntStack());
+ break;
+ case NOT:
+ pushIntStack(popIntStack() ^ 0xffffffff);
+ break;
+ case LOAD:
+ pushIntStack(cpuReadLong(popIntStack()));
+ break;
+ case PUSHSPADD:
+ if (feeble[PUSHSPADD])
+ {
+ emulate();
+ } else
+ {
+ int a;
+ int b;
+ a=sp;
+ b=popIntStack()*4;
+ pushIntStack(a+b);
+ }
+ break;
+ case STORE:
+ addr = popIntOrExt();
+ val = popIntOrExt();
+ cpuWriteLong(addr, val);
+ break;
+ case POPPC:
+ {
+ // NB!!!! does NOT flush internal stack
+ int a;
+ if (intSp>0)
+ {
+ a=popIntStack();
+ } else
+ {
+ a=pop();
+ }
+
+ if ((sp>=emulateSp)&&(emulateInProgress))
+ {
+ emulateInProgress=false;
+ /* we returned from an emulate instruction */
+ emulateOpcodeHistogram[emulateOpcode]++;
+ emulateOpcodeHistogramCycles[emulateOpcode]+=cycles-emulateCycles;
+ }
+
+ setPc(a);
+ break;
+ }
+ case POPPCREL:
+ if (feeble[POPPCREL])
+ {
+ emulate();
+ } else
+ {
+ setPc(popIntStack()+getPc());
+ }
+ break;
+ case FLIP:
+ pushIntStack(flip(popIntStack()));
+ break;
+ case ADD:
+ pushIntStack(popIntStack() + popIntStack());
+ break;
+ case SUB:
+ if (feeble[SUB])
+ {
+ emulate();
+ } else
+ {
+ int a=popIntStack();
+ int b=popIntStack();
+ pushIntStack(b-a);
+ }
+ break;
+ case PUSHSP:
+ pushIntStack(getSp());
+ break;
+ case POPSP:
+ changeSp(popIntStack());
+ intSp=0; // flush internal stack
+ break;
+ case NOP:
+ break;
+ case AND:
+ pushIntStack(popIntStack() & popIntStack());
+ break;
+ case XOR:
+ if (feeble[XOR])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack(popIntStack() ^ popIntStack());
+ }
+ break;
+ case LOADB:
+ if (feeble[LOADB])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack(cpuReadByte(popIntStack()));
+ }
+ break;
+ case STOREB:
+ if (feeble[STOREB])
+ {
+ emulate();
+ } else
+ {
+ addr = popIntStack();
+ val = popIntStack();
+ cpuWriteByte(addr, val);
+ }
+ break;
+ case LOADH:
+ if (feeble[LOADH])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack(cpuReadWord(popIntStack()));
+ }
+ break;
+ case STOREH:
+ if (feeble[STOREH])
+ {
+ emulate();
+ } else
+ {
+ addr = popIntStack();
+ val = popIntStack();
+ cpuWriteWord(addr, val);
+ }
+ break;
+ case LESSTHAN:
+ if (feeble[LESSTHAN])
+ {
+ emulate();
+ } else
+ {
+ int a;
+ int b;
+ a = popIntStack();
+ b = popIntStack();
+ pushIntStack((a < b) ? 1 : 0);
+ }
+ break;
+ case LESSTHANOREQUAL:
+ if (feeble[LESSTHANOREQUAL])
+ {
+ emulate();
+ } else
+ {
+ int a;
+ int b;
+ a = popIntStack();
+ b = popIntStack();
+ pushIntStack((a <= b) ? 1 : 0);
+ }
+ break;
+ case ULESSTHAN:
+ if (feeble[ULESSTHAN])
+ {
+ emulate();
+ } else
+ {
+ long a;
+ long b;
+ a = ((long) popIntStack()) & INTMASK;
+ b = ((long) popIntStack()) & INTMASK;
+ pushIntStack((a < b) ? 1 : 0);
+ }
+ break;
+ case ULESSTHANOREQUAL:
+ if (feeble[ULESSTHANOREQUAL])
+ {
+ emulate();
+ } else
+ {
+ long a;
+ long b;
+ a = ((long) popIntStack()) & INTMASK;
+ b = ((long) popIntStack()) & INTMASK;
+ pushIntStack((a <= b) ? 1 : 0);
+ }
+ break;
+
+ case SWAP:
+// if (feeble[SWAP])
+// {
+// emulate();
+// } else
+ {
+ int swapVal=popIntStack();;
+ pushIntStack(((swapVal >>16)&0xffff)|(swapVal<<16));
+ }
+ break;
+ case MULT16X16:
+// if (feeble[SWAP])
+// {
+// emulate();
+// } else
+ {
+ int a=popIntStack();
+ int b=popIntStack();
+ pushIntStack((a&0xffff)*(b&0xffff));
+ }
+ break;
+ case EQBRANCH:
+ if (feeble[EQBRANCH])
+ {
+ emulate();
+ } else
+ {
+ int compare;
+ int target;
+ target = popIntStack() + pc;
+ compare = popIntStack();
+ if (compare == 0)
+ {
+ setPc(target);
+ } else
+ {
+ setPc(pc + 1);
+ }
+ }
+ break;
+
+ case NEQBRANCH:
+ if (feeble[NEQBRANCH])
+ {
+ emulate();
+ } else
+ {
+ int compare;
+ int target;
+ target = popIntStack() + pc;
+ compare = popIntStack();
+ if (compare != 0)
+ {
+ setPc(target);
+ } else
+ {
+ setPc(pc + 1);
+ }
+ }
+ break;
+
+ case MULT:
+ if (feeble[MULT])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack(popIntStack() * popIntStack());
+ }
+ break;
+ case DIV:
+ if (feeble[DIV])
+ {
+ emulate();
+ } else
+ {
+ int a;
+ int b;
+ a = popIntStack();
+ b = popIntStack();
+ if (b == 0)
+ {
+ throw new CPUException();
+ }
+ pushIntStack(a / b);
+ }
+ break;
+ case MOD:
+ if (feeble[MOD])
+ {
+ emulate();
+ } else
+ {
+ int a;
+ int b;
+ a = popIntStack();
+ b = popIntStack();
+ if (b == 0)
+ {
+ throw new CPUException();
+ }
+ pushIntStack(a % b);
+ }
+ break;
+
+ case LSHIFTRIGHT:
+ if (feeble[LSHIFTRIGHT])
+ {
+ emulate();
+ } else
+ {
+ long shift;
+ long valX;
+ int t;
+ shift = ((long) popIntStack()) & INTMASK;
+ valX = ((long) popIntStack()) & INTMASK;
+ t = (int) (valX >> (shift & 0x3f));
+ pushIntStack(t);
+ }
+ break;
+
+ case ASHIFTLEFT:
+ if (feeble[ASHIFTLEFT])
+ {
+ emulate();
+ } else
+ {
+ long shift;
+ long valX;
+ shift = ((long) popIntStack()) & INTMASK;
+ valX = ((long) popIntStack()) & INTMASK;
+ int t = (int) (valX << (shift & 0x3f));
+ pushIntStack(t);
+ }
+ break;
+
+ case ASHIFTRIGHT:
+ if (feeble[ASHIFTRIGHT])
+ {
+ emulate();
+ } else
+ {
+ long shift;
+ int valX;
+ shift = ((long) popIntStack()) & INTMASK;
+ valX = popIntStack();
+ int t = valX >> (shift & 0x3f);
+ pushIntStack(t);
+ }
+ break;
+
+ case CALL:
+ if (feeble[CALL])
+ {
+ emulate();
+ } else
+ {
+ intSp=0; // flush internal stack
+ int address = pop();
+ push(pc + 1);
+ setPc(address);
+ }
+ break;
+ case CALLPCREL:
+ if (feeble[CALLPCREL])
+ {
+ emulate();
+ } else
+ {
+ intSp=0; // flush internal stack
+ int address = pop();
+ push(pc + 1);
+ setPc(address+pc);
+ }
+ break;
+
+ case EQ:
+ if (feeble[EQ])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack((popIntStack() == popIntStack()) ? 1 : 0);
+ }
+ break;
+
+ case NEQ:
+ if (feeble[NEQ])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack((popIntStack() != popIntStack()) ? 1 : 0);
+ }
+ break;
+
+ case NEG:
+ if (feeble[NEG])
+ {
+ emulate();
+ } else
+ {
+ pushIntStack(-popIntStack());
+ }
+ break;
+
+
+ case CONFIG:
+ if (emulateConfig())
+ {
+ emulate();
+ cpu=ABEL;
+ } else
+ {
+ cpu = popIntStack();
+ }
+ switch (cpu)
+ {
+ case ABEL:
+ System.err.println("ZPU feeble instruction set");
+ for (int i = 0; i < feeble.length; i++)
+ {
+ feeble[i] = true;
+ }
+
+ setFeeble();
+
+ break;
+ case ZETA:
+ System.err.println("ZPU full instruction set");
+ for (int i = 0; i < feeble.length; i++)
+ {
+ feeble[i] = false;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case SYSCALL:
+ if (feeble[SYSCALL])
+ {
+ throw new IllegalInstructionException();
+ } else
+ {
+ intSp=0; // flush internal stack
+ syscall.syscall(this);
+ }
+ break;
+
+ default:
+ throw new IllegalInstructionException();
+ }
+ }
+ }
+ if (!touchedPc)
+ {
+ setPc(pc + 1);
+ }
+ committed();
+
+ // one more instruction retired
+ instructionCount++;
+ }
+ }
+
+
+ protected void setFeeble()
+ {
+ feeble[NEQBRANCH] = false;
+ feeble[EQ] = false;
+ feeble[LOADB] = false;
+ feeble[LESSTHAN] = false;
+ feeble[ULESSTHAN] = false;
+ feeble[STOREB] = false;
+ feeble[MULT] = false;
+ feeble[CALL] = true;
+ feeble[POPPCREL] = true;
+ feeble[LESSTHANOREQUAL] = true;
+ feeble[ULESSTHANOREQUAL] = true;
+
+ feeble[PUSHSPADD] = false;
+ feeble[CALLPCREL] = false;
+ feeble[SUB] = false;
+ }
+
+
+ private int popIntOrExt()
+ {
+ int a;
+ if (intSp==0)
+ {
+ a=pop();
+ } else
+ {
+ a=popIntStack();
+ }
+ return a;
+ }
+
+ int intSp;
+
+ private int emulateSp;
+
+ private int emulateOpcode;
+
+ private boolean emulateInProgress;
+
+ protected boolean timerPending;
+
+ private boolean inInterrupt;
+ private int popIntStack()
+ {
+// if (intSp<=0)
+// throw new IllegalInstructionException();
+ intSp--;
+ return pop();
+ }
+
+ private void pushIntStack(int x)
+ {
+// if (intSp>=32)
+// throw new IllegalInstructionException();
+ push(x);
+ intSp++;
+ }
+
+
+
+ private static boolean isAddSP(int instruction)
+ {
+ return (instruction >= ADDSP) && (instruction < ADDSP + 16);
+ }
+
+
+ private static boolean isStoreSP(int instruction)
+ {
+ return (instruction >= STORESP) && (instruction < STORESP + 32);
+ }
+
+
+ protected boolean emulateConfig()
+ {
+ return false;
+ }
+
+
+ private void checkCommit() throws CPUException
+ {
+ if (!commit)
+ {
+ decodeMask=savedDecodeMask;
+ pc=savedPc;
+ setSp(savedSp);
+ committed();
+ }
+ }
+
+
+ private void committed()
+ {
+ commit=true;
+ tracer.commit();
+ }
+
+
+ private void emulate() throws CPUException
+ {
+ // NB! Do NOT flush internal stack
+// intSp=0; // flush internal stack
+ /* three total overhead to emulate instruction */
+ if (!emulateInProgress)
+ {
+ emulateInProgress=true;
+ emulateSp = sp;
+ emulateOpcode = getOpcode();
+ emulateCycles = cycles;
+ }
+ pushIntStack(pc+1);
+ setPc((cpuReadByte(pc)-32)*VECTORSIZE+VECTORBASE);
+ }
+
+
+
+ private void checkInterrupts() throws InterruptException
+ {
+ if (!tracer.simInterrupt())
+ {
+ /* These flags are set *regardless* of interrupt state. */
+ while (lastTimer+timerInterval<cycles)
+ {
+ if (timerInterval>0)
+ {
+ lastTimer+=timerInterval;
+ } else
+ {
+ lastTimer=cycles;
+ }
+ timerPending=true;
+ }
+ }
+
+ if (!interrupt)
+ return;
+
+ /* if we are in the middle of decoding an instruction, no interrupt */
+ if (decodeMask)
+ {
+ return;
+ }
+ if (tracer.simInterrupt())
+ {
+ if (!tracer.onInterrupt())
+ {
+ inInterrupt=false;
+ }
+ if (inInterrupt)
+ {
+ return;
+ }
+ /* Use trace information instead of trying to figure out when an interrupt happens. We don't try
+ * to simulate anything more complicated than timer interrupts so we don't need to worry about source.
+ */
+
+ if (tracer.onInterrupt()&&!inInterrupt)
+ {
+ if (!timer)
+ {
+ throw new IllegalInstructionException();
+ }
+
+ inInterrupt=true;
+ timerPending=true;
+ throw new InterruptException();
+ }
+
+ } else
+ {
+ if (!timerPending)
+ inInterrupt=false;
+
+ if (inInterrupt)
+ {
+ return;
+ }
+
+ if (timer&&timerPending)
+ {
+ inInterrupt=true;
+ throw new InterruptException();
+ }
+ }
+ }
+
+
+
+
+ private void cpuWriteWord(int addr, int val) throws MemoryAccessException
+ {
+ if ((addr&0x1)!=0)
+ {
+ throw new MemoryAccessException();
+ }
+ for (int i=0; i<2; i++)
+ {
+ writeByte(addr+i, val>>(8*(1-i)));
+ }
+ }
+
+ /**
+ * @param i
+ * @return
+ * @throws MemoryAccessException
+ */
+ private int cpuReadWord(int addr) throws MemoryAccessException
+ {
+ if ((addr&0x1)!=0)
+ {
+ throw new MemoryAccessException();
+ }
+ return ((readByteInternal(addr+0)&0xff)<<8) | (readByteInternal(addr+1)&0xff);
+ }
+
+ private void cpuWriteByte(int addr, int val) throws MemoryAccessException
+ {
+ writeByte(addr, val);
+ }
+
+
+ protected boolean interrupt;
+ protected long timerInterval;
+ private boolean touchedPc;
+
+ private boolean accessWatchPoint;
+
+ private int accessWatchPointAddress;
+
+ private int accessWatchPointLength;
+
+ private boolean commit;
+
+ private boolean savedDecodeMask;
+
+ private int savedSp;
+
+ private int savedPc;
+
+ private long[] profile;
+
+ private int cpu;
+
+ private long sampledCycle;
+
+ private Tracer tracer=new Tracer()
+ {
+
+ public void instructionEvent()
+ {
+
+ }
+
+ public void commit()
+ {
+ }
+
+ public void setSp(int sp)
+ {
+ }
+
+ public void dumpTraceBack()
+ {
+
+ }
+
+ public boolean onInterrupt()
+ {
+ return false;
+ }
+
+ public boolean simInterrupt()
+ {
+ return false;
+ }
+
+ };
+
+ private int instruction;
+
+ private long totalCycles;
+
+
+ private String traceFileName;
+
+ private int prevOpcode;
+
+ private long prevCycles2;
+
+ private int prevOpcode2;
+
+
+
+
+ /**
+ * checks if the CPU should halt, and halts. Fn. returns when the
+ * CPU has resumed execution.
+ * @throws EndSessionException
+ */
+ private void checkHalt() throws EndSessionException
+ {
+ synchronized(halt)
+ {
+ if (powerdown)
+ {
+ throw new EndSessionException();
+ }
+
+ if (breakNext)
+ {
+ breakNext=false;
+
+ halt.notify();
+ try
+ {
+ syscall.halted();
+ halt.wait();
+ syscall.running();
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ if (powerdown)
+ {
+ throw new EndSessionException();
+ }
+ }
+ }
+
+ private int flip(int i)
+ {
+ int t=0;
+ for (int j=0; j<32; j++)
+ {
+ t|=((i>>j)&1)<<(31-j);
+ }
+ return t;
+ }
+
+ /** the CPU is writing a long during execution */
+ public void cpuWriteLong(int addr, int val) throws MemoryAccessException
+ {
+ if (accessWatchPoint&&(addr==accessWatchPointAddress))
+ {
+ suspend();
+ }
+ if ((addr&0x3)!=0)
+ {
+ throw new MemoryAccessException();
+ }
+ if ((addr>=getIO())&&(addr<getIO()+IOSIZE))
+ {
+ ioWrite(addr, val);
+ } else if ((addr>=0)&&(addr<=memory.length*4))
+ {
+ memory[addr/4]=val;
+ validMemory[addr/4]=true;
+ } else
+ {
+ throw new MemoryAccessException();
+ }
+ }
+
+ public void writeByte(int addr, int val) throws MemoryAccessException
+ {
+ if ((addr>=0)&&(addr<memory.length*4))
+ {
+ memory[addr/4]=(memory[addr/4]&(~(0xff<<((3-addr&3)*8))))|((val&0xff)<<((3-addr&3)*8));
+ } else
+ {
+ throw new MemoryAccessException();
+ }
+ }
+
+ protected void ioWrite(int addr, int val) throws MemoryAccessException
+ {
+ addr-=getIO();
+ /* note, big endian! */
+ switch (addr)
+ {
+ case 12:
+ syscall.writeUART(val);
+ break;
+ case 20:
+ interrupt=val!=0;
+ break;
+ case 28:
+ timerInterval=val;
+ break;
+ case 32:
+ timer=val!=0;
+ break;
+ case 0x24:
+ syscall.writeUART(val);
+ break;
+ case 0x100:
+ writeTimerSampleReg(val);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+
+
+
+ protected void writeTimerSampleReg(int val)
+ {
+ if ((val&0x2)!=0)
+ {
+ sampledCycle=getSampleOffset(); // we need a fudge factor to make up for differences in when relative to the instruction the data is sampled.
+ }
+ }
+
+
+ protected long getSampleOffset()
+ {
+ return cycles+2+0xd-(0x8e-0x74);
+ }
+
+
+
+ protected int ioRead(int addr) throws CPUException
+ {
+ addr-=getIO();
+ /* note, big endian! */
+ switch (addr)
+ {
+ case 20:
+ return interrupt?1:0;
+
+ case 32:
+ return timer?1:0;
+
+ case 0x24:
+ return syscall.readUART();
+
+ /* FIFO empty? bit 0, FIFO full bit 1(never the case) */
+ case 0x28:
+ return syscall.readFIFO();
+
+ case 0x100:
+ case 0x104:
+ case 0x108:
+ case 0x10c:
+
+ case 0x110:
+ case 0x114:
+ case 0x118:
+ case 0x11c:
+ return readSampledTimer(addr, 0x100);
+
+ case 0x200:
+ return readMHz();
+
+ default:
+ throw new MemoryAccessException();
+ }
+ }
+
+
+
+
+ protected int readMHz()
+ {
+ /* 90 MHz */
+ return 100;
+ }
+
+
+ protected int readSampledTimer(int addr, int base)
+ {
+ int t=0;
+ t=(int)((sampledCycle>>(((addr-base)/4)*32))&0xffffffff);
+ return t;
+ }
+
+
+
+ private int cpuReadByte(int addr) throws MemoryAccessException
+ {
+ return readByteInternal(addr);
+ }
+
+
+ /** this is the CPU reading a long word during execution */
+ public int cpuReadLong(int addr) throws CPUException
+ {
+ if (accessWatchPoint&&(addr==accessWatchPointAddress))
+ {
+ suspend();
+ }
+ if ((addr&0x3)!=0)
+ {
+ throw new MemoryAccessException();
+ }
+ if ((addr>=getIO())&&(addr<getIO()+IOSIZE))
+ {
+ return ioRead(addr);
+ } else if ((addr>=0)&&(addr<=memory.length*4))
+ {
+ return memory[addr/4];
+ } else
+ {
+ throw new MemoryAccessException();
+ }
+ }
+
+ /**
+ * Causes a cycle to pass.
+ * @throws MemoryAccessException
+ */
+ /** increase time and record how long we spent on this instruction */
+ private void tick() throws MemoryAccessException
+ {
+ profile[pc]++;
+ int opcode;
+ opcode=readByte(pc);
+ opcodeHistogram[prevOpcode]++;
+ opcodeHistogramCycles[prevOpcode]+=cycles-prevCycles;
+ int opcodePair=groupOpcode(prevOpcode2)*256+groupOpcode(prevOpcode);
+
+ opcodePairHistogram[opcodePair]++;
+ opcodePairHistogramCycles[opcodePair]+=cycles-prevCycles2;
+
+ prevOpcode2=prevOpcode;
+ prevOpcode=opcode;
+
+
+
+ prevCycles2=prevCycles;
+ prevCycles=cycles;
+ cycles++;
+ }
+
+ private int groupOpcode(int instruction)
+ {
+ if (isAddSP(instruction))
+ {
+ return ADDSP;
+ } else if ((instruction >= LOADSP) && (instruction < LOADSP + 32))
+ {
+ return LOADSP;
+ } else if (isStoreSP(instruction))
+ {
+ return STORESP;
+ }
+
+ if ((instruction&0x80)!=0)
+ return 0x80;
+ return instruction;
+ }
+
+
+ public int readByte(int addr) throws MemoryAccessException
+ {
+ if ((addr>=0)&&(addr<memory.length*4))
+ {
+ return readByteInternal(addr);
+ } else
+ {
+ throw new MemoryAccessException();
+ }
+ }
+
+
+ protected int readByteInternal(int addr) throws MemoryAccessException
+ {
+ return (memory[addr/4]>>((3-addr&0x3)*8))&0xff;
+ }
+
+ private int pop() throws CPUException
+ {
+ int val;
+ validMemory[getSp()/4]=false;
+ val=cpuReadLong(getSp());
+ setSp(getSp() + 4);
+ return val;
+ }
+
+ private void push(int imm) throws CPUException
+ {
+ setSp(getSp() - 4);
+ cpuWriteLong(getSp(), imm);
+ }
+
+ private final class OpcodeSample
+ {
+ private final int j;
+
+ int opcode;
+
+ long count;
+
+ private OpcodeSample(int j, long l)
+ {
+ this.j = j;
+ opcode = j;
+ count = l;
+ }
+ }
+
+
+
+
+ private void initRam()
+ {
+ memory = (new int[getRAMSIZE()/4]);
+ validMemory = new boolean[getRAMSIZE()/4];
+ for (int i=0; i<validMemory.length; i++)
+ {
+ validMemory[i]=true;
+ }
+
+ profile = new long[getRAMSIZE()];
+ }
+
+
+
+ public void setPc(int pc) throws MemoryAccessException
+ {
+ if ((pc<VECTORBASE)||(pc>memory.length*4))
+ {
+ throw new MemoryAccessException();
+ }
+ this.pc = pc;
+ touchedPc=true;
+ }
+
+ public int getPc()
+ {
+ return pc;
+ }
+
+ /** resume execution. This function returns when the CPU halts again. */
+ public void cont()
+ {
+ for (;;)
+ {
+ synchronized(halt)
+ {
+ halt.notify();
+ try
+ {
+ halt.wait();
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ if (syscall.doneContinue())
+ {
+ break;
+ }
+ }
+ }
+
+ /** resume execution. This function returns when the CPU halts again. */
+ public void step()
+ {
+ synchronized(halt)
+ {
+ suspend();
+ cont();
+ }
+ }
+
+
+
+ public int getReg(int regNum) throws CPUException
+ {
+ if ((regNum>=0)&&(regNum<32))
+ {
+ return memory[regNum];
+ } else if (regNum==32)
+ {
+ return getSp();
+ } else if (regNum==33)
+ {
+ return pc;
+ } else
+ {
+ throw new RuntimeException("Illegal getReg()");
+ }
+ }
+
+ public int getREGNUM()
+ {
+ return 34;
+ }
+
+ public long getCycleCounter()
+ {
+ return cycles;
+ }
+
+ public void addWaitStates(int num)
+ {
+ }
+
+ /** tells simulator to enter the suspended state */
+ public void suspend()
+ {
+ synchronized(halt)
+ {
+ breakNext=true;
+ }
+// tracer.dumpTraceBack();
+ }
+
+
+ public long getPrevCycles()
+ {
+ return prevCycles;
+ }
+
+ public long getCycles()
+ {
+ return cycles;
+ }
+
+
+ public void enableAccessWatchPoint(int address, int length) throws CPUException
+ {
+ if (accessWatchPoint)
+ {
+ throw new HardwareWatchPointException();
+ }
+ accessWatchPointAddress=address;
+ accessWatchPointLength=length;
+ accessWatchPoint=true;
+ }
+ public void disableAccessWatchPoint(int address, int length) throws CPUException
+ {
+ if (!accessWatchPoint)
+ {
+ throw new HardwareWatchPointException();
+ }
+ if ((address!=accessWatchPointAddress)||(length!=accessWatchPointLength))
+ {
+ throw new HardwareWatchPointException();
+ }
+
+ accessWatchPoint=false;
+ }
+
+ /** POPSP changes the stack pointer */
+ public void changeSp(int sp) throws CPUException
+ {
+ setSp(sp);
+ tracer.setSp(sp);
+ }
+
+ public void setSp(int sp) throws CPUException
+ {
+ if ((sp%4)!=0)
+ {
+ throw new IllegalInstructionException();
+ }
+
+ if (sp<minStack)
+ {
+ minStack=sp;
+ }
+
+
+ this.sp = sp;
+ }
+
+
+ public int getSp()
+ {
+ return sp;
+ }
+ public int getIntSp()
+ {
+ return (intSp+(INTSTACKSIZE-1))%INTSTACKSIZE;
+ }
+
+
+
+
+ protected int getIO()
+ {
+ return 0x80000000;
+ }
+
+
+ protected int getRAMSIZE()
+ {
+ return (2*1024*1024);
+ }
+
+ protected int getStartStack()
+ {
+ return memory.length*4-0x10000;
+ }
+
+
+ public void setTraceFile(String string)
+ {
+ traceFileName=string;
+ }
+
+
+ public void setSyscall(Host syscall)
+ {
+ this.syscall=syscall;
+ }
+
+
+ public void loadImage(InputStream inputStream, int length) throws IOException, CPUException
+ {
+ if (length==-1)
+ throw new IOException("File image length not known");
+ for (int i=0; i<length; i++)
+ {
+ int t=inputStream.read();
+ writeByte(0+i, t);
+ }
+
+ }
+
+ public int getArg(int num) throws CPUException
+ {
+ return cpuReadLong(getSp()+4+num*4);
+ }
+
+
+ public int getOpcode() throws MemoryAccessException
+ {
+ return readByte(pc);
+ }
+
+ static final int INTSTACKSIZE=32;
+
+ public boolean checkMatch(Trace trace)
+ {
+ cycles=trace.cycle;
+ if (!trace.undefinedIntSp)
+ {
+ if (trace.intSp!=((intSp+(INTSTACKSIZE-1))%INTSTACKSIZE))
+ return false;
+ }
+
+ if ((getPc() != trace.pc) || (getSp() != trace.sp)
+ || (getOpcode() != trace.opcode))
+ {
+ return false;
+ }
+
+ if (cpuReadLong(getSp()) == trace.stackA)
+ {
+ if (cpuReadLong(getSp() + 4) == trace.stackB)
+ {
+ return true;
+ }
+ }
+ if ((!validMemory[getSp()/4])||cpuReadLong(getSp()) == trace.stackA)
+ {
+ if ((!validMemory[(getSp()+4)/4])||cpuReadLong(getSp() + 4) == trace.stackB)
+ {
+// System.out.println("Undefined memory location mismatch");
+ return true;
+ }
+ }
+ if (!trace.undefinedIntSp)
+ {
+ if ((intSp<1)||cpuReadLong(getSp()) == trace.stackA)
+ {
+ if ((intSp<2)||cpuReadLong(getSp() + 4) == trace.stackB)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public void sessionStarted()
+ {
+ if (traceFileName!=null)
+ {
+ tracer = new FileTracer(this, traceFileName);
+ }
+
+ /* Set the feeble flag to enable/disable instructions here */
+ initRam();
+ resetHardwareInternal();
+
+
+
+ }
+
+
+ void printState(FileTracer fileTracer)
+ {
+ System.err.println("intSp: " + getIntSp());
+ System.err.println(Integer.toHexString(getPc())+ " " +
+ Integer.toHexString(getOpcode()) + " " +
+ Integer.toHexString(getSp()) + " " +
+ Integer.toHexString(cpuReadLong(getSp())) + " " +
+ Integer.toHexString(cpuReadLong(getSp()+4)));
+ }
+
+
+
+
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/State.java b/zpu/sw/simulator/com/zylin/zpu/simulator/State.java
new file mode 100644
index 0000000..c2cb9f4
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/State.java
@@ -0,0 +1,9 @@
+package com.zylin.zpu.simulator;
+
+
+public class State
+{
+
+ public long cycle;
+ public int insn;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/Tracer.java b/zpu/sw/simulator/com/zylin/zpu/simulator/Tracer.java
new file mode 100644
index 0000000..31f1766
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/Tracer.java
@@ -0,0 +1,21 @@
+
+package com.zylin.zpu.simulator;
+
+import com.zylin.zpu.simulator.exceptions.GDBServerException;
+
+public interface Tracer
+{
+
+ void instructionEvent() throws GDBServerException;
+
+ void commit();
+
+ void setSp(int sp);
+
+ void dumpTraceBack();
+
+
+ boolean onInterrupt();
+
+ boolean simInterrupt();
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/ZPU.java b/zpu/sw/simulator/com/zylin/zpu/simulator/ZPU.java
new file mode 100644
index 0000000..84a1ca5
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/ZPU.java
@@ -0,0 +1,14 @@
+package com.zylin.zpu.simulator;
+
+public interface ZPU
+{
+ /**
+ * number of cycles passed since reboot
+ */
+ long getCycleCounter();
+
+ /**
+ * Wait this many cycles
+ */
+ void addWaitStates(int i);
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/applet/ZPUApplet.java b/zpu/sw/simulator/com/zylin/zpu/simulator/applet/ZPUApplet.java
new file mode 100644
index 0000000..731c8fc
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/applet/ZPUApplet.java
@@ -0,0 +1,281 @@
+
+package com.zylin.zpu.simulator.applet;
+
+import java.applet.Applet;
+import java.awt.TextArea;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.swing.SwingUtilities;
+
+import com.zylin.zpu.simulator.Host;
+import com.zylin.zpu.simulator.Sim;
+import com.zylin.zpu.simulator.Simulator;
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.UnsupportedSyscallException;
+
+public class ZPUApplet extends Applet implements Host
+{
+
+ private static final long serialVersionUID = 1L;
+ private TextArea console;
+ private Simulator simulator;
+ private PipedOutputStream outputPipe;
+ private PipedInputStream inputPipe;
+
+ public void init()
+ {
+ super.init();
+
+ console=new TextArea();
+ //console.setEditable(false);
+
+
+ console.addKeyListener(new KeyListener()
+ {
+
+ public void keyPressed(KeyEvent e)
+ {
+ try
+ {
+ outputPipe.write((int)e.getKeyChar());
+ } catch (Throwable e1)
+ {
+ e1.printStackTrace();
+ }
+
+ }
+
+ public void keyReleased(KeyEvent e)
+ {
+
+ }
+
+ public void keyTyped(KeyEvent e)
+ {
+
+ }
+ });
+
+ //Add the text field to the applet.
+ add(console);
+
+ //Set the layout manager so that the text field will be
+ //as wide as possible.
+ setLayout(new java.awt.GridLayout(1,0));
+
+ validate();
+ initSimulator();
+
+ }
+
+
+
+
+
+ public void start()
+ {
+ super.start();
+ }
+
+
+
+
+
+ public void stop()
+ {
+ simulator.shutdown();
+ super.stop();
+ }
+
+ private void initSimulator()
+ {
+ final ZPUApplet me = this;
+
+ try
+ {
+ outputPipe = new PipedOutputStream();
+ inputPipe = new PipedInputStream(outputPipe);
+
+ showStatus("Loading ZPU binary image...");
+
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ // lineReader=new LineNumberReader(new
+ // InputStreamReader(inputPipe));
+
+ simulator = new Simulator();
+ simulator.setSyscall(me);
+
+ String file = getParameter("executable");
+
+ URL url;
+ url = new URL(getCodeBase(), file);
+ showStatus("Loading: " + url.toString() +"...");
+
+ URLConnection connection = url.openConnection();
+
+ simulator.loadImage(connection.getInputStream(), connection.getContentLength());
+
+ simulator.run();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ thread.start();
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void syscall(Sim s) throws CPUException
+ {
+ int retval=-1;
+ int syscallErrno=0;
+ int id;
+ id=simulator.getArg(1);
+ try
+ {
+ switch (id)
+ {
+ case SYS_write:
+ writeToConsole();
+ retval=simulator.getArg(4);
+ break;
+ case SYS_read:
+ int i;
+ for (i=0; i<simulator.getArg(4); i++)
+ {
+ int t=inputPipe.read();
+ simulator.writeByte(simulator.getArg(3)+i, t);
+ if ((t=='\n')||(t=='\r'))
+ {
+ /* done reading line */
+ i++;
+ break;
+ }
+ }
+ retval=i;
+ break;
+
+ case SYS_fstat:
+ syscallErrno=EIO;
+ retval=-1;
+ break;
+
+ default:
+ simulator.suspend();
+ throw new UnsupportedSyscallException();
+ }
+ }
+ catch (IOException e)
+ {
+ retval=-1;
+ syscallErrno=EIO;
+ }
+ simulator.cpuWriteLong(simulator.getArg(0), syscallErrno);
+ simulator.cpuWriteLong(0, retval);
+ }
+
+ private void writeToConsole() throws CPUException
+ {
+ String t="";
+ for (int i=0; i<simulator.getArg(4); i++)
+ {
+ t+=(char)simulator.readByte(simulator.getArg(3)+i);
+ }
+ final String t2=t;
+ System.out.println(t2);
+ try {
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+ public void run()
+ {
+ console.append(t2);
+ }
+ });
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+
+
+
+ public boolean doneContinue()
+ {
+ return false;
+ }
+
+
+ public void writeUART(final int val)
+ {
+ try {
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+
+ public void run()
+ {
+ console.append(""+(char)(val));
+ repaint();
+
+ }
+ });
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+
+
+ public int readUART() throws CPUException
+ {
+ try
+ {
+ return inputPipe.read();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ throw new CPUException();
+ }
+ }
+
+
+
+
+
+ public int readFIFO()
+ {
+ return 0;
+ }
+
+ public void halted()
+ {
+ showStatus("ZPU application halted");
+ }
+
+ public void running()
+ {
+ showStatus("ZPU application running...");
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/BadPacketException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/BadPacketException.java
new file mode 100644
index 0000000..2e66ab4
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/BadPacketException.java
@@ -0,0 +1,22 @@
+/*
+ * Created on Nov 6, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class BadPacketException extends GDBServerException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3258131340821214260L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/CPUException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/CPUException.java
new file mode 100644
index 0000000..6a3f4fe
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/CPUException.java
@@ -0,0 +1,23 @@
+/*
+ * Created on Oct 23, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class CPUException extends GDBServerException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/DebuggerBreakpointException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/DebuggerBreakpointException.java
new file mode 100644
index 0000000..2360fa8
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/DebuggerBreakpointException.java
@@ -0,0 +1,10 @@
+package com.zylin.zpu.simulator.exceptions;
+
+public class DebuggerBreakpointException extends CPUException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/EndSessionException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/EndSessionException.java
new file mode 100644
index 0000000..13fc875
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/EndSessionException.java
@@ -0,0 +1,46 @@
+/*
+ * Created on Nov 16, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class EndSessionException extends Exception
+{
+
+ public EndSessionException()
+ {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public EndSessionException(String arg0, Throwable arg1)
+ {
+ super(arg0, arg1);
+ // TODO Auto-generated constructor stub
+ }
+
+ public EndSessionException(String arg0)
+ {
+ super(arg0);
+ // TODO Auto-generated constructor stub
+ }
+
+ public EndSessionException(Throwable arg0)
+ {
+ super(arg0);
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/GDBServerException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/GDBServerException.java
new file mode 100644
index 0000000..8232790
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/GDBServerException.java
@@ -0,0 +1,25 @@
+package com.zylin.zpu.simulator.exceptions;
+
+
+public class GDBServerException extends RuntimeException
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public GDBServerException(NumberFormatException e)
+ {
+ super(e);
+ }
+
+ public GDBServerException()
+ {
+
+ }
+
+ public GDBServerException(Exception e)
+ {
+ super(e);
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/HardwareWatchPointException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/HardwareWatchPointException.java
new file mode 100644
index 0000000..a4ad3b2
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/HardwareWatchPointException.java
@@ -0,0 +1,12 @@
+
+package com.zylin.zpu.simulator.exceptions;
+
+public class HardwareWatchPointException extends CPUException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/IllegalInstructionException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/IllegalInstructionException.java
new file mode 100644
index 0000000..a8d0802
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/IllegalInstructionException.java
@@ -0,0 +1,23 @@
+/*
+ * Created on Oct 23, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class IllegalInstructionException extends CPUException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/InterruptException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/InterruptException.java
new file mode 100644
index 0000000..bd74f04
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/InterruptException.java
@@ -0,0 +1,23 @@
+/*
+ * Created on 02.jan.2005
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class InterruptException extends CPUException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/MemoryAccessException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/MemoryAccessException.java
new file mode 100644
index 0000000..4c9ebae
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/MemoryAccessException.java
@@ -0,0 +1,23 @@
+/*
+ * Created on Oct 23, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class MemoryAccessException extends CPUException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/NoAckException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/NoAckException.java
new file mode 100644
index 0000000..377f9de
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/NoAckException.java
@@ -0,0 +1,22 @@
+/*
+ * Created on Nov 6, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.exceptions;
+
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class NoAckException extends GDBServerException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/TraceException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/TraceException.java
new file mode 100644
index 0000000..45fda54
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/TraceException.java
@@ -0,0 +1,22 @@
+
+package com.zylin.zpu.simulator.exceptions;
+
+
+public class TraceException extends GDBServerException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public TraceException(Exception e)
+ {
+ super(e);
+ }
+
+ public TraceException()
+ {
+ }
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnknownPacketException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnknownPacketException.java
new file mode 100644
index 0000000..af8a667
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnknownPacketException.java
@@ -0,0 +1,10 @@
+package com.zylin.zpu.simulator.exceptions;
+
+public class UnknownPacketException extends GDBServerException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnsupportedSyscallException.java b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnsupportedSyscallException.java
new file mode 100644
index 0000000..6b214f1
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/exceptions/UnsupportedSyscallException.java
@@ -0,0 +1,12 @@
+
+package com.zylin.zpu.simulator.exceptions;
+
+public class UnsupportedSyscallException extends CPUException
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java
new file mode 100644
index 0000000..182e426
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java
@@ -0,0 +1,364 @@
+/**
+ * Handles TCP/IP communication between simulator and GDB
+ */
+
+package com.zylin.zpu.simulator.gdb;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+
+import com.zylin.zpu.simulator.Host;
+import com.zylin.zpu.simulator.Sim;
+import com.zylin.zpu.simulator.SimApp;
+import com.zylin.zpu.simulator.exceptions.BadPacketException;
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.EndSessionException;
+import com.zylin.zpu.simulator.exceptions.GDBServerException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+import com.zylin.zpu.simulator.exceptions.UnsupportedSyscallException;
+
+public class GDBServer implements Host
+{
+ /* logging filter */
+ static final boolean UNKNOWN=false;
+ static final boolean ALL=false;
+ static final boolean CPUEXCEPTION = false;
+ static protected boolean MINIMAL=true;
+ static boolean PACKET=true;
+ static boolean REPLY=true;
+ static protected boolean IGNOREDEXCEPTIONS=false;
+
+
+
+ protected Throwable packetException;
+ protected Object packetReady=new Object();
+ private Packet packet;
+ boolean done;
+ private Socket sc;
+ public boolean alive;
+ static private int sessionNr;
+ private SimApp app;
+ Sim simulator;
+
+ public GDBServer(Sim simulator, SimApp app)
+ {
+ this.simulator=simulator;
+ this.app=app;
+ }
+
+ void print(boolean filter, String str)
+ {
+ if (filter)
+ {
+ System.out.println(str);
+ }
+ }
+
+ /** infinite loop that waits for debug sessions to be initiated via TCP/IP */
+ public void gdbServer() throws MemoryAccessException, IOException, GDBServerException, EndSessionException
+ {
+ sc=app.serverSocket.accept();
+ try
+ {
+ debugSession();
+ } catch (IOException e)
+ {
+ // the session failed...
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ } catch (GDBServerException e)
+ {
+ // connect failed...
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ } catch (EndSessionException e)
+ {
+ } catch (Throwable e)
+ {
+ // some terrible unforseen failure.
+ e.printStackTrace();
+ } finally
+ {
+ sc.close();
+ }
+ }
+
+
+
+ protected void sleepABit()
+ {
+ try
+ {
+ // just to avoid locking up the machine in a busy loop when
+ // debugging the Simulator
+ Thread.sleep(2000);
+ } catch (InterruptedException e1)
+ {
+ e1.printStackTrace();
+ }
+ }
+
+ private void debugSession() throws IOException, GDBServerException, EndSessionException, MemoryAccessException
+ {
+ print(MINIMAL, "GDB server waiting for connection " + sessionNr++ + "...");
+
+ try
+ {
+ sessionStarted();
+
+ expect('+'); // connection ack.
+
+ sessionLoop();
+ } finally
+ {
+ print(MINIMAL, "Session ended");
+ }
+
+ }
+
+ private void sessionStarted()
+ {
+ simulator.sessionStarted();
+ print(MINIMAL, "Session started");
+ }
+
+
+ private void sessionLoop() throws IOException, EndSessionException
+ {
+ alive=true;
+ while (alive)
+ {
+ try
+ {
+ /* wait for new packet to arrive and notify the packet execution thread... */
+ packet=new Packet(this);
+ packet.receive();
+
+ // During execution we can receive an abort/suspend command...
+ packet.parseAndExecute();
+
+ if (!alive)
+ throw new EndSessionException();
+ } catch (BadPacketException e)
+ {
+ // do nothing.
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ sleepABit();
+ } catch (GDBServerException e)
+ {
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ // continue processing packets
+ sleepABit();
+ }
+ }
+ }
+
+
+
+
+ void expect(char nextChar) throws IOException, GDBServerException
+ {
+ int t = read();
+ if (t!=nextChar)
+ {
+ throw new BadPacketException();
+ }
+ }
+
+ int read() throws IOException
+ {
+ flush();
+ int t=sc.getInputStream().read();
+ if (t==-1)
+ throw new IOException();
+ return t;
+ }
+
+ /**
+ * @param value
+ * @return
+ */
+ protected String printHex(int value)
+ {
+ return formatHex(value, "00000000");
+ }
+
+ /**
+ * @param value
+ * @param pad TODO
+ * @return
+ */
+ protected String formatHex(int value, String pad)
+ {
+ String t=Integer.toHexString(value);
+ if (t.length()>pad.length())
+ {
+ t=t.substring(0, pad.length());
+ }
+ return pad.substring(0, pad.length()-t.length())+t;
+ }
+
+ public void write(byte[] bytes) throws IOException
+ {
+ sc.getOutputStream().write(bytes);
+ }
+
+ void flush() throws IOException
+ {
+ sc.getOutputStream().flush();
+ }
+
+
+ private boolean enterSyscall;
+
+
+
+ /* handle all sorts of IO calls, etc. by sending them to the
+ */
+ public void syscall(Sim s) throws CPUException
+ {
+ simulator.suspend();
+ enterSyscall=true;
+ }
+
+
+ protected void performSyscall()
+ {
+ enterSyscall=false;
+ try
+ {
+ int id;
+ id=simulator.getArg(1);
+ Packet syscall;
+ syscall=new Packet(this);
+ switch (id)
+ {
+ case Host.SYS_write:
+ syscall.invokeSyscall("write", 3, "iii");
+ break;
+ case Host.SYS_read:
+ syscall.invokeSyscall("read", 3, "iii");
+ break;
+ case Host.SYS_lseek:
+ syscall.invokeSyscall("lseek", 3, "iii");
+ break;
+ case Host.SYS_open:
+ syscall.invokeSyscall("open", 3, "sii");
+ break;
+ case Host.SYS_close:
+ syscall.invokeSyscall("close", 1, "i");
+ break;
+ case Host.SYS_fstat:
+ syscall.invokeSyscall("fstat", 2, "ii");
+ break;
+ case Host.SYS_stat:
+ syscall.invokeSyscall("stat", 2, "si");
+ break;
+ case Host.SYS_isatty:
+ syscall.invokeSyscall("isatty", 1, "i");
+ break;
+ case Host.SYS_unlink:
+ syscall.invokeSyscall("unlink", 1, "s");
+ break;
+ default:
+ simulator.suspend();
+ throw new UnsupportedSyscallException();
+ }
+ simulator.cpuWriteLong(simulator.getArg(0), syscall.syscallErrno);
+ simulator.cpuWriteLong(0, syscall.syscallRetval);
+ } catch (CPUException e)
+ {
+ e.printStackTrace();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ } catch (GDBServerException e)
+ {
+ e.printStackTrace();
+ } catch (EndSessionException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean doneContinue()
+ {
+ if (!enterSyscall)
+ return true;
+ performSyscall();
+ return false;
+ }
+
+ public int getSyscallArg(int i) throws CPUException
+ {
+ return simulator.getArg(i+2);
+ }
+
+ public void writeUART(int val)
+ {
+ System.out.print((char)val);
+ System.out.flush();
+
+
+ Packet p=new Packet(this);
+ p.reply("O" + formatHex(val, "00"));
+ p.sendReply();
+
+
+ }
+ public int readUART() throws CPUException
+ {
+ try
+ {
+ if (System.in.available()<=0)
+ {
+ throw new MemoryAccessException();
+ }
+
+ return System.in.read();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ public int readFIFO()
+ {
+ try
+ {
+ return System.in.available()>0?0:1;
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ return 1;
+ }
+
+ public void halted()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void running()
+ {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java
new file mode 100644
index 0000000..ad68947
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java
@@ -0,0 +1,472 @@
+/*
+ * Created on Nov 16, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.gdb;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.zylin.zpu.simulator.exceptions.BadPacketException;
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.EndSessionException;
+import com.zylin.zpu.simulator.exceptions.GDBServerException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+import com.zylin.zpu.simulator.exceptions.NoAckException;
+import com.zylin.zpu.simulator.exceptions.UnknownPacketException;
+
+
+/** all packet related operations */
+class Packet
+{
+ private final GDBServer server;
+
+ Packet(GDBServer server)
+ {
+ this.server = server;
+ reply=new StringBuffer();
+ }
+
+ void receive() throws IOException, GDBServerException, EndSessionException
+ {
+ int t;
+ /* we spool until we see a $ */
+ this.server.expect('$');
+
+ StringBuffer packet=new StringBuffer();
+
+ int cc=0;
+ for (;;)
+ {
+ int t1;
+ t1=this.server.read();
+ t = t1;
+ if (t==0x7d)
+ {
+ int t2;
+ t2=this.server.read();
+ /* the next char is escaped after a GDB specific scheme. See
+ * gdb/gdb/remote.c */
+ t = t2;
+ t^=0x20;
+ } else
+ {
+ if (t=='#')
+ {
+ break;
+ }
+ }
+
+ cc+=t;
+
+ packet.append((char)t);
+ }
+ cc&=0xff;
+
+ String checkSum;
+ checkSum=""+(char)this.server.read()+(char)this.server.read();
+ int readCheckSum;
+ readCheckSum=Integer.parseInt(checkSum, 16);
+ if (readCheckSum!=cc)
+ {
+ // error
+ dumpHex(packet.toString());
+
+ this.server.write("-".getBytes());
+ throw new BadPacketException();
+ } else
+ {
+ // ack
+ this.server.write("+".getBytes());
+ }
+
+ cmd=packet.toString();
+ this.server.print(GDBServer.PACKET, "Got " + number + ": #$" + cmd + "#" + checkSum);
+ origCmd=cmd;
+ }
+
+ void parseAndExecute() throws IOException, EndSessionException
+ {
+ boolean silent=false;
+ try
+ {
+ if (checkPrefix("g"))
+ {
+ readRegisters();
+ } else if (checkPrefix("?"))
+ {
+ querySignal();
+ } else if (checkPrefix("s"))
+ {
+ doStep();
+ } else if (checkPrefix("m"))
+ {
+ try
+ {
+ readMemory();
+ } catch (CPUException e)
+ {
+ silent=true; // happens all the time while hovering over variables in the GUI
+ throw e;
+ }
+ } else if (checkPrefix("c"))
+ {
+ continueExecution();
+ } else if (checkPrefix("M"))
+ {
+ writeMemory();
+ } else if (checkPrefix("z4"))
+ {
+ disableAccessWatchPoint();
+ } else if (checkPrefix("Z4"))
+ {
+ enableAccessWatchPoint();
+ } else if (checkPrefix("k"))
+ {
+ /* we must send a reply, but not wait for ack before we shut down
+ the connection.
+ */
+ server.alive=false;
+ reply("OK");
+ } else
+ {
+ throw new UnknownPacketException();
+ }
+ } catch (UnknownPacketException e)
+ {
+ this.server.print(GDBServer.UNKNOWN, "Unknown packet: " + origCmd);
+ // empty reply to unknown packets
+ } catch (CPUException e)
+ {
+ if (!silent)
+ {
+ this.server.print(GDBServer.CPUEXCEPTION, "Exception handling GDB request");
+ if (GDBServer.CPUEXCEPTION)
+ {
+ e.printStackTrace();
+ }
+ }
+ reply("E01");
+ } catch (GDBServerException e)
+ {
+ e.printStackTrace();
+ reply("E01");
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ reply("E01");
+ }
+
+ sendReply();
+ }
+
+ private void checkEmpty() throws GDBServerException
+ {
+ if (cmd.length()>0)
+ {
+ throw new GDBServerException();
+ }
+ }
+ private void dumpHex(String arrayList2)
+ {
+ for (int i=0; i<arrayList2.length(); i++)
+ {
+ System.out.println(this.server.formatHex(arrayList2.charAt(i), "00"));
+ }
+ }
+ /**
+ * @param packetString
+ * @param string
+ * @return
+ */
+ private boolean checkPrefix(String string)
+ {
+ if (cmd.length() < string.length())
+ {
+ return false;
+ } else
+ {
+ return cmd.substring(0, string.length()).equals(string);
+ }
+ }
+ /**
+ * @throws GDBServerException
+ * @throws IOException
+ * @throws MemoryAccessException
+ *
+ */
+ private void continueExecution() throws GDBServerException
+ {
+ extractString("c");
+ try
+ {
+ if (!isEmpty())
+ {
+ int pc=extractInteger();
+ this.server.simulator.setPc(pc);
+ }
+ checkEmpty();
+ this.server.simulator.cont();
+ } catch (MemoryAccessException e)
+ {
+ if (GDBServer.IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ }
+ reply("S05");
+ }
+ private void doStep()
+ {
+ this.server.simulator.step();
+ reply("S05");
+ }
+ protected int extractInteger() throws GDBServerException
+ {
+ String number;
+ Pattern p=Pattern.compile("(\\-?[0-9a-fA-F]+)");
+ Matcher m = p.matcher(cmd);
+ if (!m.find())
+ {
+ throw new GDBServerException();
+ }
+ number=m.group();
+ extractString(number);
+
+ try
+ {
+ return (int)Long.parseLong(number, 16);
+ } catch (NumberFormatException e)
+ {
+ throw new GDBServerException(e);
+ }
+ }
+ /**
+ * @param string
+ * @throws GDBServerException
+ */
+ private void extractString(String string) throws GDBServerException
+ {
+ if (!checkPrefix(string))
+ {
+ throw new GDBServerException();
+ }
+ stripStart(string.length());
+ }
+ /**
+ * @throws GDBServerException
+ *
+ */
+ private void readMemory() throws CPUException, GDBServerException
+ {
+ extractString("m");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ checkEmpty();
+
+ for (int i=0; i<length; i++)
+ {
+ reply(this.server.formatHex(this.server.simulator.readByte(address+i), "00"));
+ }
+ }
+ /**
+ *
+ */
+ private void readRegisters() throws CPUException
+ {
+ for (int i=0; i<this.server.simulator.getREGNUM(); i++)
+ {
+ reply(this.server.printHex(this.server.simulator.getReg(i)));
+ }
+ }
+ private void writeMemory() throws GDBServerException, MemoryAccessException
+ {
+ extractString("M");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ extractString(":");
+
+ for (int i=0; i<length; i++)
+ {
+ String t;
+ t=cmd.substring(i*2, i*2+2);
+ int val;
+ val=Integer.parseInt(t, 16);
+ this.server.simulator.writeByte(address+i, val);
+ }
+ reply("OK");
+
+ }
+
+ private void enableAccessWatchPoint() throws GDBServerException, CPUException
+ {
+ extractString("Z4");
+ extractString(",");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ checkEmpty();
+ server.simulator.enableAccessWatchPoint(address, length);
+
+ reply("OK");
+ }
+
+ private void disableAccessWatchPoint() throws GDBServerException, CPUException
+ {
+ extractString("z4");
+ extractString(",");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ checkEmpty();
+ server.simulator.disableAccessWatchPoint(address, length);
+
+ reply("OK");
+ }
+
+
+ private void stripStart(int length)
+ {
+ cmd=cmd.substring(length);
+ }
+ private boolean isEmpty()
+ {
+ return cmd.length()==0;
+ }
+ /**
+ * @param string
+ */
+ protected void reply(String string)
+ {
+ reply.append(string);
+ }
+ void sendReply()
+ {
+ // a bit easier to debug if we can see the entire string.
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("$");
+ number++;
+ String replyString = reply.toString();
+ buffer.append(replyString);
+ byte[] data = replyString.toString().getBytes();
+ int csum = 0;
+ for (int i = 0; i < data.length; i++)
+ {
+ csum += data[i];
+ }
+ csum &= 0xff;
+ buffer.append("#");
+ String t = Integer.toHexString(csum);
+ if (t.length() == 1)
+ {
+ t = "0" + t;
+ }
+ buffer.append(t);
+ this.server.print(GDBServer.REPLY, "Reply " + number + " : " + buffer.toString());
+ try
+ {
+ this.server.write(buffer.toString().getBytes());
+ } catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ if (server.alive)
+ {
+ /* check for ack. */
+ int ack;
+ try
+ {
+ ack = (char)this.server.read();
+ } catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ if (ack == '+')
+ {
+ return;
+ }
+ this.server.print(GDBServer.MINIMAL, "Retry");
+
+ throw new NoAckException();
+ }
+ reply=new StringBuffer();
+ }
+
+ private void querySignal()
+ {
+ // SIGINT
+ // reply("S02");
+ reply("S05");
+ }
+ protected String cmd;
+ private int number;
+ private StringBuffer reply;
+ private String origCmd;
+ int syscallErrno;
+ int syscallRetval;
+
+
+
+ void invokeSyscall(String string, int argNum, String types) throws IOException, NoAckException, GDBServerException, EndSessionException, CPUException
+ {
+ string="F"+string;
+
+ int j=0;
+ for (int i=0; i<argNum; i++)
+ {
+ string+=",";
+ string+=Integer.toHexString(server.getSyscallArg(j));
+ j++;
+ if (types.charAt(i)=='s')
+ {
+ string+="/" + Integer.toHexString(server.getSyscallArg(j));
+ j++;
+ }
+ }
+
+ reply(string);
+ sendReply();
+ for (;;)
+ {
+ Packet packet=new Packet(server);
+ packet.receive();
+ if (packet.checkPrefix("F"))
+ {
+ /* this is the reply we are waiting for */
+ packet.extractString("F");
+ syscallRetval=packet.extractInteger();
+ syscallErrno=0;
+ if (packet.checkPrefix(","))
+ {
+ /* errno is optional */
+ packet.extractString(",");
+ syscallErrno = packet.extractInteger();
+ }
+ break;
+ } else
+ {
+ /* something else... */
+ try
+ {
+ packet.parseAndExecute();
+ packet.sendReply();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ } catch (EndSessionException e)
+ {
+ e.printStackTrace();
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeDRAM.java b/zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeDRAM.java
new file mode 100644
index 0000000..f641595
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeDRAM.java
@@ -0,0 +1,39 @@
+
+package com.zylin.zpu.simulator.tools;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class MakeDRAM
+{
+ public static void main(String[] args) throws IOException
+ {
+ new MakeDRAM().run(args[0]);
+ }
+
+ private void run(String string) throws IOException
+ {
+ FileInputStream file=new FileInputStream(string);
+
+ int i=0;
+ while (file.available()>4)
+ {
+ byte[] tmp=new byte[4];
+ file.read(tmp);
+ int word=0;
+ for (int j=0; j<4; j++)
+ {
+ word|=((int)(tmp[j])&0xff)<<((3-j)*8);
+ }
+ String str=Integer.toHexString(word);
+ while (str.length()<8)
+ {
+ str="0"+str;
+ }
+
+ System.out.println(str);
+ i++;
+ }
+ }
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeRam.java b/zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeRam.java
new file mode 100644
index 0000000..4a7b233
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/tools/MakeRam.java
@@ -0,0 +1,39 @@
+
+package com.zylin.zpu.simulator.tools;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class MakeRam
+{
+ public static void main(String[] args) throws IOException
+ {
+ new MakeRam().run(args[0]);
+ }
+
+ private void run(String string) throws IOException
+ {
+ FileInputStream file=new FileInputStream(string);
+
+ int i=0;
+ while (file.available()>4)
+ {
+ byte[] tmp=new byte[4];
+ file.read(tmp);
+ int word=0;
+ for (int j=0; j<4; j++)
+ {
+ word|=((int)(tmp[j])&0xff)<<((3-j)*8);
+ }
+ String str=Integer.toHexString(word);
+ while (str.length()<8)
+ {
+ str="0"+str;
+ }
+
+ System.out.println("" + i + " => x\"" + str + "\",");
+ i++;
+ }
+ }
+
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/stats/CountSequences.java b/zpu/sw/simulator/com/zylin/zpu/stats/CountSequences.java
new file mode 100644
index 0000000..0f06aec
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/stats/CountSequences.java
@@ -0,0 +1,94 @@
+/*
+ * Created on Jan 18, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package com.zylin.zpu.stats;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import com.zylin.zpu.simulator.Machine;
+
+public class CountSequences implements Machine
+{
+
+ private byte[] array;
+ private StatKeeper statKeeper;
+
+ public static void main(String[] args)
+ {
+ new CountSequences().run(args[0]);
+ }
+
+ private void run(String string)
+ {
+ try
+ {
+ File file=new File(string);
+ if (file.exists())
+ System.out.println("It exists!");
+ FileInputStream in=new FileInputStream(file);
+
+ try
+ {
+ array=new byte[(int) file.length()];
+
+ if (in.read(array)!=array.length)
+ throw new IOException();
+
+ countStats();
+
+ statKeeper.printStats();
+ } finally
+ {
+ in.close();
+ }
+
+ } catch (FileNotFoundException e)
+ {
+ e.printStackTrace();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+
+ }
+
+
+ private void countStats()
+ {
+ statKeeper=new StatKeeper(this);
+ for (int i=0; i<array.length; i++)
+ {
+ int j = array[i]&0xff;
+//
+// if ((j>=64)&&(j<96))
+// {
+// j=64;
+// } else if ((j>=96)&&(j<128))
+// {
+// j=96;
+// } else if ((j>=128)&&(j<256))
+// {
+// j=128;
+// }
+ statKeeper.countInstruction(j);
+ }
+
+ }
+
+ public long getPrevCycles()
+ {
+ return 0;
+ }
+
+ public long getCycles()
+ {
+ return 0;
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/stats/DumpIt.java b/zpu/sw/simulator/com/zylin/zpu/stats/DumpIt.java
new file mode 100644
index 0000000..80be11d
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/stats/DumpIt.java
@@ -0,0 +1,17 @@
+/*
+ * Created on 26.nov.2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.stats;
+/**
+ * @author oyvind
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public interface DumpIt
+{
+ int dumpIt(int i);
+} \ No newline at end of file
diff --git a/zpu/sw/simulator/com/zylin/zpu/stats/Instruction.java b/zpu/sw/simulator/com/zylin/zpu/stats/Instruction.java
new file mode 100644
index 0000000..252dd7f
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/stats/Instruction.java
@@ -0,0 +1,62 @@
+package com.zylin.zpu.stats;
+
+public class Instruction
+{
+ public class DumpCycles implements DumpIt
+ {
+ public int dumpIt(int i)
+ {
+ return insn[i].cycles;
+ }
+ }
+
+
+
+ public Instruction[] insn=new Instruction[256];
+ public int count;
+ public int cycles;
+
+ public Instruction addInstruction(int i)
+ {
+ if (insn[i]==null)
+ {
+ insn[i]=new Instruction();
+ }
+ return insn[i];
+ }
+
+ /**
+ * Recursive print of statistics
+ */
+ public void printStats()
+ {
+ System.out.println("Count dump");
+ DumpIt cDump = new DumpCount();
+ printCount("", cDump);
+ }
+
+ /**
+ * Recursive print of counts
+ * @param string
+ * @param dumpIt TODO
+ */
+ private void printCount(String string, DumpIt dumpIt)
+ {
+ for (int i=0; i<insn.length; i++)
+ {
+ if (insn[i]!=null)
+ {
+ insn[i].printCount(string + ", " + i, dumpIt);
+ System.out.println("Count: " + insn[i].count + string + ", " + i);
+ }
+ }
+ }
+
+ class DumpCount implements DumpIt
+ {
+ public int dumpIt(int i)
+ {
+ return insn[i].count;
+ }
+ }
+}
diff --git a/zpu/sw/simulator/com/zylin/zpu/stats/StatKeeper.java b/zpu/sw/simulator/com/zylin/zpu/stats/StatKeeper.java
new file mode 100644
index 0000000..9e16e32
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/stats/StatKeeper.java
@@ -0,0 +1,52 @@
+package com.zylin.zpu.stats;
+
+import com.zylin.zpu.simulator.Machine;
+import com.zylin.zpu.simulator.State;
+
+public class StatKeeper
+{
+ private Instruction top=new Instruction();
+ private int trackPos;
+
+ private State[] state = new State[3];
+ private Machine simulator;
+ /**
+ * @param simulator
+ */
+ public StatKeeper(Machine simulator)
+ {
+ this.simulator=simulator;
+ for (int i=0; i<state.length; i++)
+ {
+ state[i]=new State();
+ }
+ }
+ /**
+ * this instruction has been retired. Count it.
+ */
+ public void countInstruction(int instruction)
+ {
+ State currentState=state[trackPos%state.length];
+ currentState.cycle=simulator.getPrevCycles(); // start of instruction
+ currentState.insn=instruction;
+ trackPos++;
+ int backtrackNum;
+ backtrackNum=Math.min(trackPos, state.length);
+ for (int i=0; i<backtrackNum; i++)
+ {
+ Instruction t=top;
+ for (int j=0; j<=i; j++)
+ {
+ currentState=state[(trackPos-backtrackNum+j)%state.length];
+ t=t.addInstruction(currentState.insn);
+ }
+ t.count++;
+ }
+
+ }
+ public void printStats()
+ {
+ top.printStats();
+
+ }
+}
OpenPOWER on IntegriCloud