//-------------------------------------------------------------------------------------------------- // // @ 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. // //-------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- // // Base OpCodes class // //------------------------------------------------------------------------------------------------- package framework; import java.util.*; import java.math.BigDecimal; import java.math.BigInteger; import java.math.MathContext; public class DVFrameworkOpCodes extends DVOpCodes { // // Initialize opCodes hash map // protected DVFrameworkOpCodes() { DVOpCodeProcessor proc; this.processOpCode.put("ASSERT", new OC_ASSERT()); this.processOpCode.put("BASECLEAR", new OC_BASECLEAR()); this.processOpCode.put("BASEDROP", new OC_BASEDROP()); this.processOpCode.put("BASESET", new OC_BASESET()); this.processOpCode.put("BIGENDIAN", new OC_BIGENDIAN()); this.processOpCode.put("PCRES", new OC_PCRES()); this.processOpCode.put("PCSET", new OC_PCSET()); this.processOpCode.put("COMMON", new OC_COMMON()); this.processOpCode.put("DEFENDIAN", new OC_DEFENDIAN()); this.processOpCode.put("END", new OC_END()); this.processOpCode.put("EQU", new OC_EQU()); this.processOpCode.put("EXPORT", new OC_EXPORT()); this.processOpCode.put("EXTERNAL", new OC_EXTERNAL()); this.processOpCode.put("LITTLEENDIAN", new OC_LITTLEENDIAN()); this.processOpCode.put("MMAP", new OC_MMAP()); this.processOpCode.put("SECTION", new OC_SECTION()); this.processOpCode.put("SETENV", new OC_SETENV()); this.processOpCode.put("SETFILE", new OC_SETFILE()); this.processOpCode.put("TRACEON", new OC_TRACEON()); proc= new OC_BYTE_1(); this.processOpCode.put("BYTE_1", proc); this.processOpCode.put("WRD_1", proc); this.processOpCode.put("BYTE", proc); this.processOpCode.put("UTF_8", new OC_UTF_8()); this.processOpCode.put("BYTE_2", new OC_BYTE_2()); proc= new OC_WRD_2(); this.processOpCode.put("WRD_2", proc); this.processOpCode.put("HWRD", proc); this.processOpCode.put("UTF_16", new OC_UTF_16()); this.processOpCode.put("BYTE_4", new OC_BYTE_4()); proc= new OC_WRD_4(); this.processOpCode.put("WRD_4", proc); this.processOpCode.put("FWRD", proc); this.processOpCode.put("UTF_32", new OC_UTF_32()); this.processOpCode.put("BYTE_8", new OC_BYTE_8()); proc= new OC_WRD_8(); this.processOpCode.put("WRD_8", proc); this.processOpCode.put("DWRD", proc); this.processOpCode.put("BYTE_16", new OC_BYTE_16()); proc= new OC_WRD_16(); this.processOpCode.put("WRD_16", proc); this.processOpCode.put("QWRD", proc); this.processOpCode.put("BYTE_32", new OC_BYTE_32()); this.processOpCode.put("WRD_32", new OC_WRD_32()); this.processOpCode.put("BYTE_64", new OC_BYTE_64()); this.processOpCode.put("WRD_64", new OC_WRD_64()); this.processOpCode.put("BYTE_128", new OC_BYTE_128()); this.processOpCode.put("WRD_128", new OC_WRD_128()); this.processOpCode.put("BYTE_256", new OC_BYTE_256()); this.processOpCode.put("WRD_256", new OC_WRD_256()); this.processOpCode.put("BYTE_512", new OC_BYTE_512()); this.processOpCode.put("WRD_512", new OC_WRD_512()); this.processOpCode.put("BYTE_1K", new OC_BYTE_1K()); this.processOpCode.put("WRD_1K", new OC_WRD_1K()); this.processOpCode.put("BYTE_2K", new OC_BYTE_2K()); this.processOpCode.put("WRD_2K", new OC_WRD_2K()); this.processOpCode.put("BYTE_4K", new OC_BYTE_4K()); this.processOpCode.put("WRD_4K", new OC_WRD_4K()); this.processOpCode.put("BYTE_8K", new OC_BYTE_8K()); this.processOpCode.put("WRD_8K", new OC_WRD_8K()); this.processOpCode.put("BYTE_16K", new OC_BYTE_16K()); this.processOpCode.put("WRD_16K", new OC_WRD_16K()); this.processOpCode.put("BYTE_32K", new OC_BYTE_32K()); this.processOpCode.put("WRD_32K", new OC_WRD_32K()); this.processOpCode.put("BYTE_64K", new OC_BYTE_64K()); this.processOpCode.put("WRD_64K", new OC_WRD_64K()); } // // Return OpCode specific processor // @Override public DVOpCodeProcessor getOpCodeProcessor(DVStatements.Statement owner, Token opCode) { return this.processOpCode.get(opCode.image.toUpperCase()); } // // Return a null ABI, Hex Code header and hex code length // @Override public boolean verifyArchitecture(DVStatements.Statement owner, String arch) { return true; } @Override public boolean verifyExtension(DVStatements.Statement owner, String arch) { return false; } @Override public String getExtension() { return null; } @Override public DVAbi getAbi() { return null; } @Override public String getHexCodeHeader() { return this.hexCodeHeader; } @Override public int getHexCodeLength() { return this.hexCodeHeader.length(); } @Override public void postProcess() { } protected void putHexCodeHeader(String header) { this.hexCodeHeader= header; } //---------------------------------------------------------------------------------------------- // // Start opCode classes - one for each opCode // //---------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- // // ASSERT opCode // public class OC_ASSERT extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { DVExpression.ExprToken condition= owner.getOpCodeParm().getPositionalParameterValue(0); if (! DVExpression.INT_VALUE.contains(condition.type)) return owner.putErrorNoCode( "Expression for opCode ASSERT must resolve to ABSOLUTE or DISPLACEMENT without base"); if (condition.intConstant.equals(BigInteger.ZERO)) owner.putError("ASSERT opCode failed"); return null; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } } //---------------------------------------------------------------------------------------------- // // BASECLEAR opCode // public class OC_BASECLEAR extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { owner.dropAllBases(); return null; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 0, 0 }; } } //---------------------------------------------------------------------------------------------- // // BASEDROP opCode // public class OC_BASEDROP extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm.PositionalParm[] posParmList= owner.getOpCodeParm().getPositionalParmList(); for (int parmNo= 0; parmNo < posParmList.length; parmNo++) { DVExpression.ExprToken regToken= posParmList[parmNo].getParameterValue(); if (regToken == null) return owner.putErrorNoCode( String.format("Parameter No %d not specified, but default not available", parmNo+1)); if (regToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode( String.format("Parameter No %d must resolve to type ABSOLUTE", parmNo+1)); owner.dropBase(regToken.intConstant); } return null; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 256 }; } } //---------------------------------------------------------------------------------------------- // // BASESET opCode // public class OC_BASESET extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); DVSections.Section section; String baseID= null; DVExpression.ExprToken base= parm.getPositionalParameterValue(0); DVExpression.ExprToken register= parm.getPositionalParameterValue(1); if (base.type == DVExpression.TokenType.OFFSET) section= base.getOffsetSection(); else if (base.type == DVExpression.TokenType.BASE_DISPLACEMENT) { section= base.baseSection; baseID= base.baseID; } else return owner.putErrorNoCode("First parameter must resolve to either type OFFSET or type BASE_DISPLACEMENT"); BigInteger offset= base.intConstant; if (register == null) return owner.putErrorNoCode("Parameter No 2 not specified, but default not available"); if (register.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Second parameter base register must resolve to type ABSOLUTE"); if (! owner.statements.abi.verifyBaseRegister(register.intConstant)) return owner.putErrorNoCode(String.format("Base register [0x%s] is out of bound\n", DVUtil.formatHex(register.intConstant, 2))); owner.addBase(baseID, section, offset, register.intConstant); return null; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 2 }; } } //---------------------------------------------------------------------------------------------- // // CNTRES opCode // public class OC_PCRES extends DVOpCodeProcessor { @Override public DVExpression getValueExpression(DVStatements.Statement owner) { return owner.getSections().resetCounter(); } @Override public DVCode generateCode(DVStatements.Statement owner) { return new DVCode(null, null, "Program Counter has been reset to highest possible offset"); } @Override public boolean getValueInParm() { return true; } } //---------------------------------------------------------------------------------------------- // // CNTSET opCode // public class OC_PCSET extends DVOpCodeProcessor { public DVExpression getValueExpression(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); owner.getSections().setCounter(owner); return parm.getPositionalParm(0).parameter; } @Override public DVCode generateCode(DVStatements.Statement owner) { return new DVCode(null, null, "Program Counter has been set to new offset"); } @Override public boolean getValueInParm() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } } //---------------------------------------------------------------------------------------------- // // COMMON opCode // public class OC_COMMON extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); DVExpression.ExprToken symbolToken= owner.getOpCodeParm().getPositionalFirstTokenIfSingle(0); if (symbolToken == null || symbolToken.getType() != DVExpression.TokenType.SYMBOL) return owner.putErrorFalse("First parameter must be a single symbol with no operators"); symbolToken.symbol.markSymbolCommon(owner); return true; } @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); DVSymbols.Symbol symbol= parm.getPositionalFirstTokenIfSingle(0).getSymbol(); DVExpression.ExprToken alignToken= parm.getPositionalParameterValue(1); DVExpression.ExprToken sizeToken= parm.getPositionalParameterValue(2); DVExpression.ExprToken extNameToken= parm.getPositionalParameterValue(3); BigInteger alignValue; if (alignToken == null) alignValue= BigInteger.ONE; else { if (alignToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Common alignment must resolves to type ABSOLUTE"); alignValue= alignToken.intConstant; if (alignValue.compareTo(BigInteger.ZERO) < 0 || alignValue.bitCount() > 1 || alignValue.compareTo(BigInteger.valueOf(0x10000)) > 0) return owner.putErrorNoCode("Align value [" + alignValue.toString() + "] must be zero or non-negative power of 2"); } BigInteger sizeValue; if (sizeToken == null) sizeValue= BigInteger.ZERO; else { if (! DVExpression.INT_VALUE.contains(sizeToken.type)) return owner.putErrorNoCode("Common size must resolve to an ABSOLUTE or DISPLACEMENT"); sizeValue= sizeToken.intConstant; if (sizeValue.compareTo(BigInteger.ZERO) < 0) return owner.putErrorNoCode("Size resolves to a negative value"); } String extName; if (extNameToken == null) extName= null; else { if (extNameToken.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("Common external name must resolve to type STRING"); extName= extNameToken.stringConstant; } symbol.setSymbolCommon(sizeValue, alignValue, extName); return null; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 4 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false, true, true, true }; } } //---------------------------------------------------------------------------------------------- // // END opCode // public class OC_END extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { owner.getSections().setExpressionLength(); owner.statements.endOpCode= true; return true; } @Override public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // EQU opCode // public class OC_EQU extends DVOpCodeProcessor { @Override public DVExpression getValueExpression(DVStatements.Statement owner) { DVExpression expr= owner.getOpCodeParm().getPositionalParm(0).getParameter(); if (expr != null && expr.getFirstExprToken().qualifier != null) { owner.putError("Relocatable expression not allowed for opCode [EQU]"); return null; } return expr; } @Override public boolean getValueInParm() { return true; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNeedLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } } //---------------------------------------------------------------------------------------------- // // EXPORT opCode // public class OC_EXPORT extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { DVExpression.ExprToken symbolToken= owner.getOpCodeParm().getPositionalFirstTokenIfSingle(0); if (symbolToken == null || symbolToken.type != DVExpression.TokenType.SYMBOL) return owner.putErrorFalse("First parameter must be a single symbol with no operators"); symbolToken.symbol.markSymbolExported(owner); return true; } @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); DVSymbols.Symbol symbol= parm.getPositionalFirstTokenIfSingle(0).symbol; DVExpression.ExprToken typeToken= parm.getPositionalParameterValue(1); DVExpression.ExprToken bindToken= parm.getPositionalParameterValue(2); DVExpression.ExprToken sizeToken= parm.getPositionalParameterValue(3); DVExpression.ExprToken extNameToken= parm.getPositionalParameterValue(4); BigInteger typeValue; if (typeToken == null) typeValue= BigInteger.ONE; else { if (typeToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Exported symbol type must resolve to type ABSOLUTE"); typeValue= typeToken.intConstant; } BigInteger bindValue; if (bindToken == null) bindValue= DVUtil.symbolBindGlobal; else { if (bindToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Exported symbol bind must resolves to type ABSOLUTE"); bindValue= bindToken.intConstant; } BigInteger sizeValue; if (sizeToken == null) sizeValue= BigInteger.ZERO; else { if (! DVExpression.INT_VALUE.contains(sizeToken.type)) return owner.putErrorNoCode("Exported symbol size must resolves to an ABSOLUTE or DISPLACEMENT"); sizeValue= sizeToken.intConstant; if (sizeValue.compareTo(BigInteger.ZERO) < 0) return owner.putErrorNoCode("Exported symbol size resolves to a negative value"); } String extName; if (extNameToken == null) extName= parm.getPositionalFirstTokenIfSingle(0).parseToken.image; else { if (extNameToken.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("Exported symbol external name must resolve to type STRING"); extName= extNameToken.stringConstant; } // // Export symbol here // symbol.exportSymbol(owner, typeValue, bindValue, sizeValue, extName); return null; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 5 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false, true, true, true, true }; } } //---------------------------------------------------------------------------------------------- // // EXTERNAL opCode // public class OC_EXTERNAL extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { DVExpression.ExprToken symbolToken= owner.getOpCodeParm().getPositionalFirstTokenIfSingle(0); if (symbolToken == null || symbolToken.type != DVExpression.TokenType.SYMBOL) return owner.putErrorFalse("First parameter must be a single symbol with no operators"); symbolToken.symbol.markSymbolExternal(owner); return true; } @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); DVExpression.ExprToken symbolToken= parm.getPositionalFirstTokenIfSingle(0); DVExpression.ExprToken bindToken= parm.getPositionalParameterValue(1); DVExpression.ExprToken extNameToken= parm.getPositionalParameterValue(2); DVSymbols.Symbol symbol= symbolToken.symbol; BigInteger bindValue; if (bindToken == null) bindValue= DVUtil.symbolBindGlobal; else { if (bindToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("External symbol bind must resolve to type ABSOLUTE"); bindValue= bindToken.intConstant; } String extName; if (extNameToken == null) extName= parm.getPositionalFirstTokenIfSingle(0).parseToken.image; else { if (extNameToken.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("External symbol external name must resolve to type STRING"); extName= extNameToken.stringConstant; } symbol.setSymbolExternal(bindValue, extName); return null; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 3 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false, true, true }; } } //---------------------------------------------------------------------------------------------- // // DEFENDIAN opCode // public class OC_DEFENDIAN extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { if (owner.endianness == DVUtil.Endianness.UNDEFINED) return owner.putErrorFalse("Default ENDIANNESS not defined"); owner.statements.currentEndianness= owner.statements.defaultEndianness; return true; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // BIGENDIAN opCode // public class OC_BIGENDIAN extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { owner.setBigEndianness(); return true; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // LITTLEEDIAN opCode // public class OC_LITTLEENDIAN extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { owner.setLittleEndianness(); return true; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // MMAP opCode // public class OC_MMAP extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { owner.getSections().setExpressionLength(); owner.getSections().startSection(owner, owner.symbol.token, DVSections.SectionType.MMAP); return true; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNeedLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // SECTION opCode // public class OC_SECTION extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { owner.getSections().setExpressionLength(); owner.getOpCodeParm().setPrivateObject(owner.getSections() .startSection(owner, owner.symbol.token, DVSections.SectionType.SECTION)); return true; } @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); if (owner.statements.abi == null) owner.putErrorNoCode("Abi not previously specified or invalid"); DVExpression.ExprToken typeToken= parm.getPositionalParameterValue(0); DVExpression.ExprToken attrToken= parm.getPositionalParameterValue(1); DVExpression.ExprToken alignToken= parm.getPositionalParameterValue(2); DVExpression.ExprToken extNameToken= parm.getPositionalParameterValue(3); if (typeToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Section type must resolve to type ABSOLUTE"); BigInteger typeValue= typeToken.intConstant; if (attrToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Section attribute must resolve to type ABSOLUTE"); BigInteger attrValue= attrToken.intConstant; BigInteger alignValue; if (alignToken == null) alignValue= BigInteger.ONE; else { if (alignToken.type != DVExpression.TokenType.ABSOLUTE) return owner.putErrorNoCode("Section alignment must resolves to type ABSOLUTE"); alignValue= alignToken.intConstant; if (alignValue.compareTo(BigInteger.ZERO) < 0 || alignValue.bitCount() > 1 || alignValue.compareTo(BigInteger.valueOf(0x10000)) > 0) return owner.putErrorNoCode("Align value [" + alignValue.toString() + "] must be zero or non-negative power of 2"); } String extName; if (extNameToken == null) extName= null; else { if (extNameToken.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("Exported symbol external name must resolve to type STRING"); extName= extNameToken.stringConstant; } if (extName.startsWith(".rel")) return owner.putErrorNoCode("Section external names starting with <.rel> are reserved and cannot be used"); ((DVSections.Section) parm.getPrivateObject()).setAttributes(typeValue, attrValue, alignValue, extName); return null; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNeedLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 4 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false, false, true, true }; } } //---------------------------------------------------------------------------------------------- // // SETENV opCode // public class OC_SETENV extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); boolean okFlag= true; DVExpression.ExprToken arch= parm.getPositionalFirstTokenIfSingle(0); DVExpression.ExprToken opt= parm.getPositionalFirstTokenIfSingle(1); DVExpression.ExprToken abi= parm.getPositionalFirstTokenIfSingle(2); DVExpression.ExprToken os= parm.getPositionalFirstTokenIfSingle(3); String optString= ""; String osString= ""; if (arch.type != DVExpression.TokenType.STRING) okFlag= owner.putErrorFalse("Environment architecture must be a single STRING with no operators"); if (opt != null) { if (opt.type != DVExpression.TokenType.STRING) okFlag= owner.putErrorFalse("Abi options must be a single STRING with no operators"); optString= opt.stringConstant; } if (abi.type != DVExpression.TokenType.STRING) okFlag= owner.putErrorFalse("Environment abi must be a single STRING with no operators"); if (os != null) { if (os.type != DVExpression.TokenType.STRING) okFlag= owner.putErrorFalse("Environment os must be a single STRING with no operators"); osString= os.stringConstant; } if (okFlag) owner.setEnv(arch.stringConstant, optString, abi.stringConstant, osString); return okFlag; } @Override public DVCode generateCode(DVStatements.Statement owner) { return new DVCode(null, null, owner.statements.abi.getDetails()); } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } @Override public int[] getPosParmMinMax() { return new int[] { 2, 4 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false, false, true, true }; } } //---------------------------------------------------------------------------------------------- // // SETFILE opCode // public class OC_SETFILE extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { if (owner.statements.setFile) return owner.putErrorNoCode("Duplicate SETFILE opCode found - statement ignored"); owner.statements.setFile= true; return null; } public boolean getNeedSection() { return false; } public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // TRACEON opCode // public class OC_TRACEON extends DVOpCodeProcessor { @Override public boolean preProcessOpCode(DVStatements.Statement owner) { owner.statements.setLogTrace(true); return true; } @Override public boolean getNeedSection() { return false; } @Override public boolean getNoLabel() { return true; } } //---------------------------------------------------------------------------------------------- // // BYTE_1 opCode // public class OC_BYTE_1 extends DVOpCodeProcessor { @Override public DVExpression getReplExpression(DVOpCodeParm parm, DVStatements.Statement owner) { DVExpression expr= new DVExpression(owner); DVExpression addExpr; DVOpCodeParm.PositionalParm[] posParmList= owner.getOpCodeParm().getPositionalParmList(); for (DVOpCodeParm.PositionalParm p : posParmList) { DVOpCodeParm.SubParm[] subParmList= p.getSubParmList(); if (subParmList.length == 0 || (addExpr= subParmList[0].getSubParm()) == null) expr.addExpression(DVExpression.getConstantExpression(BigInteger.ONE, owner)); else expr.addExpression(addExpr); } if (expr.isEmpty()) expr.addExpression(DVExpression.getConstantExpression(BigInteger.ONE, owner)); return expr; } @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); int align= this.getAlign().intValue(); int length= this.getLength().intValue(); // // Check endianness // if (owner.endianness == DVUtil.Endianness.UNDEFINED) return owner.putErrorNoCode("Default ENDIANNESS not defined"); // // Get total length and get a corresponding byte array // int repl= owner.symbol.resultRepl.intConstant.intValue(); byte[] code= new byte[repl*length]; int codeOffset= 0; // // Loop over parm and generate code // byte[] newCode= null; int stmtOffset= owner.symbol.resultValue.intConstant.intValue(); String details= ""; int n= parm.getPositionalParmListSize(); for (int pn= 0; pn < n; pn++) { DVExpression.ExprToken value= parm.getPositionalParameterValue(pn); if (value == null) value= DVExpression.getConstantExprToken(BigInteger.ZERO, owner); DVOpCodeParm.SubParm[] subParmList= parm.getSubParmList(pn); if (subParmList.length == 0) repl= 1; //else { // if (! DVExpression.INT_VALUE.contains(subParmList[0].getSubParmValue().type)) // return owner.putErrorNoCode("Replcation value resolve to type [%s] - it must be either ABSOLUTE or DISPLACEMENT", // subParmList[0].getSubParmValue().type.name()); // repl= subParmList[0].getSubParmValue().intConstant.intValue(); //} switch(value.type){ case FLOAT : if (length < 2 || length > 32) return owner.putErrorNoCode("FLOAT constant allowed only for DATA OpCodes of" + " length between 2 and 32"); // // Compute mantissa/exponent // int bitExponent= 0; BigDecimal floatMantissa= value.floatConstant; int floatSign= floatMantissa.compareTo(BigDecimal.ZERO); int exponentLength= this.getExponentLength(); if (floatMantissa.equals(BigDecimal.ZERO)) { newCode= new byte[length]; break; } BigInteger bitFloat= BigInteger.ZERO; if (floatSign < 0) { floatMantissa= floatMantissa.negate(DVExpression.floatMC); bitFloat= BigInteger.ONE.shiftLeft(length*8-1); } bitExponent+= (1 << (exponentLength-1))-1; while (floatMantissa.compareTo(BigDecimal.ONE) == -1) { floatMantissa= floatMantissa.multiply(BD_2, DVExpression.floatMC); bitExponent--; } while (floatMantissa.compareTo(BD_2) >= 0) { floatMantissa= floatMantissa.divide(BD_2, DVExpression.floatMC); bitExponent++; } int mantissaLength= length*8-exponentLength; int shift= mantissaLength+this.guardLength; BigInteger bitMantissa= floatMantissa.multiply(BD_2.pow(shift), DVExpression.floatMC).toBigInteger(); BigDecimal xxx= floatMantissa.multiply(BD_2.pow(shift), DVExpression.floatMC); shift= bitMantissa.bitLength()-mantissaLength; if (bitMantissa.testBit(shift-1)) { bitMantissa= bitMantissa.shiftRight(shift).add(BigInteger.ONE); if (bitMantissa.bitLength() > mantissaLength) { bitMantissa.shiftRight(1); bitExponent++; } } else bitMantissa= bitMantissa.shiftRight(shift); // // Convert mantissa/exponent to IEEE format // if (bitExponent <= 0) { if (bitMantissa.testBit(-bitExponent)) { bitMantissa= bitMantissa.shiftRight(-bitExponent).add(BigInteger.ONE); if (bitMantissa.bitLength() > mantissaLength) { bitMantissa.shiftRight(1); bitExponent++; } } bitFloat= bitFloat.or(bitMantissa.shiftRight(-bitExponent+1)); } else if (bitExponent > (1 << exponentLength)-2) { bitFloat= bitFloat.or(BigInteger.valueOf((1 << exponentLength)-1).shiftLeft(mantissaLength-1)); } else { bitMantissa= bitMantissa.clearBit(mantissaLength-1); bitFloat= bitFloat.or(bitMantissa).or(BigInteger.valueOf(bitExponent).shiftLeft(mantissaLength-1)); } newCode= bitFloat.toByteArray(); details+= String.format("FLOAT, alignment [%d], length [%d], replication [%d], " + "endianness %s\n", align, length, repl, owner.endianness.name()); details+= String.format(" Code [%6s ENDIAN] -> %s\n", owner.endianness.name(), DVUtil.convertCodeToHex(newCode, length, owner.endianness == DVUtil.Endianness.BIG)); if (owner.endianness == DVUtil.Endianness.LITTLE) details+= String.format(" Code [BIG ENDIAN] -> %s\n", DVUtil.convertCodeToHex(newCode, length, true)); details+= String.format(" Code [DECIMAL ] -> %s\n", value.floatConstant.round(DVFrameworkOpCodes.precision).toString()); break; case ABSOLUTE : case DISPLACEMENT : newCode= value.intConstant.toByteArray(); if (! DVUtil.verifyOverflow(newCode, length)) return owner.putErrorNoCode("Data overflow"); details+= String.format("%s, alignment [%d], length [%d], replication [%d], " + "endianness %s\n", value.type.name(), align, length, repl, owner.endianness.name()); details+= String.format(" Code [%6s ENDIAN] -> %s\n", owner.endianness.name(), DVUtil.convertCodeToHex(newCode, length, owner.endianness == DVUtil.Endianness.BIG)); if (owner.endianness == DVUtil.Endianness.LITTLE && length > 1) details+= String.format(" Code [BIG ENDIAN] -> %s\n", DVUtil.convertCodeToHex(newCode, length, true)); details+= String.format(" Code [DECIMAL ] -> %s\n", value.intConstant.toString()); break; case OFFSET : case EXTERNAL_SIZE : case EXTERNAL_VALUE : if (repl != 1) return owner.putErrorNoCode("Relocatable data can only have a " + "replication value of one"); if (length < 4 || length > 8) return owner.putErrorNoCode( "Relocatable value accepted only for 4 and 8 byte length fields"); DVAbi.RelocationID relocationID[]; if (value.type == DVExpression.TokenType.EXTERNAL_SIZE) relocationID= owner.statements.abi.getRelocationID(owner, "SIZE", "WORD_" + Integer.toString(length*8)); else relocationID= owner.statements.abi.getRelocationID(owner, value.qualifier == null ? "ABS" : value.qualifier.toUpperCase(), "WORD_" + Integer.toString(length*8)); if (relocationID == null) return null; newCode= new byte[length]; String relIdList= ""; for (int i= 0; i < relocationID.length; i++) { owner.addRelocation(value.symbol, value.intConstant, relocationID[i]); relIdList+= " : " + relocationID[i].nameID; } relIdList= relIdList.substring(3); details+= String.format("%s, align [%d], length [%d], replication [%d], " + " endianness %s\n", value.type.name(), align, length, repl, owner.endianness.name()); details+= String.format(" Code [%6s ENDIAN] -> %s\n", owner.endianness.name(), DVUtil.convertCodeToHex(newCode, length, owner.endianness == DVUtil.Endianness.BIG)); if (owner.endianness == DVUtil.Endianness.LITTLE) details+= String.format(" Code [BIG ENDIAN] -> %s\n", DVUtil.convertCodeToHex(newCode, length, true)); details+= String.format(" Code [DECIMAL ] -> 0\n"); if (value.type == DVExpression.TokenType.OFFSET) details+= String.format( " Relocation ID type %s, Add-End 0x%s, for LOCAL symbol [%s]\n", relIdList, DVUtil.formatHex(value.intConstant, 8), value.symbol.name); else { String xsn= value.symbol.externalName; if (xsn == null) xsn= value.symbol.name; details+= String.format(" Relocation ID type %s, Add-End 0x%s, " + "for EXTERNAL symbol [%s] - external name [%s]\n", relIdList, DVUtil.formatHex(value.intConstant, 8), value.symbol.name, xsn); } break; default : return owner.putErrorNoCode(String.format("Positional paramter %d " + "resolves to %s and is not allowed for DATA OpCode", pn+1, value.type.name())); } codeOffset= DVUtil.addCode(code, codeOffset, newCode, length, repl, owner.endianness); } return new DVCode(code, formatCode(code), details); } @Override public BigInteger getLength() { return BigInteger.ONE; } @Override public BigInteger getRepl() { return null; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 256 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true , true }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } }; } public int getExponentLength() { return 0; } private static final int guardLength= 12; } //---------------------------------------------------------------------------------------------- // // BYTE_2 opCode // public class OC_BYTE_2 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_2; } @Override public int getExponentLength() { return 5; } } //---------------------------------------------------------------------------------------------- // // WRD_2 / HWRD opCode // public class OC_WRD_2 extends OC_BYTE_2 { @Override public BigInteger getAlign() { return BI_2; } } //---------------------------------------------------------------------------------------------- // // BYTE_4 opCode // public class OC_BYTE_4 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_4; } @Override public int getExponentLength() { return 8; } } //---------------------------------------------------------------------------------------------- // // WRD_4 / FWRD opCode // public class OC_WRD_4 extends OC_BYTE_4 { @Override public BigInteger getAlign() { return BI_4; } } //---------------------------------------------------------------------------------------------- // // BYTE_8 opCode // public class OC_BYTE_8 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_8; } @Override public int getExponentLength() { return 11; } } //---------------------------------------------------------------------------------------------- // // WRD_8 / DWRD opCode // public class OC_WRD_8 extends OC_BYTE_8 { @Override public BigInteger getAlign() { return BI_8; } } //---------------------------------------------------------------------------------------------- // // BYTE_16 opCode // public class OC_BYTE_16 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_16; } @Override public int getExponentLength() { return 15; } } //---------------------------------------------------------------------------------------------- // // WRD_16 / QWRD opCode // public class OC_WRD_16 extends OC_BYTE_16 { @Override public BigInteger getAlign() { return BI_16; } } //---------------------------------------------------------------------------------------------- // // BYTE_32 opCode // public class OC_BYTE_32 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_32; } @Override public int getExponentLength() { return 19; } } //---------------------------------------------------------------------------------------------- // // WRD_32 opCode // public class OC_WRD_32 extends OC_BYTE_32 { @Override public BigInteger getAlign() { return BI_32; } } //---------------------------------------------------------------------------------------------- // // BYTE_64 opCode // public class OC_BYTE_64 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_64; } } //---------------------------------------------------------------------------------------------- // // WRD_64 opCode // public class OC_WRD_64 extends OC_BYTE_64 { @Override public BigInteger getAlign() { return BI_64; } } //---------------------------------------------------------------------------------------------- // // BYTE_128 opCode // public class OC_BYTE_128 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_128; } } //---------------------------------------------------------------------------------------------- // // WRD_128 opCode // public class OC_WRD_128 extends OC_BYTE_128 { @Override public BigInteger getAlign() { return BI_128; } } //---------------------------------------------------------------------------------------------- // // BYTE_256 opCode // public class OC_BYTE_256 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_256; } } //---------------------------------------------------------------------------------------------- // // WRD_256 opCode // public class OC_WRD_256 extends OC_BYTE_256 { @Override public BigInteger getAlign() { return BI_256; } } //---------------------------------------------------------------------------------------------- // // BYTE_512 opCode // public class OC_BYTE_512 extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_512; } } //---------------------------------------------------------------------------------------------- // // WRD_512 opCode // public class OC_WRD_512 extends OC_BYTE_512 { @Override public BigInteger getAlign() { return BI_512; } } //---------------------------------------------------------------------------------------------- // // BYTE_1K opCode // public class OC_BYTE_1K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_1K; } } //---------------------------------------------------------------------------------------------- // // WRD_1K opCode // public class OC_WRD_1K extends OC_BYTE_1K { @Override public BigInteger getAlign() { return BI_1K; } } //---------------------------------------------------------------------------------------------- // // BYTE_2K opCode // public class OC_BYTE_2K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_2K; } } //---------------------------------------------------------------------------------------------- // // WRD_2K opCode // public class OC_WRD_2K extends OC_BYTE_2K { @Override public BigInteger getAlign() { return BI_2K; } } //---------------------------------------------------------------------------------------------- // // BYTE_4K opCode // public class OC_BYTE_4K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_4K; } } //---------------------------------------------------------------------------------------------- // // WRD_4K opCode // public class OC_WRD_4K extends OC_BYTE_4K { @Override public BigInteger getAlign() { return BI_4K; } } //---------------------------------------------------------------------------------------------- // // BYTE_8K opCode // public class OC_BYTE_8K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_8K; } } //---------------------------------------------------------------------------------------------- // // WRD_8K opCode // public class OC_WRD_8K extends OC_BYTE_8K { @Override public BigInteger getAlign() { return BI_8K; } } //---------------------------------------------------------------------------------------------- // // BYTE_16K opCode // public class OC_BYTE_16K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_16K; } } //---------------------------------------------------------------------------------------------- // // WRD_16K opCode // public class OC_WRD_16K extends OC_BYTE_16K { @Override public BigInteger getAlign() { return BI_16K; } } //---------------------------------------------------------------------------------------------- // // BYTE_32K opCode // public class OC_BYTE_32K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_32K; } } //---------------------------------------------------------------------------------------------- // // WRD_32K opCode // public class OC_WRD_32K extends OC_BYTE_32K { @Override public BigInteger getAlign() { return BI_32K; } } //---------------------------------------------------------------------------------------------- // // BYTE_64K opCode // public class OC_BYTE_64K extends OC_BYTE_1 { @Override public BigInteger getLength() { return BI_64K; } } //---------------------------------------------------------------------------------------------- // // WRD_64K opCode // public class OC_WRD_64K extends OC_BYTE_64K { @Override public BigInteger getAlign() { return BI_64K; } } //---------------------------------------------------------------------------------------------- // // UTF_8 opCode // public class OC_UTF_8 extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); // // Check endianness // if (owner.endianness == DVUtil.Endianness.UNDEFINED) return owner.putErrorNoCode("Default ENDIANNESS not defined"); DVExpression.ExprToken value= parm.getPositionalParameterValue(0); if (value.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("Positional parameter 1 resolve to type [%s] - Type STRING is required", value.operType.name()); int un= value.stringConstant.codePointCount(0, value.stringConstant.length()); boolean bom= DVUtil.getBooleanKeyWordValue(owner, 0, "BOM", 0l) == 1; ArrayList codeList= new ArrayList(256); int maxCpLen= 1; for (int i= 0; i < un; i++) { int cp= value.stringConstant.codePointAt(i); if (cp <= 0x7F) codeList.add(cp); else if (cp < 0x07FF) { codeList.add((cp & 0x37) + 0x80); codeList.add((cp >> 6) + 0xC0); maxCpLen= Math.max(maxCpLen, 2); } else if(cp <= 0xFFFF) { codeList.add((cp & 0x3F) + 0x80); codeList.add(((cp >> 6) & 0x3F) + 0x80); codeList.add((cp >> 12) + 0xE0); maxCpLen= Math.max(maxCpLen, 3); } else { i++; codeList.add((cp & 0x3F) + 0x80); codeList.add(((cp >> 6) & 0x3F) + 0x80); codeList.add(((cp >> 12) & 0x3F) + 0x80); codeList.add((cp >> 18) + 0xF0); maxCpLen= Math.max(maxCpLen, 4); } } int bomSize= (bom ? 3 : 0); byte[] code= new byte[bomSize+codeList.size()]; if (bom) { code[0]= (byte) 0xEF; code[1]= (byte) 0xBB; code[2]= (byte) 0xBF; } for (int i= 0; i < code.length-bomSize; i++) code[bomSize+i]= codeList.get(i).byteValue(); String hexDet= DVUtil.convertCodeToHexPlain(code, code.length*2); for (int i= 0; i < hexDet.length()-8; i+= 9) hexDet= hexDet.substring(0, i+8) + " " + hexDet.substring(i+8); String details= String.format("Unicode UTF-8 STRING, length [%d]\n" + "String -> %s\n" + (bom ? "Byte Order Mark (BOM) is required\n" : "Byte Order Mark (BOM) is not required\n") + "Code -> " + hexDet + "\n" + "Maximum Unicode Code Point length used for encoding is [%d] -> " + (maxCpLen == 1 ? "All characters are ASCII\n" : "Some characters are non-ASCII\n"), code.length, "\"" + DVUtil.escapeString(value.stringConstant) + "\"", maxCpLen); return new DVCode(code, formatCode(code), details); } @Override public BigInteger getLength() { return BigInteger.ONE; } @Override public BigInteger getRepl() { return BigInteger.ONE; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 0 } }; } @Override public String[] getKeyWordList() { return new String[] { "BOM" }; } } //---------------------------------------------------------------------------------------------- // // UTF_16 opCode // public class OC_UTF_16 extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); // // Check endianness // if (owner.endianness == DVUtil.Endianness.UNDEFINED) return owner.putErrorNoCode("Default ENDIANNESS not defined"); DVExpression.ExprToken value= parm.getPositionalParameterValue(0); if (value.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("Positional parameter 1 resolve to type [%s] - Type STRING is required", value.operType.name()); int un= value.stringConstant.codePointCount(0, value.stringConstant.length()); boolean bom= DVUtil.getBooleanKeyWordValue(owner, 0, "BOM", 0l) == 1; int codeOffset= (bom ? 2 : 0); byte[] codeBE= new byte[codeOffset+value.stringConstant.length()*2]; byte[] codeLE= new byte[codeOffset+value.stringConstant.length()*2]; if (bom) { codeBE[0]= (byte) 0xFE; codeBE[1]= (byte) 0xFF; codeLE[0]= (byte) 0xFF; codeLE[1]= (byte) 0xFE; } for (int i= 0; i < value.stringConstant.length(); i++) { if (owner.endianness == DVUtil.Endianness.LITTLE) DVUtil.addHalfIntegerToCode(codeLE, codeOffset, value.stringConstant.charAt(i), DVUtil.Endianness.LITTLE); codeOffset= DVUtil.addHalfIntegerToCode(codeBE, codeOffset, value.stringConstant.charAt(i), DVUtil.Endianness.BIG); } String details= String.format("Unicode UTF-16 SRTING, length [%d]\n" + "String -> \"" + DVUtil.escapeString(value.stringConstant) + "\"\n", codeBE.length >> 1); details+= (bom ? "Byte Order Mark (BOM) is required\n" : "Byter Order Mark (BOM) is not required\n"); if (owner.endianness == DVUtil.Endianness.LITTLE) { String hexDet= DVUtil.convertCodeToHexPlain(codeLE, codeLE.length*2); for (int i= 0; i < hexDet.length()-8; i+= 9) hexDet= hexDet.substring(0, i+8) + " " + hexDet.substring(i+8); details+= "Code [LITTLE ENDIAN] -> " + hexDet + "\n"; } String hexDet= DVUtil.convertCodeToHexPlain(codeBE, codeBE.length*2); for (int i= 0; i < hexDet.length()-8; i+= 9) hexDet= hexDet.substring(0, i+8) + " " + hexDet.substring(i+8); details+= "Code [BIG ENDIAN] -> " + hexDet + "\n"; return new DVCode(codeBE, formatCode(codeBE), details); } @Override public BigInteger getAlign() { return BI_2; } @Override public BigInteger getLength() { return BI_2; } @Override public BigInteger getRepl() { return BigInteger.ONE; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 0 } }; } @Override public String[] getKeyWordList() { return new String[] { "BOM" }; } } //---------------------------------------------------------------------------------------------- // // UTF_32 opCode // public class OC_UTF_32 extends DVOpCodeProcessor { @Override public DVCode generateCode(DVStatements.Statement owner) { DVOpCodeParm parm= owner.getOpCodeParm(); // // Check endianness // if (owner.endianness == DVUtil.Endianness.UNDEFINED) return owner.putErrorNoCode("Default ENDIANNESS not defined"); DVExpression.ExprToken value= parm.getPositionalParameterValue(0); if (value.type != DVExpression.TokenType.STRING) return owner.putErrorNoCode("Positional parameter 1 resolve to type [%s] - Type STRING is required", value.operType.name()); int un= value.stringConstant.codePointCount(0, value.stringConstant.length()); boolean bom= DVUtil.getBooleanKeyWordValue(owner, 0, "BOM", 0l) == 1; ArrayList codeList= new ArrayList(256); if (bom) codeList.add(0xFEFF); for (int i= 0; i < un; i++) { int cp= value.stringConstant.codePointAt(i); if (cp > 0xFFFF) i++; codeList.add(cp); } int codeOffset= 0; byte[] codeBE= new byte[codeList.size()*4]; byte[] codeLE= new byte[codeList.size()*4]; for (int i= 0; i < codeBE.length >> 2; i++) { if (owner.endianness == DVUtil.Endianness.LITTLE) DVUtil.addIntegerToCode(codeLE, codeOffset, codeList.get(i), DVUtil.Endianness.LITTLE); codeOffset= DVUtil.addIntegerToCode(codeBE, codeOffset, codeList.get(i), DVUtil.Endianness.BIG); } String details= String.format("Unicode UTF-32 SRTING, length [%d]\n" + "String -> \"" + DVUtil.escapeString(value.stringConstant) + "\"\n", codeBE.length >> 2); details+= (bom ? "Byte Order Mark (BOM) is required\n" : "Byter Order Mark (BOM) is not required\n"); if (owner.endianness == DVUtil.Endianness.LITTLE) { String hexDet= DVUtil.convertCodeToHexPlain(codeLE, codeLE.length*2); for (int i= 0; i < hexDet.length()-8; i+= 9) hexDet= hexDet.substring(0, i+8) + " " + hexDet.substring(i+8); details+= "Code [LITTLE ENDIAN] -> " + hexDet + "\n"; } String hexDet= DVUtil.convertCodeToHexPlain(codeBE, codeBE.length*2); for (int i= 0; i < hexDet.length()-8; i+= 9) hexDet= hexDet.substring(0, i+8) + " " + hexDet.substring(i+8); details+= "Code [BIG ENDIAN] -> " + hexDet + "\n"; return new DVCode(codeBE, formatCode(codeBE), details); } @Override public BigInteger getAlign() { return BI_4; } @Override public BigInteger getLength() { return BI_4; } @Override public BigInteger getRepl() { return BigInteger.ONE; } @Override public int[] getPosParmMinMax() { return new int[] { 1, 1 }; } @Override public boolean[] getPosParmDefault() { return new boolean[] { false }; } @Override public int[][] getSubParmMinMax() { return new int[][] { { 0, 0 } }; } @Override public String[] getKeyWordList() { return new String[] { "BOM" }; } } // // Convert binary code to hex for listing format // private String formatCode(byte[] code) { String hexCode= DVUtil.convertCodeToHexPlain(code, Math.min(code.length, DVFrameworkOpCodes.this.hexCodeHeader.length())); for (int i= 0; i < hexCode.length()-8; i+= 9) hexCode= hexCode.substring(0, i+8) + " " + hexCode.substring(i+8);for (int i= 0; i < hexCode.length()-8; i+= 9) hexCode= hexCode.substring(0, i+8) + " " + hexCode.substring(i+8); if (hexCode.length() > DVFrameworkOpCodes.this.hexCodeHeader.length()) return hexCode.substring(0, DVFrameworkOpCodes.this.hexCodeHeader.length()); for (int i= hexCode.length(); i < DVFrameworkOpCodes.this.hexCodeHeader.length(); i++) hexCode+= " "; return hexCode; } //---------------------------------------------------------------------------------------------- // // Class fields // private String hexCodeHeader= "--- Architecture/Abi no found ---"; private final HashMap processOpCode= new HashMap(32); private final BigDecimal BD_2= new BigDecimal(2); private final static MathContext precision= new MathContext(18); }