summaryrefslogtreecommitdiffstats
path: root/utils/testgen/mc-bundling-x86-gen.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/testgen/mc-bundling-x86-gen.py')
-rw-r--r--utils/testgen/mc-bundling-x86-gen.py103
1 files changed, 103 insertions, 0 deletions
diff --git a/utils/testgen/mc-bundling-x86-gen.py b/utils/testgen/mc-bundling-x86-gen.py
new file mode 100644
index 0000000..5c1c6c4
--- /dev/null
+++ b/utils/testgen/mc-bundling-x86-gen.py
@@ -0,0 +1,103 @@
+
+#!/usr/bin/python
+
+# Auto-generates an exhaustive and repetitive test for correct bundle-locked
+# alignment on x86.
+# For every possible offset in an aligned bundle, a bundle-locked group of every
+# size in the inclusive range [1, bundle_size] is inserted. An appropriate CHECK
+# is added to verify that NOP padding occurred (or did not occur) as expected.
+# Run with --align-to-end to generate a similar test with align_to_end for each
+# .bundle_lock directive.
+
+# This script runs with Python 2.7 and 3.2+
+
+from __future__ import print_function
+import argparse
+
+BUNDLE_SIZE_POW2 = 4
+BUNDLE_SIZE = 2 ** BUNDLE_SIZE_POW2
+
+PREAMBLE = '''
+# RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - \\
+# RUN: | llvm-objdump -triple i386 -disassemble -no-show-raw-insn - | FileCheck %s
+
+# !!! This test is auto-generated from utils/testgen/mc-bundling-x86-gen.py !!!
+# It tests that bundle-aligned grouping works correctly in MC. Read the
+# source of the script for more details.
+
+ .text
+ .bundle_align_mode {0}
+'''.format(BUNDLE_SIZE_POW2).lstrip()
+
+ALIGNTO = ' .align {0}, 0x90'
+NOPFILL = ' .fill {0}, 1, 0x90'
+
+def print_bundle_locked_sequence(len, align_to_end=False):
+ print(' .bundle_lock{0}'.format(' align_to_end' if align_to_end else ''))
+ print(' .rept {0}'.format(len))
+ print(' inc %eax')
+ print(' .endr')
+ print(' .bundle_unlock')
+
+def generate(align_to_end=False):
+ print(PREAMBLE)
+
+ ntest = 0
+ for instlen in range(1, BUNDLE_SIZE + 1):
+ for offset in range(0, BUNDLE_SIZE):
+ # Spread out all the instructions to not worry about cross-bundle
+ # interference.
+ print(ALIGNTO.format(2 * BUNDLE_SIZE))
+ print('INSTRLEN_{0}_OFFSET_{1}:'.format(instlen, offset))
+ if offset > 0:
+ print(NOPFILL.format(offset))
+ print_bundle_locked_sequence(instlen, align_to_end)
+
+ # Now generate an appropriate CHECK line
+ base_offset = ntest * 2 * BUNDLE_SIZE
+ inst_orig_offset = base_offset + offset # had it not been padded...
+
+ def print_check(adjusted_offset=None, nop_split_offset=None):
+ if adjusted_offset is not None:
+ print('# CHECK: {0:x}: nop'.format(inst_orig_offset))
+ if nop_split_offset is not None:
+ print('# CHECK: {0:x}: nop'.format(nop_split_offset))
+ print('# CHECK: {0:x}: incl'.format(adjusted_offset))
+ else:
+ print('# CHECK: {0:x}: incl'.format(inst_orig_offset))
+
+ if align_to_end:
+ if offset + instlen == BUNDLE_SIZE:
+ # No padding needed
+ print_check()
+ elif offset + instlen < BUNDLE_SIZE:
+ # Pad to end at nearest bundle boundary
+ offset_to_end = base_offset + (BUNDLE_SIZE - instlen)
+ print_check(offset_to_end)
+ else: # offset + instlen > BUNDLE_SIZE
+ # Pad to end at next bundle boundary, splitting the nop sequence
+ # at the nearest bundle boundary
+ offset_to_nearest_bundle = base_offset + BUNDLE_SIZE
+ offset_to_end = base_offset + (BUNDLE_SIZE * 2 - instlen)
+ if offset_to_nearest_bundle == offset_to_end:
+ offset_to_nearest_bundle = None
+ print_check(offset_to_end, offset_to_nearest_bundle)
+ else:
+ if offset + instlen > BUNDLE_SIZE:
+ # Padding needed
+ aligned_offset = (inst_orig_offset + instlen) & ~(BUNDLE_SIZE - 1)
+ print_check(aligned_offset)
+ else:
+ # No padding needed
+ print_check()
+
+ print()
+ ntest += 1
+
+if __name__ == '__main__':
+ argparser = argparse.ArgumentParser()
+ argparser.add_argument('--align-to-end',
+ action='store_true',
+ help='generate .bundle_lock with align_to_end option')
+ args = argparser.parse_args()
+ generate(align_to_end=args.align_to_end)
OpenPOWER on IntegriCloud