diff options
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 272 |
1 files changed, 166 insertions, 106 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 1a5be1b..c67ea1f 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1146,105 +1146,174 @@ static struct hash_control *op_hash; /* Hash table for register lookup. */ static struct hash_control *reg_hash; -void -i386_align_code (fragS *fragP, int count) -{ /* Various efficient no-op patterns for aligning code labels. Note: Don't try to assemble the instructions in the comments. 0L and 0w are not legal. */ - static const unsigned char f32_1[] = - {0x90}; /* nop */ - static const unsigned char f32_2[] = - {0x66,0x90}; /* xchg %ax,%ax */ - static const unsigned char f32_3[] = - {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ - static const unsigned char f32_4[] = - {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const unsigned char f32_5[] = - {0x90, /* nop */ - 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const unsigned char f32_6[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ - static const unsigned char f32_7[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const unsigned char f32_8[] = - {0x90, /* nop */ - 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const unsigned char f32_9[] = - {0x89,0xf6, /* movl %esi,%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const unsigned char f32_10[] = - {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const unsigned char f32_11[] = - {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const unsigned char f32_12[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ - static const unsigned char f32_13[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const unsigned char f32_14[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const unsigned char f16_3[] = - {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ - static const unsigned char f16_4[] = - {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const unsigned char f16_5[] = - {0x90, /* nop */ - 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const unsigned char f16_6[] = - {0x89,0xf6, /* mov %si,%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const unsigned char f16_7[] = - {0x8d,0x74,0x00, /* lea 0(%si),%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const unsigned char f16_8[] = - {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const unsigned char jump_31[] = - {0xeb,0x1d,0x90,0x90,0x90,0x90,0x90, /* jmp .+31; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const unsigned char *const f32_patt[] = { - f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, - f32_9, f32_10, f32_11, f32_12, f32_13, f32_14 - }; - static const unsigned char *const f16_patt[] = { - f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8 - }; - /* nopl (%[re]ax) */ - static const unsigned char alt_3[] = - {0x0f,0x1f,0x00}; - /* nopl 0(%[re]ax) */ - static const unsigned char alt_4[] = - {0x0f,0x1f,0x40,0x00}; - /* nopl 0(%[re]ax,%[re]ax,1) */ - static const unsigned char alt_5[] = - {0x0f,0x1f,0x44,0x00,0x00}; - /* nopw 0(%[re]ax,%[re]ax,1) */ - static const unsigned char alt_6[] = - {0x66,0x0f,0x1f,0x44,0x00,0x00}; - /* nopl 0L(%[re]ax) */ - static const unsigned char alt_7[] = - {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; - /* nopl 0L(%[re]ax,%[re]ax,1) */ - static const unsigned char alt_8[] = - {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* nopw 0L(%[re]ax,%[re]ax,1) */ - static const unsigned char alt_9[] = - {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const unsigned char alt_10[] = - {0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - static const unsigned char *const alt_patt[] = { - f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, - alt_9, alt_10 - }; +static const unsigned char f32_1[] = + {0x90}; /* nop */ +static const unsigned char f32_2[] = + {0x66,0x90}; /* xchg %ax,%ax */ +static const unsigned char f32_3[] = + {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ +static const unsigned char f32_4[] = + {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ +static const unsigned char f32_5[] = + {0x90, /* nop */ + 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ +static const unsigned char f32_6[] = + {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ +static const unsigned char f32_7[] = + {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ +static const unsigned char f32_8[] = + {0x90, /* nop */ + 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ +static const unsigned char f32_9[] = + {0x89,0xf6, /* movl %esi,%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ +static const unsigned char f32_10[] = + {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ +static const unsigned char f32_11[] = + {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ +static const unsigned char f32_12[] = + {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ + 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ +static const unsigned char f32_13[] = + {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ +static const unsigned char f32_14[] = + {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ +static const unsigned char f16_3[] = + {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ +static const unsigned char f16_4[] = + {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ +static const unsigned char f16_5[] = + {0x90, /* nop */ + 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ +static const unsigned char f16_6[] = + {0x89,0xf6, /* mov %si,%si */ + 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ +static const unsigned char f16_7[] = + {0x8d,0x74,0x00, /* lea 0(%si),%si */ + 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ +static const unsigned char f16_8[] = + {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ + 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ +static const unsigned char jump_31[] = + {0xeb,0x1d,0x90,0x90,0x90,0x90,0x90, /* jmp .+31; lotsa nops */ + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; +/* 32-bit NOPs patterns. */ +static const unsigned char *const f32_patt[] = { + f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, + f32_9, f32_10, f32_11, f32_12, f32_13, f32_14 +}; +/* 16-bit NOPs patterns. */ +static const unsigned char *const f16_patt[] = { + f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8 +}; +/* nopl (%[re]ax) */ +static const unsigned char alt_3[] = + {0x0f,0x1f,0x00}; +/* nopl 0(%[re]ax) */ +static const unsigned char alt_4[] = + {0x0f,0x1f,0x40,0x00}; +/* nopl 0(%[re]ax,%[re]ax,1) */ +static const unsigned char alt_5[] = + {0x0f,0x1f,0x44,0x00,0x00}; +/* nopw 0(%[re]ax,%[re]ax,1) */ +static const unsigned char alt_6[] = + {0x66,0x0f,0x1f,0x44,0x00,0x00}; +/* nopl 0L(%[re]ax) */ +static const unsigned char alt_7[] = + {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; +/* nopl 0L(%[re]ax,%[re]ax,1) */ +static const unsigned char alt_8[] = + {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; +/* nopw 0L(%[re]ax,%[re]ax,1) */ +static const unsigned char alt_9[] = + {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; +/* nopw %cs:0L(%[re]ax,%[re]ax,1) */ +static const unsigned char alt_10[] = + {0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; +/* 32-bit and 64-bit NOPs patterns. */ +static const unsigned char *const alt_patt[] = { + f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, + alt_9, alt_10 +}; +/* 64-bit only: nopw %cs:0L(%eax,%eax,1) */ +static const unsigned char alt64_11[] = + {0x67,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; +/* 64-bit NOPs patterns. */ +static const unsigned char *const alt64_patt[] = { + f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, + alt_9, alt_10, alt64_11 +}; + +/* Genenerate COUNT bytes of NOPs to WHERE from PATT with the maximum + size of a single NOP instruction MAX_SINGLE_NOP_SIZE. */ +static void +i386_output_nops (char *where, const unsigned char *const *patt, + int count, int max_single_nop_size) + +{ + while (count > max_single_nop_size) + { + count -= max_single_nop_size; + memcpy (where + count, patt[max_single_nop_size - 1], + max_single_nop_size); + } + + if (count) + memcpy (where, patt[count - 1], count); +} + + +/* Genenerate COUNT bytes of NOPs to WHERE with the maximum size of a + single NOP instruction LIMIT. */ + +void +i386_generate_nops (fragS *f, char *where, offsetT count, int limit) +{ + /* Output NOPs for .nop directive. */ + int max_single_nop_size; + const unsigned char *const *patt; + + if (flag_code == CODE_16BIT) + { + patt = f16_patt; + max_single_nop_size = sizeof (f16_patt) / sizeof (f16_patt[0]); + } + else if (flag_code == CODE_64BIT) + { + patt = alt64_patt; + max_single_nop_size = sizeof (alt64_patt) / sizeof (alt64_patt[0]); + } + else + { + patt = alt_patt; + max_single_nop_size = sizeof (alt_patt) / sizeof (alt_patt[0]); + } + if (limit == 0) + limit = max_single_nop_size; + else if (limit > max_single_nop_size) + { + as_bad_where (f->fr_file, f->fr_line, + _("invalide single nop size: %d (expect within [0, %d])"), + limit, max_single_nop_size); + return; + } + + i386_output_nops (where, patt, count, limit); +} + +void +i386_align_code (fragS *fragP, int count) +{ /* Only align for at least a positive non-zero boundary. */ if (count <= 0 || count > MAX_MEM_FOR_RS_ALIGN_CODE) return; @@ -1397,17 +1466,8 @@ i386_align_code (fragS *fragP, int count) /* Maximum length of an instruction is 10 byte. If the padding is greater than 10 bytes and we don't use jump, we have to break it into smaller pieces. */ - int padding = count; - while (padding > 10) - { - padding -= 10; - memcpy (fragP->fr_literal + fragP->fr_fix + padding, - patt [9], 10); - } - - if (padding) - memcpy (fragP->fr_literal + fragP->fr_fix, - patt [padding - 1], padding); + i386_output_nops (fragP->fr_literal + fragP->fr_fix, + patt, count, 10); } } fragP->fr_var = count; |