void deletePcodePair(int delIndex1, int delIndex2) { TRACE(stderr, "[deletePcodePair]"); PUTOP(pptr[delIndex1], oNOP); PUTARG(pptr[delIndex1], 0); PUTOP(pptr[delIndex2], oNOP); PUTARG(pptr[delIndex2], 0); setupPointer(); }
void deletePcode(int delIndex) { TRACE(stderr, "[deletePcode]"); PUTOP(pptr[delIndex], oNOP); PUTARG(pptr[delIndex], 0); setupPointer(); }
static void pass3(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle) { OPTYPE op; uint32_t pc; uint32_t opsize; /* Read each opcode, generate relocation information and * replace label references with program section offsets. * * CASE 1: LAC * generate RODATA relocation entry * CASE 2: PCAL instructions * replace label with I-space offset, OR * generate a PROGRAM relocation entry * CASE 3: J* instructions * replace label with I-space offset * CASE 4: LDS*, STS*, and LAS* instructions * generate a STACK relocation (if imported?) * ELSE: * pass through with no additional action */ pc = 0; do { opsize = insn_GetOpCode(poffHandle, &op); switch (GETOP(&op)) { /* Load of an address in the rodata section */ case oLAC: /* We are referencing something from the rodata section. * No special action need be taken. */ break; /* Call to a procedure or function. */ case oPCAL: { /* Check if this is a defined label, i.e., a call to * procedure or function in the same file. */ int32_t value = poffGetPcForDefinedLabel(GETARG(&op)); if (value >= 0) { /* Yes... replace the label reference with * a text section offset. No relocation record * is needed in this case. The only relocation * may be performed is a subsequent program data * section offset. */ PUTARG(&op, value); } else { /* Check if this is a undefined label. This would * occur for a call to a procedure or a function that * is defined in some other unit file. */ value = poffGetSymIndexForUndefinedLabel(GETARG(&op)); if (value >= 0) { /* Use the value zero now */ PUTARG(&op, 0); /* And generate a symbol-based relocation */ (void)poffAddRelocation(poffHandle, RLT_PCAL, value, pc); } else { DEBUG(stdout, "Failed to find call label L%04x\n", GETARG(&op)); fatal(ePOFFCONFUSION); } } } break; /* Jumps to "nearby" addresses */ case oJMP: /* Unconditional */ case oJEQUZ: /* Unary comparisons with zero */ case oJNEQZ: case oJLTZ: case oJGTEZ: case oJGTZ: case oJLTEZ: case oJEQU: /* Binary comparisons */ case oJNEQ: case oJLT: case oJGTE: case oJGT: case oJLTE: { /* Check if this is a defined label. This must be the case * because there can be no jumps into a unit file. */ int32_t value = poffGetPcForDefinedLabel(GETARG(&op)); if (value >= 0) { /* Yes... replace the label reference with * a text section offset. No relocation record * is needed in this case. The only relocation * may be performed is a subsequent program data * sectioin offset. */ PUTARG(&op, value); } else { DEBUG(stdout, "Failed to find jump label L%04x\n", GETARG(&op)); fatal(ePOFFCONFUSION); } } break; /* References to stack via level offset */ case oLAS: /* Load stack address */ case oLASX: case oLDS: /* Load value */ case oLDSH: case oLDSB: case oLDSM: case oSTS: /* Store value */ case oSTSH: case oSTSB: case oSTSM: case oLDSX: case oLDSXH: /* Load value indexed */ case oLDSXB: case oLDSXM: case oSTSX: /* Store value indexed */ case oSTSXH: case oSTSXB: case oSTSXM: { #warning REVISIT } break; /* Otherwise, it is not an interesting opcode */ default: break; } /* Save the potentially modified opcode in the temporary * program data container. */ insn_AddTmpOpCode(poffProgHandle, &op); pc += opsize; } while (GETOP(&op) != oEND); /* Replace the original program data with the new program data */ poffReplaceProgData(poffHandle, poffProgHandle); }
int unaryOptimize(void) { register uint32_t temp; register int i; int nchanges = 0; TRACE(stderr, "[unaryOptimize]"); /* At least two pcodes are need to perform unary optimizations */ i = 0; while (i < nops-1) { /* Check for a constant value being pushed onto the stack */ if (GETOP(pptr[i]) == oPUSH) { switch (GETOP(pptr[i+1])) { /* Delete unary operators on constants */ case oNEG : PUTARG(pptr[i], -GETARG(pptr[i])); deletePcode(i+1); nchanges++; break; case oABS : if ((int32_t)GETARG(pptr[i]) < 0) PUTARG(pptr[i], -(int32_t)GETARG(pptr[i])); deletePcode(i+1); nchanges++; break; case oINC : PUTARG(pptr[i], GETARG(pptr[i]) + 1); deletePcode(i+1); nchanges++; break; case oDEC : PUTARG(pptr[i], GETARG(pptr[i]) - 1); deletePcode(i+1); nchanges++; break; case oNOT : PUTARG(pptr[i], ~GETARG(pptr[i])); PUTARG(pptr[i], ~(GETARG(pptr[i]))); deletePcode(i+1); nchanges++; break; /* Simplify binary operations on constants */ case oADD : if (GETARG(pptr[i]) == 0) { deletePcodePair(i, (i+1)); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i+1], oINC); deletePcode(i); nchanges++; } /* end else if */ else if (GETARG(pptr[i]) == ARGONES) { PUTOP(pptr[i+1], oDEC); deletePcode(i); nchanges++; } /* end else if */ else i++; break; case oSUB : if (GETARG(pptr[i]) == 0) { deletePcodePair(i, (i+1)); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i+1], oDEC); deletePcode(i); nchanges++; } /* end else if */ else if (GETARG(pptr[i]) == ARGONES) { PUTOP(pptr[i+1], oINC); deletePcode(i); nchanges++; } /* end else if */ else i++; break; case oMUL : case oDIV : temp = 0; switch (GETARG(pptr[i])) { case 1 : deletePcodePair(i, (i+1)); nchanges++; break; case 16384 : temp++; case 8192 : temp++; case 4096 : temp++; case 2048 : temp++; case 1024 : temp++; case 512 : temp++; case 256 : temp++; case 128 : temp++; case 64 : temp++; case 32 : temp++; case 16 : temp++; case 8 : temp++; case 4 : temp++; case 2 : temp++; PUTARG(pptr[i], temp); if (GETOP(pptr[i+1]) == oMUL) PUTOP(pptr[i+1], oSLL); else PUTOP(pptr[i+1], oSRA); nchanges++; i++; break; default : i++; break; } /* end switch */ break; case oSLL : case oSRL : case oSRA : case oOR : if (GETARG(pptr[i]) == 0) { deletePcodePair(i, (i+1)); nchanges++; } /* end if */ else i++; break; case oAND : if (GETARG(pptr[i]) == ARGONES) { deletePcodePair(i, (i+1)); nchanges++; } /* end if */ else i++; break; /* Delete comparisons of constants to zero */ case oEQUZ : if (GETARG(pptr[i]) == 0) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcode(i+1); nchanges++; break; case oNEQZ : if (GETARG(pptr[i]) != 0) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcode(i+1); nchanges++; break; case oLTZ : if ((int32_t)GETARG(pptr[i]) < 0) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcode(i+1); nchanges++; break; case oGTEZ : if ((int32_t)GETARG(pptr[i]) >= 0) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcode(i+1); nchanges++; break; case oGTZ : if (GETARG(pptr[i]) > 0) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcode(i+1); nchanges++; break; case oLTEZ : if (GETARG(pptr[i]) <= 0) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcode(i+1); nchanges++; break; /* Simplify comparisons with certain constants */ case oEQU : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1],oEQUZ); deletePcode(i); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i], oDEC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oEQUZ); nchanges++; } /* end else if */ else if ((int32_t)GETARG(pptr[i]) == -1) { PUTOP(pptr[i], oINC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oEQUZ); nchanges++; } /* end else if */ else i++; break; case oNEQ : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1], oNEQZ); deletePcode(i); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i], oDEC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oNEQZ); nchanges++; } /* end else if */ else if ((int32_t)GETARG(pptr[i]) == -1) { PUTOP(pptr[i], oINC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oNEQZ); nchanges++; } /* end else if */ else i++; break; case oLT : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1], oLTZ); deletePcode(i); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i], oDEC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oLTZ); nchanges++; } /* end else if */ else if ((int32_t)GETARG(pptr[i]) == -1) { PUTOP(pptr[i], oINC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oLTZ); nchanges++; } /* end else if */ else i++; break; case oGTE : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1], oGTEZ); deletePcode(i); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i], oDEC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oGTEZ); nchanges++; } /* end else if */ else if ((int32_t)GETARG(pptr[i]) == -1) { PUTOP(pptr[i], oINC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oGTEZ); nchanges++; } /* end else if */ else i++; break; case oGT : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1], oGTZ); deletePcode(i); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i], oDEC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oGTZ); nchanges++; } /* end else if */ else if ((int32_t)GETARG(pptr[i]) == -1) { PUTOP(pptr[i], oINC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oGTZ); nchanges++; } /* end else if */ else i++; break; case oLTE : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1], oLTEZ); deletePcode(i); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i], oDEC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oLTEZ); nchanges++; } /* end else if */ else if ((int32_t)GETARG(pptr[i]) == -1) { PUTOP(pptr[i], oINC); PUTARG(pptr[i], 0); PUTOP(pptr[i+1], oLTEZ); nchanges++; } /* end else if */ else i++; break; /* Simplify or delete condition branches on constants */ case oJEQUZ : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+1], oJMP); deletePcode(i); } /* end if */ else deletePcodePair(i, (i+1)); nchanges++; break; case oJNEQZ : if (GETARG(pptr[i]) != 0) { PUTOP(pptr[i+1], oJMP); deletePcode(i); } /* end if */ else deletePcodePair(i, (i+1)); nchanges++; break; case oJLTZ : if ((int32_t)GETARG(pptr[i]) < 0) { PUTOP(pptr[i+1], oJMP); deletePcode(i); } /* end if */ else deletePcodePair(i, (i+1)); nchanges++; break; case oJGTEZ : if ((int32_t)GETARG(pptr[i]) >= 0) { PUTOP(pptr[i+1], oJMP); deletePcode(i); } /* end if */ else deletePcodePair(i, (i+1)); nchanges++; break; case oJGTZ : if (GETARG(pptr[i]) > 0) { PUTOP(pptr[i+1], oJMP); deletePcode(i); } /* end if */ else deletePcodePair(i, (i+1)); nchanges++; break; case oJLTEZ : if (GETARG(pptr[i]) <= 0) { PUTOP(pptr[i+1], oJMP); deletePcode(i); } /* end if */ else deletePcodePair(i, (i+1)); nchanges++; break; default : i++; break; } /* end switch */ } /* end if */ /* Delete multiple modifications of DSEG pointer */ else if (GETOP(pptr[i]) == oINDS) { if (GETOP(pptr[i+1]) == oINDS) { PUTARG(pptr[i], GETARG(pptr[i] + GETARG(pptr[i+1]))); deletePcode(i+1); } /* end if */ else i++; } /* end else if */ else i++; } /* end while */ return (nchanges); } /* end unaryOptimize */
int binaryOptimize(void) { register int i; int nchanges = 0; TRACE(stderr, "[binaryOptimize]"); /* At least two pcodes are needed to perform the following binary */ /* operator optimizations */ i = 0; while (i < nops-2) { if (GETOP(pptr[i]) == oPUSH) { if (GETOP(pptr[i+1]) == oPUSH) { switch (GETOP(pptr[i+2])) { case oADD : PUTARG(pptr[i], GETARG(pptr[i]) + GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oSUB : PUTARG(pptr[i], GETARG(pptr[i]) - GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oMUL : PUTARG(pptr[i], GETARG(pptr[i]) * GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oDIV : PUTARG(pptr[i], GETARG(pptr[i]) / (int32_t)GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oMOD : PUTARG(pptr[i], GETARG(pptr[i]) % GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oSLL : PUTARG(pptr[i], GETARG(pptr[i]) << GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oSRL : PUTARG(pptr[i], GETARG(pptr[i]) >> GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oSRA : PUTARG(pptr[i], (int32_t)GETARG(pptr[i]) >> GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oOR : PUTARG(pptr[i], GETARG(pptr[i]) | GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oAND : PUTARG(pptr[i], GETARG(pptr[i]) & GETARG(pptr[i+1])); deletePcodePair((i+1), (i+2)); nchanges++; break; case oEQU : if (GETARG(pptr[i]) == GETARG(pptr[i+1])) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcodePair((i+1), (i+2)); nchanges++; break; case oNEQ : if (GETARG(pptr[i]) != GETARG(pptr[i+1])) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcodePair((i+1), (i+2)); nchanges++; break; case oLT : if ((int32_t)GETARG(pptr[i]) < (int32_t)GETARG(pptr[i+1])) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcodePair((i+1), (i+2)); nchanges++; break; case oGTE : if ((int32_t)GETARG(pptr[i]) >= (int32_t)GETARG(pptr[i+1])) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcodePair((i+1), (i+2)); nchanges++; break; case oGT : if ((int32_t)GETARG(pptr[i]) > (int32_t)GETARG(pptr[i+1])) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcodePair((i+1), (i+2)); nchanges++; break; case oLTE : if ((int32_t)GETARG(pptr[i]) <= (int32_t)GETARG(pptr[i+1])) PUTARG(pptr[i], -1); else PUTARG(pptr[i], 0); deletePcodePair((i+1), (i+2)); nchanges++; break; default : i++; break; } /* end switch */ } /* end if */ /* A single (constant) pcode is sufficient to perform the */ /* following binary operator optimizations */ else if ((GETOP(pptr[i+1]) == oLDSH) || (GETOP(pptr[i+1]) == oLDSB) || (GETOP(pptr[i+1]) == oLAS) || (GETOP(pptr[i+1]) == oLAC)) { switch (GETOP(pptr[i+2])) { case oADD : if (GETARG(pptr[i]) == 0) { deletePcodePair(i, (i+2)); nchanges++; } /* end if */ else if (GETARG(pptr[i]) == 1) { PUTOP(pptr[i+2], oINC); deletePcode(i); nchanges++; } /* end else if */ else if (GETARG(pptr[i]) == ARGONES) { PUTOP(pptr[i+2], oDEC); deletePcode(i); nchanges++; } /* end else if */ else i++; break; case oSUB : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i], oNEG); deletePcode(i); nchanges++; } /* end if */ else i++; break; case oMUL : { int32_t stmp32 = 0; switch (GETARG(pptr[i])) { case 1 : deletePcodePair(i, (i+2)); nchanges++; break; case 16384 : stmp32++; case 8192 : stmp32++; case 4096 : stmp32++; case 2048 : stmp32++; case 1024 : stmp32++; case 512 : stmp32++; case 256 : stmp32++; case 128 : stmp32++; case 64 : stmp32++; case 32 : stmp32++; case 16 : stmp32++; case 8 : stmp32++; case 4 : stmp32++; case 2 : stmp32++; PUTOP(pptr[i], GETOP(pptr[i+1])); PUTARG(pptr[i], GETARG(pptr[i+1])); PUTOP(pptr[i+1], oPUSH); PUTARG(pptr[i+1], stmp32); PUTOP(pptr[i+2], oSLL); nchanges++; i++; break; default : i++; break; } } break; case oOR : if (GETARG(pptr[i]) == 0) { deletePcodePair(i, (i+2)); nchanges++; } /* end if */ else i++; break; case oAND : if (GETARG(pptr[i]) == ARGONES) { deletePcodePair(i, (i+2)); nchanges++; } /* end if */ else i++; break; case oEQU : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+2], oEQUZ); deletePcode(i); nchanges++; } /* end if */ else i++; break; case oNEQ : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+2], oNEQZ); deletePcode(i); nchanges++; } /* end if */ else i++; break; case oLT : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+2], oGTEZ); deletePcode(i); nchanges++; } /* end if */ else i++; break; case oGTE : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+2], oLTZ); deletePcode(i); nchanges++; } /* end if */ else i++; break; case oGT : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+2], oLTEZ); deletePcode(i); nchanges++; } /* end if */ else i++; break; case oLTE : if (GETARG(pptr[i]) == 0) { PUTOP(pptr[i+2], oGTZ); deletePcode(i); nchanges++; } /* end if */ else i++; break; default : i++; break; } /* end switch */ } /* end else if */ else i++; } /* end if */ /* Misc improvements on binary operators */ else if (GETOP(pptr[i]) == oNEG)