1 2#!/usr/bin/env python 3 4# Auto-generates an exhaustive and repetitive test for correct bundle-locked 5# alignment on x86. 6# For every possible offset in an aligned bundle, a bundle-locked group of every 7# size in the inclusive range [1, bundle_size] is inserted. An appropriate CHECK 8# is added to verify that NOP padding occurred (or did not occur) as expected. 9# Run with --align-to-end to generate a similar test with align_to_end for each 10# .bundle_lock directive. 11 12# This script runs with Python 2.7 and 3.2+ 13 14from __future__ import print_function 15import argparse 16 17BUNDLE_SIZE_POW2 = 4 18BUNDLE_SIZE = 2 ** BUNDLE_SIZE_POW2 19 20PREAMBLE = ''' 21# RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - \\ 22# RUN: | llvm-objdump -triple i386 -disassemble -no-show-raw-insn - | FileCheck %s 23 24# !!! This test is auto-generated from utils/testgen/mc-bundling-x86-gen.py !!! 25# It tests that bundle-aligned grouping works correctly in MC. Read the 26# source of the script for more details. 27 28 .text 29 .bundle_align_mode {0} 30'''.format(BUNDLE_SIZE_POW2).lstrip() 31 32ALIGNTO = ' .align {0}, 0x90' 33NOPFILL = ' .fill {0}, 1, 0x90' 34 35def print_bundle_locked_sequence(len, align_to_end=False): 36 print(' .bundle_lock{0}'.format(' align_to_end' if align_to_end else '')) 37 print(' .rept {0}'.format(len)) 38 print(' inc %eax') 39 print(' .endr') 40 print(' .bundle_unlock') 41 42def generate(align_to_end=False): 43 print(PREAMBLE) 44 45 ntest = 0 46 for instlen in range(1, BUNDLE_SIZE + 1): 47 for offset in range(0, BUNDLE_SIZE): 48 # Spread out all the instructions to not worry about cross-bundle 49 # interference. 50 print(ALIGNTO.format(2 * BUNDLE_SIZE)) 51 print('INSTRLEN_{0}_OFFSET_{1}:'.format(instlen, offset)) 52 if offset > 0: 53 print(NOPFILL.format(offset)) 54 print_bundle_locked_sequence(instlen, align_to_end) 55 56 # Now generate an appropriate CHECK line 57 base_offset = ntest * 2 * BUNDLE_SIZE 58 inst_orig_offset = base_offset + offset # had it not been padded... 59 60 def print_check(adjusted_offset=None, nop_split_offset=None): 61 if adjusted_offset is not None: 62 print('# CHECK: {0:x}: nop'.format(inst_orig_offset)) 63 if nop_split_offset is not None: 64 print('# CHECK: {0:x}: nop'.format(nop_split_offset)) 65 print('# CHECK: {0:x}: incl'.format(adjusted_offset)) 66 else: 67 print('# CHECK: {0:x}: incl'.format(inst_orig_offset)) 68 69 if align_to_end: 70 if offset + instlen == BUNDLE_SIZE: 71 # No padding needed 72 print_check() 73 elif offset + instlen < BUNDLE_SIZE: 74 # Pad to end at nearest bundle boundary 75 offset_to_end = base_offset + (BUNDLE_SIZE - instlen) 76 print_check(offset_to_end) 77 else: # offset + instlen > BUNDLE_SIZE 78 # Pad to end at next bundle boundary, splitting the nop sequence 79 # at the nearest bundle boundary 80 offset_to_nearest_bundle = base_offset + BUNDLE_SIZE 81 offset_to_end = base_offset + (BUNDLE_SIZE * 2 - instlen) 82 if offset_to_nearest_bundle == offset_to_end: 83 offset_to_nearest_bundle = None 84 print_check(offset_to_end, offset_to_nearest_bundle) 85 else: 86 if offset + instlen > BUNDLE_SIZE: 87 # Padding needed 88 aligned_offset = (inst_orig_offset + instlen) & ~(BUNDLE_SIZE - 1) 89 print_check(aligned_offset) 90 else: 91 # No padding needed 92 print_check() 93 94 print() 95 ntest += 1 96 97if __name__ == '__main__': 98 argparser = argparse.ArgumentParser() 99 argparser.add_argument('--align-to-end', 100 action='store_true', 101 help='generate .bundle_lock with align_to_end option') 102 args = argparser.parse_args() 103 generate(align_to_end=args.align_to_end) 104