code: /**
   * Copyright (c) 2004-2005, Regents of the University of California
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * Redistributions of source code must retain the above copyright notice,
   * this list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * Neither the name of the University of California, Los Angeles nor the
   * names of its contributors may be used to endorse or promote products
   * derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  package avrora.stack.isea;
  
  import avrora.arch.legacy.*;
  import avrora.core.Program;
  import cck.text.*;
  import cck.util.Util;
  import java.util.*;
  
  /**
   * The <code>ISEInterpreter</code> class implements an abstract interpreter for intraprocedural
   * side effect analysis. This abstract interpreter simply keeps tracks of which register values
   * have been written, read, or overwritten, as well as the values on the stack.
   *
   * @author Ben L. Titzer
   */
  public class ISEInterpreter implements LegacyInstrVisitor {
  
      protected final Verbose.Printer printer = Verbose.getVerbosePrinter("analysis.isea.interpreter");
  
      public interface SummaryCache {
          public ISEState getProcedureSummary(int start);
          public void recordReturnSummary(int retaddr, ISEState rs);
      }
  
      protected final Program program;
  
      protected byte readRegister(LegacyRegister r) {
          return state.readRegister(r);
      }
  
      protected byte getRegister(LegacyRegister r) {
          return state.getRegister(r);
      }
  
      protected void writeRegister(LegacyRegister r, byte val) {
          state.writeRegister(r, val);
      }
  
      protected byte getSREG() {
          return state.getSREG();
      }
  
      protected void writeSREG(byte val) {
          state.writeSREG(val);
      }
  
      protected byte readIORegister(int ioreg) {
          return state.readIORegister(ioreg);
      }
  
      protected void writeIORegister(int ioreg, byte val) {
          state.writeIORegister(ioreg, val);
      }
  
      protected int relative(int offset) {
          return pc + 2 + 2 * offset;
      }
  
      protected int absolute(int offset) {
          return 2 * offset;
      }
      protected void branch(int addr) {
          addToWorkList("BRANCH", addr, state.dup());
      }
  
      protected void jump(int addr) {
          nextPC = addr;
      }
  
      protected ISEState processReturnState(ISEState caller, ISEState ret) {
          ISEState fs = ret.dup();
          fs.mergeWithCaller(caller);
          return fs;
      }
  
      protected void postReturn(ISEState state) {
          if ( returnState == null )
              returnState = state.dup();
          else returnState.merge(state);
          cache.recordReturnSummary(nextPC, state);
      }
  
      protected void postReturnFromInterrupt(ISEState state) {
          // TODO: deal with interrupts
          if ( returnState == null )
              returnState = state.dup();
          else returnState.merge(state);
          cache.recordReturnSummary(nextPC, state);
      }
  
      protected void skip() {
          branch(program.getNextPC(nextPC));
      }
  
      protected byte popByte() {
          return state.pop();
      }
  
      void pushByte(byte val) {
          state.push(val);
      }
  
      class Item {
          final int pc;
          final ISEState state;
          Item next;
  
          Item(int pc, ISEState s) {
              this.pc = pc;
              this.state = s;
          }
      }
  
      protected int pc;
      protected int nextPC;
      protected ISEState state;
      protected ISEState returnState;
      Item head;
      Item tail;
  
      protected HashMap<Integer, ISEState> states;
      protected final SummaryCache cache;
  
      protected void addToWorkList(String str, int pc, ISEState s) {
          printAdd(str, s, pc);
          s = mergeState(pc, s);
  
          if ( s == null ) return;
  
          Item i = new Item(pc, s);
          if ( head == null ) {
              head = tail = i;
          } else {
              tail.next = i;
              tail = i;
          }
      }
  
      private void printAdd(String str, ISEState s, int pc) {
          if ( !printer.enabled ) return;
          Terminal.printBrightGreen(str);
          Terminal.println(":");
          printState(s, pc);
      }
  
      private void printState(ISEState s, int pc) {
          if ( !printer.enabled ) return;
          s.print(pc);
      }
  
      private ISEState mergeState(int pc, ISEState s) {
          ISEState es = (ISEState)states.get(new Integer(pc));
          if ( es != null ) {
              if ( es.equals(s) ) {
                  printSeen();
                  return null;
              } else {
                  printMerge(es, pc);
                  es.merge(s);
                  s = es;
                  printState(s, pc);
              }
          } else {
              states.put(new Integer(pc), s);
          }
          return s;
      }
  
      private void printMerge(ISEState es, int pc) {
          if ( !printer.enabled ) return;
          Terminal.printRed("MERGE WITH");
          Terminal.nextln();
          printState(es, pc);
          Terminal.printRed("RESULT");
          Terminal.nextln();
      }
  
      private void printSeen() {
          if ( !printer.enabled ) return;
          Terminal.printRed("SEEN");
          Terminal.nextln();
      }
  
      public ISEInterpreter(Program p, SummaryCache cs) {
          program = p;
          states = new HashMap<Integer, ISEState>();
          cache = cs;
      }
  
      public ISEState analyze(int begin_addr) {
          addToWorkList("START", begin_addr, new ISEState());
          run();
          return returnState;
      }
  
      protected void run() {
          // run the worklist to completion.
          while ( head != null ) {
              Item i = head;
              head = head.next;
  
              pc = i.pc;
              state = i.state.dup();
              LegacyInstr instr = (LegacyInstr)program.readInstr(i.pc);
              printItem(instr);
              int npc = program.getNextPC(i.pc);
              nextPC = npc;
              instr.accept(this);
              if ( nextPC >= 0 ) {
                  String str = npc == nextPC ? "FALLTHROUGH" : "JUMP";
                  addToWorkList(str, nextPC, state);
  
              }
          }
      }
  
      private void printItem(LegacyInstr instr) {
          if ( !printer.enabled ) return;
          TermUtil.printSeparator();
          printState(state, pc);
          Terminal.printBrightBlue(instr.getVariant());
          Terminal.println(" "+instr.getOperands());
          TermUtil.printThinSeparator(Terminal.MAXLINE);
      }
  
      private void mult(LegacyRegister r1, LegacyRegister r2) {
          readRegister(r1);
          readRegister(r2);
          writeSREG(ISEValue.UNKNOWN);
          writeRegister(LegacyRegister.R0, ISEValue.UNKNOWN);
          writeRegister(LegacyRegister.R1, ISEValue.UNKNOWN);
      }
  
  
      void binop(LegacyRegister r1, LegacyRegister r2) {
          readRegister(r1);
          readRegister(r2);
          writeSREG(ISEValue.UNKNOWN);
          writeRegister(r1, ISEValue.UNKNOWN);
      }
  
      void unop(LegacyRegister r1) {
          readRegister(r1);
          writeSREG(ISEValue.UNKNOWN);
          writeRegister(r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.ADC i) {
          binop(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.ADD i) {
          binop(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.ADIW i) {
          readRegister(i.r1);
          readRegister(i.r1.nextRegister());
          writeSREG(ISEValue.UNKNOWN);
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(i.r1.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.AND i) {
          binop(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.ANDI i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.ASR i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.BCLR i) {
          writeIORegister(i.imm1, ISEValue.UNKNOWN);
          //getIOReg(SREG).writeBit(i.imm1, false);
      }
  
      public void visit(LegacyInstr.BLD i) {
          readRegister(i.r1);
          writeRegister(i.r1, ISEValue.UNKNOWN);
          //writeRegister(i.r1, Arithmetic.setBit(readRegister(i.r1), i.imm1, T));
      }
  
      public void visit(LegacyInstr.BRBC i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRBS i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRCC i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRCS i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BREAK i) {
          end();
      }
  
      public void visit(LegacyInstr.BREQ i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRGE i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRHC i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRHS i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRID i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRIE i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRLO i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRLT i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRMI i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRNE i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRPL i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRSH i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRTC i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRTS i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRVC i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BRVS i) {
          branch(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.BSET i) {
          writeIORegister(i.imm1, ISEValue.UNKNOWN);
          // getIOReg(SREG).writeBit(i.imm1, true);
      }
  
      public void visit(LegacyInstr.BST i) {
          readRegister(i.r1);
          writeSREG(ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.CALL i) {
          int target = absolute(i.imm1);
          ISEState rs = cache.getProcedureSummary(target);
          ISEState fs = processReturnState(state, rs);
          addToWorkList("RET", nextPC, fs);
          end();
      }
  
      public void visit(LegacyInstr.CBI i) {
          writeIORegister(i.imm1, ISEValue.UNKNOWN);
          //getIOReg(i.imm1).writeBit(i.imm2, false);
      }
  
      public void visit(LegacyInstr.CBR i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.CLC i) {
          writeSREG(ISEValue.UNKNOWN);
          // C = false;
      }
  
      public void visit(LegacyInstr.CLH i) {
          writeSREG(ISEValue.UNKNOWN);
          // H = false;
      }
  
      public void visit(LegacyInstr.CLI i) {
          writeSREG(ISEValue.UNKNOWN);
          // disableInterrupts();
      }
  
      public void visit(LegacyInstr.CLN i) {
          writeSREG(ISEValue.UNKNOWN);
          // N = false;
      }
  
      public void visit(LegacyInstr.CLR i) {
          writeSREG(ISEValue.UNKNOWN);
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.CLS i) {
          writeSREG(ISEValue.UNKNOWN);
          // S = false;
      }
  
      public void visit(LegacyInstr.CLT i) {
          writeSREG(ISEValue.UNKNOWN);
          // T = false;
      }
  
      public void visit(LegacyInstr.CLV i) {
          writeSREG(ISEValue.UNKNOWN);
          // V = false;
      }
  
      public void visit(LegacyInstr.CLZ i) {
          writeSREG(ISEValue.UNKNOWN);
          // Z = false;
      }
  
      public void visit(LegacyInstr.COM i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.CP i) {
          readRegister(i.r1);
          readRegister(i.r2);
          writeSREG(ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.CPC i) {
          readRegister(i.r1);
          readRegister(i.r2);
          writeSREG(ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.CPI i) {
          readRegister(i.r1);
          writeSREG(ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.CPSE i) {
          readRegister(i.r1);
          readRegister(i.r2);
          writeSREG(ISEValue.UNKNOWN);
          skip();
      }
  
      public void visit(LegacyInstr.DEC i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.EICALL i) {
          throw Util.unimplemented();
      }
  
      public void visit(LegacyInstr.EIJMP i) {
          throw Util.unimplemented();
      }
  
      public void visit(LegacyInstr.ELPM i) {
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
          writeRegister(LegacyRegister.R0, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.ELPMD i) {
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.ELPMPI i) {
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(LegacyRegister.Z, ISEValue.UNKNOWN);
          writeRegister(LegacyRegister.Z.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.EOR i) {
          if ( i.r1 == i.r2 ) {
              // special case: clear the register
              writeSREG(ISEValue.UNKNOWN);
              writeRegister(i.r1, ISEValue.UNKNOWN);
          } else {
              binop(i.r1, i.r2);
          }
      }
  
      public void visit(LegacyInstr.FMUL i) {
          mult(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.FMULS i) {
          mult(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.FMULSU i) {
          mult(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.ICALL i) {
          List<Integer> iedges = program.getIndirectEdges(pc);
          if (iedges == null)
              throw Util.failure("No control flow information for indirect call at: " +
                      StringUtil.addrToString(pc));
          for (Integer target_address : iedges) {
              ISEState rs = cache.getProcedureSummary(target_address);
              ISEState fs = processReturnState(state, rs);
              addToWorkList("RET", nextPC, fs);
          }
          end();
      }
  
      public void visit(LegacyInstr.IJMP i) {
          List<Integer> iedges = program.getIndirectEdges(pc);
          if (iedges == null)
              throw Util.failure("No control flow information for indirect call at: " +
                      StringUtil.addrToString(pc));
          for (Integer target_address : iedges) {
              jump(target_address);
          }
      }
  
      public void visit(LegacyInstr.IN i) {
          writeRegister(i.r1, readIORegister(i.imm1));
      }
  
      public void visit(LegacyInstr.INC i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.JMP i) {
          jump(absolute(i.imm1));
      }
  
      public void visit(LegacyInstr.LD i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LDD i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LDI i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LDPD i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(i.r2, ISEValue.UNKNOWN);
          writeRegister(i.r2.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LDPI i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(i.r2, ISEValue.UNKNOWN);
          writeRegister(i.r2.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LDS i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LPM i) {
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
          writeRegister(LegacyRegister.R0, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LPMD i) {
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LPMPI i) {
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(LegacyRegister.Z, ISEValue.UNKNOWN);
          writeRegister(LegacyRegister.Z.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.LSL i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.LSR i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.MOV i) {
          writeRegister(i.r1, getRegister(i.r2));
      }
  
      public void visit(LegacyInstr.MOVW i) {
          writeRegister(i.r1, getRegister(i.r2));
          writeRegister(i.r1.nextRegister(), getRegister(i.r2.nextRegister()));
      }
  
      public void visit(LegacyInstr.MUL i) {
          mult(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.MULS i) {
          mult(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.MULSU i) {
          mult(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.NEG i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.NOP i) {
          // do nothing.
      }
  
      public void visit(LegacyInstr.OR i) {
          binop(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.ORI i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.OUT i) {
          writeIORegister(i.imm1, readRegister(i.r1));
      }
  
      public void visit(LegacyInstr.POP i) {
          writeRegister(i.r1, popByte());
      }
  
      public void visit(LegacyInstr.PUSH i) {
          pushByte(getRegister(i.r1));
      }
  
      public void visit(LegacyInstr.RCALL i) {
          int target = relative(i.imm1);
          ISEState rs = cache.getProcedureSummary(target);
          ISEState fs = processReturnState(state, rs);
          addToWorkList("RET", nextPC, fs);
          end();
      }
  
      private void end() {
          nextPC = -1;
      }
  
      public void visit(LegacyInstr.RET i) {
          postReturn(state);
          end();
      }
  
      public void visit(LegacyInstr.RETI i) {
          postReturnFromInterrupt(state);
          end();
      }
  
      public void visit(LegacyInstr.RJMP i) {
          jump(relative(i.imm1));
      }
  
      public void visit(LegacyInstr.ROL i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.ROR i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.SBC i) {
          binop(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.SBCI i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.SBI i) {
          writeIORegister(i.imm1, ISEValue.UNKNOWN);
          //getIOReg(i.imm1).writeBit(i.imm2, true);
      }
  
      public void visit(LegacyInstr.SBIC i) {
          readIORegister(i.imm1);
          skip();
      }
  
      public void visit(LegacyInstr.SBIS i) {
          readIORegister(i.imm1);
          skip();
      }
  
      public void visit(LegacyInstr.SBIW i) {
          readRegister(i.r1);
          readRegister(i.r1.nextRegister());
          writeSREG(ISEValue.UNKNOWN);
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(i.r1.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.SBR i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.SBRC i) {
          readRegister(i.r1);
          skip();
      }
  
      public void visit(LegacyInstr.SBRS i) {
          readRegister(i.r1);
          skip();
      }
  
      public void visit(LegacyInstr.SEC i) {
          writeSREG(ISEValue.UNKNOWN);
          // C = true;
      }
  
      public void visit(LegacyInstr.SEH i) {
          writeSREG(ISEValue.UNKNOWN);
          // H = true;
      }
  
      public void visit(LegacyInstr.SEI i) {
   System.err.println("visit sei");
          writeSREG(ISEValue.UNKNOWN);
           System.err.println(" sei visited");
          // enableInterrupts();
      }
  
      public void visit(LegacyInstr.SEN i) {
          writeSREG(ISEValue.UNKNOWN);
          // N = true;
      }
  
      public void visit(LegacyInstr.SER i) {
          writeRegister(i.r1, ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.SES i) {
          writeSREG(ISEValue.UNKNOWN);
          // S = true;
      }
  
      public void visit(LegacyInstr.SET i) {
          writeSREG(ISEValue.UNKNOWN);
          // T = true;
      }
  
      public void visit(LegacyInstr.SEV i) {
          writeSREG(ISEValue.UNKNOWN);
          // V = true;
      }
  
      public void visit(LegacyInstr.SEZ i) {
          writeSREG(ISEValue.UNKNOWN);
          // Z = true;
      }
  
      public void visit(LegacyInstr.SLEEP i) {
          // do nothing.
      }
  
      public void visit(LegacyInstr.SPM i) {
          readRegister(LegacyRegister.R0);
          readRegister(LegacyRegister.R1);
          readRegister(LegacyRegister.Z);
          readRegister(LegacyRegister.Z.nextRegister());
      }
  
      public void visit(LegacyInstr.ST i) {
          readRegister(i.r1);
          readRegister(i.r1.nextRegister());
          readRegister(i.r2);
      }
  
      public void visit(LegacyInstr.STD i) {
          readRegister(i.r1);
          readRegister(i.r1.nextRegister());
          readRegister(i.r2);
      }
  
      public void visit(LegacyInstr.STPD i) {
          readRegister(i.r1);
          readRegister(i.r1.nextRegister());
          readRegister(i.r2);
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(i.r1.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.STPI i) {
          readRegister(i.r1);
          readRegister(i.r1.nextRegister());
          readRegister(i.r2);
          writeRegister(i.r1, ISEValue.UNKNOWN);
          writeRegister(i.r1.nextRegister(), ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.STS i) {
          readRegister(i.r1);
      }
  
      public void visit(LegacyInstr.SUB i) {
          binop(i.r1, i.r2);
      }
  
      public void visit(LegacyInstr.SUBI i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.SWAP i) {
          unop(i.r1);
      }
  
      public void visit(LegacyInstr.TST i) {
          readRegister(i.r1);
          writeSREG(ISEValue.UNKNOWN);
      }
  
      public void visit(LegacyInstr.WDR i) {
          // do nothing.
      }
  }
  