//-------------------------------------------------------------------------------------------------- // // @ CopyRight Roberti & Parau Enterprises, Inc. 2021-2023 // // This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nd/4.0/ // or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. // //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- // // Utility methods for RISCV-V encoding // //-------------------------------------------------------------------------------------------------- package arch.RISCV; import java.math.BigInteger; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedList; import framework.*; import framework.DVAbi.RelocationID; import framework.DVUtil.ImmType; import framework.*; public class DVArchOpCodes extends framework.DVOpCodes { public DVArchOpCodes(DVStatements.Statement owner, String options, String abi, String os) { options= options.toUpperCase(); String arch; String optList= ""; int x= options.indexOf(':'); if (x < 0) arch= options; else { arch= options.substring(0, x); optList= options.substring(x+1); } x= optList.indexOf(':'); if (x >= 0) { extension= optList.substring(x+1); optList= optList.substring(0, x); } // // Check architecture // int processorFlags= 0; switch(arch) { case "RV32I" : this.xLen= 32; this.xLenNoBits= 5; this.noRegs= 32; this.regFileNoBits= 5; break; case "RV32E" : this.xLen= 32; this.xLenNoBits= 5; this.noRegs= 16; this.regFileNoBits= 4; processorFlags= 0x08; break; case "RV64I" : this.xLen= 64; this.xLenNoBits= 6; this.noRegs= 32; this.regFileNoBits= 5; break; default : owner.putError("Architecture specified [%s] is invalid", arch); return; } // // Check architectural options // String duplOptions= ""; boolean multFloat= false; boolean invOption= false; while (optList.length() > 0) { x= optList.indexOf(','); String opt; if (x == -1) { opt= optList; optList= ""; } else { opt= optList.substring(0, x); optList= optList.substring(x+1); } switch(opt) { case "A" : if (this.aExt) duplOptions+= "," + opt; this.aExt= true; break; case "C" : if (this.cExt) duplOptions+= "," + opt; this.cExt= true; processorFlags|= 0x01; break; case "D" : if (this.dExt) duplOptions+= "," + opt; multFloat= (fLen != 0); this.fLen= 64; this.fLenNoBits= 6; this.dExt= true; break; case "F" : if (this.fExt) duplOptions+= "," + opt; multFloat= (fLen != 0); this.fLen= 32; this.fLenNoBits= 5; this.fExt= true; break; case "M" : if (this.mExt) duplOptions+= "," + opt; this.mExt= true; break; case "N" : if (this.nExt) duplOptions+= "," + opt; this.nExt= true; break; case "Q" : if (this.qExt) duplOptions+= "," + opt; multFloat= (fLen != 0); this.fLen= 128; this.fLenNoBits= 7; this.qExt= true; break; case "S" : if (this.sExt) duplOptions+= "," + opt; this.sExt= true; break; case "ZTSO" : if (this.zTsoExt) duplOptions+= "," + opt; this.zTsoExt= true; processorFlags|= 0x10; break; case "ZICSR" : if (this.zicsrExt) duplOptions+= "," + opt; this.zicsrExt= true; break; case "ZIFENCEI" : if (this.zifenceiExt) duplOptions+= "," + opt; this.zifenceiExt= true; break; default : owner.putError("Architectural option [%s] is invalid", opt); invOption= true; } } if (this.qExt) this.dExt= true; if (this.dExt) this.fExt= true; if (this.fExt) zicsrExt= true; if (duplOptions.length() > 0) { owner.putError("These options [%s] have been specified multiple times", duplOptions.substring(1)); return; } if (invOption) return; if (multFloat) { owner.putError("Multiple floatig point options specified"); return; } useCExtension= cExt; // // Check abi // abi= abi.toUpperCase(); // // Check abi // switch(abi) { case "ILP32" : if (this.noRegs != 32 || this.xLen != 32) owner.putError("Harware configuration does not support abi [%s]", abi); break; case "ILP32F" : processorFlags|= 0x02; this.abiFLen= 32; if (this.noRegs != 32 || this.xLen != 32 || this.fLen < 32) owner.putError("Harware configuration does not support abi [%s]", abi); break; case "ILP32D" : processorFlags|= 0x04; this.abiFLen= 64; if (this.noRegs != 32 || this.xLen != 32 || this.fLen < 64) owner.putError("Harware configuration does not support abi [%s]", abi); break; case "ILP32E" : if (this.noRegs != 16) owner.putError("Harware configuration does not match abi [%s]", abi); break; case "LP64" : if (this.xLen != 64) owner.putError("Harware configuration does not support abi [%s]", abi); break; case "LP64F" : processorFlags|= 0x02; this.abiFLen= 32; this.abiFLen= 32; if (this.xLen != 64 || this.fLen < 32) owner.putError("Harware configuration does not support abi [%s]", abi); break; case "LP64D" : processorFlags|= 0x04; this.abiFLen= 64; if (this.xLen != 64 || this.fLen < 64) owner.putError("Harware configuration does not support abi [%s]", abi); break; case "LP64Q" : processorFlags|= 0x06; this.abiFLen= 128; if (this.xLen != 64 || this.fLen < 128) owner.putError("Harware configuration does not support abi [%s]", abi); break; default : owner.putError("Abi [%s] is invalid", abi); return; } if ((this.abi= new Abi(owner, abi, processorFlags)) == null) return; this.os= os.toUpperCase(); opCodeSetup(this.processOpCode); return; } // // Getter methods // @Override public boolean verifyArchitecture(DVStatements.Statement owner, String arch) { if (arch.equals("RISCV")) return true; return owner.putErrorFalse("Architecture mismatch due to configuration error\n" + "Architecture requested [%s] does not match [RISCV] loaded architecture Java Class", arch); } @Override public String getExtension() { return this.extension; } @Override public boolean verifyExtension(DVStatements.Statement owner, String ext) { return false; } @Override public DVAbi getAbi() { return this.abi; } @Override public String getHexCodeHeader() { return "--CODE-----------"; } @Override public int getHexCodeLength() { return this.getHexCodeHeader().length(); } // // Check for Branch To Branch conditions // @Override public void postProcess() { this.branchStmtList.forEach((offset, bsl) -> { for (BranchStmt brStmt : bsl) { LinkedList toBsl= DVArchOpCodes.this.branchStmtList.get(brStmt.toOffset); if (toBsl != null) for (BranchStmt toBrStmt : toBsl) { if (! toBrStmt.conditional && brStmt.toOffset.equals(toBrStmt.owner.getOffset()) && brStmt.owner.getOwnerSection() == toBrStmt.owner.getOwnerSection()) brStmt.owner.putWarning("Branch To Branch detected\n" + "Branching to unconditional branch in statement [%s]", toBrStmt.owner.getFirstLineNumber()); } } }); } // // Class used to detect branch to branch // private class BranchStmt { private BranchStmt(DVStatements.Statement owner, BigInteger toOffset, boolean conditional) { this.owner= owner; this.toOffset= toOffset; this.conditional= conditional; }; private final DVStatements.Statement owner; private final BigInteger toOffset; private final boolean conditional; } // // Class fields // private int xLen= 0; private int noRegs= 0; private int xLenNoBits=0; private int regFileNoBits= 0; private int fLenNoBits= 0; private int fLen= 0; private int abiFLen= 0; private boolean mExt= false; private boolean aExt= false; private boolean cExt= false; private boolean dExt= false; private boolean fExt= false; private boolean nExt= false; private boolean qExt= false; private boolean zTsoExt= false; private boolean sExt= false; private boolean zicsrExt= false; private boolean zifenceiExt= false; private String extension= null; private DVAbi abi= null; private String os= null; private final HashMap processOpCode= new HashMap(); private boolean useCExtension; private boolean[] regUpdateFlags= new boolean[64]; private HashMap> branchStmtList= new HashMap>(); // // Constants // private static final BigInteger[] destRegExclList= { BigInteger.ZERO }; private static enum RFormatType { NORMAL, CONST_SRC2REG, ZERO_DESTREG, ZERO_DESTREG_OK, FBOOLEAN, RM, CONST_SRC2REG_RM } public static enum IFormatType { NORMAL, CONDITIONAL, IMM_NOT_ZERO, FLOAT_REG } public static enum SFormatType { NORMAL, CONDITIONAL, FLOAT_REG } private static enum UFormatType { NORMAL, ZERO_DESTREG } private static final EnumSet immInt= EnumSet.of(ImmType.INTEGER); private static final EnumSet immIntExt= EnumSet.of(ImmType.INTEGER, ImmType.EXTERNAL); private static final EnumSet immIntBaseDsp= EnumSet.of(ImmType.INTEGER, ImmType.BASEDSP); private static final EnumSet immIntPCRel= EnumSet.of(ImmType.INTEGER, ImmType.PCREL); private static final EnumSet immIntExtBaseDsp= EnumSet.of(ImmType.INTEGER, ImmType.EXTERNAL, ImmType.BASEDSP); private static final EnumSet immIntExtPCRel= EnumSet.of(ImmType.INTEGER, ImmType.EXTERNAL, ImmType.PCREL); // // Define LINUX ABI // public class Abi extends DVAbi { private Abi(DVStatements.Statement owner, String abiName, int processorFlags) { this.abiName= abiName; this.processorFlags= processorFlags; } // // Return enviroment string // public String getEnv() { return String.format("abiNoRegs=%d;abiNoFRegs=%d;abiXLen=%d;abiFLen=%d;" + "abiWLen=%d;abiFWLen=%d;abiWID=\"%s\";abiFWID=\"%s\";", noRegs, (fLen == 0 ? 0 : 32), xLen, abiFLen, xLen >> 3, abiFLen >> 3, (xLen == 32 ? "W" : (xLen == 64 ? "D" : "Q")), (abiFLen == 0 ? "" : (abiFLen == 32 ? "S" : (abiFLen == 64 ? "D" : "Q")))); } // // Return details string for SETENV opCode // public String getDetails() { DVArchOpCodes.this.branchStmtList.clear(); return String.format( "Architecture is................................. RISCV\n" + "Number of registers............................. %d\n" + "Register bit length (XLEN)...................... %d\n" + "Number of floating registers.................... %d\n" + "Floating register bit length (FLEN)............. %d\n" + "(A) atomic extension............................ %s\n" + "(C) two byte opCode encoding extension.......... %s\n" + "(M) integer multiply/divide extension........... %s\n" + "(N) user level interrupt extension.............. %s\n" + "(ZTSO) total store ordering..................... %s\n" + "(ZICSR) control/status registers extension...... %s\n" + "(ZIFENCEI) instruction fetch fence extension.... %s\n" + "ABI............................................. %s\n" + "Operating System................................ %s", noRegs, xLen, fLen == 0 ? 0 : 32, fLen, aExt ? "Used" : "Not Used", cExt ? "Used" : "Not Used", mExt ? "Used" : "Not Used", nExt ? "Used" : "Not Used", zTsoExt ? "Used" : "Not Used", zicsrExt ? "Used" : "Not Used", zifenceiExt ? "Used" : "Not Used", abiName, os != null ? os : "Not Specified" ); } // // Verify section type // public boolean verifySectionType(BigInteger typeValue) { return DVUtil.verifySectionType(typeValue); } // // Verify section attribute // public boolean verifySectionAttribute(BigInteger attributeValue) { return DVUtil.verifySectionAttribute(attributeValue); } // // Verify symbol bind // public boolean verifyExternalSymbolBind(BigInteger bind) { return DVUtil.verifyExternalSymbolBind(bind); } public boolean verifyExportedSymbolBind(BigInteger bind) { return DVUtil.verifyExportedSymbolBind(bind); } // // Verify symbol bind // public boolean verifySymbolType(BigInteger type) { return DVUtil.verifySymbolType(type); } // // Verify if base register is valid // public boolean verifyBaseRegister(BigInteger register) { return register.compareTo(BigInteger.ZERO) >= 0 && register.bitLength() <= DVArchOpCodes.this.regFileNoBits; } // // Return Relocation ID // public DVAbi.RelocationID getRelocationID(DVStatements.Statement owner, String relocationType, String format, boolean checkOverflow) { owner.putError("Software error - getRelocationID called with unsupported arguments"); return null; } public RelocationID[] getRelocationID(DVStatements.Statement owner, String relocationType, String format) { if (relocationType == null) { owner.putError("No relocation type has been provided for external symbol"); return null; } if (! relocationType.startsWith("@")) { owner.putError("Relocation type [%s] does not start with '@' character", relocationType); return null; } String[] relocationList= relocationType.substring(1).split(".@"); RelocationID[] relId= new RelocationID[relocationList.length]; for (int i= 0; i < relocationList.length; i++ ) { String type= relocationList[i]; RelocationEntry entry= relocationMap.get(type.toUpperCase()); if (entry == null) { owner.putError("Relocation type [" + type + "] is not supported"); return null; } if (! entry.format.equals(format.toUpperCase())) { owner.putError("Relocation type [" + type + "] is not supported for format [" + format + "]"); return null; } relId[i]= new DVAbi.RelocationID(entry.id, "R_RISCV" + type); } return relId; } // // Create relocation map // private HashMap getRelocationMap() { HashMap relocationMap= new HashMap(); relocationMap.put("_32", new RelocationEntry("WORD_32", 1)); relocationMap.put("_64", new RelocationEntry("WORD_64", 2)); relocationMap.put("_RELATIVE", new RelocationEntry("WORD_" + Integer.toString(xLen), 3)); relocationMap.put("_JUMP_SLOT", new RelocationEntry("WORD_" + Integer.toString(xLen), 5)); relocationMap.put("_TLS_DTPMOD32", new RelocationEntry("WORD_32", 6)); relocationMap.put("_TLS_DTPMOD64", new RelocationEntry("WORD_64", 7)); relocationMap.put("_TLS_DTPREL32", new RelocationEntry("WORD_32", 8)); relocationMap.put("_TLS_DTPREL64", new RelocationEntry("WORD_64", 9)); relocationMap.put("_TLS_TPREL32", new RelocationEntry("WORD_32", 10)); relocationMap.put("_TLS_TPREL64", new RelocationEntry("WORD_64", 11)); // relocationMap.put("_BRANCH", new RelocationEntry("B", 16)); relocationMap.put("_JAL", new RelocationEntry("J", 17)); relocationMap.put("_CALL", new RelocationEntry("U", 18)); relocationMap.put("_CALL_PLT", new RelocationEntry("U", 19)); relocationMap.put("_GOT_HI20", new RelocationEntry("U", 20)); relocationMap.put("_TLS_GOT_HI20", new RelocationEntry("U", 21)); relocationMap.put("_TLS_GD_HI20", new RelocationEntry("U", 22)); relocationMap.put("_PCREL_HI20", new RelocationEntry("U", 23)); relocationMap.put("_PCREL_LO12_I", new RelocationEntry("I", 24)); relocationMap.put("_PCREL_LO12_S", new RelocationEntry("S", 25)); relocationMap.put("_HI20", new RelocationEntry("U", 26)); relocationMap.put("_LO12_I", new RelocationEntry("I", 27)); relocationMap.put("_LO12_S", new RelocationEntry("S", 28)); relocationMap.put("_TPREL_HI20", new RelocationEntry("U", 29)); relocationMap.put("_TPREL_LO12_I", new RelocationEntry("I", 30)); relocationMap.put("_TPREL_LO12_S", new RelocationEntry("S", 31)); // relocationMap.put("_RVC_BRANCH", new RelocationEntry("CB", 44)); // relocationMap.put("_RVC_JUMP", new RelocationEntry("CJ", 45)); // relocationMap.put("_RVC_LUI", new RelocationEntry("CI", 46)); relocationMap.put("_GPREL_I", new RelocationEntry("I", 47)); relocationMap.put("_GPREL_S", new RelocationEntry("S", 48)); relocationMap.put("_TPREL_I", new RelocationEntry("I", 49)); relocationMap.put("_TPREL_S", new RelocationEntry("S", 50)); relocationMap.put("_32_PCREL", new RelocationEntry("WORD_32", 57)); return relocationMap; } // // Internal class for relocation specification // class RelocationEntry { protected RelocationEntry(String format, int id) { this.format= format; this.id= id; } protected String format; protected int id; } // // ABI attributes // public int getElfBits() { return DVArchOpCodes.this.xLen; } public int getAddrBits() { return DVArchOpCodes.this.xLen; } public DVUtil.Endianness getElfEndianness() { return DVUtil.Endianness.LITTLE; } public DVUtil.Endianness getDefaultEndianness() { return DVUtil.Endianness.LITTLE; } public int getOsAbi() { return 0x00; } public int getAbiVersion() { return 0x01; } public int getType() { return 0x01; } public int getMachine() { return 243; } public int getVersion() { return 1; } public int getProcessorFlags() { return processorFlags; } public long getRelocationSectionAttributes() { return 0x40; } // // Class fields // private final HashMap relocationMap= this.getRelocationMap(); private final String abiName; private final int processorFlags; } // // Method to setup opCodes // private void opCodeSetup(HashMap processOpCode) { // // Suspend and resume automatic conversion to C.* two bytes opCodes // this.processOpCode.put("C.SUSPEND", new SuspendCExtension()); this.processOpCode.put("C.RESUME", new ResumeCExtension()); // // Register save area // this.processOpCode.put("CLRREGFLAGS", new ClearRegUpdateFlags("Clear update flags for all registers")); this.processOpCode.put("REGSAVE", new RegSaveArea("Conditional register save area")); this.processOpCode.put("FREGSAVE", new FloatRegSaveArea("Conditional register save area")); // // Assembler defined opCodes // this.processOpCode.put("ALIGN", new OpCodeAlign( "ALIGN: Align on specified boundary using NoOp codes")); // // RV32I Base Instruction Set // this.processOpCode.put("ILLEGAL", new NPFormat(0b0l, "ILLEGAL: Illegal operation", 0b0l, "ILLEGAL -> C.ILLEGAL: Illegal operation")); this.processOpCode.put("LUI", new UFormat(0b0110111, "LUI: Load in RegD the sign extended Immediate value shifted left by 12 bits")); this.processOpCode.put("AUIPC", new UFormat(0b0010111, "AUIPC: Add the sign extended Immediate value shifted left by 12 bits to the Program Counter and store result in RegD")); this.processOpCode.put("JAL", new JFormat(0b1101111, "JAL: Jump to PC relative sign extended Immediate shifted left by 1, and store link address in RegD")); this.processOpCode.put("JALR", new IFormat(0b1100111, 0b000, immIntExt, "JALR: Jump to ( Reg1 + immediate ) address, and store link address in RegD")); this.processOpCode.put("BEQ", new BFormat(0b1100011, 0b000, "BEQ: Branch to PC relative signed extended Immediate multiplied by 2 if signed Reg1 == Reg2 (signed)")); this.processOpCode.put("BNE", new BFormat(0b1100011, 0b001, "BNE: Branch to PC relative signed extended Immediate multiplied by 2 if Reg1 != Reg2 (signed)")); this.processOpCode.put("BLT", new BFormat(0b1100011, 0b100, "BLT: Branch to PC relative signed extended Immediate multiplied by 2 if Reg1 < Reg2 (signed)")); this.processOpCode.put("BGE", new BFormat(0b1100011, 0b101, "BGE: Branch to PC relative signed extended Immediate multiplied by 2 if Reg1 >= Reg2 (signed)")); this.processOpCode.put("BLTU", new BFormat(0b1100011, 0b110, "BLTU: Branch to PC relative signed extended Immediate multiplied by 2 if Reg1 < Reg2 (unsigned)")); this.processOpCode.put("BGEU", new BFormat(0b1100011, 0b111, "BGEU: Branch to PC relative signed extended Immediate multiplied by 2 if Reg1 >= Reg2 (unsigned)")); this.processOpCode.put("LB", new IFormat(0b0000011, 0b000, immIntExtBaseDsp, "LB: Load sign extended byte into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("LH", new IFormat(0b0000011, 0b001, immIntExtBaseDsp, "LH: Load sign extended half word into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("LW", new IFormat(0b0000011, 0b010, immIntExtBaseDsp, EnumSet.of(IFormatType.CONDITIONAL), "LW: Load sign extended (64 & 128 bits only) word into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("LBU", new IFormat(0b0000011, 0b100, immIntExtBaseDsp, "LBU: Load zero extended byte into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("LHU", new IFormat(0b0000011, 0b101, immIntExtBaseDsp, "LHU: Load zero extended half word into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("SB", new SFormat(0b0100011, 0b000, immIntExtBaseDsp, "SB: Store Reg2 low byte into Reg1 relative sign extended Immediate memory address")); this.processOpCode.put("SH", new SFormat(0b0100011, 0b001, immIntExtBaseDsp, "SH: Store Reg2 low half word into Reg1 relative sign extended Immediate memory address")); this.processOpCode.put("SW", new SFormat(0b0100011, 0b010, immIntExtBaseDsp, EnumSet.of(SFormatType.CONDITIONAL), "SW: Store Reg2 word into Reg1 relative sign extended Immediate memory address")); this.processOpCode.put("ADDI", new IFormat(0b0010011, 0b000, immIntExtBaseDsp, "ADDI: Add sign extended Immediate to Reg1 and store result into RegD")); this.processOpCode.put("SLTI", new IFormat(0b0010011, 0b010, immInt, "SLTI: Set RegD to 1 if Reg1 < Immediate (signed), set to zero otherwise")); this.processOpCode.put("SLTIU", new IFormat(0b0010011, 0b011, immInt, "SLTIU: Set RegD to 1 if Reg1 < Immediate (unsigned), set to zero otherwise")); this.processOpCode.put("XORI", new IFormat(0b0010011, 0b100, immInt, "XORI: Exclusive OR sign extended Immediate to Reg1 and store result into RegD")); this.processOpCode.put("ORI", new IFormat(0b0010011, 0b110, immInt, "ORI: OR sign extended Immediate to Reg1 and store result into RegD")); this.processOpCode.put("ANDI", new IFormat(0b0010011, 0b111, immInt, "ANDI: AND sign extended Immediate to Reg1 and store result into RegD")); this.processOpCode.put("SLLI", new SHFormat(0b0010011, 0b001, xLenNoBits, "SLLI: Shift Logical Left Reg1 by the Shift Amount and store result in RegD")); this.processOpCode.put("SRLI", new SHFormat(0b0010011, 0b101, xLenNoBits, "SRLI: Shift Logical Right Reg1 by the Shift Amount and store result in RegD")); this.processOpCode.put("SRAI", new SHFormat(0b0010011, 0b01000000000000000101, xLenNoBits, "SRAI: Shift Arithmetic Right Reg1 by the Shift Amount and store result in RegD")); this.processOpCode.put("ADD", new RFormat(0b0110011, 0b000, 0b0000000, "ADD: Add Reg2 to Reg1 and store result in RegD")); this.processOpCode.put("SUB", new RFormat(0b0110011, 0b000, 0b0100000, "SUB: Subtract Reg2 from Reg1 and store result in RegD")); this.processOpCode.put("SLL", new RFormat(0b0110011, 0b001, 0b0000000, "SLL: Shift Logical Left Reg1 by the amount in Reg2 and store result in RegD")); this.processOpCode.put("SLT", new RFormat(0b0110011, 0b010, 0b0000000, "SLT: Set RegD to 1 if Reg1 < Reg2 (signed), set to zero otherwise")); this.processOpCode.put("SLTU", new RFormat(0b0110011, 0b011, 0b0000000, "SLT: Set RegD to 1 if Reg1 < Reg2 (unsigned), set to zero otherwise")); this.processOpCode.put("XOR", new RFormat(0b0110011, 0b100, 0b0000000, "XOR: Exclusive OR SReg1 with SReg2 and store result in RegD")); this.processOpCode.put("SRL", new RFormat(0b0110011, 0b101, 0b0000000, "SRL: Shift Logical Right SReg1 by the Shift Amount in SReg2 and store result in RegD")); this.processOpCode.put("SRA", new RFormat(0b0110011, 0b101, 0b0100000, "SRA: Shift Arithmetic Right Reg1 by the Shift Amount in SReg2 and store result in RegD")); this.processOpCode.put("OR", new RFormat(0b0110011, 0b110, 0b0000000, "OR: OR SReg1 with SReg2 and store result in RegD")); this.processOpCode.put("AND", new RFormat(0b0110011, 0b111, 0b0000000, "AND: AND SReg1 with SReg2 and store result in RegD")); this.processOpCode.put("FENCE", new IFormat(0b0001111, 0b000, immInt, EnumSet.of(IFormatType.IMM_NOT_ZERO), "FENCE: Synchronize memory read and write of this hart with other harts according to Immediate bits setting")); this.processOpCode.put("ECALL", new NPFormat(0b1110011, "ECALL: Invoke software interrup trap handler")); this.processOpCode.put("EBREAK", new NPFormat( 0b000000000001_00000_000_00000_1110011, "EBREAK: Invoke software interrup trap handler", 0b1001000_000000010l, "EBREAK -> C.EBREAK: Invoke debugger interrupt trap handler")); // // RV64I additional opCodes // if (xLen >= 64) { this.processOpCode.put("LWU", new IFormat(0b0000011, 0b110, immIntExtBaseDsp, "LWU: Load zero extended word into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("LD", new IFormat(0b0000011, 0b011, immIntExtBaseDsp, EnumSet.of(IFormatType.CONDITIONAL), "LD: Load sign extended word into RegD at Reg1 relative sign extended Immediate")); this.processOpCode.put("SD", new SFormat(0b0100011, 0b011, immIntExtBaseDsp, EnumSet.of(SFormatType.CONDITIONAL), "SD: Store Reg2 double word into Reg1 relative sign extended Immediate memory address")); this.processOpCode.put("ADDIW", new IFormat(0b0011011, 0b000, immIntExtBaseDsp, "ADDIW: Add sign extended Immediate to Reg1 low word and store sign extended result into RegD")); this.processOpCode.put("SLLIW", new SHFormat(0b0011011, 0b001, 32, "SLLIW: Shift Logical Left Reg1 low word by the Shift Amount and store the result in RegD")); this.processOpCode.put("SRLIW", new SHFormat(0b0011011, 0b101, 32, "SRLIW: Shift Logical Right Reg1 low word by the Shift Amount and store the result in RegD")); this.processOpCode.put("SRAIW", new SHFormat(0b0011011, 0b01000000000000000101, 32, "SRAIW: Shift Arithmetic Right Reg1 low word by the Shift Amount and store the result in RegD")); this.processOpCode.put("ADDW", new RFormat(0b0111011, 0b000, 0b0000000, "ADDW: Add Reg2 low word to Reg1 and store sign extended result in RegD")); this.processOpCode.put("SUBW", new RFormat(0b0111011, 0b000, 0b0100000, "SUBW: Subtract Reg2 low word from Reg1 low word and store sign extended result in RegD")); this.processOpCode.put("SLLW", new RFormat(0b0111011, 0b001, 0b0000000, "SLLW: Shift Logical Left Reg1 low word by the Shift Amount in Reg2 and store result in RegD")); this.processOpCode.put("SRLW", new RFormat(0b0111011, 0b101, 0b0000000, "SRLW: Shift Logical Right Reg1 low word by the Shift Amount in Reg2 and store result in RegD")); this.processOpCode.put("SRAW", new RFormat(0b0111011, 0b101, 0b0100000, "SRAW: Shift Arithmetic Right Reg1 low word by the Shift Amount in Reg2 and store result in RegD")); } // // A extension opCodes // if (aExt) { long opCode= 0b0101111; long f3= 0b010; this.processOpCode.put("LR.W", new RFormat(opCode, f3, 0b00000, 0b0001000, "LR.W: Load Reserved word at address pointed by Reg1 into RegD sign extended")); this.processOpCode.put("LR.W.AQ", new RFormat(opCode, f3, 0b00000, 0b0001010, "LR.W.AQ: Load Reserved word at address pointed by Reg1 into RegD sign extended - Aquire")); this.processOpCode.put("LR.W.RL", new RFormat(opCode, f3, 0b00000, 0b0001001, "LR.W.RL: Load Reserved word at address pointed by Reg1 into RegD sign extended - Release")); this.processOpCode.put("LR.W.AQ.RL", new RFormat(opCode, f3, 0b00000, 0b0001011, "LR.W.AQ.RL: Load Reserved word at address pointed by Reg1 into RegD sign extended - Aquire/Relase")); this.processOpCode.put("SC.W", new RFormat(opCode, f3, 0b0001100, "CS.W: Store Conditional low word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD")); this.processOpCode.put("SC.W.AQ", new RFormat(opCode, f3, 0b0001110, "SC.W.AQ: Store Conditional low word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD - Aquire")); this.processOpCode.put("SC.W.RL", new RFormat(opCode, f3, 0b0001101, "SC.W.RL: Store Conditional low word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD - Release")); this.processOpCode.put("SC.W.AQ.RL", new RFormat(opCode, f3, 0b0001111, "SC.W.AQ.RL: Store Conditional low word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD - Aquire/Relase")); this.processOpCode.put("AMOSWAP.W", new RFormat(opCode, f3, 0b0000100, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.W: Atomic swap word in Reg2 with word at Reg1 address into RegD")); this.processOpCode.put("AMOSWAP.W.AQ", new RFormat(opCode, f3, 0b0000110, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.AQ.W: Atomic swap word in Reg2 with word at Reg1 address into RegD - Aquire")); this.processOpCode.put("AMOSWAP.W.RL", new RFormat(opCode, f3, 0b0000101, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.RL.W: Atomic swap word in Reg2 with word at Reg1 address into RegD - Relase")); this.processOpCode.put("AMOSWAP.W.AQ.RL", new RFormat(opCode, f3, 0b0000111, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.AQ.RL.W: Atomic load word at Reg1 address into RegD - Reg2 must be zero - Aquire/Release")); this.processOpCode.put("AMOADD.W", new RFormat(opCode, f3, 0b0000000, RFormatType.ZERO_DESTREG_OK, "AMOADD.W: Atomic load/sign extend word at Reg1 address into RegD and store back Reg2+RegD")); this.processOpCode.put("AMOADD.W.AQ", new RFormat(opCode, f3, 0b0000010, RFormatType.ZERO_DESTREG_OK, "AMOADD.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back Reg2+RegD - Aquire")); this.processOpCode.put("AMOADD.W.RL", new RFormat(opCode, f3, 0b0000001, RFormatType.ZERO_DESTREG_OK, "AMOADD.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back Reg2+RegD - Relase")); this.processOpCode.put("AMOADD.W.AQ.RL", new RFormat(opCode, f3, 0b0000011, RFormatType.ZERO_DESTREG_OK, "AMOADD.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back Reg2+RegD - Aquire/Release")); this.processOpCode.put("AMOXOR.W", new RFormat(opCode, f3, 0b0010000, RFormatType.ZERO_DESTREG_OK, "AMOXOR.W: Atomic load/sign extend word at Reg1 address into RegD and store back XOR(Reg2, RegD)")); this.processOpCode.put("AMOXOR.W.AQ", new RFormat(opCode, f3, 0b0010010, RFormatType.ZERO_DESTREG_OK, "AMOXOR.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back XOR(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOXOR.W.RL", new RFormat(opCode, f3, 0b0010001, RFormatType.ZERO_DESTREG_OK, "AMOXOR.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back XOR(Reg2, RegD) - Relase")); this.processOpCode.put("AMOXOR.W.AQ.RL", new RFormat(opCode, f3, 0b0010011, RFormatType.ZERO_DESTREG_OK, "AMOXOR.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back XOR(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOAND.W", new RFormat(opCode, f3, 0b0110000, RFormatType.ZERO_DESTREG_OK, "AMOAND.W: Atomic load/sign extend word at Reg1 address into RegD and store back AND(Reg2, RegD)")); this.processOpCode.put("AMOAND.W.AQ", new RFormat(opCode, f3, 0b0110010, RFormatType.ZERO_DESTREG_OK, "AMOAND.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back AND(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOAND.W.RL", new RFormat(opCode, f3, 0b0110001, RFormatType.ZERO_DESTREG_OK, "AMOAND.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back AND(Reg2, RegD) - Relase")); this.processOpCode.put("AMOAND.W.AQ.RL", new RFormat(opCode, f3, 0b0110011, RFormatType.ZERO_DESTREG_OK, "AMOAND.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back AND(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOOR.W", new RFormat(opCode, f3, 0b0100000, RFormatType.ZERO_DESTREG_OK, "AMOOR.W: Atomic load/sign extend word at Reg1 address into RegD and store back OR(Reg2, RegD)")); this.processOpCode.put("AMOOR.W.AQ", new RFormat(opCode, f3, 0b0100010, RFormatType.ZERO_DESTREG_OK, "AMOOR.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back OR(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOOR.W.RL", new RFormat(opCode, f3, 0b0100001, RFormatType.ZERO_DESTREG_OK, "AMOOR.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back OR(Reg2, RegD) - Relase")); this.processOpCode.put("AMOOR.W.AQ.RL", new RFormat(opCode, f3, 0b0100011, RFormatType.ZERO_DESTREG_OK, "AMOOR.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back OR(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMIN.W", new RFormat(opCode, f3, 0b1000000, RFormatType.ZERO_DESTREG_OK, "AMOMIN.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MIN(Reg2, RegD)")); this.processOpCode.put("AMOMIN.W.AQ", new RFormat(opCode, f3, 0b1000010, RFormatType.ZERO_DESTREG_OK, "AMOMIN.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MIN(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMIN.W.RL", new RFormat(opCode, f3, 0b1000001, RFormatType.ZERO_DESTREG_OK, "AMOMIN.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MIN(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMIN.W.AQ.RL", new RFormat(opCode, f3, 0b1000011, RFormatType.ZERO_DESTREG_OK, "AMOMIN.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MIN(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMAX.W", new RFormat(opCode, f3, 0b1010000, RFormatType.ZERO_DESTREG_OK, "AMOMAX.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MAX(Reg2, RegD)")); this.processOpCode.put("AMOMAX.W.AQ", new RFormat(opCode, f3, 0b1010010, RFormatType.ZERO_DESTREG_OK, "AMOMAX.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MAX(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMAX.W.RL", new RFormat(opCode, f3, 0b1010001, RFormatType.ZERO_DESTREG_OK, "AMOMAX.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MAX(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMAX.W.AQ.RL", new RFormat(opCode, f3, 0b1010011, RFormatType.ZERO_DESTREG_OK, "AMOMAX.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back signed MAX(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMINU.W", new RFormat(opCode, f3, 0b1000000, RFormatType.ZERO_DESTREG_OK, "AMOMINU.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD)")); this.processOpCode.put("AMOMINU.W.AQ", new RFormat(opCode, f3, 0b1000010, RFormatType.ZERO_DESTREG_OK, "AMOMINU.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMINU.W.RL", new RFormat(opCode, f3, 0b1000001, RFormatType.ZERO_DESTREG_OK, "AMOMINU.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMINU.W.AQ.RL", new RFormat(opCode, f3, 0b1000011, RFormatType.ZERO_DESTREG_OK, "AMOMINU.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMAXU.W", new RFormat(opCode, f3, 0b1010000, RFormatType.ZERO_DESTREG_OK, "AMOMAXU.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD)")); this.processOpCode.put("AMOMAXU.W.AQ", new RFormat(opCode, f3, 0b1010010, RFormatType.ZERO_DESTREG_OK, "AMOMAXU.AQ.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMAXU.W.RL", new RFormat(opCode, f3, 0b1010001, RFormatType.ZERO_DESTREG_OK, "AMOMAXU.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMAXU.W.AQ.RL", new RFormat(opCode, f3, 0b1010011, RFormatType.ZERO_DESTREG_OK, "AMOMAX.AQ.RL.W: Atomic load/sign extend word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD) - Aquire/Release")); if (xLen >= 64) { f3= 0b011; this.processOpCode.put("LR.D", new RFormat(opCode, f3, 0b0001000, 0b00000, "LR.D: Load Reserved double word at address pointed by Reg1 into RegD sign extended")); this.processOpCode.put("LR.D.AQ", new RFormat(opCode, f3, 0b0001010, 0b00000, "LR.D.AQ: Load Reserved double word at address pointed by Reg1 into RegD sign extended - Aquire")); this.processOpCode.put("LR.D.RL", new RFormat(opCode, f3, 0b0001001, 0b00000, "LR.D.RL: Load Reserved double word at address pointed by Reg1 into RegD sign extended - Release")); this.processOpCode.put("LR.D.AQ.RL", new RFormat(opCode, f3, 0b0001011, 0b00000, "LR.D.AQ.RL: Load Reserved double word at address pointed by Reg1 into RegD sign extended - Aquire/Relase")); this.processOpCode.put("SC.D", new RFormat(opCode, f3, 0b0001100, "CS.D: Store Conditional double word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD")); this.processOpCode.put("SC.D.AQ", new RFormat(opCode, f3, 0b0001110, "SC.D.AQ: Store Conditional double word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD - Aquire")); this.processOpCode.put("SC.D.RL", new RFormat(opCode, f3, 0b0001101, "SC.D.RL: Store Conditional double word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD - Release")); this.processOpCode.put("SC.D.AQ.RL", new RFormat(opCode, f3, 0b0001111, "SC.D.AQ.RL: Store Conditional double word in Reg2 at address pointed by Reg1 and load success (zero) or failure (one) into RegD - Aquire/Relase")); this.processOpCode.put("AMOSWAP.D", new RFormat(opCode, f3, 0b0000100, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.D: Atomic swap word in Reg2 with word at Reg1 address into RegD")); this.processOpCode.put("AMOSWAP.D.AQ", new RFormat(opCode, f3, 0b0000110, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.AQ.D: Atomic swap word in Reg2 with word at Reg1 address into RegD - Aquire")); this.processOpCode.put("AMOSWAP.D.RL", new RFormat(opCode, f3, 0b0000101, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.RL.D: Atomic swap word in Reg2 with word at Reg1 address into RegD - Relase")); this.processOpCode.put("AMOSWAP.D.AQ.RL", new RFormat(opCode, f3, 0b0000111, RFormatType.ZERO_DESTREG_OK, "AMOSWAP.AQ.RL.D: Atomic swap word in Reg2 with word at Reg1 address into RegD - Aquire/Release")); this.processOpCode.put("AMOADD.D", new RFormat(opCode, f3, 0b0000000, RFormatType.ZERO_DESTREG_OK, "AMOADD.D: Atomic load/sign extend double word at Reg1 address into RegD and store back Reg2+RegD")); this.processOpCode.put("AMOADD.D.AQ", new RFormat(opCode, f3, 0b0000010, RFormatType.ZERO_DESTREG_OK, "AMOADD.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back Reg2+RegD - Aquire")); this.processOpCode.put("AMOADD.D.RL", new RFormat(opCode, f3, 0b0000001, RFormatType.ZERO_DESTREG_OK, "AMOADD.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back Reg2+RegD - Relase")); this.processOpCode.put("AMOADD.D.AQ.RL", new RFormat(opCode, f3, 0b0000011, RFormatType.ZERO_DESTREG_OK, "AMOADD.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back Reg2+RegD - Aquire/Release")); this.processOpCode.put("AMOXOR.D", new RFormat(opCode, f3, 0b0010000, RFormatType.ZERO_DESTREG_OK, "AMOXOR.D: Atomic load/sign extend double word at Reg1 address into RegD and store back XOR(Reg2, RegD)")); this.processOpCode.put("AMOXOR.D.AQ", new RFormat(opCode, f3, 0b0010010, RFormatType.ZERO_DESTREG_OK, "AMOXOR.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back XOR(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOXOR.D.RL", new RFormat(opCode, f3, 0b0010001, RFormatType.ZERO_DESTREG_OK, "AMOXOR.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back XOR(Reg2, RegD) - Relase")); this.processOpCode.put("AMOXOR.D.AQ.RL", new RFormat(opCode, f3, 0b0010011, RFormatType.ZERO_DESTREG_OK, "AMOXOR.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back XOR(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOAND.D", new RFormat(opCode, f3, 0b0110000, RFormatType.ZERO_DESTREG_OK, "AMOAND.D: Atomic load/sign extend double word at Reg1 address into RegD and store back AND(Reg2, RegD)")); this.processOpCode.put("AMOAND.D.AQ", new RFormat(opCode, f3, 0b0110010, RFormatType.ZERO_DESTREG_OK, "AMOAND.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back AND(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOAND.D.RL", new RFormat(opCode, f3, 0b0110001, RFormatType.ZERO_DESTREG_OK, "AMOAND.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back AND(Reg2, RegD) - Relase")); this.processOpCode.put("AMOAND.D.AQ.RL", new RFormat(opCode, f3, 0b0110011, RFormatType.ZERO_DESTREG_OK, "AMOAND.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back AND(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOOR.D", new RFormat(opCode, f3, 0b0100000, RFormatType.ZERO_DESTREG_OK, "AMOOR.D: Atomic load/sign extend double word at Reg1 address into RegD and store back OR(Reg2, RegD)")); this.processOpCode.put("AMOOR.D.AQ", new RFormat(opCode, f3, 0b0100010, RFormatType.ZERO_DESTREG_OK, "AMOOR.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back OR(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOOR.D.RL", new RFormat(opCode, f3, 0b0100001, RFormatType.ZERO_DESTREG_OK, "AMOOR.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back OR(Reg2, RegD) - Relase")); this.processOpCode.put("AMOOR.D.AQ.RL", new RFormat(opCode, f3, 0b0100011, RFormatType.ZERO_DESTREG_OK, "AMOOR.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back OR(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMIN.D", new RFormat(opCode, f3, 0b1000000, RFormatType.ZERO_DESTREG_OK, "AMOMIN.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MIN(Reg2, RegD)")); this.processOpCode.put("AMOMIN.D.AQ", new RFormat(opCode, f3, 0b1000010, RFormatType.ZERO_DESTREG_OK, "AMOMIN.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MIN(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMIN.D.RL", new RFormat(opCode, f3, 0b1000001, RFormatType.ZERO_DESTREG_OK, "AMOMIN.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MIN(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMIN.D.AQ.RL", new RFormat(opCode, f3, 0b1000011, RFormatType.ZERO_DESTREG_OK, "AMOMIN.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MIN(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMAX.D", new RFormat(opCode, f3, 0b1010000, RFormatType.ZERO_DESTREG_OK, "AMOMAX.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MAX(Reg2, RegD)")); this.processOpCode.put("AMOMAX.D.AQ", new RFormat(opCode, f3, 0b1010010, RFormatType.ZERO_DESTREG_OK, "AMOMAX.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MAX(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMAX.D.RL", new RFormat(opCode, f3, 0b1010001, RFormatType.ZERO_DESTREG_OK, "AMOMAX.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MAX(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMAX.D.AQ.RL", new RFormat(opCode, f3, 0b1010011, RFormatType.ZERO_DESTREG_OK, "AMOMAX.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back signed MAX(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMINU.D", new RFormat(opCode, f3, 0b1000000, RFormatType.ZERO_DESTREG_OK, "AMOMINU.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD)")); this.processOpCode.put("AMOMINU.D.AQ", new RFormat(opCode, f3, 0b1000010, RFormatType.ZERO_DESTREG_OK, "AMOMINU.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMINU.D.RL", new RFormat(opCode, f3, 0b1000001, RFormatType.ZERO_DESTREG_OK, "AMOMINU.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMINU.D.AQ.RL", new RFormat(opCode, f3, 0b1000011, RFormatType.ZERO_DESTREG_OK, "AMOMINU.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MIN(Reg2, RegD) - Aquire/Release")); this.processOpCode.put("AMOMAXU.D", new RFormat(opCode, f3, 0b1010000, RFormatType.ZERO_DESTREG_OK, "AMOMAXU.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD)")); this.processOpCode.put("AMOMAXU.D.AQ", new RFormat(opCode, f3, 0b1010010, RFormatType.ZERO_DESTREG_OK, "AMOMAXU.AQ.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD) - Aquire")); this.processOpCode.put("AMOMAXU.D.RL", new RFormat(opCode, f3, 0b1010001, RFormatType.ZERO_DESTREG_OK, "AMOMAXU.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD) - Relase")); this.processOpCode.put("AMOMAXU.D.AQ.RL", new RFormat(opCode, f3, 0b1010011, RFormatType.ZERO_DESTREG_OK, "AMOMAX.AQ.RL.D: Atomic load/sign extend double word at Reg1 address into RegD and store back unsigned MAX(Reg2, RegD) - Aquire/Release")); } } // // D extension opCodes // if (dExt) { this.processOpCode.put("FLD", new IFormat(0b0000111, 0b011, immIntExtBaseDsp, EnumSet.of(IFormatType.CONDITIONAL, IFormatType.FLOAT_REG), "FLD: Load 64 bit float into RegD from Reg1 relative sign extended Immediate memory location")); this.processOpCode.put("FSD", new SFormat(0b0100111, 0b011, immIntExtBaseDsp, EnumSet.of(SFormatType.CONDITIONAL, SFormatType.FLOAT_REG), "SLD Store 64 bit float in Reg2 at Reg1 relative sign extended Immediate memory location")); this.processOpCode.put("FMADD.D", new R4Format(0b01_00000_00000_000_00000_1000011, true, "FMADD.D Compute 64 bit float [ (Reg1 x Reg2) + Reg3 ] and store 64 bit result into float RegD")); this.processOpCode.put("FMSUB.D", new R4Format(0b01_00000_00000_000_00000_1000111, true, "FMSUB.D Compute 64 bit float [ (Reg1 x Reg2) - Reg3 ] and store 64 bit result into float RegD")); this.processOpCode.put("FNMSUB.D", new R4Format(0b01_00000_00000_000_00000_1001011, true, "FNMSUB.D Compute 64 bit float [ - (Reg1 x Reg2) + Reg3 ] and store 64 bit result into float RegD")); this.processOpCode.put("FNMADD.D", new R4Format(0b01_00000_00000_000_00000_1001111, true, "FNMADD.D Compute 64 bit float [ - (Reg1 x Reg2) - Reg3 ] and store 64 bit result into float RegD")); this.processOpCode.put("FADD.D", new RFormat(0b1010011, 0b0000000, true, "FADD.D Compute 64 bit float [ Reg1 + Reg2 ] and store 64 bit result into float RegD")); this.processOpCode.put("FSUB.D", new RFormat(0b1010011, 0b0000100, true, "FSUB.D Compute 64 bit float [ Reg1 - Reg2 ] and store 64 bit result into float RegD")); this.processOpCode.put("FMUL.D", new RFormat(0b1010011, 0b0000100, true, "FMUL.D Compute 64 bit float [ Reg1 * Reg2 ] and store 64 bit result into float RegD")); this.processOpCode.put("FDIV.D", new RFormat(0b1010011, 0b0000100, true, "FDIV.D Compute 64 bit float [ Reg1 / Reg2 ] and store 64 bit result into float RegD")); this.processOpCode.put("FSQRT.D", new RFormat(0b1010011, 0b00000, 0b0101100, true, RFormatType.CONST_SRC2REG_RM, "FSQRT.D Compute 64 bit float [ SQRT( Reg1 ) ] and store 64 bit result into float RegD")); this.processOpCode.put("FSGNJ.D", new RFormat(0b1010011, 0b000, 0b0010000, true, "FSGNJ.D Inject 64 bit float Reg2 sign into 64 bit float Reg1 and store 64 bit result into float RegD")); this.processOpCode.put("FSGNJN.D", new RFormat(0b1010011, 0b001, 0b0010000, true, "FSGNJN.D Inject 64 bit float Reg2 negated sign into 64 bit float Reg1 and store 64 bit result into float RegD")); this.processOpCode.put("FSGNJX.D", new RFormat(0b1010011, 0b010, 0b0010000, true, "FSGNJX.D Inject 64 bit float Reg2 and Reg1 signs XORed together into 64 bit float Reg1 " + "and store 64 bit result into float RegD")); this.processOpCode.put("FMIN.D", new RFormat(0b1010011, 0b000, 0b0010101, true, "FMIN.D Compute 64 bit float [ MIN( Reg1 + Reg2 ) ] and store 64 bit result into float RegD")); this.processOpCode.put("FMAX.D", new RFormat(0b1010011, 0b001, 0b0010101, true, "FMAX.D Compute 64 bit float [ MAX( Reg1 + Reg2 ) ] and store 64 bit result into float RegD")); this.processOpCode.put("FCVT.S.D", new RFormat(0b1010011, 0b00001, 0b0100000, true, RFormatType.CONST_SRC2REG_RM, "FCVT.S.D Convert 64 bit float Reg1 to 32 bit float and store result into 32 bit float RegD")); this.processOpCode.put("FCVT.D.S", new RFormat(0b1010011, 0b00000, 0b0100001, true, RFormatType.CONST_SRC2REG_RM, "FCVT.D.S Convert 32 bit float Reg1 to 64 bit float and store result into 64 bit float RegD")); this.processOpCode.put("FEQ.D", new RFormat(0b1010011, 0b010, 0b1010001, "FEQ.D Compute 64 bit float [ ( Reg1 == Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FLT.D", new RFormat(0b1010011, 0b001, 0b1010001, "FLT.D Compute 64 bit float [ ( Reg1 < Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FLE.D", new RFormat(0b1010011, 0b000, 0b1010001, "FLE.D Compute 64 bit float [ ( Reg1 <= Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FCLASS.D", new RFormat(0b1010011, 0b001, 0b00000, 0b1110001, "FCLASS.D Compute 64 bit float Reg2 class and store it to low 10 bits of integer RegD zero extended")); this.processOpCode.put("FCVT.W.D", new RFormat(0b1010011, 0b00000, 0b1100001, RFormatType.CONST_SRC2REG_RM, "FCVT.W.D Convert 64 bit float Reg1 to 32 bit signed integer and store 32 bit result into RegD sign extended")); this.processOpCode.put("FCVT.WU.D", new RFormat(0b1010011, 0b00001, 0b1100001, RFormatType.CONST_SRC2REG_RM, "FCVT.WU.D Convert 64 bit float Reg1 to 32 bit unsigned integer and store 32 bit result into RegD zero extended")); this.processOpCode.put("FCVT.D.W", new RFormat(0b1010011, 0b00000, 0b1101001, true, RFormatType.CONST_SRC2REG_RM, "FCVT.D.W Convert 32 bit signed integer Reg1 to 64 bit float and store result into 64 bit float RegD")); this.processOpCode.put("FCVT.D.WU", new RFormat(0b1010011, 0b00001, 0b1101001, true, RFormatType.CONST_SRC2REG_RM, "FCVT.D.WU Convert 32 bit unsigned integer Reg1 to 64 bit float and store result into 64 bit float RegD")); if (xLen > 32) { this.processOpCode.put("FCVT.L.D", new RFormat(0b1010011, 0b00010, 0b1100001, RFormatType.CONST_SRC2REG_RM, "FCVT.L.D Convert 64 bit float Reg1 to 64 bit signed integer and store 64 bit result into integer RegD sign extended")); this.processOpCode.put("FCVT.LU.D", new RFormat(0b1010011, 0b00011, 0b1100001, RFormatType.CONST_SRC2REG_RM, "FCVT.LU.D Convert 64 bit float Reg1 to 64 bit unsigned integer and store 64 bit result into integer RegD zero extended")); this.processOpCode.put("FMV.X.D", new RFormat(0b1010011, 0b000, 0b00000, 0b1110001, "FMV.X.D Copy 64 bit float Reg2 bit pattern to low 64 bits of integer RegD sign extended")); this.processOpCode.put("FCVT.D.L", new RFormat(0b1010011, 0b00010, 0b1101001, true, RFormatType.CONST_SRC2REG_RM, "FCVT.D.L Convert 64 bit signed integer Reg1 to 64 bit float and store result into 64 bit float RegD")); this.processOpCode.put("FCVT.D.LU", new RFormat(0b1010011, 0b00011, 0b1101001, true, RFormatType.CONST_SRC2REG_RM, "FCVT.D.LU Convert 64 bit unsigned integer Reg1 to 64 bit float and store result into 64 bit float RegD")); this.processOpCode.put("FMV.D.X", new RFormat(0b1010011, 0b000, 0b00000, 0b1111001, true, "FMV.D.X Copy low 64 bit integer Reg2 bit pattern to 64 bit float RegD")); } } // // F extension opCodes // if (fExt) { this.processOpCode.put("FLW", new IFormat(0b0000111, 0b010, immIntExtBaseDsp, EnumSet.of(IFormatType.CONDITIONAL, IFormatType.FLOAT_REG), "FLW: Load 32 bit float into RegD from Reg1 relative sign extended Immediate memory location")); this.processOpCode.put("FSW", new SFormat(0b0100111, 0b010, immIntExtBaseDsp, EnumSet.of(SFormatType.CONDITIONAL, SFormatType.FLOAT_REG), "SLW Store 32 bit float in Reg2 at Reg1 relative sign extended Immediate memory location")); this.processOpCode.put("FMADD.S", new R4Format(0b1000011, true, "FMADD.S Compute 32 bit float [ (Reg1 x Reg2) + Reg3 ] and store 32 bit result into float RegD")); this.processOpCode.put("FMSUB.S", new R4Format(0b1000111, true, "FMSUB.S Compute 32 bit float [ (Reg1 x Reg2) - Reg3 ] and store 32 bit result into float RegD")); this.processOpCode.put("FNMSUB.S", new R4Format(0b1001011, true, "FNMSUB.S Compute 32 bit float [ - (Reg1 x Reg2) + Reg3 ] and store 32 bit result into float RegD")); this.processOpCode.put("FNMADD.S", new R4Format(0b1001111, true, "FNMADD.S Compute 32 bit float [ - (Reg1 x Reg2) - Reg3 ] and store 32 bit result into float RegD")); this.processOpCode.put("FADD.S", new RFormat(0b1010011, 0b0000000, true, "FADD.S Compute 32 bit float [ Reg1 + Reg2 ] and store 32 bit result into RegD")); this.processOpCode.put("FSUB.S", new RFormat(0b1010011, 0b0000100, true, "FSUB.S Compute 32 bit float [ Reg1 - Reg2 ] and store 32 bit result into RegD")); this.processOpCode.put("FMUL.S", new RFormat(0b1010011, 0b0001000, true, "FMUL.S Compute 32 bit float [ Reg1 * Reg2 ] and store 32 bit result into RegD")); this.processOpCode.put("FDIV.S", new RFormat(0b1010011, 0b0001100, true, "FDIV.S Compute 32 bit float [ Reg1 / Reg2 ] and store 32 bit result into RegD")); this.processOpCode.put("FSQRT.S", new RFormat(0b1010011, 0b00000, 0b0101100, true, RFormatType.CONST_SRC2REG_RM, "FSQRT.S Compute 32 bit float [ SQRT( Reg1 ) ] and store 32 bit result into float RegD")); this.processOpCode.put("FSGNJ.S", new RFormat(0b1010011, 0b000, 0b0010000, true, "FSGNJ.S Inject 32 bit float Reg2 sign into 32 bit float Reg1 and store 32 bit result into float RegD")); this.processOpCode.put("FSGNJN.S", new RFormat(0b1010011, 0b001, 0b0010000, true, "FSGNJN.S Inject 32 bit float Reg2 negated sign into 32 bit float Reg1 and store 32 bit result into float RegD")); this.processOpCode.put("FSGNJX.S", new RFormat(0b1010011, 0b010, 0b0010000, true, "FSGNJX.S Inject 32 bit float Reg2 and Reg1 signs XORed together into 32 bit float Reg1 " + "and store 32 bit result into RegD")); this.processOpCode.put("FMIN.S", new RFormat(0b1010011, 0b000, 0b0010100, true, "FMIN.S Compute 32 bit float [ MIN( Reg1 , Reg2 ) ] and store 32 bit result into float RegD")); this.processOpCode.put("FMAX.S", new RFormat(0b1010011, 0b010, 0b0010100, true, "FMAX.S Compute 32 bit float [ MAX( Reg1 , Reg2 ) ] and store 32 bit result into float RegD")); this.processOpCode.put("FCVT.W.S", new RFormat(0b1010011, 0b00000, 0b1100000, RFormatType.CONST_SRC2REG_RM, "FCVT.W.S Convert 32 bit float Reg1 to 32 bit signed integer and store 32 bit result into integer RegD sign extended")); this.processOpCode.put("FCVT.WU.S", new RFormat(0b1010011, 0b00001, 0b1100000, RFormatType.CONST_SRC2REG_RM, "FCVT.WU.S Convert 32 bit float Reg1 to 32 bit unsigned integer and store 32 bit result into integer RegD zero extended")); this.processOpCode.put("FMV.X.W", new RFormat(0b1010011, 0b000, 0b00000, 0b1110000, "FMV.X.W Copy 32 bit float Reg2 bit pattern to low 32 bits of RegD sign extended")); this.processOpCode.put("FEQ.S", new RFormat(0b1010011, 0b010, 0b1010000, "FEQ.S Compute 32 bit float [ ( Reg1 == Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FLT.S", new RFormat(0b1010011, 0b001, 0b1010000, "FLT.S Compute 32 bit float [ ( Reg1 < Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FLE.S", new RFormat(0b1010011, 0b000, 0b1010000, "FLE.S Compute 32 bit float [ ( Reg1 <= Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FCLASS.S", new RFormat(0b1010011, 0b001, 0b00000, 0b1110000, "FCLASS.S Compute 32 bit float Reg2 class and store it to low 10 bits of integer RegD zero extended")); this.processOpCode.put("FCVT.S.W", new RFormat(0b1010011, 0b00000, 0b1101000, true, RFormatType.CONST_SRC2REG_RM, "FCVT.S.W Convert 32 bit signed integer Reg1 to 32 bit float and store result into 32 bit float RegD")); this.processOpCode.put("FCVT.S.WU", new RFormat(0b1010011, 0b00001, 0b1101000, true, RFormatType.CONST_SRC2REG_RM, "FCVT.S.WU Convert 32 bit unsigned integer Reg1 to 32 bit float and store result into 32 bit float RegD")); this.processOpCode.put("FMV.W.X", new RFormat(0b1010011, 0b000, 0b00000, 0b1111000, true, "FMV.W.X Copy low 32 bit integer Reg2 bit pattern to 32 bit float RegD")); if (xLen > 32) { this.processOpCode.put("FCVT.L.S", new RFormat(0b1010011, 0b00010, 0b1100000, RFormatType.CONST_SRC2REG_RM, "FCVT.L.S Convert 32 bit float Reg1 to 64 bit signed integer and store 32 bit result into integer RegD sign extended")); this.processOpCode.put("FCVT.LU.S", new RFormat(0b1010011, 0b00011, 0b1100000, RFormatType.CONST_SRC2REG_RM, "FCVT.LU.S Convert 32 bit float Reg1 to 64 bit unsigned integer and store 32 bit result into integer RegD zero extended")); this.processOpCode.put("FCVT.S.L", new RFormat(0b1010011, 0b00010, 0b1101000, true, RFormatType.CONST_SRC2REG_RM, "FCVT.S.L Convert 64 bit signed integer Reg1 to 32 bit float and store result into 32 bit float RegD")); this.processOpCode.put("FCVT.S.LU", new RFormat(0b1010011, 0b00011, 0b1101000, true, RFormatType.CONST_SRC2REG_RM, "FCVT.S.LU Convert 64 bit unsigned integer Reg1 to 32 bit float and store result into 32 bit float RegD")); } } // // M extension opCodes // if (mExt) { this.processOpCode.put("MUL", new RFormat(0b0110011, 0b000, 0b0000001, "MUL Multiply xLen values in Reg1 and Reg2 and store low xLen result in RegD")); this.processOpCode.put("MULH", new RFormat(0b0110011, 0b001, 0b0000001, "MULH Multiply signed xLen values in Reg1 and Reg2 and store high xLen result in RegD")); this.processOpCode.put("MULHSU", new RFormat(0b0110011, 0b010, 0b0000001, "MULHSU Multiply signed xLen value in Reg1 and unsigned xLen value in Reg2" + "and store high xLen result in RegD")); this.processOpCode.put("MULHU", new RFormat(0b0110011, 0b011, 0b0000001, "MULHU Multiply unsigned xLen values in Reg1 and Reg2 and store high xLen result in RegD")); this.processOpCode.put("DIV", new RFormat(0b0110011, 0b100, 0b0000001, "DIV Divide signed xLen value in Reg1 by signed xLen value in Reg2 and store result in RegD")); this.processOpCode.put("DIVU", new RFormat(0b0110011, 0b101, 0b0000001, "DIVU Divide unsigned xLen value in Reg1 by unsigned xLen value in Reg2 and store result in RegD")); this.processOpCode.put("REM", new RFormat(0b0110011, 0b110, 0b0000001, "REM Divide signed xLen value in Reg1 by signed xLen value in Reg2 and store reminder in RegD")); this.processOpCode.put("REMU", new RFormat(0b0110011, 0b111, 0b0000001, "REMU Divide usigned xLen value in Reg1 by usigned xLen value in Reg2 and store reminder in RegD")); if (xLen >= 64) { this.processOpCode.put("MULW", new RFormat(0b0111011, 0b000, 0b0000001, "MULW Multiply low 32 bit signed values in Reg1 and Reg2 and " + "store low 32 bit signed result in RegD")); this.processOpCode.put("DIVW", new RFormat(0b0111011, 0b100, 0b0000001, "DIVW Divide low 32 bit signed values in Reg1 and Reg2 and " + "store 32 bit result signed extended to 64 bits in RegD")); this.processOpCode.put("DIVUW", new RFormat(0b0111011, 0b101, 0b0000001, "DIVW Divide low 32 bits unsigned values in Reg1 and Reg2 and " + "store 32 bit result signed extended to 64 bits in RegD")); this.processOpCode.put("REMW", new RFormat(0b0111011, 0b110, 0b0000001, "REMW Divide low 32 bit signed values in Reg1 and Reg2 and " + "store 32 bit reminder signed extended to 64 bits in RegD")); this.processOpCode.put("REMUW", new RFormat(0b0111011, 0b111, 0b0000001, "REMUW Divide low 32 bit unsigned values in Reg1 and Reg2 and " + "store 32 bit reminder signed extended to 64 bits in RegD")); } } // // N extension opCodes // if (nExt) { this.processOpCode.put("URET", new NPFormat(0b00000000_00100000_00000000_01110011, "URET: Return from user level interrupt")); } // // Q extension opCodes // if (qExt) { this.processOpCode.put("FLQ", new IFormat(0b0000111, 0b100, immIntExtBaseDsp, EnumSet.of(IFormatType.CONDITIONAL, IFormatType.FLOAT_REG), "FLQ: Load 128 bit float into RegD from Reg1 relative sign extended Immediate memory location")); this.processOpCode.put("FSQ", new SFormat(0b0100111, 0b100, immIntExtBaseDsp, EnumSet.of(SFormatType.CONDITIONAL, SFormatType.FLOAT_REG), "FSQ Store 128 bit float in Reg2 at Reg1 relative sign extended Immediate memory location")); this.processOpCode.put("FMADD.Q", new R4Format(0b11_00000_00000_000_00000_1000011, true, "FMADD.Q Compute 128 bit float [ (Reg1 x Reg2) + Reg3 ] and store 128 bit result into float RegD")); this.processOpCode.put("FMSUB.Q", new R4Format(0b11_00000_00000_000_00000_1000111, true, "FMSUB.Q Compute 128 bit float [ (Reg1 x Reg2) - Reg3 ] and store 128 bit result into float RegD")); this.processOpCode.put("FNMSUB.Q", new R4Format(0b11_00000_00000_000_00000_1001011, true, "FNMSUB.Q Compute 128 bit float [ - (Reg1 x Reg2) + Reg3 ] and store 128 bit result into float RegD")); this.processOpCode.put("FNMADD.Q", new R4Format(0b11_00000_00000_000_00000_1001111, true, "FNMADD.Q Compute 128 bit float [ - (Reg1 x Reg2) - Reg3 ] and store 128 bit result into float RegD")); this.processOpCode.put("FADD.Q", new RFormat(0b1010011, 0b0000011, true, "FADD.Q Compute 128 bit float [ Reg1 + Reg2 ] and store 128 bit result into float RegD")); this.processOpCode.put("FSUB.Q", new RFormat(0b1010011, 0b0000111, true, "FSUB.Q Compute 128 bit float [ Reg1 - Reg2 ] and store 128 bit result into float RegD")); this.processOpCode.put("FMUL.Q", new RFormat(0b1010011, 0b0001011, true, "FMUL.Q Compute 128 bit float [ Reg1 * Reg2 ] and store 128 bit result into float RegD")); this.processOpCode.put("FDIV.Q", new RFormat(0b1010011, 0b0001111, true, "FDIV.Q Compute 128 bit float [ Reg1 / Reg2 ] and store 128 bit result into float RegD")); this.processOpCode.put("FSQRT.Q", new RFormat(0b1010011, 0b00000, 0b0101111, true, RFormatType.CONST_SRC2REG_RM, "FSQRT.Q Compute 128 bit float [ SQRT( Reg1 ) ] and store 128 bit result into float RegD")); this.processOpCode.put("FSGNJ.Q", new RFormat(0b1010011, 0b000, 0b0010011, true, "FSGNJ.Q Inject 128 bit float Reg2 sign into 128 bit float Reg1 and store 128 bit result into float RegD")); this.processOpCode.put("FSGNJN.Q", new RFormat(0b1010011, 0b001, 0b0010011, true, "FSGNJN.Q Inject 128 bit float Reg2 negated sign into 128 bit float Reg1 and store 128 bit result into floatRegD")); this.processOpCode.put("FSGNJX.Q", new RFormat(0b1010011, 0b010, 0b0010011, true, "FSGNJX.Q Inject 128 bit float Reg2 and Reg1 signs XORed together into 128 bit float Reg1 " + "and store 128 bit result into RegD")); this.processOpCode.put("FMIN.Q", new RFormat(0b1010011, 0b000, 0b0010111, true, "FMIN.Q Compute 128 bit float [ MIN( Reg1 + Reg2 ) ] and store 128 bit result into RegD")); this.processOpCode.put("FMAX.Q", new RFormat(0b1010011, 0b001, 0b0010111, true, "FMAX.Q Compute 128 bit float [ MAX( Reg1 + Reg2 ) ] and store 128 bit result into RegD")); this.processOpCode.put("FCVT.S.Q", new RFormat(0b1010011, 0b00011, 0b0100000, true, RFormatType.CONST_SRC2REG_RM, "FCVT.S.Q Convert 128 bit float Reg1 to 32 bit float and store result into 32 bit float RegD")); this.processOpCode.put("FCVT.Q.S", new RFormat(0b1010011, 0b00000, 0b0100011, true, RFormatType.CONST_SRC2REG_RM, "FCVT.Q.S Convert 32 bit float Reg1 to 128 bit float and store result into 128 bit float RegD")); this.processOpCode.put("FCVT.D.Q", new RFormat(0b1010011, 0b00011, 0b0100001, true, RFormatType.CONST_SRC2REG_RM, "FCVT.D.Q Convert 128 bit float Reg1 to 64 bit float and store result into 64 bit float RegD")); this.processOpCode.put("FCVT.Q.D", new RFormat(0b1010011, 0b00001, 0b0100011, true, RFormatType.CONST_SRC2REG_RM, "FCVT.Q.D Convert 64 bit float Reg1 to 128 bit float and store result into 128 bit float RegD")); this.processOpCode.put("FEQ.Q", new RFormat(0b1010011, 0b010, 0b1010011, "FEQ.Q Compute 128 bit float [ ( Reg1 == Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FLT.Q", new RFormat(0b1010011, 0b001, 0b1010011, "FLT.Q Compute 128 bit float [ ( Reg1 < Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FLE.Q", new RFormat(0b1010011, 0b000, 0b1010011, "FLE.Q Compute 128 bit float [ ( Reg1 <= Reg2 ) ] and store boolean 0 or 1 result in xLen integer RegD")); this.processOpCode.put("FCLASS.Q", new RFormat(0b1010011, 0b001, 0b00000, 0b1110011, "FCLASS.Q Compute 128 bit float Reg2 class and store it to low 10 bits of integer RegD zero extended")); this.processOpCode.put("FCVT.W.Q", new RFormat(0b1010011, 0b00000, 0b1100011, RFormatType.CONST_SRC2REG_RM, "FCVT.W.Q Convert 128 bit float Reg1 to 32 bit signed integer and store 32 bit result into integer RegD sign extended")); this.processOpCode.put("FCVT.WU.Q", new RFormat(0b1010011, 0b00001, 0b1100011, RFormatType.CONST_SRC2REG_RM, "FCVT.WU.Q Convert 128 bit float Reg1 to 32 bit unsigned integer and store 32 bit result into integer RegD zero extended")); this.processOpCode.put("FCVT.Q.W", new RFormat(0b1010011, 0b00000, 0b1101011, true, RFormatType.CONST_SRC2REG_RM, "FCVT.Q.W Convert 32 bit signed integer Reg1 to 128 bit float and store result into 128 bit float RegD")); this.processOpCode.put("FCVT.Q.WU", new RFormat(0b1010011, 0b00001, 0b1101011, true, RFormatType.CONST_SRC2REG_RM, "FCVT.Q.WU Convert 32 bit unsigned integer Reg1 to 128 bit float and store result into 128 bit float RegD")); if (xLen > 32) { this.processOpCode.put("FCVT.L.Q", new RFormat(0b1010011, 0b00010, 0b1100011, RFormatType.CONST_SRC2REG_RM, "FCVT.L.Q Convert 128 bit float Reg1 to 64 bit signed integer and store 64 bit result into integer RegD sign extended")); this.processOpCode.put("FCVT.LU.Q", new RFormat(0b1010011, 0b00011, 0b1100011, RFormatType.CONST_SRC2REG_RM, "FCVT.LU.Q Convert 128 bit float Reg1 to 64 bit unsigned integer and store 64 bit result into integer RegD zero extended")); this.processOpCode.put("FCVT.Q.L", new RFormat(0b1010011, 0b00010, 0b1101011, true, RFormatType.CONST_SRC2REG_RM, "FCVT.Q.L Convert 64 bit signed integer Reg1 to 128 bit float and store result into 128 bit float RegD")); this.processOpCode.put("FCVT.Q.LU", new RFormat(0b1010011, 0b00011, 0b1101011, true, RFormatType.CONST_SRC2REG_RM, "FCVT.Q.LU Convert 64 bit unsigned integer Reg1 to 128 bit float and store result into 128 bit float RegD")); } } // // S extension opCodes // if (sExt) { this.processOpCode.put("SRET", new NPFormat(0b00000000_00100000_00000000_01110011, "SRET: Return from supervisor level interrupt")); this.processOpCode.put("MRET", new NPFormat(0b00000000_00100000_00000000_01110011, "MRET: Return from machine level interrupt")); this.processOpCode.put("SFENCE.VMA", new RFormat(0b0001001, 0b000, 0b1110011, RFormatType.ZERO_DESTREG, "SFENCE.VMA Clear VM TLB for address in Reg1 (all addresses if R0) and ASID in Reg2 (all ASIDs if R0)")); this.processOpCode.put("WFI", new NPFormat(0b00010000_01010000_00000000_01110011, "WFI: Wait for interrupt")); } // // ZICSR extension opCodes // if (zicsrExt) { this.processOpCode.put("CSRRW", new IFormat(0b1110011, 0b001, immInt, "CSRRW: Atomically store CSR, specified by immediate value, into RegD and store Reg1 content into CSR")); this.processOpCode.put("CSRRS", new IFormat(0b1110011, 0b010, immInt, "CSRRS: Atomically store CSR, specified by immediate value, into RegD and mask CSR bits using Reg1 content" + " as a sign extended mask (Reg1 OR CSR)")); this.processOpCode.put("CSRRC", new IFormat(0b1110011, 0b011, immInt, "CSRRC: Atomically store CSR, specified by immediate value, into RegD and clear CSR bits using Reg1 content" + " as a sign extended mask (~ Reg1 AND CSR)")); this.processOpCode.put("CSRRWI", new IIFormat(0b1110011, 0b101, "CSRRWI: Atomically store CSR, specified by Imm1, into RegD and store Imm2 into CSR")); this.processOpCode.put("CSRRSI", new IIFormat(0b1110011, 0b110, "CSRRSI: Atomically store CSR, specified in Imm1, into RegD and mask CSR bits using Imm2 \n" + "as a sign extended mask (Reg1 VALUE OR CSR)")); this.processOpCode.put("CSRRCI", new IIFormat(0b1110011, 0b111, "CSRRCI: Atomically store CSR, specified in Imm1, into RegD and clear CSR bits using Imm2 \n" + "as a sign extended mask (~ Reg1 VALUE AND CSR)")); } // // ZIFENCE extension opCodes // if (zifenceiExt) { this.processOpCode.put("FENCE.I", new NPFormat(0b1000000001111, "FENCE.I: Synchronize data and instruction cache for the current hart")); } } // // Return OpCode specific processor // public DVOpCodeProcessor getOpCodeProcessor(DVStatements.Statement owner, Token opCode) { return this.processOpCode.get(opCode.image.toUpperCase()); } //---------------------------------------------------------------------------------------------- // // C extension suspend and resume // //---------------------------------------------------------------------------------------------- // // Suspend C extension // public class SuspendCExtension extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { useCExtension= false; return new DVCode(null, null, cExt ? "Use of C extension has been suspended" : "C extension not specified: directive ignored "); } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } } // // Resume C extension // public class ResumeCExtension extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { useCExtension= true & cExt; return new DVCode(null, null, cExt ? "Use of C extension has been resumed" : "C extension not specified: directive ignored "); } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // Save/Restore directives and conditional save areas // //---------------------------------------------------------------------------------------------- // // Reset registers update flag vector to a previously defined one // public class ClearRegUpdateFlags extends DVOpCodeProcessor { public ClearRegUpdateFlags(String description) { this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { regUpdateFlags= new boolean[64]; return new DVCode(null, this.description + "\n Regsiter upadate flags have been cleared"); } @Override public boolean getNeedSection() { return false; } private final String description; } //---------------------------------------------------------------------------------------------- // // Special opCodes // //---------------------------------------------------------------------------------------------- // // Align opCode // public class OpCodeAlign extends DVOpCodeProcessor { public OpCodeAlign(String description) { this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { DVImmediateOperand immOper= DVUtil.getImmediate(owner, 0, "Align", 9, false, immInt); if (immOper == null) return null; if (immOper.integer.bitCount() != 1) return owner.putErrorNoCode("Align [%s] is not power of two", immOper.integer.toString()); long align= immOper.integer.longValue(); int offset= owner.getOffset().intValue(); if (! cExt && (offset & 0b11) != 0) return owner.putErrorNoCode("Current offset is not 4 byte aligned and C extension is not available"); if ((offset & 0b1) != 0) return owner.putErrorNoCode("Current offset is not 2 byte aligned"); if (offset % align == 0) return new DVCode(null, null, String.format("Already aligned - No alignemnt NOOP instructions needed")); owner.guaranteeAlignment(immOper.integer); int length= (int) align - offset % (int) align; int no2NoOp= (length >> 1) & 0b1; int no4NoOp= length >> 2; byte[] code= new byte[no2NoOp*2+no4NoOp*4]; int i= 0; if (no2NoOp > 0) { convertLongToShortCode(code, i, noopCodeC); i+= 2; } for (; i < length; i+= 4) convertLongToCode(code, i, noopCode); Long brif; if ((brif= DVUtil.getAbsoluteKeyWordValue(owner, 0, "BRCOND", 0l, 127, 0l)) == null) return null; if (brif != 0 && ((length+2) >> 2) >= brif) { if (no2NoOp > 0) convertLongToShortCode(code, 0, 0b1010000000000001 | ((length & 0b100000) >> 3) | ((length & 0b1110) << 2) | ((length & 0b10000000) >> 1) | ((length & 0b1000000) << 1) | ((length & 0b10000000000) >> 2) | ((length & 0b1100000000) << 1) | ((length & 0b10000) << 7) | ((length & 0b100000000000) << 1)); else convertLongToCode(code, 0, 0b1101111 | ((length & 0b11111111000000000000) << 0) | ((length & 0b100000000000) << 9) | ((length & 0b11111111110) << 20) | ((length & 0b100000000000000000000) << 11)); } i= 0; String hexCode= ""; String longHexCode= ""; if (no2NoOp > 0) { hexCode+= String.format(" %02X%02X ", code[0], code[1]); longHexCode+= String.format(" %02X%02X", code[0], code[1]); i+= 2; } for (; i < length; i+= 4) { if (i < 6) hexCode+= String.format(" %02X%02X%02X%02X", code[i], code[i+1], code[i+2], code[i+3]); longHexCode+= String.format(" %02X%02X%02X%02X", code[i], code[i+1], code[i+2], code[i+3]); } hexCode= hexCode.substring(1); longHexCode= longHexCode.substring(1); return new DVCode(code, hexCode, String.format("%s\n" + " Align Code............. %s\n" + " Length of Code......... %04X", this.description, longHexCode, length)); } @Override public BigInteger getLength() { return BigInteger.ZERO; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } @Override public String[] getKeyWordList() { return new String[] { "BRCOND" }; } private final String description; } private static final long noopCode= 0b1110000_00010011; private static final long noopCodeC= 0b1; // // Register save area // public class RegSaveArea extends DVOpCodeProcessor { public RegSaveArea(String description) { this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long reg; if ((reg= DVUtil.getRegister(owner, regFileNoBits, destRegExclList, 0)) == null) return null; if (! regUpdateFlags[reg.intValue()]) return new DVCode(null, null, String.format(this.description + "\n Register Save Area skipped for register [%d] due to register not being updated", reg)); return new DVCode(new byte[xLen >> 3], xLen == 4 ? "00000000" : "00000000 00000000", String.format(this.description + "\n Register Save Area for register [%d] due to register being updated", reg)); } @Override public BigInteger getLength() { return BigInteger.valueOf(0); } @Override public BigInteger getAlign() { return BigInteger.valueOf(xLen >> 3); } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } private final String description; } // // Float Register save area // public class FloatRegSaveArea extends DVOpCodeProcessor { public FloatRegSaveArea(String description) { this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long reg; if ((reg= DVUtil.getRegister(owner, regFileNoBits, destRegExclList, 0)) == null) return null; if (! regUpdateFlags[32+reg.intValue()]) return new DVCode(null, null, String.format(String.format( "Float Register Save Area skipped for register [%d] due to register not being updated", reg))); return new DVCode(new byte[abiFLen >> 3], (abiFLen >> 3) == 4 ? "00000000" : "00000000 00000000", String.format(this.description + "\n Float Register Save Area for register [%d] due to register being updated", reg)); } @Override public BigInteger getLength() { return BigInteger.valueOf(0); } @Override public BigInteger getAlign() { return BigInteger.valueOf(abiFLen >> 3); } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } private final String description; } //---------------------------------------------------------------------------------------------- // // RISC-V encoding // //---------------------------------------------------------------------------------------------- // // No parameters // public class NPFormat extends DVOpCodeProcessor { public NPFormat(long mask, String description) { this.mask= mask; this.description= description; this.maskC= null; this.descriptionC= null; } public NPFormat(long mask, String description, Long maskC, String descriptionC) { this.mask= mask; this.description= description; this.maskC= maskC; this.descriptionC= descriptionC; } @Override public DVCode generateCode(DVStatements.Statement owner) { if (useCExtension && this.maskC != null) { return new DVCode(convertLongToShortCode(this.mask), String.format("%02X%02X", this.mask & 0xFF, (this.mask >> 8) & 0xFF), String.format("%s\n" + " Machine Instruction.... %04X [BIG ENDIAN]", owner.getOpCode() + " -> C." + owner.getOpCode() + " " + this.descriptionC, this.maskC)); } return new DVCode(convertLongToCode(this.mask), String.format("%02X%02X%02X%02X", this.mask & 0xFF, (this.mask >> 8) & 0xFF, (this.mask >> 16) &0xFF, (this.mask >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction.... %08X [BIG ENDIAN]", owner.getOpCode() + " " + this.description, this.mask)); } @Override public BigInteger getLength() { return BI_4; } @Override public BigInteger getAlign() { return BI_4; } private final long mask; private final String description; private final Long maskC; private final String descriptionC; } // // R type encoding // public class RFormat extends DVOpCodeProcessor { public RFormat(long opCode, long f3, long f7, String description) { this.mask= (f7 << 25) | (f3 << 12) | opCode; this.formatType= RFormatType.NORMAL; this.floatDestReg= false; this.description= description; } public RFormat(long opCode, long f3, long f7, boolean floatDestReg, String description) { this.mask= (f7 << 25) | (f3 << 12) | opCode; this.formatType= RFormatType.NORMAL; this.floatDestReg= floatDestReg; this.description= description; } public RFormat(long opCode, long f7, boolean floatDestReg, String description) { this.mask= (f7 << 25) | opCode; this.formatType= RFormatType.RM; this.floatDestReg= floatDestReg; this.description= description; } public RFormat(long opCode, long f3, long f7, RFormatType formatType, String description) { if (formatType == RFormatType.CONST_SRC2REG_RM) this.mask= (f7 << 25) | (f3 << 20) | opCode; // f3 contains src1Reg constant else this.mask= (f7 << 25) | (f3 << 12) | opCode; this.formatType= formatType; this.floatDestReg= false; this.description= description; } public RFormat(long opCode, long f3, long f7, boolean floatDestReg, RFormatType formatType, String description) { if (formatType == RFormatType.CONST_SRC2REG_RM) this.mask= (f7 << 25) | (f3 << 20) | opCode; // f3 contains src1Reg constant else this.mask= (f7 << 25) | (f3 << 12) | opCode; this.formatType= formatType; this.floatDestReg= floatDestReg; this.description= description; } public RFormat(long opCode, long f3, long src2Reg, long f7, String description) { this.mask= (f7 << 25) | (src2Reg << 20) | (f3 << 12) | opCode; this.formatType= RFormatType.CONST_SRC2REG; this.floatDestReg= false; this.description= description; } public RFormat(long opCode, long src2Reg, long f3, long f7, boolean floatDestReg, String description) { this.mask= (f7 << 25) | (src2Reg << 20) | (f3 << 12) | opCode; this.formatType= RFormatType.CONST_SRC2REG; this.floatDestReg= floatDestReg; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg; Long src1Reg; Long src2Reg; if (this.formatType == RFormatType.ZERO_DESTREG_OK) { if ((destReg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; } else if (this.formatType == RFormatType.ZERO_DESTREG) destReg= 0l; else if ((destReg= DVUtil.getRegister(owner, regFileNoBits, destRegExclList, 0)) == null) return null; if (regUpdateFlags != null) regUpdateFlags[destReg.intValue() + (this.floatDestReg ? 32 : 0)]= true; if (owner.getOpCodeParm().getPositionalParmListSize() > 2) { if (this.formatType == RFormatType.CONST_SRC2REG || this.formatType == RFormatType.CONST_SRC2REG_RM) return owner.putErrorNoCode("Reg2 is used as opCode extension for this opCode - " + "only two positional parameters are allowed"); if (this.formatType == RFormatType.ZERO_DESTREG) return owner.putErrorNoCode("RegD is used as opCode extension for this opCode - " + "only two positional parameters are allowed"); if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 2)) == null) return null; } else { if (this.formatType == RFormatType.FBOOLEAN) return owner.putErrorNoCode("For floating boolean opCodes three register parameters are required"); if (this.formatType == RFormatType.CONST_SRC2REG || this.formatType == RFormatType.CONST_SRC2REG_RM) { if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; src2Reg= 0l; } else if(this.formatType == RFormatType.ZERO_DESTREG) { if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; } else { src1Reg= destReg; if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; } } // // Check Rm= key-word parm // Long rm= null; if (this.formatType == RFormatType.RM || this.formatType == RFormatType.CONST_SRC2REG_RM) if ((rm= DVUtil.getAbsoluteKeyWordValue(owner, 0, "RM", validRM, 7l)) == null) return null; // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode rvcCode= cRFormat(owner, destReg, src1Reg, src2Reg); if (rvcCode != null) return rvcCode; } // // Standard 4 byte encoding // long code= this.mask | (rm != null ? (rm << 12) : 0) | (src2Reg << 20) | (src1Reg << 15) | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + (this.formatType == RFormatType.ZERO_DESTREG ? "" : String.format(" Destination Register...... %2d\n", destReg)) + (this.formatType == RFormatType.CONST_SRC2REG || this.formatType == RFormatType.CONST_SRC2REG_RM ? "" : String.format(" Source 2 Register...... %2d\n", src2Reg)) + " Source 1 Register...... %2d\n" + (rm != null ? String.format(" Round Mode................ %3s", Long.toString(rm, 2)) : ""), this.description, code, src1Reg)); } @Override public BigInteger getLength() { return cExt ? BI_2 : BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 3 }; } @Override public String[] getKeyWordList() { return new String[] { "RM" }; } private final long mask; private final RFormatType formatType; private final boolean floatDestReg; private final String description; private final long[] validRM= {0, 1, 2, 3, 4, 7 }; } // // R4 type encoding // public class R4Format extends DVOpCodeProcessor { public R4Format(long opCode, String description) { this.mask= opCode; this.rmFlag= true; this.floatDestReg= false; this.description= description; } public R4Format(long opCode, boolean floatDestReg, String description) { this.mask= opCode; this.rmFlag= true; this.floatDestReg= floatDestReg; this.description= description; } public R4Format(long opCode, long f3, String description) { this.mask= opCode | (f3 << 12); this.rmFlag= false; this.floatDestReg= false; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg; Long src1Reg; Long src2Reg; Long src3Reg; if ((destReg= DVUtil.getRegister(owner, regFileNoBits, destRegExclList, 0)) == null) return null; if (regUpdateFlags != null) regUpdateFlags[destReg.intValue() + (this.floatDestReg ? 32 : 0)]= true; if (owner.getOpCodeParm().getPositionalParmListSize() < 4) { src3Reg= destReg; if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 2)) == null) return null; } else { if ((src3Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 2)) == null) return null; if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 3)) == null) return null; } // // Check Rm= key-word parm // Long rm= null; if (this.rmFlag && (rm= DVUtil.getAbsoluteKeyWordValue(owner, 0, "RM", validRM, 7l)) == null) return null; // // Standard 4 byte encoding // long code= this.mask | (src3Reg << 27) | (src2Reg << 20) | (src1Reg << 15) | (rm << 12) | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source 3 Register...... %2d\n" + " Source 1 Register...... %2d\n" + " Source 2 Register...... %2d" + (rm != null ? String.format("\n Round Mode................ %03s", Long.toString(rm, 2)) : ""), this.description, code, destReg, src3Reg, src1Reg, src2Reg, rm)); } @Override public BigInteger getLength() { return cExt ? BI_2 : BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 3, 4 }; } @Override public String[] getKeyWordList() { return new String[] { "RM" }; } private final long mask; private final boolean rmFlag; private final boolean floatDestReg; private final String description; private final long[] validRM= {0, 1, 2, 3, 4, 7 }; } // // I type encoding // public class IFormat extends DVOpCodeProcessor { public IFormat(long opCode, long f3, EnumSet immType, String description) { this.mask= (f3 << 12) | opCode; this.immType= immType; EnumSet t= immType.clone(); t.remove(ImmType.BASEDSP); this.immTypeNoBase= t; this.conditional= false; this.immNZ= false; this.floatReg= false; this.description= description; } public IFormat(long opCode, long f3, EnumSet immType, EnumSet iFormatType, String description) { this.mask= (f3 << 12) | opCode; this.immType= immType; EnumSet t= immType.clone(); t.remove(ImmType.BASEDSP); this.immTypeNoBase= t; this.conditional= iFormatType.contains(IFormatType.CONDITIONAL); this.immNZ= iFormatType.contains(IFormatType.IMM_NOT_ZERO); this.floatReg= iFormatType.contains(IFormatType.FLOAT_REG); this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg; Long srcReg= null; DVImmediateOperand immOper; long imm; Long cond= 0l; // // Check cond= key-word parm // if (owner.getOpCodeParm().getKeyWordParmListSize() > 0) { if (! this.conditional) return owner.putErrorNoCode("Key-word parameter [COND] specified but not allowed for this opCode"); if ((cond= DVUtil.getBooleanKeyWordValue(owner, 0, "COND", 0l)) == null) return null; } // // Get destination register and handle update flag logic // if ((destReg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if (cond == 0) regUpdateFlags[destReg.intValue() + (this.floatReg ? 32 : 0)]= true; if (cond == 1 && ! regUpdateFlags[destReg.intValue() + (this.floatReg ? 32 : 0)]) return new DVCode(null, null, String.format( "OpCode [%s] skipped due to destination register not having been " + "updated", owner.getOpCode())); // // Get immediate // if (owner.getOpCodeParm().getSubParmListSize(1) > 0) { if ((srcReg= DVUtil.getRegister(owner, regFileNoBits, 1, 0)) == null) return null; if ((immOper= DVUtil.getImmediate(owner, 1, 12, true, immTypeNoBase)) == null) return null; } else if ((immOper= DVUtil.getImmediate(owner, 1, 12, true, immType)) == null) return null; // // Handle base-displacement case // if (immOper.immType == ImmType.BASEDSP) { imm= maskImmediate(immOper.integer.longValue(), 12); srcReg= immOper.baseReg; // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cIFormat(owner, destReg, srcReg, immOper.integer); if (retCode != null) return retCode; } if (this.immNZ && immOper.integer.equals(BigInteger.ZERO)) return owner.putErrorNoCode("Immediate for this opCode cannot be zero"); if (this.immNZ && (destReg != 0 || srcReg != 0)) return owner.putErrorNoCode("Registers for this opCode must be zero"); long code= this.mask | (imm << 20) | (srcReg << 15) | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Src 1/Base Register...... %2d\n" + " Immediate Displacement.... %s [HEX]\n" + "%s" + " Immediate Encoded......... %s [BIN] Bits [11:0]", this.description, code, destReg, srcReg, immediateToHex(immOper.integer, 3), (immOper.sectOffset != null ? String.format(" Immediate Offset.......... %s [HEX]\n", immediateToHex(immOper.sectOffset, 6)) : ""), immediateToBinary(immOper.integer, bitSections))); } // // Check if source equals destination // if (srcReg == null) srcReg= destReg; // // Handle ABSULTE or DISPLACEMENT immediate // if (immOper.immType == ImmType.INTEGER) { imm= maskImmediate(immOper.integer.longValue(), 12); // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cIFormat(owner, destReg, srcReg, immOper.integer); if (retCode != null) return retCode; } if (this.immNZ && immOper.integer.equals(BigInteger.ZERO)) return owner.putErrorNoCode("Immediate for this opCode cannot be zero"); long code= this.mask | (imm << 20) | (srcReg << 15) | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source 1 Register...... %2d\n" + " Immediate................. %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [11:0]", this.description, code, destReg, srcReg, immediateToHex(immOper.integer, 3), immediateToBinary(immOper.integer, bitSections))); } // // Handle relocated symbol immediate // String relIdList= ""; DVAbi.RelocationID relocationID[]= abi.getRelocationID(owner, immOper.externalToken.getQualifier(), "I"); if (relocationID == null) return null; for (int i= 0; i < relocationID.length; i++) { relIdList+= " : " + relocationID[i].nameID; owner.addRelocation(immOper.externalToken.getSymbol(), immOper.externalToken.getIntConstant(), relocationID[i]); } relIdList= relIdList.substring(3); long code= this.mask | (srcReg << 15) | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source Register...... %2d\n" + " External Symbol........... %s\n" + " Relocation Add-on......... %s [HEX]\n" + " Relocation ID(s).......... %s", this.description, code, destReg, srcReg, immOper.externalToken.getSymbol().getName(), immediateToHex(immOper.integer, 3), relIdList)); } @Override public BigInteger getLength() { return this.conditional ? BigInteger.ZERO : cExt ? BI_2 : BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 2 }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 0 }, { 0, 1 } }; }; @Override public String[] getKeyWordList() { return new String[] { "COND" }; } private final long mask; private final boolean conditional; private final EnumSet immType; private final EnumSet immTypeNoBase; private final boolean immNZ; private final boolean floatReg; private final String description; private final int[] bitSections= { 12 }; } // // II type encoding // public class IIFormat extends DVOpCodeProcessor { public IIFormat(long opCode, long f3, String description) { this.mask= (f3 << 12) | opCode; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg; DVImmediateOperand immOper1; DVImmediateOperand immOper2; long imm1; Long imm2; if ((destReg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if (regUpdateFlags != null) regUpdateFlags[destReg.intValue()]= true; if ((immOper1= DVUtil.getImmediate(owner, 1, 12, false, immInt)) == null) return null; imm1= maskImmediate(immOper1.integer.longValue(), 12); if ((immOper2= DVUtil.getImmediate(owner, 2, 5, false, immInt)) == null) return null; imm2= maskImmediate(immOper2.integer.longValue(), 5); long code= this.mask | (imm2 << 20) | (imm1 << 15) | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Immediate 1st operand..... %s [HEX]\n" + " Immediate 1st encoded..... %s [BIN] Bits [11:0]\n" + " Immediate 2nd operand..... %s [HEX]\n" + " Immediate 2nd encoded..... %s [BIN] Bits [4:0]\n", this.description, code, destReg, immediateToHex(immOper1.integer, 3), immediateToBinary(immOper1.integer, bitSections1), immediateToHex(immOper2.integer, 2), immediateToBinary(immOper2.integer, bitSections2))); } @Override public BigInteger getLength() { return BI_4; } @Override public BigInteger getAlign() { return BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 3, 3 }; } private final long mask; private final String description; private final int[] bitSections1= { 12 }; private final int[] bitSections2= { 5 }; } // // SH type encoding // public class SHFormat extends DVOpCodeProcessor { public SHFormat(long opCode, long f3, int noBits, String description) { this.mask= (f3 << 12) | opCode; this.noBits= noBits; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg; Long srcReg; DVImmediateOperand immOper; long imm; if ((destReg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if (regUpdateFlags != null) regUpdateFlags[destReg.intValue()]= true; // // Check if source equals destination // if (owner.getOpCodeParm().getSubParmListSize(1) > 0) { if ((srcReg= DVUtil.getRegister(owner, regFileNoBits, 1, 0)) == null) return null; } else srcReg= destReg; // // Get immediate // immOper= DVUtil.getImmediate(owner, 1, "Shift Amount", noBits, false, immInt); if (immOper == null) return null; imm= maskImmediate(immOper.integer.longValue(), this.noBits); // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cIFormat(owner, destReg, srcReg, immOper.integer); if (retCode != null) return retCode; } long code= this.mask | (imm << 20) | (srcReg << 15) | (destReg << 7); int[] bitSections= new int[1]; bitSections[0]= noBits == 32 ? 5 : 6; return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source 1 Register...... %2d\n" + " Shift Amount.............. %s [HEX]\n" + " Shift Amount Encoded...... %s [BIN] Bits [" + String.format("%d", bitSections[0]) + ":0]\n", this.description, code, destReg, srcReg, immediateToHex(immOper.integer, 2), immediateToBinary(immOper.integer, bitSections))); } @Override public BigInteger getLength() { return cExt ? BI_2 : BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 2 }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 0 }, { 0, 1 } }; }; private final long mask; private final int noBits; private final String description; } // // S type encoding // public class SFormat extends DVOpCodeProcessor { public SFormat(long opCode, long f3, EnumSet immType, String description) { this.mask= (f3 << 12) | opCode; this.immType= immType; EnumSet t= immType.clone(); t.remove(ImmType.BASEDSP); this.immTypeNoBase= t; this.conditional= false; this.floatReg= false; this.description= description; } public SFormat(long opCode, long f3, EnumSet immType, EnumSet formatType, String description) { this.mask= (f3 << 12) | opCode; this.immType= immType; EnumSet t= immType.clone(); t.remove(ImmType.BASEDSP); this.immTypeNoBase= t; this.conditional= formatType.contains(SFormatType.CONDITIONAL); this.floatReg= formatType.contains(SFormatType.FLOAT_REG); this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long src1Reg= null; Long src2Reg; DVImmediateOperand immOper; long imm; Long cond= 0l; // // Check cond= key-word parm // if (owner.getOpCodeParm().getKeyWordParmListSize() > 0) { if (! this.conditional) return owner.putErrorNoCode("Key-word parameter [COND] specified but not allowed for this opCode"); if ((cond= DVUtil.getBooleanKeyWordValue(owner, 0, "COND", 0l)) == null) return null; } // // Get register being stored and handle update flag logic // if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if (cond == 1 && (regUpdateFlags == null || ! regUpdateFlags[src2Reg.intValue() + (this.floatReg ? 32 : 0)])) return new DVCode(null, null, String.format( "OpCode [%s] skipped due to source register not having been updated", owner.getOpCode())); // // Handle base-displacement case // if (owner.getOpCodeParm().getSubParmListSize(1) > 0) { if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 1, 0)) == null) return null; if ((immOper= DVUtil.getImmediate(owner, 1, 12, true, immTypeNoBase)) == null) return null; } else { if ((immOper= DVUtil.getImmediate(owner, 1, 12, true, immType)) == null) return null; if (immOper.immType != ImmType.BASEDSP) return owner.putErrorNoCode("Base register not specified but immediate resolve to type [%s]", immOper.immType.name()); } // // Handle base-displacement case // if (immOper.immType == ImmType.INTEGER || immOper.immType == ImmType.BASEDSP) { imm= maskImmediate(immOper.integer.longValue(), 12); if (src1Reg == null) src1Reg= immOper.baseReg; if (src1Reg == null) return owner.putErrorNoCode("Explicit base register required when using a displacement"); // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cSFormat(owner, src1Reg, src2Reg, immOper.integer); if (retCode != null) return retCode; } long code= this.mask | ((imm & 0b111111100000) << 20) | ((imm & 0b11111) << 7) | (src2Reg << 20) | (src1Reg << 15); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Source 2 Register...... %2d\n" + " Src. 1/Base Register...... %2d\n" + " Immediate Displacement.... %s [HEX]\n" + "%s" + " Immediate Encoded......... %s [BIN] Bits [11:0]", this.description, code, src2Reg, src1Reg, immediateToHex(immOper.integer, 3), (immOper.sectOffset != null ? String.format(" Immediate Offset.......... %s [HEX]\n", immediateToHex(immOper.sectOffset, 6)) : ""), immediateToBinary(immOper.integer, bitSections))); } // // Handle relocated symbol immediate // String relIdList= ""; DVAbi.RelocationID relocationID[]= abi.getRelocationID(owner, immOper.externalToken.getQualifier(), "S"); if (relocationID == null) return null; for (int i= 0; i < relocationID.length; i++) { relIdList+= " : " + relocationID[i].nameID; owner.addRelocation(immOper.externalToken.getSymbol(), immOper.externalToken.getIntConstant(), relocationID[i]); } if (immOper.immType != ImmType.EXTERNAL) return owner.putErrorNoCode("Immediate type [%s] is invalid", immOper.immType); src1Reg= DVUtil.getRegister(owner, regFileNoBits, 1, 0); if (src1Reg == null) return owner.putErrorNoCode("Explicit base register required when using a relocated symbol"); relIdList= relIdList.substring(3); long code= this.mask | (src2Reg << 20) | (src1Reg << 15); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Source 2 Register...... %2d\n" + " Src. 1/Base Register...... %2d\n" + " External Symbol........... %s\n" + " Relocation Add-on......... %s [HEX]\n" + " Relocation ID(s).......... %s", this.description, code, src2Reg, src1Reg,immOper.externalToken.getSymbol().getName(), immediateToHex(immOper.integer, 3), relIdList)); } @Override public BigInteger getLength() { return this.conditional ? BigInteger.ZERO : cExt ? BI_2 : BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 2 }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 0 }, { 0, 1 } }; }; @Override public String[] getKeyWordList() { return new String[] { "COND" }; } private final long mask; private final String description; private final EnumSet immType; private final EnumSet immTypeNoBase; private final boolean conditional; private final boolean floatReg; private final int[] bitSections= { 7, 5 }; } // // B type encoding // public class BFormat extends DVOpCodeProcessor { public BFormat(long opCode, long f3, String description) { this.mask= (f3 << 12) | opCode; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long src1Reg; Long src2Reg; long imm; if ((src1Reg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if ((src2Reg= DVUtil.getRegister(owner, regFileNoBits, 1)) == null) return null; DVImmediateOperand immOper= DVUtil.getImmediate(owner, 2, 12, true, immIntPCRel); if (immOper == null) return null; imm= maskImmediate(immOper.integer.longValue(), 13); if ((imm & 0b1) != 0) return owner.putErrorNoCode("Immediate PC relative displacement low bit is not zero"); // // Insert statement for CHECKB2B processing // LinkedList bsl= DVArchOpCodes.this.branchStmtList.get(owner.getOffset()); if (bsl == null) { bsl= new LinkedList(); DVArchOpCodes.this.branchStmtList.put(owner.getOffset(), bsl); } bsl.add(new BranchStmt(owner, immOper.integer.add(owner.getOffset()), true)); // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cBFormat(owner, src1Reg, src2Reg, immOper.integer); if (retCode != null) return retCode; } long code= this.mask | ((imm & 0b1000000000000) << 19) | ((imm & 0b100000000000) >> 4) | ((imm & 0b11111100000) << 20) | ((imm & 0b11110) << 7) | (src2Reg << 20) | (src1Reg << 15); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Source 1 Register...... %2d\n" + " Source 2 Register...... %2d\n" + " Immediate PCRel........... %03X [HEX]\n" + " Immediate Sect. Offset.... %08X [HEX]\n" + " Immediate Bits [12:1]..... %s [BIN] bits [12:1]\n", this.description, code, src1Reg, src2Reg, immOper.integer, immOper.integer.add(owner.getOffset()), immediateToBinary(immOper.integer.shiftRight(1), bitSections))); } @Override public BigInteger getLength() { return cExt ? BI_2 : BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 3, 3 }; } private final long mask; private final String description; private final int[] bitSections= { 1, 1, 6, 4 }; } // // U type encoding // public class UFormat extends DVOpCodeProcessor { public UFormat(long opCode, String description) { this.mask= opCode; this.formatType= UFormatType.NORMAL; this.description= description; } public UFormat(long opCode, UFormatType formatType, String description) { this.mask= opCode; this.formatType= formatType; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg; int immParmNo; if (this.formatType == UFormatType.NORMAL) { if ((destReg= DVUtil.getRegister(owner, regFileNoBits, destRegExclList, 0)) == null) return null; if (regUpdateFlags != null) regUpdateFlags[destReg.intValue()]= true; immParmNo= 1; } else { destReg= 0l; immParmNo= 0; } DVImmediateOperand immOper= DVUtil.getImmediate(owner, immParmNo, 32, true, immIntExtPCRel); if (immOper == null) return null; if (immOper.immType == ImmType.EXTERNAL) { String relIdList= ""; DVAbi.RelocationID relocationID[]= abi.getRelocationID(owner, immOper.externalToken.getQualifier(), "U"); if (relocationID == null) return null; for (int i= 0; i < relocationID.length; i++) { relIdList+= " : " + relocationID[i].nameID; owner.addRelocation(immOper.externalToken.getSymbol(), immOper.externalToken.getIntConstant(), relocationID[i]); } long code= this.mask | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) & 0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " External Symbol........... %s\n" + " Relocation Add-on......... %s [HEX]\n" + " Relocation ID............. %s", this.description, code, destReg, immOper.externalToken.getSymbol().getName(), immediateToHex(immOper.externalToken.getIntConstant(), 5), relIdList.substring(3))); } long imm= immOper.integer.longValue(); if ((imm & 0b111111111111) != 0) return owner.putErrorNoCode("Immediate [%05X] 12 low bits are not zero", imm); imm= maskImmediate(imm, 32); // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cUFormat(owner, destReg, imm); if (retCode != null) return retCode; } long code= this.mask | (destReg << 7) | imm; return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Immediate PCRel........... %06X [HEX]\n" + " Immediate Sect. Offset.... %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [31:12]", this.description, code, destReg, immOper.integer, immediateToHex(immOper.integer.add(owner.getOffset()), 5), immediateToBinary(immOper.integer.shiftRight(12), bitSections))); } @Override public BigInteger getLength() { return BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { this.formatType == UFormatType.NORMAL ? 2 : 1 , 2 }; } private final long mask; private final UFormatType formatType; private final String description; private final int[] bitSections= { 20 }; } // // J type encoding // public class JFormat extends DVOpCodeProcessor { public JFormat(long opCode, String description) { this.mask= opCode; this.description= description; } @Override public DVCode generateCode(DVStatements.Statement owner) { Long destReg= null; if (owner.getOpCodeParm().getPositionalParmListSize() > 1) { if ((destReg= DVUtil.getRegister(owner, regFileNoBits, 0)) == null) return null; if (regUpdateFlags != null) regUpdateFlags[destReg.intValue()]= true; } DVImmediateOperand immOper= DVUtil.getImmediate(owner, (destReg == null ? 0 : 1), 21, true, immIntExtPCRel); if (immOper == null) return null; if (destReg == null) destReg= 0l; if (immOper.immType == ImmType.EXTERNAL) { String relIdList= ""; DVAbi.RelocationID relocationID[]= abi.getRelocationID(owner, immOper.externalToken.getQualifier(), "J"); if (relocationID == null) return null; for (int i= 0; i < relocationID.length; i++) { relIdList+= " : " + relocationID[i].nameID; owner.addRelocation(immOper.externalToken.getSymbol(), immOper.externalToken.getIntConstant(), relocationID[i]); } long code= this.mask | (destReg << 7); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " External Symbol........... %s\n" + " Relocation Add-on......... %s [HEX]\n" + " Relocation ID............. %s", this.description, code, destReg, immOper.externalToken.getSymbol().getName(), immediateToHex(immOper.externalToken.getIntConstant(), 6), relIdList.substring(3))); } long imm= maskImmediate(immOper.integer.longValue(), 21); if ((imm & 0b1) != 0) return owner.putErrorNoCode("Immediate low bit [%05X] low bit is on", imm); // // Insert statement for CHECKB2B processing // LinkedList bsl= DVArchOpCodes.this.branchStmtList.get(owner.getOffset()); if (bsl == null) { bsl= new LinkedList(); DVArchOpCodes.this.branchStmtList.put(owner.getOffset(), bsl); } bsl.add(new BranchStmt(owner, immOper.integer.add(owner.getOffset()), false)); // // Check if 2 byte encoding is a possibility // if (useCExtension) { DVCode retCode= cJFormat(owner, destReg, immOper.integer); if (retCode != null) return retCode; } long code= this.mask | (destReg << 7) | ((imm & 0b100000000000000000000) << 11) | ((imm & 0b11111111110) << 20) | ((imm & 0b100000000000) << 9) | (imm & 0b11111111000000000000); return new DVCode(convertLongToCode(code), String.format("%02X%02X%02X%02X", code & 0xFF, (code >> 8) & 0xFF, (code >> 16) &0xFF, (code >> 24) & 0xFF), String.format("%s\n" + " Machine Instruction....... %08X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Immediate PCRel........... %s [HEX]\n" + " Immediate Sect. Offset.... %08X [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [20:1]", this.description, code, destReg, immediateToHex(immOper.integer, 6), immOper.integer.add(owner.getOffset()), immediateToBinary(immOper.integer.shiftRight(1), bitSections))); } @Override public BigInteger getLength() { return BI_4; } @Override public BigInteger getAlign() { return cExt ? BI_2 : BI_4; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 2 }; } private final long mask; private final String description; private final int[] bitSections= { 1, 8, 1, 10 }; } //---------------------------------------------------------------------------------------------- // // RVC processor classes // //---------------------------------------------------------------------------------------------- // // RVC R format handler // private DVCode cRFormat(DVStatements.Statement owner, long destReg, long src1Reg, long src2Reg) { String opCode= owner.getOpCode(); if (opCode.contentEquals("ADD")) { if (destReg == 0) return null; if (src1Reg == 0 && src2Reg != 0) return crEncode(owner, 0b1000000000000010, destReg, src2Reg, owner.getOpCode() + " -> C.MV: copy value from source register to destination register"); if (src1Reg != 0 && src2Reg == 0) return crEncode(owner, 0b1000000000000010, destReg, src1Reg, owner.getOpCode() + " -> C.MV: copy value from source register to destination register"); if (destReg == src1Reg) return crEncode(owner, 0b1001000000000010, destReg, src2Reg, owner.getOpCode() + " -> C.ADD: add value from source register to destination register"); if (destReg == src2Reg) return crEncode(owner, 0b1001000000000010, destReg, src1Reg, owner.getOpCode() + " -> C.ADD: add value from source register to destination register"); return null; } if (destReg < 8 || destReg > 15 || src1Reg < 8 || src1Reg > 15 || src2Reg < 8 || src2Reg > 15 || (destReg != src1Reg && destReg != src2Reg)) return null; long srcReg= destReg == src1Reg ? src2Reg : src1Reg; switch(opCode) { case "AND" : return caEncode(owner, 0b1001000000000010, destReg, srcReg, "AND -> C.AND: and value from source register with destination register"); case "OR" : return caEncode(owner, 0b1001000000000010, destReg, srcReg, "OR -> C.OR: or value from source register with destination register"); case "XOR" : return caEncode(owner, 0b1001000000000010, destReg, srcReg, "XOR -> C.XOR: xor value from source register with destination register"); case "SUB" : if (destReg == src1Reg) return caEncode(owner, 0b1001000000000010, destReg, src2Reg, "SUB -> C.SUB: subtract value of source register from destination register"); return null; case "ADD.W" : return caEncode(owner, 0b1001000000000010, destReg, srcReg, "ADD.W -> C.AND.W: add value from source register with destination register and sign extend low 32 bits"); case "SUB.W" : if (destReg == src1Reg) return caEncode(owner, 0b1001000000000010, destReg, srcReg, "SUB.W -> C.SUB.W: subtract value of source register from destination register and sign extend low 32 bits"); return null; } return null; } // // RVC I format handler // private DVCode cIFormat(DVStatements.Statement owner, long destReg, long srcReg, BigInteger immediate) { String opCode= owner.getOpCode(); int immNoBits= immediate.bitLength(); int immSign= immediate.signum(); if (immSign <= 0) immNoBits++; switch(opCode) { case "ADDI" : if (destReg != srcReg || destReg == 0 || immSign == 0) return null; if (immNoBits < 6) return ciEncode(owner, 0b0000000000000001, destReg, immediate, CiImm.I, "ADDI -> C.ADDI: add immediate value to destination register"); if (destReg == 2) { if (immNoBits < 10 && immLowBitsZero(immediate, 4)) return ciEncode(owner, 0b0110000000000001, destReg, immediate, CiImm.I16, "ADDI -> C.ADDI16SP: add immediate value multiplied by 16 to register 2"); if (validCReg(destReg) && immSign > 0 && immNoBits < 11 && immLowBitsZero(immediate, 2)) return ciwEncode(owner, 0b0000000000000000, destReg, immediate, "ADDI -> C.ADDI4SPN: add immediate value multiplied by 4 to register 2 and store result to destination register"); } return null; case "ADDI.W" : if (destReg == srcReg && immNoBits < 6) return ciEncode(owner, 0b0010000000000001, destReg, immediate, CiImm.I, "ADDI.W -> C.ADDIW: add value from source register to destination register and sign extend low 32 bits"); return null; case "SLLI" : if (destReg == srcReg && immSign > 0) { if (xLen > 64 && immediate.equals(BigInteger.valueOf(64))) return ciEncode(owner, 0b0000000000000010, destReg, BigInteger.valueOf(64), CiImm.I, "C.SLLI -> SLLI: left logical shift value of 64 in destination register encoded as zero"); if (immNoBits < 5 || (xLen > 64 && immNoBits < 6)) return ciEncode(owner, 0b0000000000000010, destReg, immediate, CiImm.I, "C.SLLI -> SLLI: left logical shift value in destination register by immediate"); } return null; case "SRLI" : if (matchCRegPair(destReg, srcReg) && immSign > 0) { if (xLen > 64 && immAllBitsOne(immediate, new int[] { 6 })) return ciEncode(owner, 0b1000000000000001, destReg, BigInteger.valueOf(64), CiImm.I, "C.SRLI -> SRLI: right logical shift value of 64 in destination register encoded as zero"); if (immNoBits < 5 || (xLen > 64 && ((immSign > 0 && immNoBits < 6) || immNoBits < 8 && immAllBitsOne(immediate, new int[] { 6, 5 })))) return ciEncode(owner, 0b1000000000000001, destReg, immediate, CiImm.I, "C.SRLI -> SRLI: right logical shift value in destination register by immediate (sign extended to 7 bits)"); } return null; case "SRAI" : if (matchCRegPair(destReg, destReg) && immSign > 0) { if (xLen > 64 &&immAllBitsOne(immediate, new int[] { 6 })) return cbEncode(owner, 0b1000010000000001, destReg, BigInteger.valueOf(64), CbImm.S, "C.SRAI -> SRAI: right arithmetic shift value in destination register by 64 encoded as zero"); if (immNoBits < 5 || (xLen > 64 && ((immSign > 0 && immNoBits < 6) || immNoBits < 8 && immAllBitsOne(immediate, new int[] { 6, 5 })))) return cbEncode(owner, 0b1000010000000001, destReg, immediate, CbImm.S, "C.SRAI -> SRAI: right arithmetic shift value in destination register by immediate (sign extended to 7 bits)"); } return null; case "ANDI" : if (matchCRegPair(destReg, destReg) && immSign > 0) return cbEncode(owner, 0b1000100000000001, destReg, immediate, CbImm.I, "C.ANDI -> SAND: and value in destination register by immediate (sign extended to 7 bits)"); return null; case "JALR" : if (destReg == 0 && srcReg != 0 && immSign == 0) return crEncode(owner, 0b1000000000000010, srcReg, destReg, "C.J -> JALR: branch to source resgister address"); if (destReg == 1 && srcReg != 0 && immSign == 0) return crEncode(owner, 0b1001000000000010, destReg, srcReg, "C.J -> JALR: branch to source resgister address and store return address in register 1"); return null; case "LW" : if (! (immSign >= 0 && immNoBits < 8 && immLowBitsZero(immediate, 2))) return null; if (srcReg == 2 && destReg != 0) return ciEncode(owner, 0b0100000000000010, destReg, immediate, CiImm.L32, "C.LWSP -> LW: load 32 bit value at offset Immediate[7:2] off register 2 into RegD"); if (validCRegPair(srcReg, destReg)) return clEncode(owner, 0b0100000000000000, destReg, srcReg, immediate, ClsImm.L32, "C.LW -> LW: load 32 bit value at offset Immediate[6:2] off Reg1 into RegD"); return null; case "LD" : if (! (immSign >= 0 && immNoBits < 9 && immLowBitsZero(immediate, 3))) return null; if (srcReg == 2 && destReg != 0) return ciEncode(owner, 0b0110000000000010, destReg, immediate, CiImm.L64, "C.LDSP -> LD: load 64 bit value at offset Immediate[9:3] off register 2 into RegD"); if (validCRegPair(srcReg, destReg)) return clEncode(owner, 0b0110000000000000, destReg, srcReg, immediate, ClsImm.L64, "C.LD -> LD: load 64 bit value at offset Immediate[7:3] off Reg1 into RegD"); return null; case "LQ" : if (! (immSign >= 0 && immNoBits < 10 && immLowBitsZero(immediate, 4))) return null; if (srcReg == 2 && destReg != 0) return ciEncode(owner, 0b0010000000000010, destReg, immediate, CiImm.L128, "C.LQSP -> LQ: load 128 bit value at offset Immediate[10:4] off register 2 into RegD"); if (validCRegPair(srcReg, destReg)) return clEncode(owner, 0b0110000000000000, destReg, srcReg, immediate, ClsImm.L128, "C.LQ -> LQ: load 128 bit value at offset Immediate[8:4] off Reg1 into RegD"); return null; case "FLW" : if (! (immSign >= 0 && immNoBits < 8 && immLowBitsZero(immediate, 2))) return null; if (xLen == 32 && srcReg == 2) return ciEncode(owner, 0b0110000000000010, destReg, immediate, CiImm.L32, "C.FLWSP -> FLW: load 32 bit value at offset Immediate[7:2] off register 2 into float RegD"); if (xLen == 32 && validCRegPair(srcReg, destReg)) return clEncode(owner, 0b0110000000000000, destReg, srcReg, immediate, ClsImm.L32, "C.FLW -> FLW: load 32 bit value at offset Immediate[6:2] off Reg1 into float RegD"); return null; case "FLD" : if (! (immSign >= 0 && immNoBits < 9 && immLowBitsZero(immediate, 3))) return null; if (xLen <= 64 && srcReg == 2 && destReg != 0) return ciEncode(owner, 0b0010000000000010, destReg, immediate, CiImm.L64, "C.FLDSP -> FLD: load 64 bit value at offset Immediate[9:3] off register 2 into float RegD"); if (xLen <= 64 && validCRegPair(srcReg, destReg)) return clEncode(owner, 0b0010000000000000, destReg, srcReg, immediate, ClsImm.L64, "C.FLD -> FLD: load 64 bit value at offset Immediate[7:3] off Reg1 into float RegD"); return null; } return null; } // // RVC S format handler // private DVCode cSFormat(DVStatements.Statement owner, long src1Reg, long src2Reg, BigInteger immediate) { String opCode= owner.getOpCode(); int immSign= immediate.signum(); int immNoBits= immediate.bitLength(); switch(opCode) { case "SW" : if (src1Reg == 2 && immSign >= 0 && immNoBits < 8 && immLowBitsZero(immediate, 2)) return cssEncode(owner, 0b1100000000000010, src2Reg, immediate, CssImm.L32, "C.SWSP -> SW: store 32 bit value in Reg2 (Source) at offset Immediate[7:2] off register 2 (Base)"); if (validCRegPair(src1Reg, src2Reg) && immSign >= 0 && immNoBits < 7 && immLowBitsZero(immediate, 2)) return csEncode(owner, 0b1100000000000000, src2Reg, src1Reg, immediate, ClsImm.L32, "C.SW -> SW: store 32 bit value in Reg2 (Source) at offset Immediate[6:2] off Reg1 (Base)"); return null; case "SD" : if (src1Reg == 2 && immSign >= 0 && immNoBits < 9 && immLowBitsZero(immediate, 3)) return cssEncode(owner, 0b1110000000000010, src2Reg, immediate, CssImm.L64, "C.SDSP -> SD: store 64 bit value in Reg2 (Source) at offset Immediate[9:3] off register 2 (Base)"); if (validCRegPair(src1Reg, src2Reg) && immSign >= 0 && immNoBits < 8 && immLowBitsZero(immediate, 3)) return csEncode(owner, 0b1110000000000000, src2Reg, src1Reg, immediate, ClsImm.L64, "C.SD -> SD: store 64 bit value in Reg2 (Source) at offset Immediate[7:3] off Reg1 (Base)"); return null; case "SQ" : if (src1Reg == 2 && immSign >= 0 && immNoBits < 10 && immLowBitsZero(immediate, 4)) return cssEncode(owner, 0b1010000000000010, src2Reg, immediate, CssImm.L128, "C.SQSP -> SQ: store 128 bit value in Reg2 (Source) at offset Immediate[10:4] off register 2 (Base)"); if (validCRegPair(src1Reg, src2Reg) && immSign >= 0 && immNoBits < 9 && immLowBitsZero(immediate, 4)) return csEncode(owner, 0b1010000000000000, src2Reg, src1Reg, immediate, ClsImm.L128, "C.SQ -> SQ: store 128 bit value in Reg2 (Source) at offset Immediate[8:4] off Reg1 (Base)"); return null; case "FSW" : if (xLen == 32 && src1Reg == 2 && immSign >= 0 && immNoBits < 8 && immLowBitsZero(immediate, 2)) return cssEncode(owner, 0b1110000000000010, src2Reg, immediate, CssImm.L32, "C.FSWSP -> FSW: store 32 bit value in float Reg2 (Source) at offset Immediate[7:2] off register 2 (Base)"); if (xLen == 32 && validCRegPair(src1Reg, src2Reg) && immSign >= 0 && immNoBits < 7 && immLowBitsZero(immediate, 2)) return csEncode(owner, 0b1110000000000000, src2Reg, src1Reg, immediate, ClsImm.L32, "C.FSW -> FSW: store 32 bit value in float Reg2 (Source) at offset Immediate[6:2] off Reg1 (Base)"); return null; case "FSD" : if (xLen <= 64 && src1Reg == 2 && immSign >= 0 && immNoBits < 9 && immLowBitsZero(immediate, 3)) return cssEncode(owner, 0b1010000000000010, src2Reg, immediate, CssImm.L64, "C.FSDSP -> FSD: store 64 bit value in float Reg2 (Source) at offset Immediate[9:3] off register 2 (Base)"); if (xLen <= 64 && validCRegPair(src1Reg, src2Reg) && immSign >= 0 && immNoBits < 8 && immLowBitsZero(immediate, 3)) return csEncode(owner, 0b1010000000000000, src2Reg, src1Reg, immediate, ClsImm.L64, "C.FSD -> FSD: store 64 bit value in float Reg2 (Source) at offset Immediate[7:3] off Reg1 (Base)"); return null; } return null; } // // RVC B format handler // private DVCode cBFormat(DVStatements.Statement owner, long src1Reg, long src2Reg, BigInteger immediate) { String opCode= owner.getOpCode(); int immNoBits= immediate.bitLength(); switch(opCode) { case "BEQ" : if (validCReg(src1Reg) && src2Reg == 0 && immNoBits < 9) return cbEncode(owner, 0b1100000000000001, src1Reg, immediate, CbImm.B, "C.BEQZ -> BEQ: branch to relative PC immediate when source register is zero"); if (validCReg(src2Reg) && src1Reg == 0 && immNoBits < 9) return cbEncode(owner, 0b1100000000000001, src2Reg, immediate, CbImm.B, "C.BEQZ -> BEQ: branch to relative PC immediate when source register is zero"); return null; case "BNE" : if (validCReg(src1Reg) && src2Reg == 0 && immNoBits < 9) return cbEncode(owner, 0b1110000000000001, src1Reg, immediate, CbImm.B, "C.BNEZ -> BNE: branch to relative PC immediate when source register is not equal zero"); if (validCReg(src2Reg) && src1Reg == 0 && immNoBits < 9) return cbEncode(owner, 0b1110000000000001, src2Reg, immediate, CbImm.B, "C.BNEZ -> BNE: branch to relative PC immediate when source register is not equal zero"); return null; } return null; } // // RVC U format handler // private DVCode cUFormat(DVStatements.Statement owner, long destReg, long imm) { String opCode= owner.getOpCode(); return null; } // // RVC J format handler // private DVCode cJFormat(DVStatements.Statement owner, long destReg, BigInteger immediate) { String opCode= owner.getOpCode(); switch(opCode) { case "JAL" : if (destReg == 0 && immediate.bitLength() < 12) return cjEncode(owner, 0b1010000000000001, immediate, "C.J -> JAL: branch to relative PC immediate without storing return address in any register"); if (xLen == 32 && destReg == 1 && immediate.bitLength() < 12) return cjEncode(owner, 0b0010000000000001, immediate, "C.JAL -> JAL: branch to relative PC immediate and store return address in register 1"); return null; } return null; } //---------------------------------------------------------------------------------------------- // // RVC encoding // //---------------------------------------------------------------------------------------------- // // CR type encoding // private static DVCode crEncode(DVStatements.Statement owner, long mask, long destReg, long src2Reg, String description) { long code= mask | (destReg << 7) | (src2Reg << 2); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("At OFFSET=%04X: %s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Dest/Src2 Register...... %2d\n" + " Source 1 Register...... %2d", owner.getOffset().intValue(), description, code, destReg, src2Reg)); } // // CI type encoding // private static DVCode ciEncode(DVStatements.Statement owner, long mask, long reg, BigInteger immediate, CiImm type, String description) { long imm= maskImmediate(immediate, getCiHighBit(type)+1); long code= mask | (reg << 7) | getCiImm(type, imm); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("At OFFSET=%04X: %s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Dest/src Register...... %2d\n" + " Immediate................. %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [%d:%d]", owner.getOffset().intValue(), description, code, reg, immediateToHex(immediate, 3), immediateToBinary(immediate.shiftRight(getCiShift(type)), getCiBitSections(type)), getCiHighBit(type), getCiShift(type))); } private static int getCiShift(CiImm type) { return (new int[] { 0, 4, 2, 3, 4 })[type.ordinal()]; } private static int getCiHighBit(CiImm type) { return (new int[] { 5, 9, 7, 8, 9 })[type.ordinal()]; } private static long getCiImm(CiImm type, long imm) { switch(type) { case I : return ((imm & 0b100000) << 7) | ((imm & 0b11111) << 2); case I16 : return ((imm & 0b1000000000) << 3) | ((imm & 0b110000000) >> 4) | ((imm & 0b1000000) >> 1) | ((imm & 0b100000) >> 3) | ((imm & 0b10000) << 2); case L32 : return ((imm & 0b11000000) >> 4) | ((imm & 0b100000) << 7) | ((imm & 0b11100) << 2); case L64 : return ((imm & 0b111000000) >> 2) | ((imm & 0b100000) << 7) | ((imm & 0b11000) << 2); default : return ((imm & 0b1111000000) >> 4) | ((imm & 0b100000) << 7) | ((imm & 0b10000) << 2); } } private static int[] getCiBitSections(CiImm type) { return (new int[][] { { 1, 5 } , { 1, 2, 1, 1, 1 } , { 2, 1, 3 } , { 3, 1, 2 } , { 4, 1, 1 } })[type.ordinal()]; } enum CiImm { I, I16, L32, L64, L128 } // // CSS type encoding // private static DVCode cssEncode(DVStatements.Statement owner, long mask, long reg, BigInteger immediate, CssImm type, String description) { long code= mask | (reg << 2) | getCssImm(type, immediate.longValue()); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("At OFFSET=%04X: %s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Dest/src Register...... %2d\n" + " Immediate................. %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [%d:%d]", owner.getOffset().intValue(), description, code, reg, immediateToHex(immediate, 3), immediateToBinary(immediate.shiftRight(getCssShift(type)), getCssBitSections(type)), getCssHighBit(type), getCssShift(type))); } private static int getCssShift(CssImm type) { return (new int[] { 2, 3, 4 })[type.ordinal()]; } private static int getCssHighBit(CssImm type) { return (new int[] { 7, 8, 9 })[type.ordinal()]; } private static long getCssImm(CssImm type, long imm) { switch(type) { case L32 : return ((imm & 0b11000000) << 1) | ((imm & 0b11100) << 8); case L64 : return ((imm & 0b111000000) << 1) | ((imm & 0b11000) << 7); default : return ((imm & 0b111100000) << 1) | ((imm & 0b10000) << 6); } } private static int[] getCssBitSections(CssImm type) { return (new int[][] { { 2, 4 } , { 3, 3 } , { 4, 2 } })[type.ordinal()]; } enum CssImm { L32, L64, L128 } // // CIW type encoding // private static DVCode ciwEncode(DVStatements.Statement owner, long mask, long reg, BigInteger immediate, String description) { long code= mask | (reg << 2) | ((immediate.longValue() & 0b1111111100) << 3); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("%s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source Register...... 2\n" + " Immediate................. %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [9:2]", description, code, reg, immediateToHex(immediate, 3), immediateToBinary(immediate.shiftRight(2), new int[] { 4, 2, 1, 1 }))); } // // CL type encoding // private static DVCode clEncode(DVStatements.Statement owner, long mask, long destReg, long src1Reg, BigInteger immediate, ClsImm type, String description) { long code= mask | ((destReg-8) << 2) | ((src1Reg-8) << 7) | (getClsImm(type, immediate.longValue()) >> (type.ordinal()+2)); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("%s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source Register...... %2d\n" + " Immediate................. %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [%d:%d]", description, code, destReg, src1Reg, immediateToHex(immediate, 2), immediateToBinary(immediate.shiftRight((type.ordinal()+2)), getClsBitSections(type)), 5+type.ordinal(), type.ordinal())); } // // CS type encoding // private static DVCode csEncode(DVStatements.Statement owner, long mask, long srcReg, long baseReg, BigInteger immediate, ClsImm type, String description) { long code= mask | ((srcReg-8) << 2) | ((baseReg-8) << 7) | (getClsImm(type, immediate.longValue()) >> (type.ordinal()+2)); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("%s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Source Register...... %2d\n" + " Base Register...... %2d\n" + " Immediate................. %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [%d:%d]", description, code, srcReg, baseReg, immediateToHex(immediate, 2), immediateToBinary(immediate, getClsBitSections(type)), 5+type.ordinal(), type.ordinal())); } private static long getClsImm(ClsImm type, long imm) { switch(type) { case L32 : return ((imm & 0b1000000) >> 1) | ((imm & 0b111000) << 7) | ((imm & 0b100) << 4); case L64 : return ((imm & 0b110000000) << 1) | ((imm & 0b111000) << 7); default : return ((imm & 0b100000000) << 2) | ((imm & 0b11000000) << 1) | ((imm & 0b110000) << 7) ; } } private static int[] getClsBitSections(ClsImm type) { return (new int[][] { { 1, 3, 1 } , { 2, 3 } , { 1, 2, 2 } })[type.ordinal()]; } enum ClsImm { L32, L64, L128 } // // CA type encoding // private static DVCode caEncode(DVStatements.Statement owner, long mask, long destReg, long src2Reg, String description) { long code= mask | ((destReg-8) << 7) | ((src2Reg-8) << 2); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("At OFFSET=%04X: %s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Destination Register...... %2d\n" + " Source Register...... %2d", owner.getOffset().intValue(), description, code, destReg, src2Reg)); } private static DVCode cbEncode(DVStatements.Statement owner, long mask, long reg, BigInteger immediate, CbImm type, String description) { long code= mask | (reg << 7) | getCbImm(type, immediate.longValue()); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("At OFFSET=%04X: %s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Source Register...... %2d\n" + " Immediate" + getCbImmType(type) + "....... %s [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [%d:%d]", owner.getOffset().intValue(), description, code, reg, immediateToHex(immediate, 3), immediateToBinary(immediate.shiftRight(getCbShift(type)), getCbBitSections(type)), getCbHighBit(type), getCbShift(type))); } private static long getCbImm(CbImm type, long imm) { switch(type) { case B : return ((imm & 0b100000000) << 4) | ((imm & 0b11000000) >> 1) | ((imm & 0b100000) >> 3) | ((imm & 0b11000) << 7) | ((imm & 0b110) << 2); case I : return ((imm & 0b100000) << 7) | ((imm & 0b11111) << 2); default : return ((imm & 0b100000) << 7) | ((imm & 0b11111) << 2); } } private static int getCbShift(CbImm type) { return (new int[] { 1, 0, 0 })[type.ordinal()]; } private static int getCbHighBit(CbImm type) { return (new int[] { 8, 5, 5 })[type.ordinal()]; } private static int[] getCbBitSections(CbImm type) { return (new int[][] { { 1, 2, 1, 1, 2, } , { 1, 5 } , { 1, 2, 2 } })[type.ordinal()]; } private static String getCbImmType(CbImm type) { return (new String[] { " PC Offset", " .........", " Shift...." })[type.ordinal()]; } enum CbImm { B, I, S } // // CJ type encoding // private static DVCode cjEncode(DVStatements.Statement owner, long mask, BigInteger immediate, String description) { long imm= maskImmediate(immediate.longValue(), 12); long code= mask | ((imm & 0b100000000000 ) << 1) | ((imm & 0b10000000000 ) >> 2) | ((imm & 0b1100000000 ) << 1) | ((imm & 0b10000000 ) >> 1) | ((imm & 0b1000000 ) << 1) | ((imm & 0b100000 ) >> 3) | ((imm & 0b10000 ) << 7) | ((imm & 0b1110 ) << 2); return new DVCode(convertLongToShortCode(code), String.format("%02X%02X", code & 0xFF, (code >> 8) & 0xFF), String.format("At OFFSET=%04X: %s\n" + " Machine Instruction....... %04X [BIG ENDIAN]\n" + " Immediate PC Offset....... %s [HEX]\n" + " Immediate Sect. Offset.... %08X [HEX]\n" + " Immediate Encoded......... %s [BIN] Bits [11:1]", owner.getOffset().intValue(), description, code, immediateToHex(immediate, 3), owner.getOffset().add(immediate).intValue(), immediateToBinary(immediate.shiftRight(1), new int[] { 1, 1, 2, 1, 1, 1, 1, 3 }))); } //---------------------------------------------------------------------------------------------- // // Utility methods and constants // //---------------------------------------------------------------------------------------------- // // Convert long to long/short machine instruction // private byte[] convertLongToCode(long l) { return new byte[] { (byte) (l & 0xFF), (byte) ((l >> 8) & 0xFF), (byte) ((l >> 16) & 0xFF), (byte) ((l >> 24) & 0xFF) }; } private byte[] convertLongToCode(byte[] code, int offset, long l) { code[offset]= (byte) (l & 0xFF); code[offset+1]= (byte) ((l >> 8) & 0xFF); code[offset+2]= (byte) ((l >> 16) & 0xFF); code[offset+3]= (byte) ((l >> 24) & 0xFF); return code; } private static byte[] convertLongToShortCode(long l) { return new byte[] { (byte) (l & 0xFF), (byte) ((l >> 8) & 0xFF) }; } private byte[] convertLongToShortCode(byte[] code, int offset, long l) { code[offset]= (byte) (l & 0xFF); code[offset+1]= (byte) ((l >> 8) & 0xFF); return code; } // // Check if low bits of immediate are zero // private boolean immLowBitsZero(BigInteger imm, int noBits) { return imm.and(BigInteger.ONE.shiftLeft(noBits).subtract(BigInteger.ONE)).signum() == 0; } // // Check a list of bits // private boolean immAllBitsOne(BigInteger imm, int[] bitList) { boolean cond= true; for (int i= 0; i < bitList.length; i++) cond &= imm.testBit(bitList[i]); return true; } // // Mask immediate // public static long maskImmediate(long imm, int noBits) { return imm & ((1l << noBits)-1l); } public static long maskImmediate(BigInteger imm, int noBits) { return imm.longValue() & ((1l << noBits)-1l); } // // Format immediate to hex // public static String immediateToHex(BigInteger imm, int width) { return immediateToHex(imm.toString(16).toUpperCase(), width); } public static String immediateToHex(long imm, int width) { return immediateToHex(Long.toString(imm, 16).toUpperCase(), width); } private static String immediateToHex(String t, int width) { String sign; if (t.substring(0,1).equals("-")) { t= t.substring(1); sign= "-"; } else sign= "+"; if(t.length() < width) t= String.format("%" + Integer.toString(width) + "s", t).replace(' ', '0'); return sign + t; } // // Format immediate to binary // public static String immediateToBinary(long imm, int[] bitSect) { return immediateToBinary(BigInteger.valueOf(imm), bitSect); } public static String immediateToBinary(BigInteger imm, int[] bitSect) { int noBits= 0; for (int i= 0; i < bitSect.length; i++) noBits+= bitSect[i]; int bitLength= imm.bitLength(); String pad= imm.signum() < 0 ? "1" : "0"; String immBin= ""; noBits--; for (int i= 0; i < bitSect.length; i++) { immBin+= "_"; for(int j= 0; j < bitSect[i]; j++) { if (noBits > bitLength) immBin+= pad; else immBin+= imm.testBit(noBits) ? "1" : "0"; noBits--; } } return immBin.substring(1); } // // Check if register for C type opCode // private boolean validCReg(long r) { return (r > 7 && r < 16); } // // Check if register pair is within range for C type opCode // private boolean validCRegPair(long r1, long r2) { return (r1 > 7 && r1 < 16 && r2 > 7 && r2 < 16); } // // Check if register pair is same register and is within range for C type opCode // private boolean matchCRegPair(long r1, long r2) { return (r1 == r2 && r1 > 7 && r1 < 16); } }