summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/powerpc/stringloops/memcmp.c
blob: b1fa7546957f76a65b03f18f1622cbe3dbee4232 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// SPDX-License-Identifier: GPL-2.0
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "utils.h"

#define SIZE 256
#define ITERATIONS 10000

#define LARGE_SIZE (5 * 1024)
#define LARGE_ITERATIONS 1000
#define LARGE_MAX_OFFSET 32
#define LARGE_SIZE_START 4096

#define MAX_OFFSET_DIFF_S1_S2 48

int vmx_count;
int enter_vmx_ops(void)
{
	vmx_count++;
	return 1;
}

void exit_vmx_ops(void)
{
	vmx_count--;
}
int test_memcmp(const void *s1, const void *s2, size_t n);

/* test all offsets and lengths */
static void test_one(char *s1, char *s2, unsigned long max_offset,
		unsigned long size_start, unsigned long max_size)
{
	unsigned long offset, size;

	for (offset = 0; offset < max_offset; offset++) {
		for (size = size_start; size < (max_size - offset); size++) {
			int x, y;
			unsigned long i;

			y = memcmp(s1+offset, s2+offset, size);
			x = test_memcmp(s1+offset, s2+offset, size);

			if (((x ^ y) < 0) &&	/* Trick to compare sign */
				((x | y) != 0)) { /* check for zero */
				printf("memcmp returned %d, should have returned %d (offset %ld size %ld)\n", x, y, offset, size);

				for (i = offset; i < offset+size; i++)
					printf("%02x ", s1[i]);
				printf("\n");

				for (i = offset; i < offset+size; i++)
					printf("%02x ", s2[i]);
				printf("\n");
				abort();
			}

			if (vmx_count != 0) {
				printf("vmx enter/exit not paired.(offset:%ld size:%ld s1:%p s2:%p vc:%d\n",
					offset, size, s1, s2, vmx_count);
				printf("\n");
				abort();
			}
		}
	}
}

static int testcase(bool islarge)
{
	char *s1;
	char *s2;
	unsigned long i;

	unsigned long comp_size = (islarge ? LARGE_SIZE : SIZE);
	unsigned long alloc_size = comp_size + MAX_OFFSET_DIFF_S1_S2;
	int iterations = islarge ? LARGE_ITERATIONS : ITERATIONS;

	s1 = memalign(128, alloc_size);
	if (!s1) {
		perror("memalign");
		exit(1);
	}

	s2 = memalign(128, alloc_size);
	if (!s2) {
		perror("memalign");
		exit(1);
	}

	srandom(time(0));

	for (i = 0; i < iterations; i++) {
		unsigned long j;
		unsigned long change;
		char *rand_s1 = s1;
		char *rand_s2 = s2;

		for (j = 0; j < alloc_size; j++)
			s1[j] = random();

		rand_s1 += random() % MAX_OFFSET_DIFF_S1_S2;
		rand_s2 += random() % MAX_OFFSET_DIFF_S1_S2;
		memcpy(rand_s2, rand_s1, comp_size);

		/* change one byte */
		change = random() % comp_size;
		rand_s2[change] = random() & 0xff;

		if (islarge)
			test_one(rand_s1, rand_s2, LARGE_MAX_OFFSET,
					LARGE_SIZE_START, comp_size);
		else
			test_one(rand_s1, rand_s2, SIZE, 0, comp_size);
	}

	srandom(time(0));

	for (i = 0; i < iterations; i++) {
		unsigned long j;
		unsigned long change;
		char *rand_s1 = s1;
		char *rand_s2 = s2;

		for (j = 0; j < alloc_size; j++)
			s1[j] = random();

		rand_s1 += random() % MAX_OFFSET_DIFF_S1_S2;
		rand_s2 += random() % MAX_OFFSET_DIFF_S1_S2;
		memcpy(rand_s2, rand_s1, comp_size);

		/* change multiple bytes, 1/8 of total */
		for (j = 0; j < comp_size / 8; j++) {
			change = random() % comp_size;
			s2[change] = random() & 0xff;
		}

		if (islarge)
			test_one(rand_s1, rand_s2, LARGE_MAX_OFFSET,
					LARGE_SIZE_START, comp_size);
		else
			test_one(rand_s1, rand_s2, SIZE, 0, comp_size);
	}

	return 0;
}

static int testcases(void)
{
	testcase(0);
	testcase(1);
	return 0;
}

int main(void)
{
	test_harness_set_timeout(300);
	return test_harness(testcases, "memcmp");
}