Skip to content

Commit c0e4def

Browse files
author
H. Peter Anvin (Intel)
committed
assemble: factor out calcsize_speculative()
Currently speculative size calculations is only done during jmp_match(), but it might be used for other things in the future. Either way, it is cleaner to have it factored out into a separate function. Signed-off-by: H. Peter Anvin (Intel) <[email protected]>
1 parent 94c6ecd commit c0e4def

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

asm/assemble.c

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ static int64_t assemble(insn *instruction);
7676
static int64_t insn_size(insn *instruction);
7777

7878
static int64_t calcsize(insn *, const struct itemplate *);
79+
static int64_t calcsize_speculative(const insn *, const struct itemplate *);
7980
static int emit_prefixes(struct out_data *data, const insn *ins);
8081
static void gencode(struct out_data *data, insn *ins);
8182
static 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

Comments
 (0)