gt:             int target = rp1(HL), source = rp1((command & 0060) >> 4);
context: /*
   * Z80Impl.java - Z80 processor implementation, which uses an ALU based on
   * YAZE.
   * 
   * (C) 2009, Mikko Nummelin <mikko.nummelin@tkk.fi>
   * 
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 02111-1307, USA.
   */
  package org.mn.z80util.z80.yaze;
  
  import java.util.*;
  
  import org.apache.log4j.*;
  
  import org.mn.z80util.z80.*;
  import org.mn.z80util.disassembler.*;
  
  public class YazeBasedZ80Impl implements Z80 {
  
      Logger LOG = Logger.getLogger(YazeBasedZ80Impl.class);
      /* YAZE based arithmetic-logical unit, which also hosts AF and AF' */
      private YazeBasedALU alu = null;
  
      /* Z80 command parsing helpers */
      private boolean ixmode = false, iymode = false;
      private byte command;
  
      public YazeBasedZ80Impl() {
          this.alu = new YazeBasedALU();
      }
  
      @Override
      public synchronized void reset() {
          Random rand = new Random(System.nanoTime());
          rand.nextBytes(regs);
          alu.af(rand.nextInt());
          haltState = false;
          setReg(IM_IFF, (byte) 0x00);
          setRegPair(PC, (short) 0x0000);
      }
      private AddressBusProvider ula;
  
      @Override
      public void setUla(AddressBusProvider ula) {
          this.ula = ula;
      }
  
      /* T-states and halt */
      private int ts;
  
      @Override
      public int getTStates() {
          return ts;
      }
  
      @Override
      public void setTStates(int value) {
          ts = value;
      }
      private boolean haltState = false;
  
      @Override
      public void setHaltState(boolean value) {
          haltState = value;
          LOG.debug("Processor halt state set to: " + haltState);
      }
  
      /* Interrupt routines and helpers */
      @Override
      public void NMI() {
          LOG.trace("Generating non-maskable interrupt.");
          haltState = false;
          regs[IM_IFF] = (byte) ((regs[IM_IFF] & ~1) | ((regs[IM_IFF] & 1) << 1));
          push(PC);
          setRegPair(PC, (short) 0x0066);
      }
  
      @Override
      public void interrupt() {
          haltState = false;
          if ((getReg(IM_IFF) & 1) != 0) {
              setReg(IM_IFF, (byte) (getReg(IM_IFF) & ~3));
              push(PC);
              switch (getReg(IM_IFF) >> 2) {
                  case 0:
                      LOG.trace("Generating interrupt of mode 0.");
                      setRegPair(PC, (short) 0x0038);
                      break;
                  case 1:
                      LOG.trace("Generating interrupt of mode 1.");
                      setRegPair(PC, (short) 0x0038);
                      break;
                  case 2:
                      LOG.trace("Generating interrupt of mode 2.");
                      int iv = (getReg(I) << 8) | 0xff;
                      LOG.trace("Interrupt vector pointer is: " + iv);
                      int jumpAddress = ula.getWord((short) iv);
                      LOG.trace("Jump address is: " + jumpAddress);
                      setRegPair(PC, (short) jumpAddress);
                      break;
              }
          }
      }
      /* Register accessors and helpers */
      private byte[] regs = new byte[23];
  
      /**
       * Gets register. Note that A, F and their alternatives reside in the ALU.
       */
      @Override
      public byte getReg(int regno) {
          if (regno == F) {
              return (byte) alu.f();
          } else if (regno == A) {
              return (byte) alu.a();
          } else if (regno == F_ALT) {
              return (byte) alu.f_alt();
          } else if (regno == A_ALT) {
              return (byte) alu.a_alt();
          } else if (regno < 6) {
              return regs[regno];
          } else if ((regno >= 8) && (regno < 14)) {
              return regs[regno - 2];
          } else {
              return regs[regno - 4];
          }
      }
  
      @Override
      public void setReg(int regno, byte value) {
          if (regno == F) {
              alu.f((byte) value);
          } else if (regno == A) {
              alu.a((byte) value);
          } else if (regno == F_ALT) {
              alu.f_alt((byte) value);
          } else if (regno == A_ALT) {
              alu.a_alt((byte) value);
          } else if (regno < 6) {
              regs[regno] = value;
          } else if ((regno >= 8) && (regno < 14)) {
              regs[regno - 2] = value;
          } else {
              regs[regno - 4] = value;
          }
      }
  
      @Override
      public short getRegPair(int regpairno) {
          int regno = regpairno << 1;
          short tmp;
          short high = (short) (getReg(regno) & 0xff);
          short low = (short) (getReg((short) (regno + 1)) & 0xff);
          if ((regpairno == AF) || (regpairno == AF_ALT)) {
              tmp = high;
              high = low;
              low = tmp;
          }
          return (short) (low | (high << 8));
      }
  
      @Override
      public void setRegPair(int regpairno, short value) {
          int regno = regpairno << 1;
          byte tmp;
          byte low = (byte) (value & 0xff);
          byte high = (byte) ((value >> 8) & 0xff);
          if ((regpairno == AF) || (regpairno == AF_ALT)) {
              tmp = high;
              high = low;
              low = tmp;
          }
          setReg(regno, high);
          setReg((short) (regno + 1), low);
      }
  
      @Override
      public void setFlag(int flag, boolean value) {
          if (value) {
              alu.f(alu.f() | flag);
          } else {
              alu.f(alu.f() & ~flag);
          }
      }
  
      @Override
      public boolean testFlag(int flag) {
          return ((alu.f() & flag) != 0);
      }
  
      /**
       * Executes next command from memory, pointed by register pair PC.
       */
      @Override
      public synchronized void executeNextCommand() {
  
          if (haltState) {
              ts = 0;
              return;
          }
  
          ts -= 4;
          ixmode = iymode = false;
          command = fetchByte();
  
          /* IX and IY modes */
          while ((command == (byte) 0xdd) || (command == (byte) 0xfd)) {
              ts -= 4;
              if (command == (byte) 0xdd) {
                  ixmode = true;
                  iymode = false;
              } else {
                  ixmode = false;
                  iymode = true;
              }
              command = fetchByte();
          }
  
          /* CBh and EDh extensions */
          if ((command & 0xff) == 0xcb) {
              CBh();
              return;
          } else if ((command & 0xff) == 0xed) {
              EDh();
              return;
          }
  
          /* Main fork, mostly octal notation to highlight some symmetries. */
  
          /* NOP: 00000000 */
          if ((command & 0377) == 0000) {
              // do nothing
  
              /* EX AF,AF': 00001000 */
          } else if ((command & 0377) == 0010) {
              alu.ex_af();
  
              /* DJNZ dis: 00010000 */
          } else if ((command & 0377) == 0020) {
              byte tmp = fetchByte();
              setReg(B, (byte) (getReg(B) - 1));
              if (getReg(B) != 0) {
                  rjump(tmp);
                  ts -= 9;
              } else {
                  ts -= 4;
              }
  
              /* JR dis: 00011000 */
          } else if ((command & 0377) == 0030) {
              byte tmp = fetchByte();
              rjump(tmp);
              ts -= 8;
  
              /* JR <cond>,dis: 001CC000 */
          } else if ((command & 0347) == 0040) {
              byte tmp = fetchByte();
              if (flagCond((command & 0030) >> 3)) {
                  rjump(tmp);
                  ts -= 8;
              } else {
                  ts -= 3;
              }
  
              /* LD <rp>,NN: 00RP0001 */
          } else if ((command & 0317) == 0001) {
              short tmp = fetchWord();
              setRegPair(rp1((command & 0060) >> 4), tmp);
              ts -= 6;
  
              /* ADD HL,<rp>: 00RP1001 */
          } else if ((command & 0317) == 0011) {
  