// Path: simulator/src/org/z64sim/memory/Memory.java
// public class Memory {
// 
//     private static MemoryTopComponent window = null;
//     //private static Program program = null;
//     private static Program program = new Program(); // aggiunto per evitare nullPointerException
// 
//     // This class cannot be instantiated
//     private Memory() {
//     }
// 
//     public static Program getProgram() {
//         return program;
//     }
// 
//     public static void setProgram(Program program) {
//         Memory.program = program;
//     }
//     
//     public static void setWindow(MemoryTopComponent w) {
//         Memory.window = w;
//     }
// 
//     public static MemoryTopComponent getWindow() {
//         return Memory.window;
//     }
// 
//     public static void redrawMemory() {
//         if (Memory.window != null) {
//             Memory.window.memoryTable.setModel(new MemoryTableModel());
//             int _startRow = (int) (Memory.program._start / 8);
// 
//             // Select the row corresponding to the entry point
//             Memory.window.memoryTable.setRowSelectionInterval(_startRow, _startRow);
// 
//             // Scroll to that row
//             Memory.window.memoryTable.scrollRectToVisible(new Rectangle(Memory.window.memoryTable.getCellRect(_startRow, 0, true)));
// 
//             // Show the panel
//             Memory.window.requestVisible();
//         }
//         
//     }
// 
// }
// 
// Path: simulator/src/org/z64sim/program/instructions/OperandImmediate.java
// public class OperandImmediate extends Operand {
// 
//     private long value;
// 
//     public OperandImmediate(long value) {
//         super(32);
//         // Basically an immediate is 32-bit long, except when it cannot
//         // be represented using 32 bits (!!!)
//         if(value > Integer.MAX_VALUE) {
//             this.setSize(64);
//         }
// 
//         this.value = value;
//     }
// 
//     public long getValue() {
//         return value;
//     }
// 
//     @Override
//     public String toString() {
//         return "$" + this.value;
//     }
// 
//     // This call actually sums the value of the label. This is because we could
//     // write an instruction such as "movq $constant+10". The +10 is stored in the
//     // 'value' field of the object, and we have then to sum $constant.
//     public void relocate(long value) {
//         this.value += value;
//     }
// }
// 
// Path: simulator/src/org/z64sim/program/instructions/OperandMemory.java
// public class OperandMemory extends Operand {
// 
//     private int base = -1;
//     private int scale = -1;
//     private int index = -1;
//     private int displacement = -1;
// 
//     // In z64 assembly you can say both (%ax) or (%rax) for example, so we must
//     // account fot the size of the base register as well
//     // On the other hand, the index is always a 64-bit register
//     private int base_size = -1;
// 
//     public OperandMemory(int base, int base_size, int index, int scale, int displacement, int size) {
//         super(size);
// 
//         this.base = base;
//         this.base_size = base_size;
//         this.index = index;
//         this.scale = scale;
//         this.displacement = displacement;
//     }
// 
//     public int getDisplacement() {
//         return displacement;
//     }
// 
//     public int getScale() {
//         return scale;
//     }
// 
//     public int getIndex() {
//         return index;
//     }
// 
//     public long getBase() {
//         return base;
//     }
// 
//     public int getBaseSize() {
//         return base_size;
//     }
// 
//     public void setDisplacement(int displacement) {
//         this.displacement = displacement;
//     }
// 
//     public String toString() {
//         String representation = "";
// 
//         if(this.displacement != -1) {
//             representation = representation.concat(String.format("$%x", this.displacement));
//         }
// 
//         if(this.base != -1 || this.index != -1) {
//             representation = representation.concat("(");
//         }
// 
//         if(this.base != -1) {
//             representation = representation.concat(Register.getRegisterName(this.base, this.base_size));
//         }
// 
//         if(this.index != -1) {
//             representation = representation.concat(", " + Register.getRegisterName(this.index, 64));
//             representation = representation.concat(", " + this.scale);
//         }
// 
//         if(this.base != -1 || this.index != -1) {
//             representation = representation.concat(")");
//         }
// 
//         return representation;
//     }
// 
//     public void relocate(long value) {
//         this.displacement += value;
//     }
// }


