@@ -76,6 +76,7 @@ static int64_t assemble(insn *instruction);
7676static int64_t insn_size (insn * instruction );
7777
7878static int64_t calcsize (insn * , const struct itemplate * );
79+ static int64_t calcsize_speculative (const insn * , const struct itemplate * );
7980static int emit_prefixes (struct out_data * data , const insn * ins );
8081static void gencode (struct out_data * data , insn * ins );
8182static enum match_result find_match (const struct itemplate * * tempp ,
@@ -711,7 +712,8 @@ static void no_match_error(enum match_result m, const insn *ins)
711712}
712713
713714/* This is a real hack. The jcc8 or jmp8 byte code must come first. */
714- static enum match_result jmp_match (const struct itemplate * temp , const insn * ins )
715+ static enum match_result
716+ jmp_match (const insn * ins , const struct itemplate * temp )
715717{
716718 const struct operand * const op0 = get_operand_const (ins , 0 );
717719 int64_t delta ;
@@ -752,34 +754,18 @@ static enum match_result jmp_match(const struct itemplate *temp, const insn *ins
752754 * instruction size.
753755 *
754756 * Note that the instruction size is to be *subtracted* from the
755- * initial (beginning-of-instruction) delta value.
757+ * initial (beginning-of-instruction) delta value, or *added* to the
758+ * limiting value compared to.
756759 */
757760 delta = op0 -> offset - ins -> loc .offset ;
758- if (delta - 2 < -128 || delta - 15 > 127 ) {
761+ if (delta < -128 + 2 || delta > 127 + 15 ) {
759762 /* This cannot be a byte-sized jump */
760763 return MERR_INVALOP ;
761- } else if (delta - 15 >= -128 && delta - 2 <= 127 ) {
764+ } else if (delta >= -128 + 15 && delta <= 127 + 2 ) {
762765 /* It is guaranteed to be a valid byte-sized jump, no need to test */
763766 } else {
764- /*
765- * Need to do this the hard way.
766- *
767- * However, calcsize() can modify the instruction structure,
768- * but after a mismatch we have to revert to the original
769- * state, so make a copy here and hold error messages.
770- */
771- int64_t isize ;
772- insn tmpins ;
773- errhold hold ;
774-
775- tmpins = * ins ;
776- tmpins .dummy = true;
777- hold = nasm_error_hold_push ();
778-
779- isize = calcsize (& tmpins , temp );
780-
781- if (nasm_error_hold_pop (hold , false) >= ERR_NONFATAL )
782- return MERR_INVALOP ;
767+ /* Borderline: need to do this the hard way... */
768+ int64_t isize = calcsize_speculative (ins , temp );
783769 if (isize < 0 )
784770 return MERR_INVALOP ;
785771 delta -= isize ;
@@ -1380,11 +1366,46 @@ static int ea_evex_flags(insn *ins, const struct operand *opy)
13801366 return 0 ;
13811367}
13821368
1369+ /*
1370+ * Call calcsize() without modifying the source instruction, and without
1371+ * generating errors. This is used to answer the question "how long would
1372+ * this instruction be if it were to be generated at this point in the
1373+ * code." This is currently used by jmp_match() but may be used by other
1374+ * things in the future.
1375+ *
1376+ * Returns < 0 if generating the instruction would throw an error.
1377+ */
1378+ static int64_t
1379+ calcsize_speculative (const insn * ins , const struct itemplate * const temp )
1380+ {
1381+ int64_t isize ;
1382+ insn tmpins ;
1383+ errhold hold ;
1384+
1385+ tmpins = * ins ;
1386+ tmpins .dummy = true;
1387+ hold = nasm_error_hold_push ();
1388+
1389+ isize = calcsize (& tmpins , temp );
1390+
1391+ if (nasm_error_hold_pop (hold , false) >= ERR_NONFATAL )
1392+ return -1 ;
1393+
1394+ return isize ;
1395+ }
1396+
1397+
13831398/* Common construct */
13841399#define case3 (x ) case (x): case (x)+1: case (x)+2
13851400#define case4 (x ) case3(x): case (x)+3
13861401
1387- static int64_t calcsize (insn * ins , const struct itemplate * const temp )
1402+ /*
1403+ * calcsize() is assumed to be processing a *confirmed* instruction for
1404+ * the purpose of code generation: it can modify *ins, and will throw
1405+ * errors for invalid code. Use calcsize_speculative() if it is necessary
1406+ * to calculate the size of a *potential* instruction.
1407+ */
1408+ static int64_t calcsize (insn * ins , const struct itemplate * temp )
13881409{
13891410 const int bits = ins -> bits ;
13901411 const uint8_t * codes = temp -> code ;
@@ -3350,7 +3371,7 @@ static enum match_result matches(const struct itemplate * const itemp,
33503371 * Check if special handling needed for relaxable jump
33513372 */
33523373 if (itemp_has (itemp , IF_JMP_RELAX ))
3353- return jmp_match (itemp , ins );
3374+ return jmp_match (ins , itemp );
33543375
33553376 return MOK_GOOD ;
33563377}
0 commit comments