home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / PcodeObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  26.8 KB  |  788 lines  |  [TEXT/KAHL]

  1. /* PcodeObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define SHOW_ME_OPCODEREC  /* we want to see the definition for OpcodeRec */
  31. #include "PcodeObject.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34.  
  35.  
  36. #if DEBUG
  37.     #define MINPCODEARRAYLENGTH (4) /* ridiculously small for debugging */
  38. #else
  39.     #define MINPCODEARRAYLENGTH (128)
  40. #endif
  41.  
  42.  
  43. struct PcodeRec
  44.     {
  45.         OpcodeRec*            OpcodeArray;
  46.         long                        NumInstructions;
  47.         long                        MaxArrayLength;
  48.     };
  49.  
  50.  
  51. PcodeRec*                    NewPcode(void)
  52.     {
  53.         PcodeRec*                Pcode;
  54.  
  55.         Pcode = (PcodeRec*)AllocPtrCanFail(sizeof(PcodeRec),"PcodeRec");
  56.         if (Pcode == NIL)
  57.             {
  58.              FailurePoint1:
  59.                 return NIL;
  60.             }
  61.         Pcode->OpcodeArray = (OpcodeRec*)AllocPtrCanFail(MINPCODEARRAYLENGTH
  62.             * sizeof(OpcodeRec),"OpcodeRec");
  63.         if (Pcode->OpcodeArray == NIL)
  64.             {
  65.              FailurePoint2:
  66.                 ReleasePtr((char*)Pcode);
  67.                 goto FailurePoint1;
  68.             }
  69.         Pcode->NumInstructions = 0;
  70.         Pcode->MaxArrayLength = MINPCODEARRAYLENGTH;
  71.         return Pcode;
  72.     }
  73.  
  74.  
  75. static MyBoolean    ExtendPcodeLength(PcodeRec* Pcode)
  76.     {
  77.         CheckPtrExistence(Pcode);
  78.         if (Pcode->NumInstructions == Pcode->MaxArrayLength)
  79.             {
  80.                 long                        NewLength;
  81.                 OpcodeRec*            NewVector;
  82.  
  83.                 NewLength = Pcode->MaxArrayLength * 2 + 1;
  84.                 NewVector = (OpcodeRec*)ResizePtr((char*)Pcode->OpcodeArray,
  85.                     NewLength * sizeof(OpcodeRec));
  86.                 if (NewVector == NIL)
  87.                     {
  88.                         /* failed */
  89.                         return False;
  90.                     }
  91.                 Pcode->OpcodeArray = NewVector;
  92.                 Pcode->MaxArrayLength = NewLength;
  93.             }
  94.         return True;
  95.     }
  96.  
  97.  
  98. void                            DisposePcode(PcodeRec* Pcode)
  99.     {
  100.         long                        Scan;
  101.         long                        Limit;
  102.  
  103.         CheckPtrExistence(Pcode);
  104.         Limit = Pcode->NumInstructions;
  105.         Scan = 0;
  106.         while (Scan < Limit)
  107.             {
  108.                 switch (Pcode->OpcodeArray[Scan].Opcode)
  109.                     {
  110.                         case epFuncCallUnresolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  111.                         case epFuncCallResolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  112.                             if (Scan + 1 < Limit)
  113.                                 {
  114.                                     /* conditional needed since it's possible they could have had an */
  115.                                     /* error before they got a chance to put the operands */
  116.                                     ReleasePtr(Pcode->OpcodeArray[Scan + 1].ImmediateString);
  117.                                 }
  118.                             if (Scan + 2 < Limit)
  119.                                 {
  120.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 2].DataTypeArray));
  121.                                 }
  122.                             Scan += 5;
  123.                             break;
  124.                         case epOperationBooleanEqual: /* <opcode> */
  125.                         case epOperationBooleanNotEqual:
  126.                         case epOperationBooleanAnd:
  127.                         case epOperationBooleanOr:
  128.                         case epOperationBooleanNot:
  129.                         case epOperationBooleanToInteger:
  130.                         case epOperationBooleanToFloat:
  131.                         case epOperationBooleanToDouble:
  132.                         case epOperationBooleanToFixed:
  133.                         case epOperationIntegerAdd:
  134.                         case epOperationIntegerSubtract:
  135.                         case epOperationIntegerNegation:
  136.                         case epOperationIntegerMultiply:
  137.                         case epOperationIntegerDivide:
  138.                         case epOperationIntegerModulo:
  139.                         case epOperationIntegerShiftLeft:
  140.                         case epOperationIntegerShiftRight:
  141.                         case epOperationIntegerGreaterThan:
  142.                         case epOperationIntegerLessThan:
  143.                         case epOperationIntegerGreaterThanOrEqual:
  144.                         case epOperationIntegerLessThanOrEqual:
  145.                         case epOperationIntegerEqual:
  146.                         case epOperationIntegerNotEqual:
  147.                         case epOperationIntegerAbs:
  148.                         case epOperationIntegerToBoolean:
  149.                         case epOperationIntegerToFloat:
  150.                         case epOperationIntegerToDouble:
  151.                         case epOperationIntegerToFixed:
  152.                         case epOperationFloatAdd:
  153.                         case epOperationFloatSubtract:
  154.                         case epOperationFloatNegation:
  155.                         case epOperationFloatMultiply:
  156.                         case epOperationFloatDivide:
  157.                         case epOperationFloatGreaterThan:
  158.                         case epOperationFloatLessThan:
  159.                         case epOperationFloatGreaterThanOrEqual:
  160.                         case epOperationFloatLessThanOrEqual:
  161.                         case epOperationFloatEqual:
  162.                         case epOperationFloatNotEqual:
  163.                         case epOperationFloatAbs:
  164.                         case epOperationFloatToBoolean:
  165.                         case epOperationFloatToInteger:
  166.                         case epOperationFloatToDouble:
  167.                         case epOperationFloatToFixed:
  168.                         case epOperationDoubleAdd:
  169.                         case epOperationDoubleSubtract:
  170.                         case epOperationDoubleNegation:
  171.                         case epOperationDoubleMultiply:
  172.                         case epOperationDoubleDivide:
  173.                         case epOperationDoubleGreaterThan:
  174.                         case epOperationDoubleLessThan:
  175.                         case epOperationDoubleGreaterThanOrEqual:
  176.                         case epOperationDoubleLessThanOrEqual:
  177.                         case epOperationDoubleEqual:
  178.                         case epOperationDoubleNotEqual:
  179.                         case epOperationDoubleAbs:
  180.                         case epOperationDoubleToBoolean:
  181.                         case epOperationDoubleToInteger:
  182.                         case epOperationDoubleToFloat:
  183.                         case epOperationDoubleToFixed:
  184.                         case epOperationDoubleSin:
  185.                         case epOperationDoubleCos:
  186.                         case epOperationDoubleTan:
  187.                         case epOperationDoubleAtan:
  188.                         case epOperationDoubleLn:
  189.                         case epOperationDoubleExp:
  190.                         case epOperationDoubleSqrt:
  191.                         case epOperationDoublePower:
  192.                         case epOperationFixedAdd:
  193.                         case epOperationFixedSubtract:
  194.                         case epOperationFixedNegation:
  195.                         case epOperationFixedMultiply:
  196.                         case epOperationFixedDivide:
  197.                         case epOperationFixedShiftLeft:
  198.                         case epOperationFixedShiftRight:
  199.                         case epOperationFixedGreaterThan:
  200.                         case epOperationFixedLessThan:
  201.                         case epOperationFixedGreaterThanOrEqual:
  202.                         case epOperationFixedLessThanOrEqual:
  203.                         case epOperationFixedEqual:
  204.                         case epOperationFixedNotEqual:
  205.                         case epOperationFixedAbs:
  206.                         case epOperationFixedToBoolean:
  207.                         case epOperationFixedToInteger:
  208.                         case epOperationFixedToFloat:
  209.                         case epOperationFixedToDouble:
  210.                         case epGetBooleanArraySize: /* <opcode> */
  211.                         case epGetIntegerArraySize:
  212.                         case epGetFloatArraySize:
  213.                         case epGetDoubleArraySize:
  214.                         case epGetFixedArraySize:
  215.                         case epReturnFromSubroutine: /* <opcode> */
  216.                         case epLoadImmediateNILArray: /* <opcode> */
  217.                         case epMakeBooleanArray: /* <opcode> */
  218.                         case epMakeIntegerArray:
  219.                         case epMakeFloatArray:
  220.                         case epMakeDoubleArray:
  221.                         case epMakeFixedArray:
  222.                         case epStackPop: /* <opcode> */
  223.                         case epDuplicate: /* <opcode> */
  224.                         case epNop: /* <opcode> */
  225.                         case epStackAllocate: /* <opcode> */
  226.                         case epResizeBooleanArray2: /* <opcode> */
  227.                         case epResizeIntegerArray2:
  228.                         case epResizeFloatArray2:
  229.                         case epResizeDoubleArray2:
  230.                         case epResizeFixedArray2:
  231.                         case epStoreBooleanIntoArray2: /* <opcode> */
  232.                         case epStoreIntegerIntoArray2:
  233.                         case epStoreFloatIntoArray2:
  234.                         case epStoreDoubleIntoArray2:
  235.                         case epStoreFixedIntoArray2:
  236.                         case epLoadBooleanFromArray2: /* <opcode> */
  237.                         case epLoadIntegerFromArray2:
  238.                         case epLoadFloatFromArray2:
  239.                         case epLoadDoubleFromArray2:
  240.                         case epLoadFixedFromArray2:
  241.                         case epOperationBooleanXor:
  242.                         case epOperationIntegerAnd:
  243.                         case epOperationFixedAnd:
  244.                         case epOperationIntegerOr:
  245.                         case epOperationFixedOr:
  246.                         case epOperationIntegerXor:
  247.                         case epOperationFixedXor:
  248.                         case epOperationIntegerImpreciseDivide:
  249.                         case epOperationFloatShiftLeft:
  250.                         case epOperationDoubleShiftLeft:
  251.                         case epOperationFloatShiftRight:
  252.                         case epOperationDoubleShiftRight:
  253.                         case epOperationIntegerNot:
  254.                         case epOperationDoubleAsin:
  255.                         case epOperationDoubleAcos:
  256.                         case epOperationDoubleSqr:
  257.                         case epOperationTestIntegerNegative:
  258.                         case epOperationTestFloatNegative:
  259.                         case epOperationTestDoubleNegative:
  260.                         case epOperationTestFixedNegative:
  261.                         case epOperationGetSignInteger:
  262.                         case epOperationGetSignFloat:
  263.                         case epOperationGetSignDouble:
  264.                         case epOperationGetSignFixed:
  265.                         case epPrintBool: /* <opcode> */
  266.                         case epPrintDouble: /* <opcode> */
  267.                             Scan += 1;
  268.                             break;
  269.                         case epStackPopMultiple: /* <opcode> <numwords> */
  270.                         case epStackDeallocateUnder: /* <opcode> <numwords> */
  271.                         case epOperationBooleanToIntegerBuried:  /* <opcode> <stackindex> */
  272.                         case epOperationBooleanToFloatBuried:
  273.                         case epOperationBooleanToDoubleBuried:
  274.                         case epOperationBooleanToFixedBuried:
  275.                         case epOperationIntegerToBooleanBuried:
  276.                         case epOperationIntegerToFloatBuried:
  277.                         case epOperationIntegerToDoubleBuried:
  278.                         case epOperationIntegerToFixedBuried:
  279.                         case epOperationFloatToBooleanBuried:
  280.                         case epOperationFloatToIntegerBuried:
  281.                         case epOperationFloatToDoubleBuried:
  282.                         case epOperationFloatToFixedBuried:
  283.                         case epOperationDoubleToBooleanBuried:
  284.                         case epOperationDoubleToIntegerBuried:
  285.                         case epOperationDoubleToFloatBuried:
  286.                         case epOperationDoubleToFixedBuried:
  287.                         case epOperationFixedToBooleanBuried:
  288.                         case epOperationFixedToIntegerBuried:
  289.                         case epOperationFixedToFloatBuried:
  290.                         case epOperationFixedToDoubleBuried:
  291.                         case epBranchUnconditional: /* <opcode> <branchoffset> */
  292.                         case epBranchIfZero:
  293.                         case epBranchIfNotZero:
  294.                         case epStoreIntegerOnStack: /* <opcode> <stackindex> */
  295.                         case epStoreFloatOnStack:
  296.                         case epStoreDoubleOnStack:
  297.                         case epStoreArrayOnStack:
  298.                         case epLoadIntegerFromStack:
  299.                         case epLoadFloatFromStack:
  300.                         case epLoadDoubleFromStack:
  301.                         case epLoadArrayFromStack:
  302.                         case epLoadImmediateInteger: /* <opcode> <integer>; also used for boolean & fixed */
  303.                             Scan += 2;
  304.                             break;
  305.                         case epLoadImmediateFloat: /* <opcode> ^<float> */
  306.                             if (Scan + 1 < Limit)
  307.                                 {
  308.                                     /* conditional needed since it's possible they could have had an */
  309.                                     /* error before they got a chance to put the operands */
  310.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 1].ImmediateFloat));
  311.                                 }
  312.                             Scan += 2;
  313.                             break;
  314.                         case epLoadImmediateDouble: /* <opcode> ^<double> */
  315.                             if (Scan + 1 < Limit)
  316.                                 {
  317.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 1].ImmediateDouble));
  318.                                 }
  319.                             Scan += 2;
  320.                             break;
  321.                         case epErrorTrap: /* <opcode> ^"<errorstring>" */
  322.                         case epGetSampleLeftArray: /* <opcode> ^"<namestring>" */
  323.                         case epGetSampleRightArray:
  324.                         case epGetSampleMonoArray:
  325.                         case epGetWaveTableArray:
  326.                         case epGetWaveTableFrames:
  327.                         case epGetWaveTableTables:
  328.                         case epPrintString: /* <opcode> ^"<string>" */
  329.                             if (Scan + 1 < Limit)
  330.                                 {
  331.                                     ReleasePtr(Pcode->OpcodeArray[Scan + 1].ImmediateString);
  332.                                 }
  333.                             Scan += 2;
  334.                             break;
  335.                         default:
  336.                             EXECUTE(PRERR(ForceAbort,"DisposePcode:  unknown opcode"));
  337.                             break;
  338.                     }
  339.             }
  340.         ReleasePtr((char*)(Pcode->OpcodeArray));
  341.         ReleasePtr((char*)Pcode);
  342.     }
  343.  
  344.  
  345. long                            PcodeGetNextAddress(PcodeRec* Pcode)
  346.     {
  347.         CheckPtrExistence(Pcode);
  348.         return Pcode->NumInstructions;
  349.     }
  350.  
  351.  
  352. OpcodeRec*                GetOpcodeFromPcode(PcodeRec* Pcode)
  353.     {
  354.         CheckPtrExistence(Pcode);
  355.         return Pcode->OpcodeArray;
  356.     }
  357.  
  358.  
  359. /* get the number of cells in the array */
  360. long                            GetNumberOfValidCellsInPcode(PcodeRec* Pcode)
  361.     {
  362.         CheckPtrExistence(Pcode);
  363.         return Pcode->NumInstructions;
  364.     }
  365.  
  366.  
  367. /* put a new opcode array into the pcode.  this does not allocate or release any */
  368. /* memory, but merely updates the pointer.  it should not be called by anyone */
  369. /* except the optimizer.   after the optimizer is done, it resizes the array to */
  370. /* be exactly the size we need. */
  371. void                            UpdateOpcodeInPcode(PcodeRec* Pcode, OpcodeRec* NewOpcodeArray,
  372.                                         long NewNumInstructions)
  373.     {
  374.         CheckPtrExistence(Pcode);
  375.         CheckPtrExistence(NewOpcodeArray);
  376.         ERROR((NewNumInstructions < 0) || (NewNumInstructions
  377.             > PtrSize((char*)NewOpcodeArray) / sizeof(OpcodeRec)),PRERR(ForceAbort,
  378.             "UpdateOpcodeInPcode:  bad array size problem"));
  379.         Pcode->OpcodeArray = NewOpcodeArray;
  380.         Pcode->NumInstructions = NewNumInstructions;
  381.     }
  382.  
  383.  
  384. /* Add a pcode instruction.  *Index returns the index of the instruction so that */
  385. /* branches can be patched up.  if Index is NIL, then it won't bother returning */
  386. /* anything. */
  387. MyBoolean                    AddPcodeInstruction(PcodeRec* Pcode, Pcodes Opcode, long* Index)
  388.     {
  389.         CheckPtrExistence(Pcode);
  390.         if (!ExtendPcodeLength(Pcode))
  391.             {
  392.                 return False;
  393.             }
  394.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  395.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  396.         Pcode->OpcodeArray[Pcode->NumInstructions].Opcode = Opcode;
  397.         if (Index != NIL)
  398.             {
  399.                 *Index = Pcode->NumInstructions;
  400.             }
  401.         Pcode->NumInstructions += 1;
  402.         return True;
  403.     }
  404.  
  405.  
  406. MyBoolean                    AddPcodeOperandDouble(PcodeRec* Pcode, double ImmediateData)
  407.     {
  408.         double*                    NewDouble;
  409.  
  410.         CheckPtrExistence(Pcode);
  411.         if (!ExtendPcodeLength(Pcode))
  412.             {
  413.                 return False;
  414.             }
  415.         NewDouble = (double*)AllocPtrCanFail(sizeof(double),"PcodeDouble");
  416.         if (NewDouble == NIL)
  417.             {
  418.                 return False;
  419.             }
  420.         *NewDouble = ImmediateData;
  421.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  422.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  423.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateDouble = NewDouble;
  424.         Pcode->NumInstructions += 1;
  425.         return True;
  426.     }
  427.  
  428.  
  429. MyBoolean                    AddPcodeOperandFloat(PcodeRec* Pcode, float ImmediateData)
  430.     {
  431.         float*                    NewFloat;
  432.  
  433.         CheckPtrExistence(Pcode);
  434.         if (!ExtendPcodeLength(Pcode))
  435.             {
  436.                 return False;
  437.             }
  438.         NewFloat = (float*)AllocPtrCanFail(sizeof(float),"PcodeFloat");
  439.         if (NewFloat == NIL)
  440.             {
  441.                 return False;
  442.             }
  443.         *NewFloat = ImmediateData;
  444.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  445.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  446.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateFloat = NewFloat;
  447.         Pcode->NumInstructions += 1;
  448.         return True;
  449.     }
  450.  
  451.  
  452. MyBoolean                    AddPcodeOperandInteger(PcodeRec* Pcode, long ImmediateData)
  453.     {
  454.         CheckPtrExistence(Pcode);
  455.         if (!ExtendPcodeLength(Pcode))
  456.             {
  457.                 return False;
  458.             }
  459.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  460.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  461.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateInteger = ImmediateData;
  462.         Pcode->NumInstructions += 1;
  463.         return True;
  464.     }
  465.  
  466.  
  467. /* the string must be null terminated */
  468. MyBoolean                    AddPcodeOperandString(PcodeRec* Pcode, char* String, long Length)
  469.     {
  470.         char*                        NewString;
  471.  
  472.         CheckPtrExistence(Pcode);
  473.         if (!ExtendPcodeLength(Pcode))
  474.             {
  475.                 return False;
  476.             }
  477.         NewString = AllocPtrCanFail(Length + 1,"PcodeString");
  478.         if (NewString == NIL)
  479.             {
  480.                 return False;
  481.             }
  482.         CopyData(String,NewString,Length);
  483.         NewString[Length] = 0; /* null termination */
  484.  
  485.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  486.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  487.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateString = NewString;
  488.         Pcode->NumInstructions += 1;
  489.         return True;
  490.     }
  491.  
  492.  
  493. MyBoolean                    AddPcodeOperandDataTypeArray(PcodeRec* Pcode, DataTypes* DataTypeArray)
  494.     {
  495.         DataTypes*            NewTypeArray;
  496.  
  497.         CheckPtrExistence(Pcode);
  498.         if (!ExtendPcodeLength(Pcode))
  499.             {
  500.                 return False;
  501.             }
  502.         NewTypeArray = (DataTypes*)CopyPtr((char*)DataTypeArray);
  503.         if (NewTypeArray == NIL)
  504.             {
  505.                 return False;
  506.             }
  507.         SetTag(NewTypeArray,"PcodeDataTypeArray");
  508.  
  509.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  510.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  511.         Pcode->OpcodeArray[Pcode->NumInstructions].DataTypeArray = NewTypeArray;
  512.         Pcode->NumInstructions += 1;
  513.         return True;
  514.     }
  515.  
  516.  
  517. void                            ResolvePcodeBranch(PcodeRec* Pcode, long Where, long Destination)
  518.     {
  519.         CheckPtrExistence(Pcode);
  520.         ERROR((Where < 0) || (Where + 1 >= Pcode->NumInstructions),PRERR(ForceAbort,
  521.             "ResolvePcodeBranch:  address out of range"));
  522.         ERROR((Pcode->OpcodeArray[Where].Opcode != epBranchUnconditional)
  523.             && (Pcode->OpcodeArray[Where].Opcode != epBranchIfZero)
  524.             && (Pcode->OpcodeArray[Where].Opcode != epBranchIfNotZero),PRERR(ForceAbort,
  525.             "ResolvePcodeBranch:  patching a non-branch instruction"));
  526.         Pcode->OpcodeArray[Where + 1].ImmediateInteger = Destination;
  527.     }
  528.  
  529.  
  530. static MyBoolean    LocalStrEqu(char* Left, char* Right, long LeftLen, long RightLen)
  531.     {
  532.         if (LeftLen == RightLen)
  533.             {
  534.                 return MemEqu(Left,Right,LeftLen);
  535.             }
  536.         return False;
  537.     }
  538.  
  539.  
  540. void                            PcodeUnlink(PcodeRec* Function, char* DeadFuncName,
  541.                                         PcodeRec* DeadFuncCode)
  542.     {
  543.         long                        Scan;
  544.         long                        Limit;
  545.  
  546.         CheckPtrExistence(Function);
  547.         CheckPtrExistence(DeadFuncCode);
  548.         Limit = Function->NumInstructions;
  549.         Scan = 0;
  550.         while (Scan < Limit)
  551.             {
  552.                 /* first, see if we have to delink it */
  553.                 if (Function->OpcodeArray[Scan].Opcode == epFuncCallResolved)
  554.                     {
  555.                         /* this is the one we have to delink. */
  556.                         /*    0              1              2            3            4    */
  557.                         /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  558.                         /* will be converted to */
  559.                         /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  560.                         ERROR(LocalStrEqu(Function->OpcodeArray[Scan + 1].ImmediateString,
  561.                             DeadFuncName,StrLen(Function->OpcodeArray[Scan + 1].ImmediateString),
  562.                             PtrSize(DeadFuncName)) && (DeadFuncCode->OpcodeArray
  563.                             != Function->OpcodeArray[Scan + 4].FunctionOpcodeRecPtr),
  564.                             PRERR(ForceAbort,"PcodeUnlink:  found a function with the right name "
  565.                             "but it's not linked to the same code record"));
  566.                         ERROR(!LocalStrEqu(Function->OpcodeArray[Scan + 1].ImmediateString,
  567.                             DeadFuncName,StrLen(Function->OpcodeArray[Scan + 1].ImmediateString),
  568.                             PtrSize(DeadFuncName)) && (DeadFuncCode->OpcodeArray
  569.                             == Function->OpcodeArray[Scan + 4].FunctionOpcodeRecPtr),
  570.                             PRERR(ForceAbort,"PcodeUnlink:  found a function that's linked to this "
  571.                             "code record, but with a different function name"));
  572.                         if (LocalStrEqu(Function->OpcodeArray[Scan + 1].ImmediateString,
  573.                             DeadFuncName,StrLen(Function->OpcodeArray[Scan + 1].ImmediateString),
  574.                             PtrSize(DeadFuncName)))
  575.                             {
  576.                                 /* if the name is the same, then delink it */
  577.                                 Function->OpcodeArray[Scan].Opcode = epFuncCallUnresolved;
  578.                                 Function->OpcodeArray[Scan + 4].FunctionOpcodeRecPtr = NIL;
  579.                             }
  580.                     }
  581.                 /* now, advance the program counter the right amount */
  582.                 Scan += GetInstructionLength(Function->OpcodeArray[Scan].Opcode);
  583.             }
  584.     }
  585.  
  586.  
  587. long                            GetInstructionLength(Pcodes OpcodeWord)
  588.     {
  589.         switch (OpcodeWord)
  590.             {
  591.                 case epFuncCallUnresolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  592.                 case epFuncCallResolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  593.                     return 5;
  594.                 case epOperationBooleanEqual: /* <opcode> */
  595.                 case epOperationBooleanNotEqual:
  596.                 case epOperationBooleanAnd:
  597.                 case epOperationBooleanOr:
  598.                 case epOperationBooleanNot:
  599.                 case epOperationBooleanToInteger:
  600.                 case epOperationBooleanToFloat:
  601.                 case epOperationBooleanToDouble:
  602.                 case epOperationBooleanToFixed:
  603.                 case epOperationIntegerAdd:
  604.                 case epOperationIntegerSubtract:
  605.                 case epOperationIntegerNegation:
  606.                 case epOperationIntegerMultiply:
  607.                 case epOperationIntegerDivide:
  608.                 case epOperationIntegerModulo:
  609.                 case epOperationIntegerShiftLeft:
  610.                 case epOperationIntegerShiftRight:
  611.                 case epOperationIntegerGreaterThan:
  612.                 case epOperationIntegerLessThan:
  613.                 case epOperationIntegerGreaterThanOrEqual:
  614.                 case epOperationIntegerLessThanOrEqual:
  615.                 case epOperationIntegerEqual:
  616.                 case epOperationIntegerNotEqual:
  617.                 case epOperationIntegerAbs:
  618.                 case epOperationIntegerToBoolean:
  619.                 case epOperationIntegerToFloat:
  620.                 case epOperationIntegerToDouble:
  621.                 case epOperationIntegerToFixed:
  622.                 case epOperationFloatAdd:
  623.                 case epOperationFloatSubtract:
  624.                 case epOperationFloatNegation:
  625.                 case epOperationFloatMultiply:
  626.                 case epOperationFloatDivide:
  627.                 case epOperationFloatGreaterThan:
  628.                 case epOperationFloatLessThan:
  629.                 case epOperationFloatGreaterThanOrEqual:
  630.                 case epOperationFloatLessThanOrEqual:
  631.                 case epOperationFloatEqual:
  632.                 case epOperationFloatNotEqual:
  633.                 case epOperationFloatAbs:
  634.                 case epOperationFloatToBoolean:
  635.                 case epOperationFloatToInteger:
  636.                 case epOperationFloatToDouble:
  637.                 case epOperationFloatToFixed:
  638.                 case epOperationDoubleAdd:
  639.                 case epOperationDoubleSubtract:
  640.                 case epOperationDoubleNegation:
  641.                 case epOperationDoubleMultiply:
  642.                 case epOperationDoubleDivide:
  643.                 case epOperationDoubleGreaterThan:
  644.                 case epOperationDoubleLessThan:
  645.                 case epOperationDoubleGreaterThanOrEqual:
  646.                 case epOperationDoubleLessThanOrEqual:
  647.                 case epOperationDoubleEqual:
  648.                 case epOperationDoubleNotEqual:
  649.                 case epOperationDoubleAbs:
  650.                 case epOperationDoubleToBoolean:
  651.                 case epOperationDoubleToInteger:
  652.                 case epOperationDoubleToFloat:
  653.                 case epOperationDoubleToFixed:
  654.                 case epOperationDoubleSin:
  655.                 case epOperationDoubleCos:
  656.                 case epOperationDoubleTan:
  657.                 case epOperationDoubleAtan:
  658.                 case epOperationDoubleLn:
  659.                 case epOperationDoubleExp:
  660.                 case epOperationDoubleSqrt:
  661.                 case epOperationDoublePower:
  662.                 case epOperationFixedAdd:
  663.                 case epOperationFixedSubtract:
  664.                 case epOperationFixedNegation:
  665.                 case epOperationFixedMultiply:
  666.                 case epOperationFixedDivide:
  667.                 case epOperationFixedShiftLeft:
  668.                 case epOperationFixedShiftRight:
  669.                 case epOperationFixedGreaterThan:
  670.                 case epOperationFixedLessThan:
  671.                 case epOperationFixedGreaterThanOrEqual:
  672.                 case epOperationFixedLessThanOrEqual:
  673.                 case epOperationFixedEqual:
  674.                 case epOperationFixedNotEqual:
  675.                 case epOperationFixedAbs:
  676.                 case epOperationFixedToBoolean:
  677.                 case epOperationFixedToInteger:
  678.                 case epOperationFixedToFloat:
  679.                 case epOperationFixedToDouble:
  680.                 case epGetBooleanArraySize: /* <opcode> */
  681.                 case epGetIntegerArraySize:
  682.                 case epGetFloatArraySize:
  683.                 case epGetDoubleArraySize:
  684.                 case epGetFixedArraySize:
  685.                 case epReturnFromSubroutine: /* <opcode> */
  686.                 case epLoadImmediateNILArray: /* <opcode> */
  687.                 case epMakeBooleanArray: /* <opcode> */
  688.                 case epMakeIntegerArray:
  689.                 case epMakeFloatArray:
  690.                 case epMakeDoubleArray:
  691.                 case epMakeFixedArray:
  692.                 case epStackPop: /* <opcode> */
  693.                 case epDuplicate: /* <opcode> */
  694.                 case epNop: /* <opcode> */
  695.                 case epStackAllocate: /* <opcode> */
  696.                 case epResizeBooleanArray2: /* <opcode> */
  697.                 case epResizeIntegerArray2:
  698.                 case epResizeFloatArray2:
  699.                 case epResizeDoubleArray2:
  700.                 case epResizeFixedArray2:
  701.                 case epStoreBooleanIntoArray2: /* <opcode> */
  702.                 case epStoreIntegerIntoArray2:
  703.                 case epStoreFloatIntoArray2:
  704.                 case epStoreDoubleIntoArray2:
  705.                 case epStoreFixedIntoArray2:
  706.                 case epLoadBooleanFromArray2: /* <opcode> */
  707.                 case epLoadIntegerFromArray2:
  708.                 case epLoadFloatFromArray2:
  709.                 case epLoadDoubleFromArray2:
  710.                 case epLoadFixedFromArray2:
  711.                 case epOperationBooleanXor:
  712.                 case epOperationIntegerAnd:
  713.                 case epOperationFixedAnd:
  714.                 case epOperationIntegerOr:
  715.                 case epOperationFixedOr:
  716.                 case epOperationIntegerXor:
  717.                 case epOperationFixedXor:
  718.                 case epOperationIntegerImpreciseDivide:
  719.                 case epOperationFloatShiftLeft:
  720.                 case epOperationDoubleShiftLeft:
  721.                 case epOperationFloatShiftRight:
  722.                 case epOperationDoubleShiftRight:
  723.                 case epOperationIntegerNot:
  724.                 case epOperationDoubleAsin:
  725.                 case epOperationDoubleAcos:
  726.                 case epOperationDoubleSqr:
  727.                 case epOperationTestIntegerNegative:
  728.                 case epOperationTestFloatNegative:
  729.                 case epOperationTestDoubleNegative:
  730.                 case epOperationTestFixedNegative:
  731.                 case epOperationGetSignInteger:
  732.                 case epOperationGetSignFloat:
  733.                 case epOperationGetSignDouble:
  734.                 case epOperationGetSignFixed:
  735.                 case epPrintBool: /* <opcode> */
  736.                 case epPrintDouble: /* <opcode> */
  737.                     return 1;
  738.                 case epStackPopMultiple: /* <opcode> <numwords> */
  739.                 case epStackDeallocateUnder: /* <opcode> <numwords> */
  740.                 case epOperationBooleanToIntegerBuried:  /* <opcode> <stackindex> */
  741.                 case epOperationBooleanToFloatBuried:
  742.                 case epOperationBooleanToDoubleBuried:
  743.                 case epOperationBooleanToFixedBuried:
  744.                 case epOperationIntegerToBooleanBuried:
  745.                 case epOperationIntegerToFloatBuried:
  746.                 case epOperationIntegerToDoubleBuried:
  747.                 case epOperationIntegerToFixedBuried:
  748.                 case epOperationFloatToBooleanBuried:
  749.                 case epOperationFloatToIntegerBuried:
  750.                 case epOperationFloatToDoubleBuried:
  751.                 case epOperationFloatToFixedBuried:
  752.                 case epOperationDoubleToBooleanBuried:
  753.                 case epOperationDoubleToIntegerBuried:
  754.                 case epOperationDoubleToFloatBuried:
  755.                 case epOperationDoubleToFixedBuried:
  756.                 case epOperationFixedToBooleanBuried:
  757.                 case epOperationFixedToIntegerBuried:
  758.                 case epOperationFixedToFloatBuried:
  759.                 case epOperationFixedToDoubleBuried:
  760.                 case epBranchUnconditional: /* <opcode> <branchoffset> */
  761.                 case epBranchIfZero:
  762.                 case epBranchIfNotZero:
  763.                 case epStoreIntegerOnStack: /* <opcode> <stackindex> */
  764.                 case epStoreFloatOnStack:
  765.                 case epStoreDoubleOnStack:
  766.                 case epStoreArrayOnStack:
  767.                 case epLoadIntegerFromStack:
  768.                 case epLoadFloatFromStack:
  769.                 case epLoadDoubleFromStack:
  770.                 case epLoadArrayFromStack:
  771.                 case epLoadImmediateInteger: /* <opcode> <integer>; also used for boolean & fixed */
  772.                 case epLoadImmediateFloat: /* <opcode> ^<float> */
  773.                 case epLoadImmediateDouble: /* <opcode> ^<double> */
  774.                 case epGetSampleLeftArray: /* <opcode> ^"<namestring>" */
  775.                 case epGetSampleRightArray:
  776.                 case epGetSampleMonoArray:
  777.                 case epGetWaveTableArray:
  778.                 case epGetWaveTableFrames:
  779.                 case epGetWaveTableTables:
  780.                 case epErrorTrap: /* <opcode> ^"<errorstring>" */
  781.                 case epPrintString: /* <opcode> ^"<string>" */
  782.                     return 2;
  783.                 default:
  784.                     EXECUTE(PRERR(ForceAbort,"GetInstructionLength:  unknown opcode"));
  785.             }
  786.         EXECUTE(PRERR(ForceAbort,"GetInstructionLength:  control reached end of function"));
  787.     }
  788.