/**
  * Generate code to fetch all the arguments needed for a given operand number and encoding. The
  * different argument encodings of the Assembler need different arguments to be passed to the
  * emitter function. For instance, a register-displacement mode operand needs to be given a base
  * register and an immediate displacement. This function generates the appropriate arguments given
  * the operand number and encoding; that is, it generates reads of the appropriate Instruction
  * argument and fetches of the appropriate pieces of information from the operand.
  *
  * @param argNumber The argument being generated.
  * @param argEcoding The encoding to use.
  */
 private static void emitArgs(int argNumber, ArgumentType argEncoding) {
   String op = getOperand(argNumber);
   switch (argEncoding) {
     case LabelOrImmediate:
       emit("getImm(" + op + "), getLabel(" + op + ")");
       break;
     case RegisterDisplacement:
       emit("getBase(" + op + "), getDisp(" + op + ")");
       break;
     case Absolute:
       emit("getDisp(" + op + ").toWord().toAddress()");
       break;
     case RegisterOffset:
       emit("getIndex(" + op + "), getScale(" + op + "), getDisp(" + op + ")");
       break;
     case RegisterIndexed:
       emit(
           "getBase(" + op + "), getIndex(" + op + "), getScale(" + op + "), getDisp(" + op + ")");
       break;
     case RegisterIndirect:
       emit("getBase(" + op + ")");
       break;
     default:
       emit("get" + argEncoding.getOptName() + "(" + op + ")");
   }
 }
 /**
  * For a given string representing a valid operand encoding for the Assembler, return the
  * corresponding Assembler constant. This function only looks for encodings of operand types, and
  * will not accept strings that correspond to size encodings.
  *
  * @param str A valid Assembler encoding of operand type
  * @return The Assembler constant corresponding to str, or -1 if none
  */
 private static ArgumentType getEncoding(String str, Class<?> type) {
   if (str.equals("Reg")) {
     if (type == null) {
       throw new Error("Unable to encode Reg with no type information");
     }
     String typeName = type.getName();
     str = typeName.substring(typeName.lastIndexOf('$') + 1) + "_Reg";
   }
   for (ArgumentType arg : ArgumentType.values()) {
     if (arg.getOptName().equals(str)) {
       return arg;
     }
   }
   throw new Error(
       "Unable to encode the argument " + str + " of type " + type + " as a valid argument type");
 }
 /**
  * Given an operand number and an encoding, generate a test to determine whether the given operand
  * matches the encoding. That is, generate code to the Assembler that examines a given operand of
  * the current Instruction, and determines whether it is of the type encoded by the given
  * encoding. This is used to generate the if statements of the dispatch functions for each opt
  * compiler opcode.
  *
  * @param argNumber The argument to examine
  * @param argEncoding The encoding for which to check
  */
 private static void emitTest(int argNumber, ArgumentType argEncoding) {
   if (argEncoding.isSize()) emit("is" + argEncoding.getOptName() + "(inst)");
   else emit("is" + argEncoding.getOptName() + "(" + getOperand(argNumber) + ")");
 }