@@ -343,6 +343,14 @@ int32_t TR_DataAccessAccelerator::performOnBlock(TR::Block* block, TreeTopContai
343343 ++result;
344344 }
345345 break ;
346+ // DAA External Decimal Check
347+ case TR::com_ibm_dataaccess_ExternalDecimal_checkExternalDecimal_:
348+ if (comp ()->target ().cpu .supportsFeature (OMR_FEATURE_S390_VECTOR_PACKED_DECIMAL_ENHANCEMENT_FACILITY_3)
349+ && inlineCheckExternalDecimal (treeTop, callNode))
350+ {
351+ ++result;
352+ }
353+ break ;
346354
347355 default :
348356 matched = false ;
@@ -846,6 +854,99 @@ bool TR_DataAccessAccelerator::inlineCheckPackedDecimal(TR::TreeTop *callTreeTop
846854 return false ;
847855 }
848856
857+ bool TR_DataAccessAccelerator::inlineCheckExternalDecimal (TR::TreeTop *callTreeTop, TR::Node *callNode)
858+ {
859+ TR::Node *byteArrayNode = callNode->getChild (0 );
860+ TR::Node *offsetNode = callNode->getChild (1 );
861+ TR::Node *precisionNode = callNode->getChild (2 );
862+ TR::Node *typeNode = callNode->getChild (3 );
863+ TR::Node *bytesWithSpacesNode = callNode->getChild (4 );
864+
865+ int32_t precision = precisionNode->getInt ();
866+ int32_t bytesWithSpaces = bytesWithSpacesNode->getInt ();
867+ int32_t type = typeNode->getInt ();
868+ const char *failMsg = NULL ;
869+
870+ /* Hardware expects both, precision and bytesWithSpaces to be
871+ * 5 bit unsigned binary integer. However, 0 is valid only for
872+ * bytesWithSpaces. This is why precision must be within [1-31]
873+ * range and bytesWithSpaces must be within [0-31] range.
874+ */
875+ // TODO: Add support for non-constant arguments
876+ if (!isChildConst (callNode, 2 ))
877+ failMsg = " Precision is not constant" ;
878+ else if (precision < 1 || precision > 31 )
879+ failMsg = " Precision value is not in valid range [1-31]" ;
880+ else if (!isChildConst (callNode, 3 ))
881+ failMsg = " Decimal type node is not constant" ;
882+ else if (type < 1 || type > 4 )
883+ failMsg = " Invalid decimal type. Supported types are (1|2|3|4)" ;
884+ else if (!isChildConst (callNode, 4 ))
885+ failMsg = " bytesWithSpaces node is not constant" ;
886+ else if (bytesWithSpaces < 0 || bytesWithSpaces > 31 )
887+ failMsg = " bytesWithSpaces value not in valid range [0-31]" ;
888+
889+ if (failMsg)
890+ {
891+ TR::DebugCounter::incStaticDebugCounter (comp (),
892+ TR::DebugCounter::debugCounterName (comp (),
893+ " DAA/rejected/chkZonedDecimal" ));
894+
895+ return printInliningStatus (false , callNode, failMsg);
896+ }
897+
898+ if (performTransformation (comp (), " O^O TR_DataAccessAccelerator: inlineCheckZonedDecimal on callNode %p\n " , callNode))
899+ {
900+ TR::DebugCounter::incStaticDebugCounter (comp (),
901+ TR::DebugCounter::debugCounterName (comp (),
902+ " DAA/inlined/chkZonedDecimal" ));
903+
904+ insertByteArrayNULLCHK (callTreeTop, callNode, byteArrayNode);
905+
906+ TR::DataType decimalType = TR::DataTypes::NoType;
907+ TR::ILOpCodes loadOpCode = TR::BadILOp;
908+ if (type == 1 )
909+ {
910+ decimalType = TR::ZonedDecimal;
911+ loadOpCode = TR::zdloadi;
912+ }
913+ else if (type == 2 )
914+ {
915+ decimalType = TR::ZonedDecimalSignLeadingEmbedded;
916+ loadOpCode = TR::zdsleLoadi;
917+ }
918+ else if (type == 3 )
919+ {
920+ decimalType = TR::ZonedDecimalSignTrailingSeparate;
921+ loadOpCode = TR::zdstsLoadi;
922+ }
923+ else if (type == 4 )
924+ {
925+ decimalType = TR::ZonedDecimalSignLeadingSeparate;
926+ loadOpCode = TR::zdslsLoadi;
927+ }
928+ int32_t precisionSizeInNumberOfBytes = TR::DataType::getSizeFromBCDPrecision (decimalType, precision);
929+
930+ insertByteArrayBNDCHK (callTreeTop, callNode, byteArrayNode, offsetNode, 0 );
931+ insertByteArrayBNDCHK (callTreeTop, callNode, byteArrayNode, offsetNode, precisionSizeInNumberOfBytes - 1 );
932+
933+ TR::SymbolReference* zonedDecimalSymbolReference = comp ()->getSymRefTab ()->findOrCreateArrayShadowSymbolRef (decimalType, NULL , precisionSizeInNumberOfBytes, fe ());
934+ TR::Node* zdchkChild0Node = TR::Node::createWithSymRef (loadOpCode, 1 , 1 , constructAddressNode (callNode, byteArrayNode, offsetNode), zonedDecimalSymbolReference);
935+ zdchkChild0Node->setDecimalPrecision (precision);
936+
937+ byteArrayNode->decReferenceCount ();
938+ offsetNode->decReferenceCount ();
939+ precisionNode->decReferenceCount ();
940+ typeNode->decReferenceCount ();
941+
942+ TR::Node* bytesWithSpacesConstNode = TR::Node::bconst (static_cast <uint8_t >(bytesWithSpaces));
943+ TR::Node::recreateWithoutProperties (callNode, TR::zdchk, 2 , zdchkChild0Node, bytesWithSpacesConstNode);
944+ return true ;
945+ }
946+
947+ return false ;
948+ }
949+
849950TR::Node* TR_DataAccessAccelerator::insertIntegerGetIntrinsic (TR::TreeTop* callTreeTop, TR::Node* callNode, int32_t sourceNumBytes, int32_t targetNumBytes)
850951 {
851952 if (targetNumBytes != 1 && targetNumBytes != 2 && targetNumBytes != 4 && targetNumBytes != 8 )
0 commit comments