import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.Map;
import org.z64sim.memory.Memory;
import org.z64sim.program.instructions.OperandImmediate;
import org.z64sim.program.instructions.OperandMemory;
            this.data.add(val[i]);
        }
        return addr;
    }

    /**
     * A relocation entry. Points to the initial address of the instruction. It
     * is then the role of the relocate() method to account for differences in
     * the various instruction formats.
     */
    private class RelocationEntry {

        private final long applyTo;
        private final String label;

        public RelocationEntry(long applyTo, String label) {
            this.applyTo = applyTo;
            this.label = label;
        }

        private void relocateImmediate(OperandImmediate op, Instruction insn) throws ProgramException {
            // Get target address of the relocation
            long target = findLabelAddress(this.label);
            if (target == -1) {
                throw new ProgramException("Label " + this.label + " was not defined in the program");
            }

            op.relocate(target);
        }

// Path: simulator/src/org/z64sim/memory/Memory.java
// public class Memory {
// 
//     private static MemoryTopComponent window = null;
//     //private static Program program = null;
//     private static Program program = new Program(); // aggiunto per evitare nullPointerException
// 
//     // This class cannot be instantiated
//     private Memory() {
//     }
// 
//     public static Program getProgram() {
//         return program;
//     }
// 
//     public static void setProgram(Program program) {
//         Memory.program = program;
//     }
//     
//     public static void setWindow(MemoryTopComponent w) {
//         Memory.window = w;
//     }
// 
//     public static MemoryTopComponent getWindow() {
//         return Memory.window;
//     }
// 
//     public static void redrawMemory() {
//         if (Memory.window != null) {
//             Memory.window.memoryTable.setModel(new MemoryTableModel());
//             int _startRow = (int) (Memory.program._start / 8);
// 
//             // Select the row corresponding to the entry point
//             Memory.window.memoryTable.setRowSelectionInterval(_startRow, _startRow);
// 
//             // Scroll to that row
//             Memory.window.memoryTable.scrollRectToVisible(new Rectangle(Memory.window.memoryTable.getCellRect(_startRow, 0, true)));
// 
//             // Show the panel
//             Memory.window.requestVisible();
//         }
//         
//     }
// 
// }
// 
// Path: simulator/src/org/z64sim/program/instructions/OperandImmediate.java
// public class OperandImmediate extends Operand {
// 
//     private long value;
// 
//     public OperandImmediate(long value) {
//         super(32);
//         // Basically an immediate is 32-bit long, except when it cannot
//         // be represented using 32 bits (!!!)
//         if(value > Integer.MAX_VALUE) {
//             this.setSize(64);
//         }
// 
//         this.value = value;
//     }
// 
//     public long getValue() {
//         return value;
//     }
// 
//     @Override
//     public String toString() {
//         return "$" + this.value;
//     }
// 
//     // This call actually sums the value of the label. This is because we could
//     // write an instruction such as "movq $constant+10". The +10 is stored in the
//     // 'value' field of the object, and we have then to sum $constant.
//     public void relocate(long value) {
//         this.value += value;
//     }
// }
// 
// Path: simulator/src/org/z64sim/program/instructions/OperandMemory.java
// public class OperandMemory extends Operand {
// 
//     private int base = -1;
//     private int scale = -1;
//     private int index = -1;
//     private int displacement = -1;
// 
//     // In z64 assembly you can say both (%ax) or (%rax) for example, so we must
//     // account fot the size of the base register as well
//     // On the other hand, the index is always a 64-bit register
//     private int base_size = -1;
// 
//     public OperandMemory(int base, int base_size, int index, int scale, int displacement, int size) {
//         super(size);
// 
//         this.base = base;
//         this.base_size = base_size;
//         this.index = index;
//         this.scale = scale;
//         this.displacement = displacement;
//     }
// 
//     public int getDisplacement() {
//         return displacement;
//     }
// 
//     public int getScale() {
//         return scale;
//     }
// 
//     public int getIndex() {
//         return index;
//     }
// 
//     public long getBase() {
//         return base;
//     }
// 
//     public int getBaseSize() {
//         return base_size;
//     }
// 
//     public void setDisplacement(int displacement) {
//         this.displacement = displacement;
//     }
// 
//     public String toString() {
//         String representation = "";
// 
//         if(this.displacement != -1) {
//             representation = representation.concat(String.format("$%x", this.displacement));
//         }
// 
//         if(this.base != -1 || this.index != -1) {
//             representation = representation.concat("(");
//         }
// 
//         if(this.base != -1) {
//             representation = representation.concat(Register.getRegisterName(this.base, this.base_size));
//         }
// 
//         if(this.index != -1) {
//             representation = representation.concat(", " + Register.getRegisterName(this.index, 64));
//             representation = representation.concat(", " + this.scale);
//         }
// 
//         if(this.base != -1 || this.index != -1) {
//             representation = representation.concat(")");
//         }
// 
//         return representation;
//     }
// 
//     public void relocate(long value) {
//         this.displacement += value;
//     }
// }


// Path: simulator/src/org/z64sim/program/Program.java
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.Map;
import org.z64sim.memory.Memory;
import org.z64sim.program.instructions.OperandImmediate;
import org.z64sim.program.instructions.OperandMemory;

            this.data.add(val[i]);
        }
        return addr;
    }

    /**
     * A relocation entry. Points to the initial address of the instruction. It
     * is then the role of the relocate() method to account for differences in
     * the various instruction formats.
     */
    private class RelocationEntry {

        private final long applyTo;
        private final String label;

        public RelocationEntry(long applyTo, String label) {
            this.applyTo = applyTo;
            this.label = label;
        }

        private void relocateImmediate(OperandImmediate op, Instruction insn) throws ProgramException {
            // Get target address of the relocation
            long target = findLabelAddress(this.label);
            if (target == -1) {
                throw new ProgramException("Label " + this.label + " was not defined in the program");
            }

            op.relocate(target);
        }

        private void relocateMemory(OperandMemory op, Instruction insn) throws ProgramException {