| /********************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| **********************************************************************/ |
| /* -*-C++-*- |
| **************************************************************************** |
| * |
| * File: ExpPCode.cpp |
| * Description: |
| * |
| * Created: 8/25/97 |
| * Language: C++ |
| * |
| * |
| * |
| **************************************************************************** |
| */ |
| |
| #include "Platform.h" |
| |
| |
| #include "exp_stdh.h" |
| #include "str.h" |
| #include "exp_datetime.h" |
| #include "exp_expr.h" |
| #include "exp_function.h" |
| #include "ExpPCode.h" |
| #include "exp_tuple_desc.h" |
| |
| // Uncomment the line below to debug new PCode instructions. |
| // #define SQLMX_DEBUG_PCIT |
| |
| PCodeSegment::PCodeSegment(PCodeBinary* pcode) : NAVersionedObject() { |
| str_cpy_all((char*)&eyeCatcher_, PC_eyeCatcher, PC_eyeCatcherSize); |
| flags_ = 0; |
| pCodeSegmentSize_ = 0; |
| setPCodeBinary(pcode); |
| } |
| |
| |
| unsigned char PCodeSegment::getClassVersionID() { |
| return 1; |
| } |
| |
| |
| Long PCodeSegment::pack(void *space) { |
| convAddrToOffsetInPCode(space); |
| pCodeSegment_.pack(space); |
| return NAVersionedObject::pack(space); |
| } |
| |
| Lng32 PCodeSegment::unpack(void *base, void * reallocator) { |
| if (pCodeSegment_.unpack(base)) return -1; |
| convOffsetToAddrInPCode(base); |
| return NAVersionedObject::unpack(base, reallocator); |
| } |
| |
| Int32 PCodeSegment::getPCodeSegmentSize() { |
| return pCodeSegmentSize_; |
| } |
| |
| void PCodeSegment::setPCodeSegmentSize(Int32 size) { |
| pCodeSegmentSize_ = size; |
| } |
| |
| |
| short PCodeSegment::getClassSize() { |
| Int32 trueSize = sizeof(*this) + getPCodeSegmentSize(); |
| return( (short)(trueSize + (trueSize % 8)) ); |
| } |
| |
| // PCodeSegment::replaceAttributesPtr |
| // |
| // Find all attributes pointers in the pcode segment which aren't referenced in |
| // the passed in list of clauses. Copy these attributes pointers into the |
| // passed in space object and replace the old attributes pointer in the pcode |
| // segment with the new pointer |
| // |
| void PCodeSegment::replaceAttributesPtr(ex_clause* clauses, Space* space) |
| { |
| Int32 addrBuf[6]; |
| |
| PCodeBinary *pcode = getPCodeBinary(); |
| if (!pcode) |
| return; |
| |
| Int32 length = *(pcode++); |
| pcode += (2 * length); |
| |
| // Loop through all the PCODE instructions |
| while (pcode[0] != PCIT::END) { |
| |
| // Determine if we're dealing with a PCODE instruction with an embedded addr |
| Int32* addrs= PCode::getEmbeddedAddresses(pcode[0], addrBuf); |
| |
| // Only do more work if an embedded address was found *and* it's not a |
| // clause pointer (since that's handled elsewhere). |
| if ((addrs[0] != -1) && |
| (pcode[0] != PCIT::CLAUSE_BRANCH) && |
| (pcode[0] != PCIT::CLAUSE_EVAL)) |
| { |
| // Go through each attribute position in pcode |
| while (*addrs != -1) { |
| // Assume attributes pointer is not referenced in clauses |
| NABoolean found = FALSE; |
| |
| Attributes* attr = (Attributes*)GetPCodeBinaryAsPtr(pcode, *addrs); |
| |
| // It's possible that the attributes pointer is NULL. In this case |
| // there's nothing to look for and copy over. |
| if (attr == NULL){ |
| addrs++; |
| continue; |
| } |
| |
| // Search the operands of all clauses to find any matching pairs. |
| for (ex_clause* clause = clauses; |
| clause; |
| clause = clause->getNextClause()) |
| { |
| Int32 numOperands = clause->getNumOperands(); |
| for (Int32 i=0; i < numOperands; i++) { |
| Attributes* attrOld = clause->getOperand(i); |
| |
| // If the attribute in the pcode segment matches an attributes |
| // pointer in the clause, then it was copied over correctly and |
| // we don't need to do anything special. |
| if (attrOld == attr) { |
| found = TRUE; |
| break; |
| } |
| } |
| |
| // No need to look further - we found it |
| if (found) |
| break; |
| } |
| |
| // If the attributes pointer in the pcode segment was not found in the |
| // operands list for all the clauses, that means the attributes pointer |
| // needs to be copied and reset in the pcode segment |
| if (!found) { |
| Int32 size = attr->getClassSize(); |
| |
| Attributes* attrNew = (Attributes*) new(space) char[size]; |
| memcpy((char*)attrNew, (char*)attr, size); |
| |
| // Update pcode segment with new attributes pointer |
| setPtrAsPCodeBinary(pcode, *addrs, (Long)attrNew); |
| // pcode[*addrs] = (PCodeBinary)attrNew; |
| } |
| |
| // Advance to the next attribute postion. |
| addrs++; |
| } |
| } |
| pcode += PCode::getInstructionLength(pcode); |
| } |
| } |
| |
| // Locate the clause pointer "oldClause" in the pcode segment and replace it |
| // with the clause "newClause". |
| void PCodeSegment::replaceClauseEvalPtr(ex_clause* oldClause, |
| ex_clause* newClause) |
| { |
| PCodeBinary *pcode = getPCodeBinary(); |
| if (!pcode) |
| return; |
| |
| Int32 length = *(pcode++); |
| pcode += (2 * length); |
| |
| while (pcode[0] != PCIT::END) { |
| if (pcode[0] == PCIT::CLAUSE_BRANCH) { |
| if ((ex_clause*)*(Long*)&pcode[1 + PCODEBINARIES_PER_PTR] == oldClause) { |
| setPtrAsPCodeBinary(pcode, 1 + PCODEBINARIES_PER_PTR, (Long) newClause); |
| // pcode[2] = (PCodeBinary)newClause; |
| } |
| } |
| else if (pcode[0] == PCIT::CLAUSE_EVAL) { |
| if ((ex_clause*)*(Long*)&pcode[1] == oldClause) { |
| setPtrAsPCodeBinary(pcode, 1, (Long) newClause); |
| // pcode[1] = (PCodeBinary)newClause; |
| } |
| } |
| pcode += PCode::getInstructionLength(pcode); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // The following 2 methods change all the addresses embedded in the pcode |
| // byte code to offsets (and vice versa) for packing/unpacking |
| // |
| // convAddrToOffsetInPCode uses the pcode eval driver in ex_expr::eval |
| // as a model. This method traverses through the whole entire byte code |
| // segment and finds all addresses for the ex_clause object and translates |
| // the address to offset. |
| // |
| // convOffsetToAddrInPCode translates the offsets to addresses |
| // ----------------------------------------------------------------------- |
| void PCodeSegment::convAddrToOffsetInPCode(void * space) { |
| PCodeBinary *pcode = getPCodeBinary(); |
| if (!pcode) |
| return; |
| |
| Int32 length = *(pcode++); |
| pcode += (2 * length); |
| |
| while (pcode[0] != PCIT::END) { |
| Int32 addrBuf[6]; |
| Int32 *addrs = PCode::getEmbeddedAddresses(pcode[0], addrBuf); |
| for(Int32 i = 0; addrs[i] > 0; i++) { |
| if ( (char*)((long)pcode[addrs[i]]) != NULL ) |
| *(Long*)&(pcode[addrs[i]]) = |
| ((Space*)space)->convertToOffset((char*)*(Long*)&(pcode[addrs[i]])); |
| } |
| pcode += PCode::getInstructionLength(pcode); |
| } |
| } |
| |
| void PCodeSegment::convOffsetToAddrInPCode(void* base) { |
| PCodeBinary *pcode = getPCodeBinary(); |
| if (!pcode) |
| return; |
| |
| // skip over the ATP's |
| Int32 length = *(pcode++); |
| pcode += (2 * length); |
| |
| while (pcode[0] != PCIT::END) { |
| Int32 addrBuf[6]; |
| Int32 *addrs = PCode::getEmbeddedAddresses(pcode[0], addrBuf); |
| for(Int32 i = 0; addrs[i] > 0; i++) { |
| // Zero offset is a null pointer ... |
| if ( pcode[addrs[i]] != 0 ) |
| setPtrAsPCodeBinary(pcode, addrs[i], |
| (Long)(base) - GetPCodeBinaryAsPtr(pcode, addrs[i])); |
| } |
| pcode += PCode::getInstructionLength(pcode); |
| } |
| } |
| |
| // Determine if the PCODE operation is a branch or target |
| // |
| Int32 PCode::IsBranchInstruction(PCI *pci) |
| { |
| switch(pci->getOperation()) |
| { |
| case PCIT::Op_BRANCH: |
| case PCIT::Op_CLAUSE_BRANCH: |
| case PCIT::Op_NOT_NULL_BRANCH: |
| case PCIT::Op_NOT_NULL_BRANCH_COMP: |
| case PCIT::Op_NOT_NULL_BITMAP_BRANCH: |
| case PCIT::Op_BRANCH_AND: |
| case PCIT::Op_BRANCH_OR: |
| return 1; |
| } |
| return 0; |
| } |
| |
| // Determine if the PCODE operation is a target. |
| // |
| Int32 PCode::IsTargetInstruction(PCI *pci) |
| { |
| switch(pci->getOperation()) |
| { |
| case PCIT::Op_TARGET: |
| return 1; |
| } |
| return 0; |
| } |
| |
| // Determine if the PCODE operation is a CLAUSE_EVAL. |
| // |
| Int32 PCode::IsClauseEvalInstruction(PCI *pci) |
| { |
| switch(pci->getOperation()) |
| { |
| case PCIT::Op_CLAUSE_EVAL: |
| case PCIT::Op_CLAUSE_BRANCH: |
| return 1; |
| } |
| return 0; |
| } |
| |
| Int32 PCode::IsBranchOrTarget(PCI *pci) |
| { |
| switch(pci->getOperation()) |
| { |
| case PCIT::Op_BRANCH: |
| case PCIT::Op_CLAUSE_BRANCH: |
| case PCIT::Op_BRANCH_AND: |
| case PCIT::Op_BRANCH_OR: |
| case PCIT::Op_NOT_NULL_BRANCH: |
| case PCIT::Op_NOT_NULL_BRANCH_COMP: |
| case PCIT::Op_NOT_NULL_BITMAP_BRANCH: |
| case PCIT::Op_TARGET: |
| return 1; |
| } |
| return 0; |
| } |
| |
| //Determine if PCODE operation is a MOVE to a temporary location |
| //assumes Atp = 0 and Atp Index = 1 is the temporary space. |
| |
| Int32 PCode::IsTemporaryStore(PCI *pci) |
| { |
| if(((pci->getOperand(0) == 0) && |
| (pci->getOperand(1) == 1) && |
| (pci->getOperation() == PCIT::Op_MOVE) && |
| PCode::getInstruction(pci) == PCIT::MOVE_MBIN8_MBIN8_IBIN32S)) |
| return 1; |
| |
| return 0; |
| } |
| |
| Int32 PCode::IsTemporaryLoad(PCI *pci) |
| { |
| if((pci->getOperand(3) == 0) && |
| (pci->getOperand(4) == 1) && |
| (pci->getOperation() == PCIT::Op_MOVE) && |
| (PCode::getInstruction(pci) == PCIT::MOVE_MBIN8_MBIN8_IBIN32S)) |
| return 1; |
| |
| return 0; |
| } |
| |
| // Determine if the PCODE operation results in a access to/from temporary space |
| // |
| Int32 PCode::IsTemporaryAccess(PCI *pci) |
| { |
| PCIT::AddressingMode am; |
| for(Int32 i=0,op=0; |
| i<pci->getNumberAddressingModes(); |
| i++,op+=PCIT::getNumberOperandsForAddressingMode(am)) |
| { |
| am = pci->getAddressingMode(i); |
| if(!PCIT::isMemoryAddressingMode(am)) |
| continue; |
| if((pci->getOperand(op) == 0)&&(pci->getOperand(op+1) == 1)) |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| Int32 PCI::temporaryStoreLoadMatch(PCI *store, PCI *load) { |
| if(!PCode::IsTemporaryStore(store)) return 0; |
| if(!PCode::IsTemporaryLoad(load)) return 0; |
| |
| if((store->getOperand(6) == load->getOperand(6))&& |
| (store->getOperand(2) == load->getOperand(5))) |
| return 1; |
| |
| return 0; |
| } |
| |
| Int32 PCI::temporaryStoreLoadOverlap(PCI *store, PCI *load) { |
| |
| if(PCode::IsTemporaryAccess(load) == 0) |
| return 0; |
| Int32 storeStart, storeLength, storeEnd, loadStart, loadLength, loadEnd; |
| storeStart = store->getOperand(2); |
| storeLength = store->getOperand(6); |
| storeEnd = storeStart+storeLength; |
| PCIT::AddressingMode am; |
| for(Int32 i=0,op=0; |
| i<load->getNumberAddressingModes(); |
| i++,op+=PCIT::getNumberOperandsForAddressingMode(am)) |
| { |
| am = load->getAddressingMode(i); |
| if(!PCIT::isMemoryAddressingMode(am)) |
| continue; |
| if(!((load->getOperand(op) == 0)&&(load->getOperand(op+1) == 1))) |
| continue; |
| loadStart = load->getOperand(op+2); |
| loadLength = load->getMemoryOperandLength(am, op); |
| loadEnd = loadStart+loadLength; |
| if(((loadStart >= storeStart) && (loadStart < storeEnd)) || |
| ((loadEnd > storeStart) && (loadEnd <= storeEnd)) || |
| ((loadStart < storeStart) && (storeEnd < loadEnd))) |
| return 1; |
| } |
| return 0; |
| } |
| |
| Int32 PCI::replaceUsesOfTarget(PCI *store, PCI *use, Int32 check) { |
| |
| // Get store PCI target info |
| Int32 storTgtAtp = store->getOperand(0); |
| Int32 storTgtAtpIndex = store->getOperand(1); |
| Int32 storTgtStart = store->getOperand(2); |
| Int32 storTgtLength = store->getOperand(6); |
| Int32 storTgtEnd = storTgtStart+storTgtLength; |
| |
| // Get store PCI source info |
| Int32 storSrcAtp = store->getOperand(3); |
| Int32 storSrcAtpIndex = store->getOperand(4); |
| Int32 storSrcStart = store->getOperand(5); |
| |
| PCIT::AddressingMode am; |
| |
| Int32 retVal = 0; // Assume everything OK. |
| |
| for(Int32 i=0,op=0; i < use->getNumberAddressingModes(); i++) |
| { |
| am = use->getAddressingMode(i); |
| if(PCIT::isMemoryAddressingMode(am)) { |
| Int32 useAtp = use->getOperand(op); |
| Int32 useAtpIndex = use->getOperand(op+1); |
| Int32 useStart = use->getOperand(op+2); |
| Int32 useLength = use->getMemoryOperandLength(am, op); |
| Int32 useEnd = useStart+useLength; |
| |
| if(storTgtAtp == useAtp && |
| storTgtAtpIndex == useAtpIndex) { |
| |
| |
| if(useLength == 0 && |
| use->getOperation() == PCIT::Op_OPDATA && |
| storTgtStart >= useStart) |
| { |
| // OPDATA instruction do not record the length of the |
| // data they point to. Assume that it is the same |
| // length as the source. |
| // |
| useEnd = storTgtEnd; |
| } |
| |
| |
| if(storTgtStart >= useEnd || |
| storTgtEnd <= useStart) { |
| // No overlap, do not replace but continue to check |
| // next operand of the use PCI |
| |
| } else if (storTgtStart <= useStart && |
| storTgtEnd >= useEnd && |
| (i != 0 || |
| use->getOperation() == PCIT::Op_RANGE_LOW || |
| use->getOperation() == PCIT::Op_RANGE_HIGH) && |
| use->getOperation() != PCIT::Op_OPDATA) { |
| |
| // use is completely within store PCI target place, |
| // And this is not the first operand (result). |
| // replace with store source |
| // |
| if(!check) { |
| use->setOperand(op, storSrcAtp); |
| use->setOperand(op+1, storSrcAtpIndex ); |
| use->setOperand(op+2, storSrcStart + (useStart - storTgtStart)); |
| } |
| // else, just check, will return later as replaciable (retVal == 0) |
| |
| // continue to check the next operand of the use PCI. |
| } else { |
| // The use is within the target location of store PCI but we |
| // can not eliminate this store PCI because: |
| // 1). the use PCI is Op_OPDATA for CLAUSE_EVAL, or |
| // 2). it is the storage place of the use PCI, such as |
| // temp = temp + ... and the store PCI is to initialize temp |
| |
| // Now, there are 3 cases that we either quit, or continue: |
| // A). if we do checking and are looking at the target of use |
| // PCI, i.e. i is 0 or case 2, then return 1, as we can |
| // not eliminate the store PCI anyway; |
| // B). if we do checking and are looking at a source operand |
| // of use PCI, then continue to check other operands; |
| // C). if we do replacement, then we can not eliminate the |
| // store PCI because we can not replace this operand of the |
| // use PCI. So set retVal to 1, but continue as we may be |
| // able to replace other operands of the use PCI. |
| if(check && i == 0) { |
| return 1; // don't even try to replace later |
| } else if (!check) { |
| retVal = 1; |
| } |
| } |
| |
| } |
| // else ATP and ATP index do not match, do not replace. |
| // |
| |
| } |
| |
| op += PCIT::getNumberOperandsForAddressingMode(am); |
| } |
| |
| return retVal; |
| } |
| |
| |
| PCode::PCode(CollHeap *heap, Space* space) |
| : pciList_(heap), heap_(heap), space_(space), profileCounts_(0), |
| profileTimes_(0) { |
| }; |
| |
| PCode::~PCode() { |
| profilePrint(); |
| }; |
| |
| Int32 PCode::size() { |
| PCIListIter iter(pciList_); |
| Int32 size = 0; |
| |
| for(PCI *pci = iter.first(); pci; pci = iter.next()) |
| size += pci->getGeneratedCodeSize(); |
| |
| return size; |
| } |
| |
| #define AM_LENGTH(a) (( a == PCIT::MATTR6) ? 6 : \ |
| ( a == PCIT::MUNIV \ |
| || a == PCIT::MATTR5) ? 5 : \ |
| ( a == PCIT::MATTR4 \ |
| || a == PCIT::IATTR4) ? 4 : \ |
| ( a == PCIT::IATTR3 \ |
| || a == PCIT::MATTR3) ? 3 : \ |
| ( a == PCIT::IATTR2 \ |
| || a == PCIT::MBIN8 \ |
| || a == PCIT::MBIN8S \ |
| || a == PCIT::MBIN8U \ |
| || a == PCIT::MBIN16U \ |
| || a == PCIT::MBIN16S \ |
| || a == PCIT::MBIN32U \ |
| || a == PCIT::MBIN32S \ |
| || a == PCIT::MBIN64U \ |
| || a == PCIT::MBIN64S \ |
| || a == PCIT::MPTR32 \ |
| || a == PCIT::MASCII \ |
| || a == PCIT::MUNI \ |
| || a == PCIT::MBIGS \ |
| || a == PCIT::MBIGU \ |
| || a == PCIT::MDECS \ |
| || a == PCIT::MDECU \ |
| || a == PCIT::IBIN64S \ |
| || a == PCIT::MFLT32 \ |
| || a == PCIT::MFLT64) ? 2 : \ |
| ( a == PCIT::IBIN8U \ |
| || a == PCIT::IBIN16U \ |
| || a == PCIT::IBIN32S) ? 1 : \ |
| ( a == PCIT::IPTR) ? PCODEBINARIES_PER_PTR : \ |
| 0) |
| |
| // Local MACROs for constructing the instruction map |
| // |
| #define I6(inst,am1,am2,am3,am4,am5,am6,op) {(((Int64)PCIT::inst<<36)|((Int64)PCIT::am1<<30)|((Int64)PCIT::am2<<24)|((Int64)PCIT::am3<<18)|((Int64)PCIT::am4<<12)|((Int64)PCIT::am5<<6)|((Int64)PCIT::am6)),PCIT::op,"" # op "",AM_LENGTH(PCIT::am1)+AM_LENGTH(PCIT::am2)+AM_LENGTH(PCIT::am3)+AM_LENGTH(PCIT::am4)+AM_LENGTH(PCIT::am5)+AM_LENGTH(PCIT::am6)+1,6} |
| #define I5(inst,am1,am2,am3,am4,am5,op) {(((Int64)PCIT::inst<<36)|((Int64)PCIT::am1<<30)|((Int64)PCIT::am2<<24)|((Int64)PCIT::am3<<18)|((Int64)PCIT::am4<<12)|((Int64)PCIT::am5<<6)),PCIT::op,"" # op "",AM_LENGTH(PCIT::am1)+AM_LENGTH(PCIT::am2)+AM_LENGTH(PCIT::am3)+AM_LENGTH(PCIT::am4)+AM_LENGTH(PCIT::am5)+1,5} |
| #define I4(inst,am1,am2,am3,am4,op) {(((Int64)PCIT::inst<<36)|((Int64)PCIT::am1<<30)|((Int64)PCIT::am2<<24)|((Int64)PCIT::am3<<18)|((Int64)PCIT::am4<<12)),PCIT::op,"" # op "",AM_LENGTH(PCIT::am1)+AM_LENGTH(PCIT::am2)+AM_LENGTH(PCIT::am3)+AM_LENGTH(PCIT::am4)+1,4} |
| #define I3(inst,am1,am2,am3,op) {(((Int64)PCIT::inst<<36)|((Int64)PCIT::am1<<30)|((Int64)PCIT::am2<<24)|((Int64)PCIT::am3<<18)),PCIT::op,"" # op "",AM_LENGTH(PCIT::am1)+AM_LENGTH(PCIT::am2)+AM_LENGTH(PCIT::am3)+1,3} |
| #define I2(inst,am1,am2, op) {(((Int64)PCIT::inst<<36)|((Int64)PCIT::am1<<30)|((Int64)PCIT::am2<<24)),PCIT::op, "" # op "",AM_LENGTH(PCIT::am1)+AM_LENGTH(PCIT::am2)+1,2} |
| #define I1(inst,am1,op) {(((Int64)PCIT::inst<<36)|((Int64)PCIT::am1<<30)),PCIT::op,"" # op "",AM_LENGTH(PCIT::am1)+1,1} |
| #define I0(inst,op) {(((Int64)PCIT::inst<<36)),PCIT::op,"" # op "",1,0} |
| #define IopCodeNotInUse(op) {0,op,"opCodeNotInUse",1,0} |
| // create the instruction map array once per process |
| // the size of the (# of operations) * (# of addressing modes) |
| static const PCIMap opcodeMap[] = { |
| I2(Op_OPDATA,MPTR32,IBIN32S,OPDATA_MPTR32_IBIN32S), // Instruction 0 |
| I2(Op_OPDATA,MBIN16U,IBIN32S,OPDATA_MBIN16U_IBIN32S), // Instruction 1 |
| |
| I1(Op_MOVE,MBIN32S,MOVE_MBIN32S), // Instruction 2 |
| I2(Op_MOVE,MBIN32S,IBIN32S,MOVE_MBIN32S_IBIN32S), // Instruction 3 |
| I3(Op_MOVE,MBIN8,MBIN8,IBIN32S,MOVE_MBIN8_MBIN8_IBIN32S), // Instruction 4 |
| I2(Op_MOVE,MBIN32U,MBIN16U,MOVE_MBIN32U_MBIN16U), // Instruction 5 |
| I2(Op_MOVE,MBIN32S,MBIN16U,MOVE_MBIN32S_MBIN16U), // Instruction 6 |
| I2(Op_MOVE,MBIN64S,MBIN16U,MOVE_MBIN64S_MBIN16U), // Instruction 7 |
| I2(Op_MOVE,MBIN32U,MBIN16S,MOVE_MBIN32U_MBIN16S), // Instruction 8 |
| I2(Op_MOVE,MBIN32S,MBIN16S,MOVE_MBIN32S_MBIN16S), // Instruction 9 |
| I2(Op_MOVE,MBIN64S,MBIN16S,MOVE_MBIN64S_MBIN16S), // Instruction 10 |
| I2(Op_MOVE,MBIN64S,MBIN32U,MOVE_MBIN64S_MBIN32U), // Instruction 11 |
| I2(Op_MOVE,MBIN64S,MBIN32S,MOVE_MBIN64S_MBIN32S), // Instruction 12 |
| I3(Op_MOVE,MBIN64S,MDECS,IBIN32S,MOVE_MBIN64S_MDECS_IBIN32S), // Instruction 13 |
| I3(Op_MOVE,MBIN64S,MDECU,IBIN32S,MOVE_MBIN64S_MDECU_IBIN32S), // Instruction 14 |
| |
| IopCodeNotInUse(15), // Instruction 15 not in use |
| |
| I1(Op_NULL,MBIN16U,NULL_MBIN16U), // Instruction 16 |
| I2(Op_NULL,MBIN16U,IBIN16U,NULL_MBIN16U_IBIN16U), // Instruction 17 |
| I3(Op_NULL,MBIN32S,MBIN16U,IBIN32S,NULL_TEST_MBIN32S_MBIN16U_IBIN32S), // Instruction 18 |
| I3(Op_NOT_NULL_BRANCH,MBIN16S,MBIN16S,IBIN32S,NOT_NULL_BRANCH_MBIN16S_MBIN16S_IBIN32S), // Instruction 19 |
| I4(Op_NOT_NULL_BRANCH,MBIN16S,MBIN16S,MBIN16S,IBIN32S,NOT_NULL_BRANCH_MBIN16S_MBIN16S_MBIN16S_IBIN32S), // Instruction 20 |
| I1(Op_NULL_VIOLATION,MBIN16U,NULL_VIOLATION_MBIN16U), // Instruction 21 |
| I2(Op_NULL_VIOLATION,MBIN16U,MBIN16U,NULL_VIOLATION_MBIN16U_MBIN16U), // Instruction 22 |
| |
| IopCodeNotInUse(23), |
| IopCodeNotInUse(24), |
| IopCodeNotInUse(25), |
| IopCodeNotInUse(26), |
| IopCodeNotInUse(27), |
| IopCodeNotInUse(28), // Instruction 28 not in use |
| IopCodeNotInUse(29), // Instruction 29 not in use |
| IopCodeNotInUse(30), // Instruction 30 not in use |
| |
| I2(Op_ZERO,MBIN32S,MBIN32U,ZERO_MBIN32S_MBIN32U), // Instruction 31 |
| I2(Op_NOTZERO,MBIN32S,MBIN32U,NOTZERO_MBIN32S_MBIN32U), // Instruction 32 |
| |
| I3(Op_EQ,MBIN32S,MBIN16S,MBIN16S,EQ_MBIN32S_MBIN16S_MBIN16S), // Instruction 33 |
| I3(Op_EQ,MBIN32S,MBIN16S,MBIN32S,EQ_MBIN32S_MBIN16S_MBIN32S), // Instruction 34 |
| |
| IopCodeNotInUse(35), |
| |
| I3(Op_EQ,MBIN32S,MBIN32S,MBIN32S,EQ_MBIN32S_MBIN32S_MBIN32S), // Instruction 36 |
| I3(Op_EQ,MBIN32S,MBIN16U,MBIN16U,EQ_MBIN32S_MBIN16U_MBIN16U), // Instruction 37 |
| I3(Op_EQ,MBIN32S,MBIN16U,MBIN32U,EQ_MBIN32S_MBIN16U_MBIN32U), // Instruction 38 |
| |
| IopCodeNotInUse(39), |
| |
| I3(Op_EQ,MBIN32S,MBIN32U,MBIN32U,EQ_MBIN32S_MBIN32U_MBIN32U), // Instruction 40 |
| I3(Op_EQ,MBIN32S,MBIN16S,MBIN32U,EQ_MBIN32S_MBIN16S_MBIN32U), // Instruction 41 |
| |
| IopCodeNotInUse(42), |
| |
| I3(Op_LT,MBIN32S,MBIN16S,MBIN16S,LT_MBIN32S_MBIN16S_MBIN16S), // Instruction 43 |
| I3(Op_LT,MBIN32S,MBIN16S,MBIN32S,LT_MBIN32S_MBIN16S_MBIN32S), // Instruction 44 |
| |
| IopCodeNotInUse(45), |
| |
| I3(Op_LT,MBIN32S,MBIN32S,MBIN32S,LT_MBIN32S_MBIN32S_MBIN32S), // Instruction 46 |
| I3(Op_LT,MBIN32S,MBIN16U,MBIN16U,LT_MBIN32S_MBIN16U_MBIN16U), // Instruction 47 |
| I3(Op_LT,MBIN32S,MBIN16U,MBIN32U,LT_MBIN32S_MBIN16U_MBIN32U), // Instruction 48 |
| |
| IopCodeNotInUse(49), |
| |
| I3(Op_LT,MBIN32S,MBIN32U,MBIN32U,LT_MBIN32S_MBIN32U_MBIN32U), // Instruction 50 |
| I3(Op_LT,MBIN32S,MBIN16S,MBIN32U,LT_MBIN32S_MBIN16S_MBIN32U), // Instruction 51 |
| |
| IopCodeNotInUse(52), |
| |
| I3(Op_GT,MBIN32S,MBIN16S,MBIN16S,GT_MBIN32S_MBIN16S_MBIN16S), // Instruction 53 |
| I3(Op_GT,MBIN32S,MBIN16S,MBIN32S,GT_MBIN32S_MBIN16S_MBIN32S), // Instruction 54 |
| |
| IopCodeNotInUse(55), |
| |
| I3(Op_GT,MBIN32S,MBIN32S,MBIN32S,GT_MBIN32S_MBIN32S_MBIN32S), // Instruction 56 |
| I3(Op_GT,MBIN32S,MBIN16U,MBIN16U,GT_MBIN32S_MBIN16U_MBIN16U), // Instruction 57 |
| I3(Op_GT,MBIN32S,MBIN16U,MBIN32U,GT_MBIN32S_MBIN16U_MBIN32U), // Instruction 58 |
| |
| IopCodeNotInUse(59), |
| |
| I3(Op_GT,MBIN32S,MBIN32U,MBIN32U,GT_MBIN32S_MBIN32U_MBIN32U), // Instruction 60 |
| I3(Op_GT,MBIN32S,MBIN16S,MBIN32U,GT_MBIN32S_MBIN16S_MBIN32U), // Instruction 61 |
| |
| IopCodeNotInUse(62), |
| |
| I3(Op_AND,MBIN32S,MBIN32S,MBIN32S,AND_MBIN32S_MBIN32S_MBIN32S), // Instruction 63 |
| I3(Op_OR,MBIN32S,MBIN32S,MBIN32S,OR_MBIN32S_MBIN32S_MBIN32S), // Instruction 64 |
| |
| I3(Op_ADD,MBIN16S,MBIN16S,MBIN16S,ADD_MBIN16S_MBIN16S_MBIN16S), // Instruction 65 |
| I3(Op_ADD,MBIN32S,MBIN32S,MBIN32S,ADD_MBIN32S_MBIN32S_MBIN32S), // Instruction 66 |
| I3(Op_ADD,MBIN64S,MBIN64S,MBIN64S,ADD_MBIN64S_MBIN64S_MBIN64S), // Instruction 67 |
| I3(Op_SUB,MBIN16S,MBIN16S,MBIN16S,SUB_MBIN16S_MBIN16S_MBIN16S), // Instruction 68 |
| I3(Op_SUB,MBIN32S,MBIN32S,MBIN32S,SUB_MBIN32S_MBIN32S_MBIN32S), // Instruction 69 |
| I3(Op_SUB,MBIN64S,MBIN64S,MBIN64S,SUB_MBIN64S_MBIN64S_MBIN64S), // Instruction 70 |
| I3(Op_MUL,MBIN16S,MBIN16S,MBIN16S,MUL_MBIN16S_MBIN16S_MBIN16S), // Instruction 71 |
| I3(Op_MUL,MBIN32S,MBIN32S,MBIN32S,MUL_MBIN32S_MBIN32S_MBIN32S), // Instruction 72 |
| I3(Op_MUL,MBIN64S,MBIN64S,MBIN64S,MUL_MBIN64S_MBIN64S_MBIN64S), // Instruction 73 |
| |
| IopCodeNotInUse(74), // Instruction 74 not in use |
| IopCodeNotInUse(75), // Instruction 75 not in use |
| IopCodeNotInUse(76), // Instruction 76 not in use |
| |
| I2(Op_SUM,MBIN32S,MBIN32S,SUM_MBIN32S_MBIN32S), // Instruction 77 |
| |
| IopCodeNotInUse(78), |
| |
| I2(Op_SUM,MBIN64S,MBIN64S,SUM_MBIN64S_MBIN64S), // Instruction 79 |
| |
| IopCodeNotInUse(80), |
| IopCodeNotInUse(81), // Instruction 81 not in use |
| IopCodeNotInUse(82), // Instruction 82 not in use |
| |
| I3(Op_MOD,MBIN32S,MBIN32S,MBIN32S,MOD_MBIN32S_MBIN32S_MBIN32S), // Instruction 83 |
| I4(Op_MINMAX,MBIN8,MBIN8,MBIN32S,IBIN32S,MINMAX_MBIN8_MBIN8_MBIN32S_IBIN32S), // Instruction 84 |
| |
| IopCodeNotInUse(85), // Instruction 85 not in use |
| IopCodeNotInUse(86), // Instruction 86 not in use |
| |
| I3(Op_ENCODE,MASCII,MBIN16S,IBIN32S,ENCODE_MASCII_MBIN16S_IBIN32S), // Instruction 87 |
| I3(Op_ENCODE,MASCII,MBIN16U,IBIN32S,ENCODE_MASCII_MBIN16U_IBIN32S), // Instruction 88 |
| I3(Op_ENCODE,MASCII,MBIN32S,IBIN32S,ENCODE_MASCII_MBIN32S_IBIN32S), // Instruction 89 |
| I3(Op_ENCODE,MASCII,MBIN32U,IBIN32S,ENCODE_MASCII_MBIN32U_IBIN32S), // Instruction 90 |
| I3(Op_ENCODE,MASCII,MBIN64S,IBIN32S,ENCODE_MASCII_MBIN64S_IBIN32S), // Instruction 91 |
| |
| IopCodeNotInUse(92), |
| |
| I4(Op_ENCODE,MASCII,MASCII,IBIN32S,IBIN32S,ENCODE_NXX), // Instruction 93 |
| I4(Op_HASH,MBIN32U,MPTR32,IBIN32S,IBIN32S,HASH_MBIN32U_MPTR32_IBIN32S_IBIN32S), // Instruction 94 |
| I1(Op_BRANCH,IBIN32S,BRANCH), // Instruction 95 |
| |
| IopCodeNotInUse(96), // Instruction 96 not in use |
| |
| I2(Op_RANGE_LOW,MBIN32S,IBIN64S,RANGE_LOW_S32S64), // Instruction 97 |
| I2(Op_RANGE_HIGH,MBIN32S,IBIN64S,RANGE_HIGH_S32S64), // Instruction 98 |
| I2(Op_RANGE_LOW,MBIN32U,IBIN64S,RANGE_LOW_U32S64), // Instruction 99 |
| I2(Op_RANGE_HIGH,MBIN32U,IBIN64S,RANGE_HIGH_U32S64), // Instruction 100 |
| I2(Op_RANGE_LOW,MBIN64S,IBIN64S,RANGE_LOW_S64S64), // Instruction 101 |
| I2(Op_RANGE_HIGH,MBIN64S,IBIN64S,RANGE_HIGH_S64S64), // Instruction 102 |
| I2(Op_RANGE_LOW,MBIN16S,IBIN64S,RANGE_LOW_S16S64), // Instruction 103 |
| I2(Op_RANGE_HIGH,MBIN16S,IBIN64S,RANGE_HIGH_S16S64), // Instruction 104 |
| I2(Op_RANGE_LOW,MBIN16U,IBIN64S,RANGE_LOW_U16S64), // Instruction 105 |
| I2(Op_RANGE_HIGH,MBIN16U,IBIN64S,RANGE_HIGH_U16S64), // Instruction 106 |
| |
| IopCodeNotInUse(107), // Instruction 107 not in use |
| |
| I2(Op_CLAUSE_EVAL,IPTR,IBIN32S,CLAUSE_EVAL), // Instruction 108 |
| I2(Op_CLAUSE_BRANCH,IPTR,IPTR,CLAUSE_BRANCH), // Instruction 109 |
| |
| I0(Op_PROFILE,PROFILE), // Instruction 110 |
| |
| IopCodeNotInUse(111), // Instruction 111 not in use |
| IopCodeNotInUse(112), // Instruction 112 not in use |
| |
| I0(Op_NOP,NOP), // Instruction 113 |
| I0(Op_END,END), // Instruction 114 |
| |
| I3(Op_FILL_MEM_BYTES,MASCII,IBIN32S,IBIN8U,FILL_MEM_BYTES), // Instruction 115 |
| |
| I2(Op_MOVE,MBIN16U,IBIN16U,MOVE_MBIN16U_IBIN16U), // Instruction 116 |
| |
| I4(Op_EQ,MBIN32S,MASCII,MASCII,IBIN32S,EQ_MBIN32S_MASCII_MASCII), // Instruction 117 |
| |
| I3(Op_ADD,MBIN32S,MBIN16S,MBIN16S,ADD_MBIN32S_MBIN16S_MBIN16S), // Instruction 118 |
| I3(Op_ADD,MBIN32S,MBIN16S,MBIN32S,ADD_MBIN32S_MBIN16S_MBIN32S), // Instruction 119 |
| |
| IopCodeNotInUse(120), |
| |
| I3(Op_ADD,MBIN64S,MBIN32S,MBIN64S,ADD_MBIN64S_MBIN32S_MBIN64S), // Instruction 121 |
| |
| IopCodeNotInUse(122), |
| |
| I3(Op_SUB,MBIN32S,MBIN16S,MBIN16S,SUB_MBIN32S_MBIN16S_MBIN16S), // Instruction 123 |
| I3(Op_SUB,MBIN32S,MBIN16S,MBIN32S,SUB_MBIN32S_MBIN16S_MBIN32S), // Instruction 124 |
| I3(Op_SUB,MBIN32S,MBIN32S,MBIN16S,SUB_MBIN32S_MBIN32S_MBIN16S), // Instruction 125 |
| |
| I3(Op_MUL,MBIN32S,MBIN16S,MBIN16S,MUL_MBIN32S_MBIN16S_MBIN16S), // Instruction 126 |
| I3(Op_MUL,MBIN32S,MBIN16S,MBIN32S,MUL_MBIN32S_MBIN16S_MBIN32S), // Instruction 127 |
| |
| IopCodeNotInUse(128), |
| |
| I3(Op_DIV,MBIN64S,MBIN64S,MBIN64S,DIV_MBIN64S_MBIN64S_MBIN64S), // Instruction 129 |
| I4(Op_LT,MBIN32S,MASCII,MASCII,IBIN32S,LT_MBIN32S_MASCII_MASCII), // Instruction 130 |
| I4(Op_LE,MBIN32S,MASCII,MASCII,IBIN32S,LE_MBIN32S_MASCII_MASCII), // Instruction 131 |
| I4(Op_GT,MBIN32S,MASCII,MASCII,IBIN32S,GT_MBIN32S_MASCII_MASCII), // Instruction 132 |
| I4(Op_GE,MBIN32S,MASCII,MASCII,IBIN32S,GE_MBIN32S_MASCII_MASCII), // Instruction 133 |
| |
| I3(Op_LE,MBIN32S,MBIN16S,MBIN16S,LE_MBIN32S_MBIN16S_MBIN16S), // Instruction 134 |
| I3(Op_LE,MBIN32S,MBIN16S,MBIN32S,LE_MBIN32S_MBIN16S_MBIN32S), // Instruction 135 |
| |
| IopCodeNotInUse(136), |
| |
| I3(Op_LE,MBIN32S,MBIN32S,MBIN32S,LE_MBIN32S_MBIN32S_MBIN32S), // Instruction 137 |
| I3(Op_LE,MBIN32S,MBIN16U,MBIN16U,LE_MBIN32S_MBIN16U_MBIN16U), // Instruction 138 |
| I3(Op_LE,MBIN32S,MBIN16U,MBIN32U,LE_MBIN32S_MBIN16U_MBIN32U), // Instruction 139 |
| |
| IopCodeNotInUse(140), |
| |
| I3(Op_LE,MBIN32S,MBIN32U,MBIN32U,LE_MBIN32S_MBIN32U_MBIN32U), // Instruction 141 |
| I3(Op_LE,MBIN32S,MBIN16S,MBIN32U,LE_MBIN32S_MBIN16S_MBIN32U), // Instruction 142 |
| |
| IopCodeNotInUse(143), |
| |
| I3(Op_GE,MBIN32S,MBIN16S,MBIN16S,GE_MBIN32S_MBIN16S_MBIN16S), // Instruction 144 |
| I3(Op_GE,MBIN32S,MBIN16S,MBIN32S,GE_MBIN32S_MBIN16S_MBIN32S), // Instruction 145 |
| |
| IopCodeNotInUse(146), |
| |
| I3(Op_GE,MBIN32S,MBIN32S,MBIN32S,GE_MBIN32S_MBIN32S_MBIN32S), // Instruction 147 |
| I3(Op_GE,MBIN32S,MBIN16U,MBIN16U,GE_MBIN32S_MBIN16U_MBIN16U), // Instruction 148 |
| I3(Op_GE,MBIN32S,MBIN16U,MBIN32U,GE_MBIN32S_MBIN16U_MBIN32U), // Instruction 149 |
| |
| IopCodeNotInUse(150), |
| |
| I3(Op_GE,MBIN32S,MBIN32U,MBIN32U,GE_MBIN32S_MBIN32U_MBIN32U), // Instruction 151 |
| I3(Op_GE,MBIN32S,MBIN16S,MBIN32U,GE_MBIN32S_MBIN16S_MBIN32U), // Instruction 152 |
| |
| IopCodeNotInUse(153), |
| IopCodeNotInUse(154), |
| IopCodeNotInUse(155), |
| |
| I3(Op_HASHCOMB,MBIN32U,MBIN32U,MBIN32U,HASHCOMB_MBIN32U_MBIN32U_MBIN32U), // Instruction 156 |
| I3(Op_EQ,MBIN32S,MBIN16U,MBIN16S,EQ_MBIN32S_MBIN16U_MBIN16S), // Instruction 157 |
| I3(Op_LT,MBIN32S,MBIN16U,MBIN16S,LT_MBIN32S_MBIN16U_MBIN16S), // Instruction 158 |
| I3(Op_LE,MBIN32S,MBIN16U,MBIN16S,LE_MBIN32S_MBIN16U_MBIN16S), // Instruction 159 |
| I3(Op_GT,MBIN32S,MBIN16U,MBIN16S,GT_MBIN32S_MBIN16U_MBIN16S), // Instruction 160 |
| I3(Op_GE,MBIN32S,MBIN16U,MBIN16S,GE_MBIN32S_MBIN16U_MBIN16S), // Instruction 161 |
| |
| I3(Op_EQ,MBIN32S,MBIN64S,MBIN64S,EQ_MBIN32S_MBIN64S_MBIN64S), // Instruction 162 |
| I3(Op_LT,MBIN32S,MBIN64S,MBIN64S,LT_MBIN32S_MBIN64S_MBIN64S), // Instruction 163 |
| I3(Op_LE,MBIN32S,MBIN64S,MBIN64S,LE_MBIN32S_MBIN64S_MBIN64S), // Instruction 164 |
| I3(Op_GT,MBIN32S,MBIN64S,MBIN64S,GT_MBIN32S_MBIN64S_MBIN64S), // Instruction 165 |
| I3(Op_GE,MBIN32S,MBIN64S,MBIN64S,GE_MBIN32S_MBIN64S_MBIN64S), // Instruction 166 |
| I3(Op_NE,MBIN32S,MBIN64S,MBIN64S,NE_MBIN32S_MBIN64S_MBIN64S), // Instruction 167 |
| |
| I4(Op_BRANCH_AND,IPTR,IPTR,MBIN32S,MBIN32S,BRANCH_AND), // Instruction 168 |
| I4(Op_BRANCH_OR,IPTR,IPTR,MBIN32S,MBIN32S,BRANCH_OR), // Instruction 169 |
| |
| I4(Op_HASH,MBIN32U,MBIN32S,IBIN32S,IBIN32S,HASH_MBIN32U_MBIN32_IBIN32S_IBIN32S), // Instruction 170 |
| I4(Op_HASH,MBIN32U,MBIN16S,IBIN32S,IBIN32S,HASH_MBIN32U_MBIN16_IBIN32S_IBIN32S), // Instruction 171 |
| // I4(Op_HASH,MBIN32U,MPTR32,IBIN32S,IBIN32S,HASH_MBIN32U_MPTR32_IBIN32S_IBIN32S), // Instruction 172 |
| IopCodeNotInUse(172), |
| I4(Op_HASH,MBIN32U,MBIN64S,IBIN32S,IBIN32S,HASH_MBIN32U_MBIN64_IBIN32S_IBIN32S),//8byte |
| |
| IopCodeNotInUse(174), // Instruction 174 not in use |
| IopCodeNotInUse(175), // Instruction 175 not in use |
| |
| I4(Op_ENCODE,MASCII,MDECS,IBIN32S,IBIN32S,ENCODE_DECS), // Instruction 176 |
| |
| IopCodeNotInUse(177), // Instruction 177 not in use |
| IopCodeNotInUse(178), // Instruction 178 not in use |
| IopCodeNotInUse(179), // Instruction 179 not in use |
| IopCodeNotInUse(180), // Instruction 180 not in use |
| |
| I6(Op_GENFUNC,IBIN32S,MBIN8,MBIN8,IBIN32S,MBIN8,IBIN32S,GENFUNC_PCODE_1), // Instruction 181 |
| |
| IopCodeNotInUse(182), |
| |
| I3(Op_MUL,MBIN64S,MBIN16S,MBIN32S,MUL_MBIN64S_MBIN16S_MBIN32S), // Instruction 183 |
| I3(Op_MUL,MBIN64S,MBIN32S,MBIN32S,MUL_MBIN64S_MBIN32S_MBIN32S), // Instruction 184 |
| |
| IopCodeNotInUse(185), |
| |
| I3(Op_MOD,MBIN32U,MBIN32U,MBIN32S,MOD_MBIN32U_MBIN32U_MBIN32S), // Instruction 186 |
| I4(Op_NOT_NULL_BRANCH,MBIN32S,MBIN16S,MBIN16S,IBIN32S, |
| NOT_NULL_BRANCH_MBIN32S_MBIN16S_MBIN16S_IBIN32S), // Instruction 187 |
| I3(Op_NOT_NULL_BRANCH,MBIN32S,MBIN16S,IBIN32S, |
| NOT_NULL_BRANCH_MBIN32S_MBIN16S_IBIN32S), // Instruction 188 |
| I4(Op_NOT_NULL_BRANCH,MBIN32S,MBIN16S,IBIN32S,IBIN32S, |
| NOT_NULL_BRANCH_MBIN32S_MBIN16S_IBIN32S_IBIN32S), // Instruction 189 |
| I2(Op_NOT_NULL_BRANCH,MBIN16S,IBIN32S,NOT_NULL_BRANCH_MBIN16S_IBIN32S), // Instruction 190 |
| I6(Op_GENFUNC,IBIN32S,MBIN8,MBIN8,MBIN8,IBIN32S,IBIN32S, |
| GENFUNC_MBIN8_MBIN8_MBIN8_IBIN32S_IBIN32S), // Instruction 191 |
| |
| IopCodeNotInUse(192), |
| |
| I2(Op_MOVE,MFLT64,MBIN16S,MOVE_MFLT64_MBIN16S), // Instruction 193 |
| I2(Op_MOVE,MFLT64,MFLT32,MOVE_MFLT64_MFLT32), // Instruction 194 |
| |
| IopCodeNotInUse(195), |
| |
| I3(Op_NE,MBIN32S,MBIN16S,MBIN16S,NE_MBIN32S_MBIN16S_MBIN16S), // Instruction 196 |
| |
| IopCodeNotInUse(197), |
| IopCodeNotInUse(198), // Instruction 198 not in use |
| IopCodeNotInUse(199), // Instruction 199 not in use |
| |
| I2(Op_MOVE,MBIN8,MBIN8,MOVE_MBIN8_MBIN8), // Instruction 200 |
| I2(Op_MOVE,MBIN16U,MBIN16U,MOVE_MBIN16U_MBIN16U), // Instruction 201 |
| I2(Op_MOVE,MBIN32U,MBIN32U,MOVE_MBIN32U_MBIN32U), // Instruction 202 |
| I2(Op_MOVE,MBIN64S,MBIN64S,MOVE_MBIN64S_MBIN64S), // Instruction 203 |
| |
| I3(Op_ADD,MFLT64,MFLT64,MFLT64,ADD_MFLT64_MFLT64_MFLT64), // Instruction 204 |
| I3(Op_SUB,MFLT64,MFLT64,MFLT64,SUB_MFLT64_MFLT64_MFLT64), // Instruction 205 |
| I3(Op_MUL,MFLT64,MFLT64,MFLT64,MUL_MFLT64_MFLT64_MFLT64), // Instruction 206 |
| I3(Op_DIV,MFLT64,MFLT64,MFLT64,DIV_MFLT64_MFLT64_MFLT64), // Instruction 207 |
| |
| IopCodeNotInUse(208), |
| |
| I2(Op_SUM,MFLT64,MFLT64,SUM_MFLT64_MFLT64), // Instruction 209 |
| I1(Op_RANGE_LOW,MFLT64,RANGE_MFLT64), // Instruction 210 |
| |
| I3(Op_NE,MBIN32S,MFLT64,MFLT64,NE_MBIN32S_MFLT64_MFLT64), // Instruction 211 |
| I3(Op_NE,MBIN32S,MFLT32,MFLT32,NE_MBIN32S_MFLT32_MFLT32), // Instruction 212 |
| |
| I3(Op_GT,MBIN32S,MFLT64,MFLT64,GT_MBIN32S_MFLT64_MFLT64), // Instruction 213 |
| I3(Op_GT,MBIN32S,MFLT32,MFLT32,GT_MBIN32S_MFLT32_MFLT32), // Instruction 214 |
| |
| I3(Op_GE,MBIN32S,MFLT64,MFLT64,GE_MBIN32S_MFLT64_MFLT64), // Instruction 215 |
| I3(Op_GE,MBIN32S,MFLT32,MFLT32,GE_MBIN32S_MFLT32_MFLT32), // Instruction 216 |
| |
| I3(Op_EQ,MBIN32S,MFLT64,MFLT64,EQ_MBIN32S_MFLT64_MFLT64), // Instruction 217 |
| I3(Op_EQ,MBIN32S,MFLT32,MFLT32,EQ_MBIN32S_MFLT32_MFLT32), // Instruction 218 |
| |
| I3(Op_LE,MBIN32S,MFLT64,MFLT64,LE_MBIN32S_MFLT64_MFLT64), // Instruction 219 |
| I3(Op_LE,MBIN32S,MFLT32,MFLT32,LE_MBIN32S_MFLT32_MFLT32), // Instruction 220 |
| |
| I3(Op_LT,MBIN32S,MFLT64,MFLT64,LT_MBIN32S_MFLT64_MFLT64), // Instruction 221 |
| I3(Op_LT,MBIN32S,MFLT32,MFLT32,LT_MBIN32S_MFLT32_MFLT32), // Instruction 222 |
| |
| I3(Op_HASH2_DISTRIB,MBIN32U,MBIN32U,MBIN32U,HASH2_DISTRIB), // Instruction 223 |
| |
| I4(Op_NULL_BITMAP,MPTR32,IBIN32S,IBIN16U,IBIN32S,NULL_BITMAP), // Instruction 224 |
| |
| IopCodeNotInUse(225), // Instruction 225 not in use |
| IopCodeNotInUse(226), // Instruction 226 not in use |
| IopCodeNotInUse(227), // Instruction 227 not in use |
| |
| I3(Op_OPDATA,MPTR32,IBIN32S,IBIN32S,OPDATA_MPTR32_IBIN32S_IBIN32S), // Instruction 228 |
| |
| IopCodeNotInUse(229), // Instruction 229 not in use |
| IopCodeNotInUse(230), // Instruction 230 not in use |
| |
| I2(Op_OPDATA,MATTR5,IBIN32S,OPDATA_MATTR5_IBIN32S), // Instruction 231 |
| |
| IopCodeNotInUse(232), |
| IopCodeNotInUse(233), |
| IopCodeNotInUse(234), |
| IopCodeNotInUse(235), |
| IopCodeNotInUse(236), |
| |
| I4(Op_DIV_ROUND,MBIN64S,MBIN64S,MBIN64S,IBIN32S, |
| DIV_MBIN64S_MBIN64S_MBIN64S_ROUND), // Instruction 237 |
| I4(Op_NULL_VIOLATION,MPTR32,MPTR32,IPTR,IPTR, |
| NULL_VIOLATION_MPTR32_MPTR32_IPTR_IPTR), // Instruction 238 |
| |
| I5(Op_OFFSET,IPTR,IPTR,MBIN32S,MBIN64S,MBIN64S, |
| OFFSET_IPTR_IPTR_MBIN32S_MBIN64S_MBIN64S), // Instruction 239 |
| I5(Op_OFFSET,IPTR,IPTR,IBIN32S,MBIN64S,MBIN64S, |
| OFFSET_IPTR_IPTR_IBIN32S_MBIN64S_MBIN64S), // Instruction 240 |
| |
| I4(Op_ADD,MBIGS,MBIGS,MBIGS,IBIN32S,ADD_MBIGS_MBIGS_MBIGS_IBIN32S), // Instruction 241 |
| I4(Op_SUB,MBIGS,MBIGS,MBIGS,IBIN32S,SUB_MBIGS_MBIGS_MBIGS_IBIN32S), // Instruction 242 |
| I6(Op_MUL,MBIGS,MBIGS,MBIGS,IBIN32S,IBIN32S,IBIN32S,MUL_MBIGS_MBIGS_MBIGS_IBIN32S), // Instruction 243 |
| I4(Op_MOVE,MBIGS,MBIGS,IBIN32S,IBIN32S,MOVE_MBIGS_MBIGS_IBIN32S_IBIN32S), // Instruction 244 |
| I3(Op_MOVE,MBIGS,MBIN64S,IBIN32S,MOVE_MBIGS_MBIN64S_IBIN32S), // Instruction 245 |
| I3(Op_MOVE,MBIN64S,MBIGS,IBIN32S,MOVE_MBIN64S_MBIGS_IBIN32S), // Instruction 246 |
| |
| I5(Op_NOT_NULL_BRANCH,MBIN32S,MBIN32S,MBIN32S,IATTR4,IBIN32S, |
| NOT_NULL_BRANCH_MBIN32S_MBIN32S_MBIN32S_IATTR4_IBIN32S), // Instruction 247 |
| I4(Op_NOT_NULL_BRANCH,MBIN32S,MBIN32S,IATTR3,IBIN32S, |
| NOT_NULL_BRANCH_MBIN32S_MBIN32S_IATTR3_IBIN32S), // Instruction 248 |
| I5(Op_NOT_NULL_BRANCH_COMP,MBIN32S,MBIN32S,MBIN32S,IATTR4,IBIN32S, |
| NOT_NULL_BRANCH_COMP_MBIN32S_MBIN32S_MBIN32S_IATTR4_IBIN32S), // Instruction 249 |
| I4(Op_NOT_NULL_BRANCH_COMP,MBIN32S,MBIN32S,IATTR3,IBIN32S, |
| NOT_NULL_BRANCH_COMP_MBIN32S_MBIN32S_IATTR3_IBIN32S), // Instruction 250 |
| |
| I4(Op_MOVE,MASCII,MASCII,IBIN32S,IBIN32S,MOVE_MASCII_MASCII_IBIN32S_IBIN32S), // Instruction 251 |
| |
| IopCodeNotInUse(252), |
| IopCodeNotInUse(253), |
| IopCodeNotInUse(254), |
| IopCodeNotInUse(255), |
| IopCodeNotInUse(256), |
| IopCodeNotInUse(257), |
| IopCodeNotInUse(258), |
| IopCodeNotInUse(259), |
| IopCodeNotInUse(260), |
| IopCodeNotInUse(261), |
| |
| I4(Op_NULL,MBIN32S,MATTR5,IBIN32S,IBIN32S,NULL_TEST_MBIN32S_MATTR5_IBIN32S_IBIN32S), // Instruction 262 |
| I4(Op_NE,MBIN32S,MASCII,MASCII,IBIN32S,NE_MBIN32S_MASCII_MASCII), // Instruction 263 |
| |
| I0(Op_RETURN,RETURN), // Instruction 264 |
| I1(Op_RETURN,IBIN32S,RETURN_IBIN32S), // Instruction 265 |
| |
| I1(Op_HASHCOMB,MBIN32U,HASHCOMB_BULK_MBIN32U), // Instruction 266 |
| I0(Op_NOT_NULL_BRANCH,NOT_NULL_BRANCH_BULK), // Instruction 267 |
| I0(Op_MOVE,MOVE_BULK), // Instruction 268 |
| I0(Op_NULL_BITMAP,NULL_BITMAP_BULK), // Instruction 269 |
| |
| I5(Op_COMP,MBIN32S,MBIGS,MBIGS,IBIN32S,IBIN32S, |
| COMP_MBIN32S_MBIGS_MBIGS_IBIN32S_IBIN32S), // Instruction 270 obsolete |
| |
| I2(Op_SUM,MBIN64S,MBIN32S,SUM_MBIN64S_MBIN32S), // Instruction 271 |
| |
| IopCodeNotInUse(272), |
| |
| I6(Op_BRANCH_AND,IBIN32S,IBIN32S,MBIN32S,MBIN32S,IBIN32S,IBIN32S,BRANCH_AND_CNT), // Instruction 273 |
| I6(Op_BRANCH_OR,IBIN32S,IBIN32S,MBIN32S,MBIN32S,IBIN32S,IBIN32S,BRANCH_OR_CNT), // Instruction 274 |
| |
| I6(Op_COMP,MBIN32S,MASCII,MASCII,IBIN32S,IBIN32S,IBIN32S, |
| COMP_MBIN32S_MASCII_MASCII_IBIN32S_IBIN32S_IBIN32S), // Instruction 275 |
| |
| IopCodeNotInUse(276), // obsolete Instruction 276 |
| IopCodeNotInUse(277), |
| IopCodeNotInUse(278), |
| IopCodeNotInUse(279), |
| |
| I6(Op_COMP,MBIN32S,MATTR4,MATTR4,IBIN32S,IBIN32S,IBIN32S, |
| COMP_MBIN32S_MATTR4_MATTR4_IBIN32S_IBIN32S_IBIN32S), // Instruction 280 |
| I6(Op_COMP,MBIN32S,MUNI,MUNI,IBIN32S,IBIN32S,IBIN32S, |
| COMP_MBIN32S_MUNI_MUNI_IBIN32S_IBIN32S_IBIN32S), // Instruction 281 |
| I4(Op_MOVE,MUNI,MUNI,IBIN32S,IBIN32S,MOVE_MUNI_MUNI_IBIN32S_IBIN32S), // Instruction 282 |
| |
| IopCodeNotInUse(283), // Instruction 283 |
| |
| I2(Op_MOVE,MATTR5,MATTR5,MOVE_MATTR5_MATTR5), // Instruction 284 |
| I4(Op_COMP,MBIN32S,MATTR5,MATTR5,IBIN32S,COMP_MBIN32S_MATTR5_MATTR5_IBIN32S), // Instruction 285 |
| I2(Op_HASH,MBIN32U,MATTR5,HASH_MBIN32U_MATTR5), // Instruction 286 |
| I4(Op_GENFUNC,MATTR5,MATTR5,MBIN32S,MBIN32S,SUBSTR_MATTR5_MATTR5_MBIN32S_MBIN32S), // Instruction 287 |
| I3(Op_GENFUNC,MATTR5,MATTR5,IBIN32S,GENFUNC_MATTR5_MATTR5_IBIN32S), // Instruction 288 |
| |
| // BigNum, map is not available for now. |
| I3(Op_MOVE,MBIGS,MBIN32S,IBIN32S,MOVE_MBIGS_MBIN32S_IBIN32S), // Instruction 289 |
| I3(Op_MOVE,MBIGS,MBIN16S,IBIN32S,MOVE_MBIGS_MBIN16S_IBIN32S), // Instruction 290 |
| |
| IopCodeNotInUse(291), // Instruction 291 |
| IopCodeNotInUse(292), // Instruction 292 |
| |
| I4(Op_COMP,MBIN32S,MUNIV,MUNIV,IBIN32S,COMP_MBIN32S_MUNIV_MUNIV_IBIN32S), // Instruction 293 |
| I2(Op_HASH,MBIN32U,MUNIV,HASH_MBIN32U_MUNIV), // Instruction 294 |
| |
| I2(Op_MOVE,MFLT64,MBIN32S,MOVE_MFLT64_MBIN32S), // Instruction 295 |
| I2(Op_MOVE,MFLT64,MBIN64S,MOVE_MFLT64_MBIN64S), // Instruction 296 |
| |
| I2(Op_GENFUNC,MBIN32U,MATTR5,STRLEN_MBIN32U_MATTR5), // Instruction 297 |
| I2(Op_GENFUNC,MBIN32U,MUNIV,STRLEN_MBIN32U_MUNIV), // Instruction 298 |
| I4(Op_GENFUNC,MATTR5,MATTR5,MBIN32S,IBIN32S, |
| GENFUNC_MATTR5_MATTR5_MBIN32S_IBIN32S), // Instruction 299 |
| I3(Op_GENFUNC,MBIN32S,MATTR5,MATTR5,POS_MBIN32S_MATTR5_MATTR5), // Instruction 300 |
| I5(Op_GENFUNC,MBIN32S,MATTR5,MATTR5,IBIN32S,IBIN32S, |
| LIKE_MBIN32S_MATTR5_MATTR5_IBIN32S_IBIN32S), // Instruction 301 |
| I2(Op_MOVE,MBIN16U,MBIN8,MOVE_MBIN16U_MBIN8), // Instruction 302 |
| |
| // Header clause |
| I6(Op_HDR,MPTR32,IBIN32S,IBIN32S,IBIN32S,IBIN32S,IBIN32S, |
| HDR_MPTR32_IBIN32S_IBIN32S_IBIN32S_IBIN32S_IBIN32S), // Instruction 303 |
| |
| // Special nulls for all data formats |
| I5(Op_NOT_NULL_BRANCH,MBIN32S,MATTR3,MATTR3,IBIN32S,IBIN32S, |
| NNB_SPECIAL_NULLS_MBIN32S_MATTR3_MATTR3_IBIN32S_IBIN32S), // Instruction 304 |
| |
| I4(Op_NULLIFZERO,MPTR32,MATTR3,MPTR32,IBIN32S, |
| NULLIFZERO_MPTR32_MATTR3_MPTR32_IBIN32S), // Instruction 305 |
| |
| I2(Op_NOT_NULL_BRANCH,MATTR3,IBIN32S, NNB_MATTR3_IBIN32S), // Instruction 306 |
| |
| // Null helper for hash |
| I4(Op_NOT_NULL_BRANCH,MBIN32S,MATTR3,IBIN32S,IBIN32S, // Instruction 307 |
| NNB_MBIN32S_MATTR3_IBIN32S_IBIN32S), |
| |
| I5(Op_REPLACE_NULL, MBIN32S, MATTR3, MBIN8, MBIN8, IBIN32S, |
| REPLACE_NULL_MATTR3_MBIN32S), // Instruction 308 |
| I5(Op_REPLACE_NULL, MBIN32U, MATTR3, MBIN8, MBIN8, IBIN32S, |
| REPLACE_NULL_MATTR3_MBIN32U), // Instruction 309 |
| I5(Op_REPLACE_NULL, MBIN16S, MATTR3, MBIN8, MBIN8, IBIN32S, |
| REPLACE_NULL_MATTR3_MBIN16S), // Instruction 310 |
| I5(Op_REPLACE_NULL, MBIN16U, MATTR3, MBIN8, MBIN8, IBIN32S, |
| REPLACE_NULL_MATTR3_MBIN16U), // Instruction 311 |
| |
| I5(Op_SUM,MATTR3,MATTR3,IBIN32S,MBIN32S,MBIN32S, |
| SUM_MATTR3_MATTR3_IBIN32S_MBIN32S_MBIN32S), // Instruction 312 |
| I5(Op_SUM,MATTR3,MATTR3,IBIN32S,MBIN64S,MBIN64S, |
| SUM_MATTR3_MATTR3_IBIN32S_MBIN64S_MBIN64S), // Instruction 313 |
| I5(Op_SUM,MATTR3,MATTR3,IBIN32S,MBIN64S,MBIN32S, |
| SUM_MATTR3_MATTR3_IBIN32S_MBIN64S_MBIN32S), // Instruction 314 |
| I5(Op_SUM,MATTR3,MATTR3,IBIN32S,MFLT64,MFLT64, |
| SUM_MATTR3_MATTR3_IBIN32S_MFLT64_MFLT64), // Instruction 315 |
| |
| I2(Op_UPDATE_ROWLEN3,MATTR5,IBIN32S,UPDATE_ROWLEN3_MATTR5_IBIN32S), // Instruction 316 |
| |
| I3(Op_FILL_MEM_BYTES,MATTR5,IBIN32S,IBIN32S,FILL_MEM_BYTES_VARIABLE), // Instruction 317 |
| |
| I3(Op_MOVE,MASCII,MATTR5,IBIN32S,MOVE_MASCII_MATTR5_IBIN32S), // Instruction 318 |
| I3(Op_MOVE,MATTR5,MASCII,IBIN32S,MOVE_MATTR5_MASCII_IBIN32S), // Instruction 319 |
| I5(Op_COMP,MBIN32S,MATTR5,MPTR32,IBIN32S,IBIN32S, |
| SWITCH_MBIN32S_MATTR5_MPTR32_IBIN32S_IBIN32S), // Instruction 320 |
| I5(Op_COMP,MBIN32S,MBIN64S,MPTR32,IBIN32S,IBIN32S, |
| SWITCH_MBIN32S_MBIN64S_MPTR32_IBIN32S_IBIN32S), // Instruction 321 |
| I1(Op_BRANCH,MBIN32S,BRANCH_INDIRECT_MBIN32S), // Instruction 322 |
| I3(Op_GENFUNC,MATTR5,MATTR5,MATTR5,CONCAT_MATTR5_MATTR5_MATTR5), // Instruction 323 |
| I6(Op_SUM,MATTR3,MATTR3,IBIN32S,MBIGS,MBIGS,IBIN32S, |
| SUM_MATTR3_MATTR3_IBIN32S_MBIGS_MBIGS_IBIN32S), // Instruction 324 |
| |
| I2(Op_NULL_BYTES,MPTR32,IBIN32S,NULL_BYTES), // Instruction 325 |
| I6(Op_COPYVARROW, MBIN8, MBIN8, IBIN32S, IBIN32S, IBIN32S,IBIN32S, |
| COPYVARROW_MBIN8_MBIN8_IBIN32S_IBIN32S_IBIN32S_IBIN32S), // Instruction 326 |
| I3(Op_CONV_VC_PTR,MBIN32S,MATTR5,IBIN32S,CONVVCPTR_MBIN32S_MATTR5_IBIN32S), // Instruction 327 |
| I3(Op_CONV_VC_PTR,MFLT32,MATTR5,IBIN32S,CONVVCPTR_MFLT32_MATTR5_IBIN32S), // Instruction 328 |
| I2(Op_CONV_VC_PTR,MATTR5,MATTR5,CONVVCPTR_MATTR5_MATTR5), // Instruction 329 |
| I3(Op_CONV_VC_PTR,MBIN64S,MATTR5,IBIN32S,CONVVCPTR_MBIN64S_MATTR5_IBIN32S), // Instruction 330 |
| |
| I3(Op_DECODE,MASCII,MBIN16S,IBIN32S,DECODE_MASCII_MBIN16S_IBIN32S), // Instruction 331 |
| I3(Op_DECODE,MASCII,MBIN16U,IBIN32S,DECODE_MASCII_MBIN16U_IBIN32S), // Instruction 332 |
| I3(Op_DECODE,MASCII,MBIN32S,IBIN32S,DECODE_MASCII_MBIN32S_IBIN32S), // Instruction 333 |
| I3(Op_DECODE,MASCII,MBIN32U,IBIN32S,DECODE_MASCII_MBIN32U_IBIN32S), // Instruction 334 |
| I3(Op_DECODE,MASCII,MBIN64S,IBIN32S,DECODE_MASCII_MBIN64S_IBIN32S), // Instruction 335 |
| I4(Op_DECODE,MASCII,MASCII,IBIN32S,IBIN32S,DECODE_DATETIME), // Instruction 336 |
| I4(Op_DECODE,MASCII,MASCII,IBIN32S,IBIN32S,DECODE_NXX), // Instruction 337 |
| I4(Op_DECODE,MASCII,MDECS,IBIN32S,IBIN32S,DECODE_DECS), // Instruction 338 |
| |
| I2(Op_NEG,MASCII,MASCII,NEGATE_MASCII_MASCII), // Instruction 339 |
| |
| I3(Op_ENCODE,MASCII,MBIN8S,IBIN32S,ENCODE_MASCII_MBIN8S_IBIN32S), // Instruction 340 |
| I3(Op_ENCODE,MASCII,MBIN8U,IBIN32S,ENCODE_MASCII_MBIN8U_IBIN32S), // Instruction 341 |
| |
| I3(Op_DECODE,MASCII,MBIN8S,IBIN32S,DECODE_MASCII_MBIN8S_IBIN32S), // Instruction 342 |
| I3(Op_DECODE,MASCII,MBIN8U,IBIN32S,DECODE_MASCII_MBIN8U_IBIN32S), // Instruction 343 |
| |
| I2(Op_MOVE,MBIN16S,MBIN8S,MOVE_MBIN16S_MBIN8S), // Instruction 344 |
| I2(Op_MOVE,MBIN16U,MBIN8U,MOVE_MBIN16U_MBIN8U), // Instruction 345 |
| I2(Op_MOVE,MBIN32S,MBIN8S,MOVE_MBIN32S_MBIN8S), // Instruction 346 |
| I2(Op_MOVE,MBIN32U,MBIN8U,MOVE_MBIN32U_MBIN8U), // Instruction 347 |
| I2(Op_MOVE,MBIN64S,MBIN8S,MOVE_MBIN64S_MBIN8S), // Instruction 348 |
| I2(Op_MOVE,MBIN64U,MBIN8U,MOVE_MBIN64U_MBIN8U), // Instruction 349 |
| |
| I3(Op_EQ,MBIN32S,MBIN8S,MBIN8S,EQ_MBIN32S_MBIN8S_MBIN8S), // Instruction 350 |
| I3(Op_NE,MBIN32S,MBIN8S,MBIN8S,NE_MBIN32S_MBIN8S_MBIN8S), // Instruction 351 |
| I3(Op_LT,MBIN32S,MBIN8S,MBIN8S,LT_MBIN32S_MBIN8S_MBIN8S), // Instruction 352 |
| I3(Op_GT,MBIN32S,MBIN8S,MBIN8S,GT_MBIN32S_MBIN8S_MBIN8S), // Instruction 353 |
| I3(Op_LE,MBIN32S,MBIN8S,MBIN8S,LE_MBIN32S_MBIN8S_MBIN8S), // Instruction 354 |
| I3(Op_GE,MBIN32S,MBIN8S,MBIN8S,GE_MBIN32S_MBIN8S_MBIN8S), // Instruction 355 |
| |
| I3(Op_EQ,MBIN32S,MBIN8U,MBIN8U,EQ_MBIN32S_MBIN8U_MBIN8U), // Instruction 356 |
| I3(Op_NE,MBIN32S,MBIN8U,MBIN8U,NE_MBIN32S_MBIN8U_MBIN8U), // Instruction 357 |
| I3(Op_LT,MBIN32S,MBIN8U,MBIN8U,LT_MBIN32S_MBIN8U_MBIN8U), // Instruction 358 |
| I3(Op_GT,MBIN32S,MBIN8U,MBIN8U,GT_MBIN32S_MBIN8U_MBIN8U), // Instruction 359 |
| I3(Op_LE,MBIN32S,MBIN8U,MBIN8U,LE_MBIN32S_MBIN8U_MBIN8U), // Instruction 360 |
| I3(Op_GE,MBIN32S,MBIN8U,MBIN8U,GE_MBIN32S_MBIN8U_MBIN8U), // Instruction 361 |
| |
| I2(Op_MOVE,MBIN64S,MBIN64U,MOVE_MBIN64S_MBIN64U), // Instruction 362 |
| I2(Op_MOVE,MBIN64U,MBIN64S,MOVE_MBIN64U_MBIN64S), // Instruction 363 |
| I2(Op_MOVE,MBIN64U,MBIN64U,MOVE_MBIN64U_MBIN64U), // Instruction 364 |
| |
| I2(Op_RANGE_LOW,MBIN8S,IBIN64S,RANGE_LOW_S8S64), // Instruction 365 |
| I2(Op_RANGE_HIGH,MBIN8S,IBIN64S,RANGE_HIGH_S8S64), // Instruction 366 |
| I2(Op_RANGE_LOW,MBIN8U,IBIN64S,RANGE_LOW_U8S64), // Instruction 367 |
| I2(Op_RANGE_HIGH,MBIN8U,IBIN64S,RANGE_HIGH_U8S64), // Instruction 368 |
| |
| I2(Op_MOVE,MBIN8S,MBIN16S,MOVE_MBIN8S_MBIN16S), // Instruction 369 |
| I2(Op_MOVE,MBIN8U,MBIN16U,MOVE_MBIN8U_MBIN16U), // Instruction 370 |
| |
| I2(Op_MOVE,MBIN8U,MBIN16S,MOVE_MBIN8U_MBIN16S), // Instruction 371 |
| I2(Op_MOVE,MBIN8S,MBIN16U,MOVE_MBIN8S_MBIN16U), // Instruction 372 |
| |
| }; |
| |
| #undef I |
| #undef I0 |
| #undef I1 |
| #undef I2 |
| #undef I4 |
| #undef I5 |
| #undef I6 |
| #undef IopCodeNotInUse |
| |
| // Set the position within pCode where an embedded address resides. |
| Int32 *PCode::getEmbeddedAddresses(Int32 opcode, Int32 addr[]) { |
| //static int addr[6]; |
| switch(opcode) { |
| case PCIT::CLAUSE_EVAL: |
| addr[0] = 1; |
| addr[1] = -1; |
| break; |
| |
| case PCIT::CLAUSE_BRANCH: |
| addr[0] = 3; // address of branch clause starts from pcode[3] |
| addr[1] = -1; |
| break; |
| |
| case PCIT::NULL_VIOLATION_MPTR32_MPTR32_IPTR_IPTR: |
| addr[0] = 5; |
| addr[1] = 7; // address of 2nd attributes struct starts from pcode[7] |
| addr[2] = -1; |
| break; |
| |
| case PCIT::NOT_NULL_BRANCH_MBIN32S_MBIN16S_MBIN16S_IBIN32S: |
| addr[0] = 7; |
| addr[1] = 9; // should be pcode[9], but don't know if this opcode is used |
| addr[2] = -1; |
| break; |
| |
| default: |
| addr[0] = -1; |
| break; |
| } |
| return addr; |
| } |
| |
| Int32 PCode::getInstructionLength(PCodeBinary * pcode) { |
| PCodeBinary opcode = pcode[0]; |
| |
| if(opcode < 0 || opcode >= PCIT::LAST_PCODE_INSTR) |
| { |
| char tmpbuf[100]; |
| str_sprintf(tmpbuf, "Invalid opcode: %d\n", opcode); |
| NAAssert(tmpbuf, __FILE__ , __LINE__ ); |
| } |
| |
| if ((opcode == PCIT::HASHCOMB_BULK_MBIN32U) || |
| (opcode == PCIT::NOT_NULL_BRANCH_BULK) || |
| (opcode == PCIT::MOVE_BULK) || |
| (opcode == PCIT::NULL_BITMAP_BULK)) |
| return pcode[1]; |
| |
| Int32 len = opcodeMap[opcode].length; |
| return len; |
| } |
| |
| const char * PCode::getOpcodeString(Int32 opcode) |
| { |
| if(opcode < 0 || opcode >= PCIT::LAST_PCODE_INSTR) |
| { |
| char tmpbuf[100]; |
| str_sprintf(tmpbuf, "Invalid opcode: %d\n", opcode); |
| NAAssert(tmpbuf, __FILE__ , __LINE__ ); |
| } |
| |
| return opcodeMap[opcode].opcodeString; |
| } |
| |
| PCIT::Instruction PCode::getInstruction(PCI *pci) { |
| |
| if (pci->getOperation() == PCIT::Op_TARGET) //Target instructions are just placeholders. |
| return(PCIT::NOP); |
| |
| Int32 shift = 36; |
| Int64 code = pci->getOperation() ; |
| code = code << shift; |
| Int32 i = 0; |
| for(i=0; i<pci->getNumberAddressingModes(); i++) { |
| shift -= 6; |
| code |= ((Int64)pci->getAddressingMode(i)) << shift; |
| } |
| for(i=0; i<PCIT::LAST_PCODE_INSTR; i++) { |
| if(opcodeMap[i].instruction == code) { |
| |
| #ifdef SQLMX_DEBUG_PCIT |
| if (getenv("SQLMX_DEBUG_PCIT")) { |
| cerr << " Instruction " << (PCIT::Instruction)opcodeMap[i].opcode |
| << endl; |
| } |
| #endif |
| return (PCIT::Instruction)opcodeMap[i].opcode; |
| } |
| } |
| #ifdef _DEBUG |
| fprintf(stderr, |
| "ERROR(getInstruction) -- Unknown instruction, opcode = %d\n", |
| pci->getOperation()); |
| #endif // _DEBUG |
| ExpAssert(0, "Unknown PCode Instruction"); |
| |
| return(PCIT::NOP); |
| }; |
| |
| const PCIMap &PCode::getMapEntry (Int32 i) { |
| |
| if ( ((char*)(&opcodeMap[i])) < (((char *)opcodeMap) + sizeof(opcodeMap))) { |
| return opcodeMap[i]; |
| } |
| else { |
| return opcodeMap[PCIT::LAST_PCODE_INSTR - 1]; |
| } |
| } |
| |
| Int32 PCode::getOpCodeMapElements(Int32 opcode, PCIT::Operation &operation, |
| PCIT::AddressingMode am[], Int32 &numAModes ) |
| { |
| if( (opcode == PCIT::END) || (opcode < 0) || (opcode >=PCIT::LAST_PCODE_INSTR)) |
| return 1; |
| |
| Int64 instruction = opcodeMap[opcode].instruction >> |
| ( 36 - (opcodeMap[opcode].numAmodes * 6)); |
| for( Int32 count = opcodeMap[opcode].numAmodes; count > 0; count--) |
| { |
| am[count-1] = |
| (PCIT::AddressingMode)(instruction & OPCODE_MAP_FIRSTSIX_BITS); |
| instruction >>= 6; |
| } |
| operation = (PCIT::Operation)instruction; |
| numAModes = opcodeMap[opcode].numAmodes; |
| return 0; |
| } |
| |
| Int32 PCode::isInstructionRangeType( PCIT::Instruction instruction) |
| { |
| switch(instruction) |
| { |
| case PCIT::RANGE_LOW_S8S64: |
| case PCIT::RANGE_HIGH_S8S64: |
| case PCIT::RANGE_LOW_U8S64: |
| case PCIT::RANGE_HIGH_U8S64: |
| case PCIT::RANGE_LOW_S16S64: |
| case PCIT::RANGE_HIGH_S16S64: |
| case PCIT::RANGE_LOW_U16S64: |
| case PCIT::RANGE_HIGH_U16S64: |
| case PCIT::RANGE_LOW_S32S64: |
| case PCIT::RANGE_HIGH_S32S64: |
| case PCIT::RANGE_LOW_U32S64: |
| case PCIT::RANGE_HIGH_U32S64: |
| case PCIT::RANGE_LOW_S64S64: |
| case PCIT::RANGE_HIGH_S64S64: |
| return 1; |
| default: |
| return 0; |
| }; |
| } |
| |
| Int32 PCode::profileInit() { |
| if(profileCounts_) delete [] profileCounts_; |
| if(profileTimes_) delete [] profileTimes_; |
| profileCounts_ = new Int32[size()+1]; |
| profileTimes_ = new Int32[size()+1]; |
| |
| for(Int32 i=0; i<size()+1; i++) { |
| profileCounts_[i] = 0; |
| profileTimes_[i] = 0; |
| } |
| |
| return 0; |
| } |
| Int32 PCode::profilePrint() { |
| PCIListIter iter(pciList_); |
| |
| if(!profileCounts_) return 0; |
| Int32 pciNum = 0; |
| for(PCI *pci = iter.first(); pci; pci = iter.next()) { |
| if(pci->getOperation() == PCIT::Op_PROFILE) { |
| pci = iter.next(); |
| continue; |
| } |
| pciNum++; |
| } |
| return 0; |
| } |
| //buffer should be 32 bytes |
| void PCIT::operandString(Int32 operand, char* buffer) { |
| // str_sprintf(buffer, "%8.8X", operand); |
| str_sprintf(buffer, "%09d", operand); |
| } |
| |
| void PCode::print(PCIList code) { |
| #ifdef _DEBUG |
| PCIListIter iter(code); |
| for(PCI *pci = iter.first(); pci; pci = iter.next()) { |
| pci->print(); |
| fprintf(stderr, "\n"); |
| } |
| #endif |
| } |
| #ifdef _DEBUG |
| void PCI::print() { |
| char buffer[32]; |
| PCIT::operandString(operation_, buffer); |
| fprintf(stderr, "%p,%3d,%d %s(", |
| this, |
| getCodePosition(), |
| getGeneratedCodeSize(), |
| buffer); |
| if(getNumberAddressingModes() > 0) |
| fprintf(stderr, "%s", |
| PCIT::addressingModeString(getAddressingMode(0))); |
| Int32 i=1; |
| for(; i<getNumberAddressingModes(); i++) |
| fprintf(stderr, ",%s", |
| PCIT::addressingModeString(getAddressingMode(i))); |
| fprintf(stderr, ") "); |
| for(i=0; i<getNumberOperands(); i++) { |
| PCIT::operandString(getOperand(i), buffer); |
| fprintf(stderr, "%s ", buffer); |
| } |
| }; |
| #endif |
| |
| void PCode::displayContents(PCIList code, Space *space) { |
| char buf[256]; |
| char operandBuf[32]; |
| // str_sprintf(buf, " PCode:\n"); |
| |
| PCIListIter iter(code); |
| PCI * pci = iter.first(); |
| |
| while (pci != NULL) { |
| char tbuf[256]; |
| // TODO: Need to check pci casting is correct |
| str_sprintf(buf, " PCI(%09ld)[%3d,%d] %s(", (Int64)pci, pci->getCodePosition(), |
| pci->getGeneratedCodeSize(), |
| PCIT::operationString(pci->getOperation())); |
| |
| if(pci->getNumberAddressingModes() > 0) { |
| str_sprintf(tbuf, "%s", |
| PCIT::addressingModeString(pci->getAddressingMode(0))); |
| str_cat(buf, tbuf, buf); |
| } |
| |
| Int32 i=1; |
| for(; i<pci->getNumberAddressingModes(); i++) { |
| str_sprintf(tbuf, ",%s", |
| PCIT::addressingModeString(pci->getAddressingMode(i))); |
| str_cat(buf, tbuf, buf); |
| } |
| str_cat(buf, ") ", buf); |
| for(i=0; i<pci->getNumberOperands(); i++) { |
| PCIT::operandString(pci->getOperand(i), operandBuf); |
| str_sprintf(tbuf, "%s ", operandBuf); |
| str_cat(buf, tbuf, buf); |
| } |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| pci = iter.next(); |
| } |
| |
| str_sprintf(buf, "\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| }; |
| |
| void PCode::displayContents(PCodeBinary* pCode, Space *space) { |
| char buf[256]; |
| |
| // skip over the ATP's |
| Int32 length = *(pCode++); |
| |
| str_sprintf(buf, "Num ATP/ATPIndex pairs: %d", length); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| for (Int32 i = 0; i < length; i++) |
| { |
| str_sprintf(buf, "Pair #%d: atp = %d, atpindex = %d", |
| i+1, pCode[0], pCode[1]); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| pCode += 2; |
| } |
| |
| while (pCode[0] != PCIT::END) |
| { |
| Int32 opcode = *(pCode++); |
| |
| str_sprintf(buf, " %s ", |
| PCIT::instructionString(PCIT::Instruction(opcode))); |
| |
| Lng32 pcodeLength = PCode::getInstructionLength(pCode-1) - 1; |
| |
| char tbuf[256]; |
| char operandBuf[32]; |
| for (Int32 i=0; i<pcodeLength; i++) |
| { |
| PCIT::operandString(pCode[i], operandBuf); |
| str_sprintf(tbuf, "%s ", operandBuf); |
| str_cat(buf, tbuf, buf); |
| } |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| pCode += pcodeLength; |
| } // while |
| |
| str_sprintf(buf, "\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| |
| Int32 PCode::dumpContents(PCIList code, char * buf, Int32 bufLen) { |
| char operandBuf[32]; |
| Int32 len = 0; |
| |
| PCIListIter iter(code); |
| PCI * pci = iter.first(); |
| |
| buf[0] = 0; |
| while (pci != NULL) { |
| // TODO: Need to check pci casting is correct |
| char tbuf[256]; |
| str_sprintf(tbuf, "PCI(%09ld)[%3d,%d] %s(", (Int64)pci, pci->getCodePosition(), |
| pci->getGeneratedCodeSize(), |
| PCIT::operationString(pci->getOperation())); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| return len - str_len(tbuf); |
| str_cat(buf, tbuf, buf); |
| |
| if(pci->getNumberAddressingModes() > 0) { |
| str_sprintf(tbuf, "%s", |
| PCIT::addressingModeString(pci->getAddressingMode(0))); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| return len - str_len(tbuf); |
| str_cat(buf, tbuf, buf); |
| } |
| |
| Int32 i=1; |
| for(; i<pci->getNumberAddressingModes(); i++) { |
| str_sprintf(tbuf, ",%s", |
| PCIT::addressingModeString(pci->getAddressingMode(i))); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| return len - str_len(tbuf); |
| str_cat(buf, tbuf, buf); |
| } |
| str_cat(buf, ") ", buf); |
| for(i=0; i<pci->getNumberOperands(); i++) { |
| PCIT::operandString(pci->getOperand(i), operandBuf); |
| str_sprintf(tbuf, "%s ", operandBuf); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| return len - str_len(tbuf); |
| str_cat(buf, tbuf, buf); |
| } |
| pci = iter.next(); |
| } |
| |
| buf[len] = '#'; |
| buf[len+1] = 0; |
| return len; |
| }; |
| |
| void PCode::dumpContents(PCodeBinary* pCode, char* buf, Int32 bufLen) { |
| char tbuf[256]; |
| Int32 len = 0; |
| |
| // skip over the ATP's |
| Int32 length = *(pCode++); |
| |
| buf[0] = 0; |
| str_sprintf(tbuf, "Num ATP/ATPIndex pairs: %d", length); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| return; |
| str_cat(buf, tbuf, buf); |
| for (Int32 i = 0; i < length; i++) |
| { |
| str_sprintf(tbuf, "Pair #%d: atp = %d, atpindex = %d", |
| i+1, pCode[0], pCode[1]); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| return; |
| str_cat(buf, tbuf, buf); |
| pCode += 2; |
| } |
| |
| while (pCode[0] != PCIT::END) |
| { |
| Int32 opcode = *(pCode++); |
| |
| str_sprintf(tbuf, " %s ", |
| PCIT::instructionString(PCIT::Instruction(opcode))); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| break; |
| str_cat(buf, tbuf, buf); |
| |
| Lng32 pcodeLength = PCode::getInstructionLength(pCode-1) - 1; |
| |
| char operandBuf[32]; |
| for (Int32 i=0; i<pcodeLength; i++) |
| { |
| PCIT::operandString(pCode[i], operandBuf); |
| str_sprintf(tbuf, "%s ", operandBuf); |
| len += str_len(tbuf); |
| if (len >= bufLen - 2) |
| break; |
| str_cat(buf, tbuf, buf); |
| } |
| pCode += pcodeLength; |
| } // while |
| |
| buf[len] = '#'; |
| buf[len+1] = 0; |
| } |
| |
| PCodeBinary * PCode::generateCodeSegment(Int32 length, |
| Int32 *atpCode, |
| Int32 *atpIndexCode, |
| Int32 *codeSize) { |
| |
| // Generate the code |
| // |
| Int32 pc = 0; |
| |
| PCodeBinary *code = new(space_) PCodeBinary[size() + 1 + (1 + 2 * length)]; |
| *codeSize = sizeof(PCodeBinary) * (size() + 1 + (1 + 2 * length)); |
| |
| code[pc++] = (Int32)length; |
| for(Int32 i=0; i<length; i++) { |
| code[pc++] = atpCode[i]; |
| code[pc++] = atpIndexCode[i]; |
| } |
| PCIListIter iter(pciList_); |
| for(PCI *pci = iter.first(); pci; pci = iter.next()) { |
| if(pci->getOperation() == PCIT::Op_TARGET) |
| continue; |
| code[pc++] = getInstruction(pci); |
| for(Int32 i=0; i<pci->getNumberOperands(); i++) |
| code[pc++] = pci->getOperand(i); |
| } |
| code[pc++] = PCIT::END; |
| |
| return code; |
| } |
| |
| |
| PCIT::AddressingMode PCIT::getMemoryAddressingMode(Int32 datatype) |
| { |
| switch(datatype) |
| { |
| case REC_BIN8_UNSIGNED: return PCIT::MBIN8U; break; |
| case REC_BIN8_SIGNED: return PCIT::MBIN8S; break; |
| |
| case REC_BIN16_UNSIGNED: |
| case REC_BPINT_UNSIGNED: return PCIT::MBIN16U; break; |
| |
| case REC_BIN16_SIGNED: return PCIT::MBIN16S; break; |
| case REC_BIN32_UNSIGNED: return PCIT::MBIN32U; break; |
| case REC_BIN32_SIGNED: return PCIT::MBIN32S; break; |
| case REC_BIN64_UNSIGNED: return PCIT::MBIN64U; break; |
| case REC_BIN64_SIGNED: return PCIT::MBIN64S; break; |
| case REC_IEEE_FLOAT32: return PCIT::MFLT32; break; |
| case REC_IEEE_FLOAT64: return PCIT::MFLT64; break; |
| case REC_DECIMAL_LSE: return PCIT::MDECS; break; |
| case REC_DECIMAL_UNSIGNED: return PCIT::MDECU; break; |
| |
| case REC_BOOLEAN: return PCIT::MASCII; break; |
| case REC_BYTE_F_ASCII: return PCIT::MASCII; break; |
| |
| case REC_BYTE_V_ASCII: return PCIT::MATTR5; break; |
| case REC_NCHAR_F_UNICODE: return PCIT::MUNI; break; |
| case REC_NCHAR_V_UNICODE: return PCIT::MUNIV; break; |
| case REC_NUM_BIG_UNSIGNED: return PCIT::MBIGU; break; |
| case REC_NUM_BIG_SIGNED: return PCIT::MBIGS; break; |
| }; |
| return PCIT::AM_NONE; |
| } |
| |
| Int16 PCIT::getDataTypeForMemoryAddressingMode(PCIT::AddressingMode am) |
| { |
| switch(am) |
| { |
| case PCIT::MBIN8S: return REC_BIN8_SIGNED; break; |
| case PCIT::MBIN8U: return REC_BIN8_UNSIGNED; break; |
| case PCIT::IBIN16U: |
| case PCIT::MBIN16U: return REC_BIN16_UNSIGNED; break; |
| case PCIT::MBIN16S: return REC_BIN16_SIGNED; break; |
| case PCIT::MBIN32U: return REC_BIN32_UNSIGNED; break; |
| case PCIT::IBIN32S: |
| case PCIT::MBIN32S: return REC_BIN32_SIGNED; break; |
| case PCIT::IBIN64S: |
| case PCIT::MBIN64S: return REC_BIN64_SIGNED; break; |
| case PCIT::MBIN64U: return REC_BIN64_UNSIGNED; break; |
| case PCIT::MFLT32: return REC_IEEE_FLOAT32; break; |
| case PCIT::MFLT64: return REC_IEEE_FLOAT64; break; |
| case PCIT::MDECS: return REC_DECIMAL_LSE; break; |
| case PCIT::MDECU: return REC_DECIMAL_UNSIGNED; break; |
| case PCIT::MASCII: return REC_BYTE_F_ASCII; break; |
| case PCIT::MBIGU: return REC_NUM_BIG_UNSIGNED; break; |
| case PCIT::MBIGS: return REC_NUM_BIG_SIGNED; break; |
| }; |
| return -1; |
| } |
| |
| |
| Int32 PCIT::getNumberOperandsForAddressingMode(PCIT::AddressingMode am) |
| { |
| switch(am) |
| { |
| case PCIT::MATTR6: |
| return 7; |
| case PCIT::MUNIV: |
| case PCIT::MATTR5: |
| return 6; |
| case PCIT::MATTR4: |
| return 5; |
| case PCIT::MATTR3: |
| return 4; |
| case PCIT::IATTR4: |
| return 4; |
| case PCIT::IATTR3: |
| return 3; |
| |
| case PCIT::IATTR2: |
| return 2; |
| |
| case PCIT::MBIN8: |
| case PCIT::MBIN8S: |
| case PCIT::MBIN8U: |
| case PCIT::MBIN16U: |
| case PCIT::MBIN16S: |
| case PCIT::MBIN32U: |
| case PCIT::MBIN32S: |
| case PCIT::MBIN64U: |
| case PCIT::MBIN64S: |
| case PCIT::MFLT32: |
| case PCIT::MFLT64: |
| case PCIT::MPTR32: |
| case PCIT::MDECS: |
| case PCIT::MDECU: |
| case PCIT::MASCII: |
| case PCIT::MUNI: |
| case PCIT::MBIGS: |
| case PCIT::MBIGU: |
| return 3; |
| |
| case PCIT::IBIN64S: |
| return 2; |
| |
| case PCIT::IBIN8U: |
| case PCIT::IBIN16U: |
| case PCIT::IBIN32S: |
| return 1; |
| case PCIT::IPTR: |
| return PCODEBINARIES_PER_PTR; |
| }; |
| return 0; |
| } |
| |
| |
| Int32 PCIT::getOperandLengthForAddressingMode(PCIT::AddressingMode am) |
| { |
| switch(am) |
| { |
| case PCIT::MBIGS: |
| case PCIT::MBIGU: |
| case PCIT::MUNI: |
| case PCIT::MUNIV: |
| case PCIT::MATTR6: |
| case PCIT::MATTR5: |
| case PCIT::MATTR4: |
| case PCIT::MATTR3: |
| case PCIT::MPTR32: |
| case PCIT::MASCII: |
| case PCIT::MDECS: |
| case PCIT::MDECU: |
| case PCIT::MBIN8S: |
| case PCIT::MBIN8U: |
| case PCIT::IBIN8U: |
| case PCIT::IATTR4: |
| case PCIT::IATTR3: |
| case PCIT::IATTR2: |
| return 1; |
| case PCIT::MBIN16U: |
| case PCIT::MBIN16S: |
| case PCIT::IBIN16U: |
| return 2; |
| case PCIT::MBIN32U: |
| case PCIT::MBIN32S: |
| case PCIT::MFLT32: |
| case PCIT::IBIN32S: |
| return 4; |
| case PCIT::MBIN64U: |
| case PCIT::MBIN64S: |
| case PCIT::MFLT64: |
| case PCIT::IBIN64S: |
| return 8; |
| case PCIT::IPTR: |
| return sizeof(char*); |
| default : |
| NAAssert("Invalid addressing mode passed to PCIT::getOperandLengthForAddressingMode", __FILE__ , __LINE__ ); |
| return 0; |
| |
| }; |
| } |
| |
| Int32 PCIT::isMemoryAddressingMode(PCIT::AddressingMode am) |
| { |
| switch(am) |
| { |
| case PCIT::MBIN8: |
| case PCIT::MBIN8U: |
| case PCIT::MBIN8S: |
| case PCIT::MBIN16U: |
| case PCIT::MBIN16S: |
| case PCIT::MBIN32U: |
| case PCIT::MBIN32S: |
| case PCIT::MBIN64U: |
| case PCIT::MBIN64S: |
| case PCIT::MFLT32: |
| case PCIT::MFLT64: |
| case PCIT::MPTR32: |
| case PCIT::MDECS: |
| case PCIT::MDECU: |
| case PCIT::MASCII: |
| case PCIT::MBIGS: |
| case PCIT::MBIGU: |
| case PCIT::MATTR3: |
| case PCIT::MATTR4: |
| case PCIT::MATTR5: |
| case PCIT::MATTR6: |
| case PCIT::MUNI: |
| case PCIT::MUNIV: |
| return 1; |
| }; |
| return 0; |
| } |
| |
| const char *PCIT::operationString(PCIT::Operation op) { |
| switch(op) { |
| /* case PCIT::Op_ATP_VCX: return("ATP_VCX"); |
| case PCIT::Op_LEA_ATP: return("LEA_ATP"); |
| case PCIT::Op_LD_ATP: return("LD_ATP"); |
| case PCIT::Op_LD_UNALIGNED_ATP: return("LD_UNALIGNED_ATP"); |
| case PCIT::Op_MV_ATP_N: return("MV_N");*/ |
| case PCIT::Op_OPDATA: return("OPDATA"); |
| |
| case PCIT::Op_MOVE: return("MOVE"); |
| case PCIT::Op_NULL: return("NULL"); |
| case PCIT::Op_NOT_NULL_BRANCH: return("NOT_NULL_BRANCH"); |
| case PCIT::Op_NOT_NULL_BRANCH_COMP: return("NOT_NULL_BRANCH_COMP"); |
| case PCIT::Op_NOT_NULL_BITMAP_BRANCH: return("NOT_NULL_BITMAP_BRANCH"); |
| case PCIT::Op_NULL_BITMAP: return("NULL_BITMAP"); |
| case PCIT::Op_NULL_BYTES: return("NULL_BYTES"); |
| case PCIT::Op_NULL_VIOLATION: return("NULL_VIOLATION"); |
| |
| case PCIT::Op_UPDATE_ROWLEN: return("UPDATE_ROWLEN"); |
| case PCIT::Op_UPDATE_ROWLEN2: return("UPDATE_ROWLEN2"); |
| case PCIT::Op_UPDATE_ROWLEN3: return("UPDATE_ROWLEN3"); |
| |
| case PCIT::Op_EQ: return("EQ"); |
| case PCIT::Op_LT: return("LT"); |
| case PCIT::Op_GT: return("GT"); |
| case PCIT::Op_LE: return("LE"); |
| case PCIT::Op_GE: return("GE"); |
| case PCIT::Op_NE: return("NE"); |
| case PCIT::Op_COMP: return("COMP"); |
| case PCIT::Op_ZERO: return("ZERO"); |
| case PCIT::Op_NOTZERO: return("NOTZERO"); |
| |
| case PCIT::Op_AND: return("AND"); |
| case PCIT::Op_OR: return("OR"); |
| case PCIT::Op_SUM: return("SUM"); |
| case PCIT::Op_MINMAX: return("MINMAX"); |
| case PCIT::Op_ADD: return("ADD"); |
| case PCIT::Op_SUB: return("SUB"); |
| case PCIT::Op_MUL: return("MUL"); |
| case PCIT::Op_DIV: return("DIV"); |
| case PCIT::Op_DIV_ROUND: return("DIV_ROUND"); |
| case PCIT::Op_MOD: return("MOD"); |
| |
| case PCIT::Op_BITOR: return("BITOR"); |
| |
| case PCIT::Op_HASHCOMB: return("HASHCOMB"); |
| |
| case PCIT::Op_ENCODE: return("ENCODE"); |
| case PCIT::Op_DECODE: return("DECODE"); |
| |
| case PCIT::Op_GENFUNC: return("GENFUNC"); |
| case PCIT::Op_HASH: return("HASH"); |
| case PCIT::Op_FILL_MEM_BYTES: return("FILL_MEM_BYTES"); |
| case PCIT::Op_RETURN: return("RETURN"); |
| |
| case PCIT::Op_BRANCH: return("BRANCH"); |
| case PCIT::Op_BRANCH_AND: return("BRANCH_AND"); |
| case PCIT::Op_BRANCH_OR: return("BRANCH_OR"); |
| case PCIT::Op_TARGET: return("TARGET"); |
| case PCIT::Op_RANGE_LOW: return("RANGE_LOW"); |
| case PCIT::Op_RANGE_HIGH: return("RANGE_HIGH"); |
| case PCIT::Op_REPLACE_NULL: return("REPLACE_NULL"); |
| |
| case PCIT::Op_CLAUSE: return("CLAUSE"); |
| case PCIT::Op_CLAUSE_BRANCH: return("CLAUSE_BRANCH"); |
| case PCIT::Op_CLAUSE_EVAL: return("CLAUSE_EVAL"); |
| |
| case PCIT::Op_PROFILE: return("PROFILE"); |
| |
| case PCIT::Op_NOP: return("NOP"); |
| |
| case PCIT::Op_HASH2_DISTRIB: return("HASH2_DISTRIB"); |
| |
| case PCIT::Op_OFFSET: return("OFFSET"); |
| |
| case PCIT::Op_HDR: return("HEADER"); |
| |
| case PCIT::Op_COPYVARROW: return("COPYVARROW"); |
| |
| case PCIT::Op_CONV_VC_PTR: return("CONV_VC_PTR"); |
| |
| case PCIT::Op_END: return("END"); |
| default: return("UNKNOWN OPERATION"); |
| } |
| } |
| |
| const char *PCIT::addressingModeString(PCIT::AddressingMode am) { |
| switch(am) { |
| case PCIT::MBIN8: return("MBIN8"); |
| case PCIT::MBIN8S: return("MBIN8S"); |
| case PCIT::MBIN8U: return("MBIN8U"); |
| case PCIT::MBIN16U: return("MBIN16U"); |
| case PCIT::MBIN16S: return("MBIN16S"); |
| case PCIT::MBIN32U: return("MBIN32U"); |
| case PCIT::MBIN32S: return("MBIN32S"); |
| case PCIT::MBIN64U: return("MBIN64U"); |
| case PCIT::MBIN64S: return("MBIN64S"); |
| case PCIT::MFLT32: return("MFLT32"); |
| case PCIT::MFLT64: return("MFLT64"); |
| case PCIT::MPTR32: return("MPTR32"); |
| case PCIT::MDECS: return("MDECS"); |
| case PCIT::MDECU: return("MDECU"); |
| case PCIT::MASCII: return("MASCII"); |
| case PCIT::MBIGS: return("MBIGS"); |
| case PCIT::MBIGU: return("MBIGU"); |
| |
| case PCIT::IBIN8U: return("IBIN8U"); |
| case PCIT::IBIN16U: return("IBIN16U"); |
| case PCIT::IBIN64S: return("IBIN64S"); |
| case PCIT::IBIN32S: return("IBIN32S"); |
| case PCIT::IATTR4: return("IATTR4"); |
| case PCIT::IATTR3: return("IATTR3"); |
| case PCIT::IATTR2: return("IATTR2"); |
| |
| case PCIT::MATTR3: return("MATTR3"); |
| case PCIT::MATTR4: return("MATTR4"); |
| case PCIT::MATTR5: return("MATTR5"); |
| case PCIT::MATTR6: return("MATTR6"); |
| |
| case PCIT::MUNI: return("MUNI"); |
| case PCIT::MUNIV: return("MUNIV"); |
| |
| case PCIT::IPTR: return("IPTR"); |
| |
| default: return("UNKNOWN ADDRESSING MODE"); |
| } |
| }; |
| |
| |
| char *PCIT::instructionString(PCIT::Instruction instr) { |
| return (char *)PCode::getOpcodeString(instr); |
| } |
| Int32 PCI::getGeneratedCodeSize() { |
| switch(getOperation()) { |
| case PCIT::Op_TARGET: |
| return 0; |
| break; |
| } |
| |
| return 1 + getNumberOperands(); |
| } |
| |
| Int32 PCI::getMemoryOperandLength(PCIT::AddressingMode am, Int32 op) |
| { |
| switch(PCode::getInstruction(this)) { |
| case PCIT::OPDATA_MPTR32_IBIN32S: |
| return 0; |
| case PCIT::HASH_MBIN32U_MPTR32_IBIN32S_IBIN32S: |
| if (am == PCIT::MBIN32U) |
| return 4; |
| if (am == PCIT::MPTR32) |
| return getOperand(7); |
| return 0; |
| case PCIT::ENCODE_MASCII_MBIN8S_IBIN32S: |
| case PCIT::ENCODE_MASCII_MBIN8U_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN8S_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN8U_IBIN32S: |
| return 1; |
| case PCIT::ENCODE_MASCII_MBIN16S_IBIN32S: |
| case PCIT::ENCODE_MASCII_MBIN16U_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN16S_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN16U_IBIN32S: |
| return 2; |
| case PCIT::ENCODE_MASCII_MBIN32S_IBIN32S: |
| case PCIT::ENCODE_MASCII_MBIN32U_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN32S_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN32U_IBIN32S: |
| return 4; |
| case PCIT::ENCODE_MASCII_MBIN64S_IBIN32S: |
| case PCIT::DECODE_MASCII_MBIN64S_IBIN32S: |
| return 8; |
| case PCIT::FILL_MEM_BYTES: |
| return getOperand(getNumberOperands()-2); |
| default: |
| if (am == PCIT::MBIN8) { |
| // Some PCI instructions have multiple MBIN8 operands with potentially |
| // different lengths, and so it's important to associate the right |
| // operand with the right length. From what I can tell, however, |
| // CONCAT is the only one. |
| if ((getOperation() == PCIT::Op_GENFUNC) && |
| (getOperand(0) == ITM_CONCAT) && (op == 4)) { |
| |
| // Length of 1st operand is second to last PCI operand |
| return getOperand(getNumberOperands()-2); |
| } |
| |
| // Otherwise the length should be the last one. |
| return getOperand(getNumberOperands()-1); |
| } |
| else if ((am == PCIT::MBIGU) || (am == PCIT::MBIGS)) { |
| return getOperand(getNumberOperands()-1); |
| } |
| return PCIT::getOperandLengthForAddressingMode(am); |
| } |
| } |
| |
| // Load the target null bitmap address so it can be set if needed. |
| PCIList PCode::loadOpDataNullBitmapAddress(Attributes *attr, |
| Int32 loc, |
| CollHeap *heap) |
| { |
| return loadOpDataAddress(attr, attr->getNullIndOffset(), loc, heap); |
| } |
| |
| PCIList PCode::loadOpDataNullAddress(Attributes *attr, Int32 loc, CollHeap *heap) |
| { |
| return loadOpDataAddress(attr, attr->getNullIndOffset(), loc, heap); |
| } |
| |
| PCIList PCode::loadOpDataVCAddress(Attributes *attr, Int32 loc, CollHeap *heap) |
| { |
| if(attr->isIndirectVC()) |
| { |
| // For indirect varchars, use the OPDATA_MATTR5_IBIN32 instruction. |
| // This will set both the vclen pointer and the data pointer in the |
| // op_data array. |
| UInt32 comboLen = 0; |
| char* comboPtr = (char*)&comboLen; |
| |
| // Use combo fields for specifying vc/null lengths |
| comboPtr[0] = (char)attr->getNullIndicatorLength(); |
| comboPtr[1] = (char)attr->getVCIndicatorLength(); |
| |
| PCIList pciList(heap); |
| AML aml(PCIT::MATTR5, PCIT::IBIN32S); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), attr->getOffset(), |
| attr->getVoaOffset(), attr->getLength(), comboLen, |
| ex_clause::MAX_OPERANDS + loc); |
| PCI pci(PCIT::Op_OPDATA, aml, ol); |
| pciList.append(pci); |
| return pciList; |
| } |
| else |
| { |
| return loadOpDataAddress(attr, attr->getVCLenIndOffset(), |
| ex_clause::MAX_OPERANDS + loc, heap); |
| } |
| } |
| |
| PCIList PCode::loadOpDataDataAddress(Attributes *attr, Int32 loc, CollHeap *heap) |
| { |
| return loadOpDataAddress(attr, (Int32)attr->getOffset(), |
| 2 * ex_clause::MAX_OPERANDS + loc, heap); |
| } |
| |
| PCIList PCode::loadOpDataAddress(Attributes *attr, Int32 offset, Int32 loc, |
| CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| AML aml(PCIT::MPTR32, PCIT::IBIN32S); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), offset, loc); |
| PCI pci(PCIT::Op_OPDATA, aml, ol); |
| pciList.append(pci); |
| return pciList; |
| } |
| |
| PCIList PCode::loadOpDataNullBitmap(Attributes *attr, Int32 loc, CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| AML aml(PCIT::MPTR32, PCIT::IBIN32S, PCIT::IBIN32S); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), attr->getNullIndOffset(), |
| attr->getNullBitIndex(), loc); |
| PCI pci(PCIT::Op_OPDATA, aml, ol); |
| pciList.append(pci); |
| return pciList; |
| } |
| |
| PCIList PCode::loadOpDataNull(Attributes *attr, Int32 loc, CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| AML aml(PCIT::MBIN16U, PCIT::IBIN32S); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), attr->getNullIndOffset(), loc); |
| PCI pci(PCIT::Op_OPDATA, aml, ol); |
| pciList.append(pci); |
| return pciList; |
| } |
| |
| PCIList PCode::storeValue(Int32 value, Attributes *attr, CollHeap *heap) |
| { |
| return storeValue(value, attr, attr->getOffset(), heap); |
| } |
| |
| PCIList PCode::storeValue(Int32 value, Attributes *attr, UInt32 offset, |
| CollHeap *heap) |
| { |
| if ( attr->isSQLMXAlignedFormat() ) |
| return( storeShortValue( (Int32) value, attr, offset, heap ) ); |
| |
| PCIList pciList(heap); |
| |
| AML aml(PCIT::MBIN32S, PCIT::IBIN32S); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), (Int32)offset, value); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| pciList.append(pci); |
| return pciList; |
| } |
| |
| PCIList PCode::storeShortValue(UInt32 value, |
| Attributes *attr, |
| UInt32 offset, |
| CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| |
| AML aml(PCIT::MBIN16U, PCIT::IBIN16U); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), (Int32)offset, (Int16)value); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| pciList.append(pci); |
| return pciList; |
| } |
| |
| PCIList PCode::storeShortVoa(Attributes *attr, CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| |
| // The voaOffset data member is only set for both of the SQL/MX disk |
| // formats for the first fixed field and all variable length fields. |
| // Other data formats have the voaOffset initialized to ExpOffsetMax. |
| if ((attr->isSQLMXDiskFormat() && |
| (attr->getVoaOffset() != ExpOffsetMax) && |
| (attr->getOffset() != ExpOffsetMax))) |
| { |
| pciList.append(storeShortValue( |
| attr->getOffset() - attr->getVCIndicatorLength(), |
| attr, |
| attr->getVoaOffset(), |
| heap |
| )); |
| } |
| return pciList; |
| } |
| |
| PCIList PCode::storeVoa(Attributes *attr, CollHeap *heap) |
| { |
| // The voaOffset data member is only set for SQLMX and SQLMX_ALIGNED format. |
| // Other data formats have the voaOffset initialized to ExpOffsetMax. |
| // The voa offset is 0 for the first fixed field offset and this is handled |
| // by a separate clause now ExHeaderClause. |
| if ( (attr->getVoaOffset() > 0) && |
| (attr->getVoaOffset() != ExpOffsetMax) && |
| (attr->getOffset() != ExpOffsetMax) && |
| attr->isSQLMXDiskFormat() ) |
| { |
| if ( attr->isSQLMXAlignedFormat() ) |
| return( storeShortVoa( attr, heap ) ); |
| else |
| return storeVoaValue(attr, |
| attr->getVoaOffset(), |
| (attr->getOffset() - |
| attr->getVCIndicatorLength() - |
| attr->getNullIndicatorLength()), |
| heap); |
| } |
| |
| PCIList pciList(heap); |
| |
| return pciList; |
| } |
| |
| PCIList PCode::storeVoaValue(Attributes *attr, UInt32 offset, |
| UInt32 value, CollHeap *heap, |
| short varOnly) { |
| PCIList pciList(heap); |
| |
| if (attr->isSQLMXDiskFormat() && |
| (!varOnly || (varOnly && (attr->getVCIndicatorLength() > 0)))) |
| { |
| pciList.append(PCode::storeValue(value, attr, (Int32)offset, heap)); |
| } |
| return pciList; |
| } |
| |
| PCIList PCode::updateRowLen(Attributes *attr, CollHeap *heap, UInt32 flags) |
| { |
| PCIList pciList(heap); |
| |
| if (attr->getVCIndicatorLength() > 0 && |
| attr->isSQLMXDiskFormat()) |
| { |
| UInt32 comboLen1 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| comboPtr1[0] = (char)attr->getNullIndicatorLength(), |
| comboPtr1[1] = (char)attr->getVCIndicatorLength(); |
| |
| UInt32 alignment = (attr->isSQLMXAlignedFormat() && |
| (attr->getNextFieldIndex() == ExpOffsetMax)) |
| ? ExpAlignedFormat::ALIGNMENT : 0; |
| |
| // Use a length of -1 to indicate that this instruction in effect |
| // operates on the whole row. If the attr length is used, then we |
| // are subject to copy propagation and other pcode optimizations. |
| // If this happens then we might end up computing the rowlen for some |
| // other tuple that might not even be a row in Aligned Format. |
| AML aml(PCIT::MATTR5, PCIT::IBIN32S); |
| OL ol(attr->getAtp(), attr->getAtpIndex(), (Int32)attr->getOffset(), |
| (Int32)attr->getVoaOffset(), -1, comboLen1, |
| alignment); |
| |
| PCI pci(PCIT::Op_UPDATE_ROWLEN3, aml, ol); |
| pciList.append(pci); |
| } |
| |
| return pciList; |
| } |
| |
| // Move fixed source to fixed destination. |
| PCIList PCode::moveValue(Attributes *dst, Attributes *src, CollHeap *heap) |
| { |
| if (dst->getLength() == src->getLength()) |
| { |
| PCIList code(heap); |
| |
| AML aml(PCIT::MBIN8,PCIT::MBIN8,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)dst->getLength()); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| code.append(pci); |
| |
| return code; |
| } |
| else |
| { |
| PCIList code(heap); |
| |
| AML aml(PCIT::getMemoryAddressingMode(dst->getDatatype()), |
| PCIT::getMemoryAddressingMode(src->getDatatype()), |
| PCIT::IBIN32S,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)dst->getLength(), |
| (Int32)src->getLength()); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| code.append(pci); |
| |
| return code; |
| } |
| } |
| |
| PCIList PCode::copyVarRow(Attributes *dst, |
| Attributes *src, |
| UInt32 lastVOAoffset, |
| Int16 lastVcIndicatorLength, |
| Int16 lastNullIndicatorLength, |
| Int16 alignment, |
| CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| if (lastVOAoffset > 0 && lastVcIndicatorLength > 0 ) |
| { |
| UInt32 comboLen1 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| comboPtr1[0] = (char)lastNullIndicatorLength, |
| comboPtr1[1] = (char)lastVcIndicatorLength; |
| |
| AML aml(PCIT::MBIN8, PCIT::MBIN8, PCIT::IBIN32S, PCIT::IBIN32S, PCIT::IBIN32S,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)lastVOAoffset, |
| (Int32)comboLen1, |
| (Int32)alignment, |
| (Int32) ((SimpleType*)src)->getLength()); |
| |
| PCI pci(PCIT::Op_COPYVARROW, aml, ol); |
| pciList.append(pci); |
| } |
| return pciList; |
| } |
| // Move varchar source to varchar destination. |
| // source or destination can be "indirect" |
| // For disk format, it handles setting the VOA in the target. |
| PCIList PCode::moveVarcharValue(Attributes *dst, |
| Attributes *src, |
| CollHeap *heap) |
| { |
| PCIList code(heap); |
| |
| // Handles all varchar's in disk format - ones with a fixed offset and |
| // "indirect" varchar's where the offset must be read from the VOA. |
| // Handles setting the VOA in the target for the varchar being moved too. |
| |
| UInt32 comboLen1 = 0; |
| UInt32 comboLen2 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| char* comboPtr2 = (char*)&comboLen2; |
| |
| // Use combo fields for specifying vc/null lengths of both operands |
| comboPtr1[0] = (char)dst->getNullIndicatorLength(), |
| comboPtr1[1] = (char)dst->getVCIndicatorLength(); |
| comboPtr2[0] = (char)src->getNullIndicatorLength(), |
| comboPtr2[1] = (char)src->getVCIndicatorLength(); |
| |
| AML aml(PCIT::MATTR5,PCIT::MATTR5); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), dst->getOffset(), |
| dst->getVoaOffset(), dst->getLength(), comboLen1, |
| src->getAtp(), src->getAtpIndex(), src->getOffset(), |
| src->getVoaOffset(), src->getLength(), comboLen2); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| code.append(pci); |
| |
| return code; |
| } |
| |
| // Move varchar source to fixed destination. |
| // source or destination can be "indirect" |
| // For disk format, it handles setting the VOA in the target. |
| PCIList PCode::moveVarcharFixedValue(Attributes *dst, |
| Attributes *src, |
| CollHeap *heap) |
| { |
| PCIList code(heap); |
| |
| UInt32 comboLen1 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| |
| // Use combo fields for specifying vc/null lengths of both operands |
| comboPtr1[0] = (char)src->getNullIndicatorLength(), |
| comboPtr1[1] = (char)src->getVCIndicatorLength(); |
| |
| AML aml(PCIT::MASCII,PCIT::MATTR5,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)src->getVoaOffset(), src->getLength(), comboLen1, |
| (Int32)dst->getLength()); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| code.append(pci); |
| |
| return code; |
| } |
| |
| // Move fixed source to varchar destination. |
| // source or destination can be "indirect" |
| // For disk format, it handles setting the VOA in the target. |
| PCIList PCode::moveFixedVarcharValue(Attributes *dst, |
| Attributes *src, |
| CollHeap *heap) |
| { |
| PCIList code(heap); |
| |
| UInt32 comboLen1 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| |
| // Use combo fields for specifying vc/null lengths of both operands |
| comboPtr1[0] = (char)dst->getNullIndicatorLength(); |
| comboPtr1[1] = (char)dst->getVCIndicatorLength(); |
| |
| AML aml(PCIT::MATTR5,PCIT::MASCII,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| (Int32)dst->getVoaOffset(), (Int32)dst->getLength(), comboLen1, |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)src->getLength()); |
| PCI pci(PCIT::Op_MOVE, aml, ol); |
| code.append(pci); |
| |
| return code; |
| } |
| |
| // Convert varchar ptr source to destination. |
| // source is a varchar ptr. |
| PCIList PCode::convertVarcharPtrToTarget(Attributes *dst, |
| Attributes *src, |
| CollHeap *heap) |
| { |
| PCIList code(heap); |
| |
| UInt32 comboLen1 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| UInt32 comboLen2 = 0; |
| char* comboPtr2 = (char*)&comboLen2; |
| |
| // Use combo fields for specifying vc/null lengths of both operands |
| comboPtr1[0] = (char)src->getNullIndicatorLength(), |
| comboPtr1[1] = (char)src->getVCIndicatorLength(); |
| if (dst->getDatatype() == REC_BYTE_V_ASCII) |
| { |
| comboPtr2[0] = (char)dst->getNullIndicatorLength(); |
| comboPtr2[1] = (char)dst->getVCIndicatorLength(); |
| } |
| |
| if (dst->getDatatype() == REC_FLOAT32) |
| { |
| AML aml(PCIT::MFLT32,PCIT::MATTR5,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)src->getVoaOffset(), src->getLength(), comboLen1, |
| (Int32)dst->getLength()); |
| PCI pci(PCIT::Op_CONV_VC_PTR, aml, ol); |
| code.append(pci); |
| } |
| else if (dst->getDatatype() == REC_BIN32_SIGNED) |
| { |
| AML aml(PCIT::MBIN32S,PCIT::MATTR5,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)src->getVoaOffset(), src->getLength(), comboLen1, |
| (Int32)dst->getLength()); |
| PCI pci(PCIT::Op_CONV_VC_PTR, aml, ol); |
| code.append(pci); |
| } |
| else if (dst->getDatatype() == REC_BIN64_SIGNED) |
| { |
| AML aml(PCIT::MBIN64S,PCIT::MATTR5,PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| src->getAtp(), src->getAtpIndex(), (Int32)src->getOffset(), |
| (Int32)src->getVoaOffset(), src->getLength(), comboLen1, |
| (Int32)dst->getLength()); |
| PCI pci(PCIT::Op_CONV_VC_PTR, aml, ol); |
| code.append(pci); |
| } |
| else if (dst->getDatatype() == REC_BYTE_V_ASCII) |
| { |
| AML aml(PCIT::MATTR5,PCIT::MATTR5); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), dst->getOffset(), |
| dst->getVoaOffset(), dst->getLength(), comboLen2, |
| src->getAtp(), src->getAtpIndex(), src->getOffset(), |
| src->getVoaOffset(), src->getLength(), comboLen1); |
| PCI pci(PCIT::Op_CONV_VC_PTR, aml, ol); |
| code.append(pci); |
| } |
| |
| return code; |
| } |
| |
| // notNullBranch, when specified, indicates a (previous) code location of |
| // a branch instruction that wants to skip this code (in case |
| // the value is not NULL). nulBranch is the code location of the final |
| // branch that gets generated here to take after the zero fill is done. |
| // |
| PCIID PCode::generateJumpAndBranch(Attributes *dst, |
| PCIList& code, |
| PCIID notNullBranch, |
| Int32 genUncondJump) |
| { |
| PCIID nulBranch = 0; |
| |
| // generate an unconditional jump over the code that handles the |
| // not-NULL case |
| if (genUncondJump) |
| { |
| AML aml(PCIT::IBIN32S); |
| OL ol((PCIType::Operand)0); |
| PCI pci(PCIT::Op_BRANCH, aml, ol); |
| code.append(pci); |
| nulBranch = code.getTailId(); |
| } |
| |
| // jump target for the case that we move a non-NULL value |
| if (notNullBranch) |
| { |
| AML aml; |
| OL ol((Int64) notNullBranch); |
| PCI pci(PCIT::Op_TARGET, aml, ol); |
| code.append(pci); |
| } |
| |
| return nulBranch; |
| } |
| |
| // Adds code to zero-fill the data portion of a NULL value. |
| // notNullBranch, when specified, indicates a (previous) code location of |
| // a branch instruction that wants to skip this code (in case |
| // the value is not NULL). nulBranch is the code location of the final |
| // branch that gets generated here to take after the zero fill is done. |
| // |
| PCIID PCode::zeroFillNullValue(Attributes *dst, |
| PCIList& code, |
| PCIID notNullBranch, |
| Int32 genUncondJump) |
| { |
| PCIID nulBranch = 0; |
| |
| // Zero fill the destination. |
| |
| // If the destination is a variable length field, then do this separately. |
| // The voa offset will be written here too rather than generate a separate |
| // PCI to do this. |
| if (dst->isVariableLength()) |
| { |
| UInt32 comboLen1 = 0; |
| char* comboPtr1 = (char*)&comboLen1; |
| comboPtr1[0] = (char)dst->getNullIndicatorLength(), |
| comboPtr1[1] = (char)dst->getVCIndicatorLength(); |
| |
| UInt32 len; |
| // if going to disk format, clearing vcIndLen is sufficient |
| if (dst->isSQLMXDiskFormat() || |
| dst->isTrafodionDiskFormat()) |
| len = 0; |
| else |
| len = dst->getLength(); |
| |
| AML aml(PCIT::MATTR5, PCIT::IBIN32S, PCIT::IBIN32S); |
| OL ol(dst->getAtp(), dst->getAtpIndex(), (Int32)dst->getOffset(), |
| (Int32)dst->getVoaOffset(), dst->getLength(), comboLen1, |
| len, 0); |
| |
| PCI pci(PCIT::Op_FILL_MEM_BYTES, aml, ol); |
| |
| code.append(pci); |
| } |
| else |
| { |
| // For fixed fields, there could be padding before the data offset but |
| // not needed in the calculation here. |
| AML aml(PCIT::MASCII, PCIT::IBIN32S, PCIT::IBIN8U); |
| OL ol(dst->getAtp(), dst->getAtpIndex(),dst->getOffset(),dst->getLength(),0); |
| PCI pci(PCIT::Op_FILL_MEM_BYTES, aml, ol); |
| code.append(pci); |
| } |
| |
| nulBranch = generateJumpAndBranch(dst, code, notNullBranch, genUncondJump); |
| |
| |
| return nulBranch; |
| } |
| |
| PCIList PCode::isNull(Attributes *attrDst, |
| Attributes *attrSrc, |
| CollHeap* heap) |
| { |
| PCIList pciList(heap); |
| |
| // For aligned format the source nullness can be checked directly using |
| // the null bit index for the source operand. |
| // For exploded format or packed format the voa offset must be retrieved |
| // to get to the start of the field and then the 2 bytes of nullness can |
| // be checked there. |
| Int32 flag = ((attrSrc->isIndirectVC() && !attrSrc->isSQLMXAlignedFormat()) |
| ? 1 : 0); |
| |
| AML aml(PCIT::MBIN32S, PCIT::MATTR5, PCIT::IBIN32S, PCIT::IBIN32S); |
| OL ol(attrDst->getAtp(), attrDst->getAtpIndex(), (Int32)attrDst->getOffset(), |
| attrSrc->getAtp(), attrSrc->getAtpIndex(), |
| (Int32)attrSrc->getNullIndOffset(), attrSrc->getVoaOffset(), |
| attrSrc->getTupleFormat(), attrSrc->getNullBitIndex(), |
| flag, -1); |
| PCI pci(PCIT::Op_NULL, aml, ol); |
| pciList.append(pci); |
| |
| return pciList; |
| } |
| |
| PCIList PCode::isNotNull(Attributes *attrDst, |
| Attributes *attrSrc, |
| CollHeap *heap) |
| { |
| PCIList pciList(heap); |
| |
| |
| // For aligned format the source nullness can be checked directly using |
| // the null bit index for the source operand. |
| // For exploded format or packed format the voa offset must be retrieved |
| // to get to the start of the field and then the 2 bytes of nullness can |
| // be checked there. |
| Int32 flag = ((attrSrc->isIndirectVC() && !attrSrc->isSQLMXAlignedFormat()) |
| ? 1 : 0); |
| |
| AML aml(PCIT::MBIN32S, PCIT::MATTR5, PCIT::IBIN32S, PCIT::IBIN32S); |
| OL ol(attrDst->getAtp(), attrDst->getAtpIndex(), (Int32)attrDst->getOffset(), |
| attrSrc->getAtp(), attrSrc->getAtpIndex(), |
| (Int32)attrSrc->getNullIndOffset(), attrSrc->getVoaOffset(), |
| attrSrc->getTupleFormat(), attrSrc->getNullBitIndex(), |
| flag, 0); |
| PCI pci(PCIT::Op_NULL, aml, ol); |
| pciList.append(pci); |
| |
| return pciList; |
| } |
| |
| // Generate PCI's necessary before clause execution. Currently, this |
| // only covers TARGET PCI's that need to be generated because of |
| // branch clauses. |
| // |
| void PCode::preClausePCI(ex_clause *clause, PCIList& code) { |
| |
| // If this clause is a target of a branch clause, then insert a |
| // TARGET PCI for each branch clause that targets this clause. |
| // Use this clause's address as the target operand for now. This |
| // will be fixed up in expr::pCodeGenerate() by matching BRANCH-TARGET |
| // pairs which have the same operand. |
| // |
| if(clause->isBranchTarget()) { |
| for(Int32 i=0; i<clause->getNumberBranchTargets(); i++) |
| { |
| AML aml; |
| OL ol((Int64) clause); |
| PCI pci(PCIT::Op_TARGET, aml, ol); |
| code.append(pci); |
| } |
| } |
| } |
| |
| // Generate PCI's necessary after clause execution. |
| // |
| void PCode::postClausePCI(ex_clause *clause, PCIList& code) { |
| } |
| |
| |
| PCIID PCode::nullBranchHelper(AttributesPtr *attrs, |
| Attributes *attrA, |
| Attributes *attrB, |
| PCIList& code) { |
| |
| PCIID nulBranch = 0; |
| Attributes *tgt = attrs[0]; |
| |
| // If there are two nullable inputs... |
| // |
| if(attrB) |
| { |
| // If the output is nullable, add the NULL branch instructions, |
| // |
| |
| if(tgt->getNullFlag()) |
| { |
| PCodeTupleFormats tpf(tgt->getTupleFormat(), |
| attrA->getTupleFormat(), |
| attrB->getTupleFormat()); |
| |
| Int32 tgtNullIndOff = tgt->getNullIndOffset(); |
| Int32 attrANullIndOff = attrA->getNullIndOffset(); |
| Int32 attrBNullIndOff = attrB->getNullIndOffset(); |
| |
| // For source operands: |
| // For indirect varchars in packed format use the negated voa offset. |
| // Then at runtime the code knows to get the offset value out of the |
| // voa entry and jump to the actual value to test the nullness of the |
| // field. |
| // For aligned format the null indicator offset is used since the |
| // null bitmap is statically known. |
| // For exploded format the varchar field offset is known at compile |
| // time and the attribute is not marked as 'indirect'. |
| if (attrA->isIndirectVC() && !attrA->isSQLMXAlignedFormat()) |
| attrANullIndOff = -( (Int32)attrA->getVoaOffset() ); |
| if (attrB->isIndirectVC() && !attrB->isSQLMXAlignedFormat()) |
| attrBNullIndOff = -( (Int32)attrB->getVoaOffset() ); |
| |
| // For target operand, a negative NullIndOffset indicates that |
| // it is an indirect varchar in packed format. In this case, the runtime |
| // will use the loop variable varOffset. All other formats will |
| // have valid NullIndOffset. |
| |
| // If either of the input args are null, then output is null. |
| AML aml(PCIT::MBIN32S,PCIT::MBIN32S,PCIT::MBIN32S,PCIT::IATTR4,PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgtNullIndOff, |
| attrA->getAtp(), attrA->getAtpIndex(), attrANullIndOff, |
| attrB->getAtp(), attrB->getAtpIndex(), attrBNullIndOff, |
| EXPAND_PCODEATTRNULL3(*(UInt32 *)&tpf, tgt, attrA, attrB), |
| 0); |
| |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH, aml, ol); |
| code.append(pci); |
| |
| nulBranch = zeroFillNullValue(tgt, code, code.getTailId()); |
| } |
| // |
| // Otherwise do a null violation check. |
| // |
| else |
| { |
| if( attrA->isSQLMXAlignedFormat() || attrB->isSQLMXAlignedFormat() ) |
| { |
| AML aml(PCIT::MPTR32,PCIT::MPTR32,PCIT::IPTR,PCIT::IPTR); |
| OL ol(attrA->getAtp(), attrA->getAtpIndex(), |
| attrA->getNullIndOffset(), |
| attrB->getAtp(), attrB->getAtpIndex(), |
| attrB->getNullIndOffset(), |
| (Int64)attrA, (Int64)attrB |
| ); |
| PCI pci(PCIT::Op_NULL_VIOLATION, aml, ol); |
| code.append(pci); |
| } |
| else |
| { |
| AML aml(PCIT::MBIN16U, PCIT::MBIN16U); |
| OL ol(attrA->getAtp(), attrA->getAtpIndex(), |
| attrA->getNullIndOffset(), |
| attrB->getAtp(), attrB->getAtpIndex(), |
| attrB->getNullIndOffset()); |
| PCI pci(PCIT::Op_NULL_VIOLATION, aml, ol); |
| code.append(pci); |
| } |
| } |
| } |
| // |
| // Otherwise, if there is only one nullable input... |
| // |
| else if(attrA) |
| { |
| // If the output is nullable, add the NULL branch instruction |
| // |
| if(tgt->getNullFlag()) |
| { |
| PCodeTupleFormats tpf(tgt->getTupleFormat(), |
| attrA->getTupleFormat()); |
| |
| Int32 tgtNullIndOff = tgt->getNullIndOffset(); |
| Int32 attrANullIndOff = attrA->getNullIndOffset(); |
| |
| // For indirect varchars in packed format use the negated voa offset. |
| // Then at runtime the code knows to get the offset value out of the |
| // voa entry and jump to the actual value to test the nullness of the |
| // field. |
| // For aligned format the null indicator offset is used since the |
| // null bitmap is statically known. |
| // For exploded format the varchar field offset is known at compile |
| // time and the attribute is not marked as 'indirect'. |
| if (attrA->isIndirectVC() && !attrA->isSQLMXAlignedFormat()) |
| attrANullIndOff = -( (Int32)attrA->getVoaOffset() ); |
| |
| // If the input arg is null, then output is null. |
| AML aml(PCIT::MBIN32S,PCIT::MBIN32S,PCIT::IATTR3,PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgtNullIndOff, |
| attrA->getAtp(), attrA->getAtpIndex(), attrANullIndOff, |
| EXPAND_PCODEATTRNULL2(*(UInt32 *)&tpf, tgt, attrA), |
| 0); |
| |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH, aml, ol); |
| code.append(pci); |
| |
| nulBranch = zeroFillNullValue(tgt, code, code.getTailId()); |
| } |
| // |
| // otherwise do a null violation check. |
| // |
| else |
| { |
| if( attrA->isSQLMXAlignedFormat() ) |
| { |
| AML aml(PCIT::MPTR32,PCIT::MPTR32,PCIT::IPTR,PCIT::IPTR); |
| OL ol(attrA->getAtp(),attrA->getAtpIndex(),attrA->getNullIndOffset(), |
| attrA->getAtp(),attrA->getAtpIndex(),attrA->getNullIndOffset(), |
| (Int64)attrA, |
| (Int64)0 |
| ); |
| PCI pci(PCIT::Op_NULL_VIOLATION, aml, ol); |
| code.append(pci); |
| } |
| else |
| { |
| AML aml(PCIT::MBIN16U); |
| OL ol(attrA->getAtp(), attrA->getAtpIndex(), |
| attrA->getNullIndOffset()); |
| PCI pci(PCIT::Op_NULL_VIOLATION, aml, ol); |
| code.append(pci); |
| } |
| } |
| } |
| |
| return nulBranch; |
| } |
| |
| PCIID PCode::nullBranchHelperForComp(AttributesPtr *attrs, |
| Attributes *attrA, |
| Attributes *attrB, |
| NABoolean isSpecialNulls, |
| PCIList & code) { |
| |
| PCIID nulBranch = 0; |
| Attributes *tgt = attrs[0]; |
| |
| if (isSpecialNulls) |
| { |
| PCIID id; |
| |
| // Support the case where 1 or both operands are nullable |
| // and this is an equi predicate. |
| // This check was done when pcode was generated. |
| |
| // |
| // If only one operand is nullable, then the result is 0 (because we're |
| // only dealing with ITM_EQUAL right now). Generate a null branch |
| // check, and then fall-through to a move of 0 into the result. |
| // |
| if(!attrs[1]->getNullFlag() || !attrs[2]->getNullFlag()) |
| { |
| // |
| // Currently there is no NOT_NULL_BRANCH instruction that supports the |
| // aligned row format which simply checks for NULL in the source operand |
| // without setting a tgt/result. Rather than create a new instruction |
| // at this time |
| // , use an existing NOT_NULL_BRANCH instruction that will be |
| // slightly less efficient. |
| // |
| |
| // First add NOT_NULL_BRANCH |
| Attributes* src = (attrs[1]->getNullFlag() ? attrs[1] : attrs[2]); |
| |
| PCodeTupleFormats tpf(tgt->getTupleFormat(), src->getTupleFormat()); |
| Int32 srcNullIndOff = src->getNullIndOffset(); |
| |
| // for indirect varchars, use the negated voaOffset. |
| if (src->isIndirectVC() && !src->isSQLMXAlignedFormat()) |
| srcNullIndOff = -( (Int32)src->getVoaOffset() ); |
| |
| // If the input arg is null, then output is null. |
| AML aml(PCIT::MBIN32S, PCIT::MBIN32S, PCIT::IATTR3,PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getOffset(), |
| src->getAtp(), src->getAtpIndex(), srcNullIndOff, |
| EXPAND_PCODEATTRNULL2(*(UInt32 *)&tpf, tgt, src), |
| 0); |
| |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH_COMP, aml, ol); |
| code.append(pci); |
| |
| id = code.getTailId(); |
| |
| // Now add store of 0 to result |
| AML aml2(PCIT::MBIN32S, PCIT::IBIN32S); |
| OL ol2(tgt->getAtp(), tgt->getAtpIndex(), tgt->getOffset(), 0); |
| PCI pci2(PCIT::Op_MOVE, aml2, ol2); |
| code.append(pci2); |
| } |
| else |
| { |
| // only support the case where both operands are nullable |
| // and this is an equi predicate. |
| // This check was done when pcode was generated. |
| AML aml(PCIT::MBIN32S, PCIT::MATTR3, PCIT::MATTR3, |
| PCIT::IBIN32S, PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), (Int32)tgt->getOffset(), |
| attrA->getAtp(), attrA->getAtpIndex(), attrA->getNullIndOffset(), |
| attrA->getNullBitIndex(), |
| attrB->getAtp(), attrB->getAtpIndex(), attrB->getNullIndOffset(), |
| attrB->getNullBitIndex(), |
| ITM_EQUAL, |
| 0); |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH, aml, ol); |
| code.append(pci); |
| |
| id = code.getTailId(); |
| } |
| |
| nulBranch = generateJumpAndBranch(tgt, code, id); |
| } |
| |
| // If there are two nullable inputs... |
| // |
| else if (attrB) |
| { |
| assert(!tgt->isIndirectVC()); |
| |
| PCodeTupleFormats tpf(tgt->getTupleFormat(), |
| attrA->getTupleFormat(), |
| attrB->getTupleFormat()); |
| |
| Int32 attrANullIndOff = attrA->getNullIndOffset(); |
| Int32 attrBNullIndOff = attrB->getNullIndOffset(); |
| |
| // For indirect varchars in packed format use the negated voa offset. |
| // Then at runtime the code knows to get the offset value out of the |
| // voa entry and jump to the actual value to test the nullness of the |
| // field. |
| // For aligned format the null indicator offset is used since the |
| // null bitmap is statically known. |
| // For exploded format the varchar field offset is known at compile |
| // time and the attribute is not marked as 'indirect'. |
| if (attrA->isIndirectVC() && !attrA->isSQLMXAlignedFormat()) |
| attrANullIndOff = -( (Int32)attrA->getVoaOffset() ); |
| if (attrB->isIndirectVC() && !attrB->isSQLMXAlignedFormat()) |
| attrBNullIndOff = -( (Int32)attrB->getVoaOffset() ); |
| |
| // If either of the input args are null, then output is null. |
| AML aml(PCIT::MBIN32S,PCIT::MBIN32S,PCIT::MBIN32S,PCIT::IATTR4,PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getOffset(), |
| attrA->getAtp(), attrA->getAtpIndex(), attrANullIndOff, |
| attrB->getAtp(), attrB->getAtpIndex(), attrBNullIndOff, |
| EXPAND_PCODEATTRNULL3(*(UInt32 *)&tpf, tgt, attrA, attrB), |
| 0); |
| |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH_COMP, aml, ol); |
| code.append(pci); |
| nulBranch = generateJumpAndBranch(tgt, code, code.getTailId()); |
| } |
| // |
| // Otherwise, if there is only one nullable input... |
| // |
| else if (attrA) |
| { |
| PCodeTupleFormats tpf(tgt->getTupleFormat(), attrA->getTupleFormat()); |
| |
| Int32 attrANullIndOff = attrA->getNullIndOffset(); |
| |
| // For indirect varchars in packed format use the negated voa offset. |
| // Then at runtime the code knows to get the offset value out of the |
| // voa entry and jump to the actual value to test the nullness of the |
| // field. |
| // For aligned format the null indicator offset is used since the |
| // null bitmap is statically known. |
| // For exploded format the varchar field offset is known at compile |
| // time and the attribute is not marked as 'indirect'. |
| if (attrA->isIndirectVC() && !attrA->isSQLMXAlignedFormat()) |
| attrANullIndOff = -( (Int32)attrA->getVoaOffset() ); |
| |
| // If the input is null, then output is null. |
| AML aml(PCIT::MBIN32S,PCIT::MBIN32S,PCIT::IATTR3,PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getOffset(), |
| attrA->getAtp(), attrA->getAtpIndex(), attrANullIndOff, |
| EXPAND_PCODEATTRNULL2(*(UInt32 *)&tpf, tgt, attrA), |
| 0); |
| |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH_COMP, aml, ol); |
| code.append(pci); |
| nulBranch = generateJumpAndBranch(attrs[0], code, code.getTailId()); |
| } |
| |
| return nulBranch; |
| } |
| |
| PCIID PCode::nullBranchHelperForHash(AttributesPtr *attrs, |
| Attributes *attrA, |
| Attributes *attrB, |
| PCIList & code) { |
| |
| PCIID nulBranch = 0; |
| |
| Attributes *tgt = attrs[0]; |
| |
| // This will handle all formats of source data ... |
| AML aml(PCIT::MBIN32S, PCIT::MATTR3, PCIT::IBIN32S, PCIT::IBIN32S); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getOffset(), |
| attrA->getAtp(), attrA->getAtpIndex(), attrA->getNullIndOffset(), |
| attrA->getNullBitIndex(), |
| ex_clause::NULL_HASH, 0); |
| |
| PCI pci(PCIT::Op_NOT_NULL_BRANCH, aml, ol); |
| code.append(pci); |
| nulBranch = generateJumpAndBranch(tgt, code, code.getTailId()); |
| |
| return nulBranch; |
| } |
| |
| PCIID PCode::nullBranch(ex_clause *clause, |
| PCIList& code, |
| AttributesPtr *attrs) |
| { |
| // Rowsets cannot be null. |
| if ((attrs[0]->getRowsetSize() > 0) || (attrs[1]->getRowsetSize() > 0)) { |
| return 0; |
| } |
| |
| // If NULL is not relevant for this operation, there is nothing to do here. |
| // Skip this check for hash operation because though the nullRelevant is |
| // turned off for eval_clause reasons, it is needed here to store a constant |
| // hash value for nulls. |
| // In hash's eval_clause, hash function's destination is not nullable |
| // so turning on nullRelevant flag causes eval_clause to write to |
| // opdata[0] which is not setup since it was skipped in the first place. |
| if(!clause->isNullRelevant()) |
| { |
| if ((clause->getType() == ex_clause::FUNCTION_TYPE) && |
| ((((ex_function_clause*)clause)->origFunctionOperType() == ITM_HASH) || |
| (((ex_function_clause*)clause)->origFunctionOperType() == ITM_HDPHASH))) |
| { |
| // null is relevant for hash if we are generating pcode. |
| } |
| else |
| { |
| return 0; |
| } |
| } |
| |
| // If none of the operands are nullable, there is nothing to do here. |
| // |
| if(!clause->isAnyOperandNullable()) |
| return 0; |
| |
| // Find the nullable inputs |
| // |
| PCIID nulBranch = 0; |
| Attributes *attrA = NULL, *attrB = NULL; |
| if(clause->isAnyInputNullable()) |
| { |
| for(Int32 i=1; i<clause->getNumOperands(); i++) { |
| if(attrs[i]->getNullFlag()) { |
| if(!attrA) { |
| attrA = attrs[i]; |
| } else if(!attrB) |
| attrB = attrs[i]; |
| else { |
| // Null Branch: Too many nullable operands |
| assert(!attrA || !attrB); |
| } |
| } |
| } |
| } |
| if(attrA) |
| { |
| if ((clause->getType() == ex_clause::COMP_TYPE) || |
| (clause->getType() == ex_clause::LIKE_TYPE)) |
| nulBranch = nullBranchHelperForComp(attrs, attrA, attrB, |
| (clause->isSpecialNulls() != 0), |
| code); |
| else if ((clause->getType() == ex_clause::FUNCTION_TYPE) && |
| ((((ex_function_clause*)clause)->origFunctionOperType() == ITM_HASH) || |
| (((ex_function_clause*)clause)->origFunctionOperType() == ITM_HDPHASH))) |
| { |
| nulBranch = nullBranchHelperForHash(attrs, attrA, attrB, code); |
| } |
| else |
| nulBranch = nullBranchHelper(attrs, attrA, attrB, code); |
| } |
| // |
| // Otherwise, if there are no nullable inputs, but the output is nullable, |
| // set the output to not null. |
| // |
| Attributes *tgt = attrs[0]; |
| if(!attrA && clause->isAnyOutputNullable()) |
| { |
| // Check if we need to handle the null bitmap for the aligned row format. |
| if ( tgt->isSQLMXAlignedFormat() ) |
| { |
| AML aml( PCIT::MPTR32, // ptr to target null bitmap to clear |
| PCIT::IBIN32S, // flag - set or test |
| PCIT::IBIN16U, // null bit index |
| PCIT::IBIN32S // value to set to (on/off) |
| ); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getNullIndOffset(), |
| PCIT::NULL_BITMAP_SET, (Int16)tgt->getNullBitIndex(), 0); |
| PCI pci(PCIT::Op_NULL_BITMAP, aml, ol); |
| code.append(pci); |
| } |
| else if ( tgt->isSQLMXFormat() ) |
| { |
| AML aml( PCIT::MPTR32, // ptr to target null bitmap to clear |
| PCIT::IBIN32S // value to set to (on/off) |
| ); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getNullIndOffset(), 0); |
| PCI pci(PCIT::Op_NULL_BYTES, aml, ol); |
| code.append(pci); |
| } |
| else // exploded format |
| { |
| AML aml(PCIT::MBIN16U); |
| OL ol(tgt->getAtp(), tgt->getAtpIndex(), tgt->getNullIndOffset()); |
| PCI pci(PCIT::Op_NULL, aml, ol); |
| code.append(pci); |
| } |
| } |
| |
| return nulBranch; |
| } |