blob: 5c1c6c45628005f5c5b8e6e9cfb204428c2800c3 [file] [log] [blame]
Derek Schuffb11917c2013-01-31 17:00:03 +00001
Eli Benderskyb17201f2012-12-20 19:16:57 +00002#!/usr/bin/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.
Eli Bendersky59d15212013-01-07 23:12:59 +00009# Run with --align-to-end to generate a similar test with align_to_end for each
10# .bundle_lock directive.
Eli Benderskyb17201f2012-12-20 19:16:57 +000011
Eli Bendersky59d15212013-01-07 23:12:59 +000012# This script runs with Python 2.7 and 3.2+
Eli Benderskyb17201f2012-12-20 19:16:57 +000013
14from __future__ import print_function
Eli Bendersky59d15212013-01-07 23:12:59 +000015import argparse
Eli Benderskyb17201f2012-12-20 19:16:57 +000016
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
Eli Bendersky59d15212013-01-07 23:12:59 +000035def print_bundle_locked_sequence(len, align_to_end=False):
36 print(' .bundle_lock{0}'.format(' align_to_end' if align_to_end else ''))
Eli Benderskyb17201f2012-12-20 19:16:57 +000037 print(' .rept {0}'.format(len))
38 print(' inc %eax')
39 print(' .endr')
40 print(' .bundle_unlock')
41
Eli Bendersky59d15212013-01-07 23:12:59 +000042def generate(align_to_end=False):
Eli Benderskyb17201f2012-12-20 19:16:57 +000043 print(PREAMBLE)
Derek Schuffb11917c2013-01-31 17:00:03 +000044
Eli Benderskyb17201f2012-12-20 19:16:57 +000045 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))
Eli Bendersky59d15212013-01-07 23:12:59 +000054 print_bundle_locked_sequence(instlen, align_to_end)
Eli Benderskyb17201f2012-12-20 19:16:57 +000055
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...
Eli Bendersky59d15212013-01-07 23:12:59 +000059
Derek Schuffb11917c2013-01-31 17:00:03 +000060 def print_check(adjusted_offset=None, nop_split_offset=None):
Eli Bendersky59d15212013-01-07 23:12:59 +000061 if adjusted_offset is not None:
62 print('# CHECK: {0:x}: nop'.format(inst_orig_offset))
Derek Schuffb11917c2013-01-31 17:00:03 +000063 if nop_split_offset is not None:
64 print('# CHECK: {0:x}: nop'.format(nop_split_offset))
Eli Bendersky59d15212013-01-07 23:12:59 +000065 print('# CHECK: {0:x}: incl'.format(adjusted_offset))
66 else:
67 print('# CHECK: {0:x}: incl'.format(inst_orig_offset))
Derek Schuffb11917c2013-01-31 17:00:03 +000068
Eli Bendersky59d15212013-01-07 23:12:59 +000069 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
Derek Schuffb11917c2013-01-31 17:00:03 +000078 # 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
Eli Bendersky59d15212013-01-07 23:12:59 +000081 offset_to_end = base_offset + (BUNDLE_SIZE * 2 - instlen)
Derek Schuffb11917c2013-01-31 17:00:03 +000082 if offset_to_nearest_bundle == offset_to_end:
83 offset_to_nearest_bundle = None
84 print_check(offset_to_end, offset_to_nearest_bundle)
Eli Benderskyb17201f2012-12-20 19:16:57 +000085 else:
Eli Bendersky59d15212013-01-07 23:12:59 +000086 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()
Eli Benderskyb17201f2012-12-20 19:16:57 +000093
94 print()
95 ntest += 1
96
97if __name__ == '__main__':
Eli Bendersky59d15212013-01-07 23:12:59 +000098 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)