162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_cistatic int is_branch_cond(const char *cond)
462306a36Sopenharmony_ci{
562306a36Sopenharmony_ci	if (cond[0] == '\0')
662306a36Sopenharmony_ci		return 1;
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci	if (cond[0] == 'a' && cond[1] == '\0')
962306a36Sopenharmony_ci		return 1;
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci	if (cond[0] == 'c' &&
1262306a36Sopenharmony_ci	    (cond[1] == 'c' || cond[1] == 's') &&
1362306a36Sopenharmony_ci	    cond[2] == '\0')
1462306a36Sopenharmony_ci		return 1;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	if (cond[0] == 'e' &&
1762306a36Sopenharmony_ci	    (cond[1] == '\0' ||
1862306a36Sopenharmony_ci	     (cond[1] == 'q' && cond[2] == '\0')))
1962306a36Sopenharmony_ci		return 1;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (cond[0] == 'g' &&
2262306a36Sopenharmony_ci	    (cond[1] == '\0' ||
2362306a36Sopenharmony_ci	     (cond[1] == 't' && cond[2] == '\0') ||
2462306a36Sopenharmony_ci	     (cond[1] == 'e' && cond[2] == '\0') ||
2562306a36Sopenharmony_ci	     (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
2662306a36Sopenharmony_ci		return 1;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	if (cond[0] == 'l' &&
2962306a36Sopenharmony_ci	    (cond[1] == '\0' ||
3062306a36Sopenharmony_ci	     (cond[1] == 't' && cond[2] == '\0') ||
3162306a36Sopenharmony_ci	     (cond[1] == 'u' && cond[2] == '\0') ||
3262306a36Sopenharmony_ci	     (cond[1] == 'e' && cond[2] == '\0') ||
3362306a36Sopenharmony_ci	     (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
3462306a36Sopenharmony_ci		return 1;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	if (cond[0] == 'n' &&
3762306a36Sopenharmony_ci	    (cond[1] == '\0' ||
3862306a36Sopenharmony_ci	     (cond[1] == 'e' && cond[2] == '\0') ||
3962306a36Sopenharmony_ci	     (cond[1] == 'z' && cond[2] == '\0') ||
4062306a36Sopenharmony_ci	     (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
4162306a36Sopenharmony_ci		return 1;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (cond[0] == 'b' &&
4462306a36Sopenharmony_ci	    cond[1] == 'p' &&
4562306a36Sopenharmony_ci	    cond[2] == 'o' &&
4662306a36Sopenharmony_ci	    cond[3] == 's' &&
4762306a36Sopenharmony_ci	    cond[4] == '\0')
4862306a36Sopenharmony_ci		return 1;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (cond[0] == 'v' &&
5162306a36Sopenharmony_ci	    (cond[1] == 'c' || cond[1] == 's') &&
5262306a36Sopenharmony_ci	    cond[2] == '\0')
5362306a36Sopenharmony_ci		return 1;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (cond[0] == 'b' &&
5662306a36Sopenharmony_ci	    cond[1] == 'z' &&
5762306a36Sopenharmony_ci	    cond[2] == '\0')
5862306a36Sopenharmony_ci		return 1;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return 0;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic int is_branch_reg_cond(const char *cond)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	if ((cond[0] == 'n' || cond[0] == 'l') &&
6662306a36Sopenharmony_ci	    cond[1] == 'z' &&
6762306a36Sopenharmony_ci	    cond[2] == '\0')
6862306a36Sopenharmony_ci		return 1;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	if (cond[0] == 'z' &&
7162306a36Sopenharmony_ci	    cond[1] == '\0')
7262306a36Sopenharmony_ci		return 1;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if ((cond[0] == 'g' || cond[0] == 'l') &&
7562306a36Sopenharmony_ci	    cond[1] == 'e' &&
7662306a36Sopenharmony_ci	    cond[2] == 'z' &&
7762306a36Sopenharmony_ci	    cond[3] == '\0')
7862306a36Sopenharmony_ci		return 1;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (cond[0] == 'g' &&
8162306a36Sopenharmony_ci	    cond[1] == 'z' &&
8262306a36Sopenharmony_ci	    cond[2] == '\0')
8362306a36Sopenharmony_ci		return 1;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	return 0;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic int is_branch_float_cond(const char *cond)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	if (cond[0] == '\0')
9162306a36Sopenharmony_ci		return 1;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if ((cond[0] == 'a' || cond[0] == 'e' ||
9462306a36Sopenharmony_ci	     cond[0] == 'z' || cond[0] == 'g' ||
9562306a36Sopenharmony_ci	     cond[0] == 'l' || cond[0] == 'n' ||
9662306a36Sopenharmony_ci	     cond[0] == 'o' || cond[0] == 'u') &&
9762306a36Sopenharmony_ci	    cond[1] == '\0')
9862306a36Sopenharmony_ci		return 1;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if (((cond[0] == 'g' && cond[1] == 'e') ||
10162306a36Sopenharmony_ci	     (cond[0] == 'l' && (cond[1] == 'e' ||
10262306a36Sopenharmony_ci				 cond[1] == 'g')) ||
10362306a36Sopenharmony_ci	     (cond[0] == 'n' && (cond[1] == 'e' ||
10462306a36Sopenharmony_ci				 cond[1] == 'z')) ||
10562306a36Sopenharmony_ci	     (cond[0] == 'u' && (cond[1] == 'e' ||
10662306a36Sopenharmony_ci				 cond[1] == 'g' ||
10762306a36Sopenharmony_ci				 cond[1] == 'l'))) &&
10862306a36Sopenharmony_ci	    cond[2] == '\0')
10962306a36Sopenharmony_ci		return 1;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	if (cond[0] == 'u' &&
11262306a36Sopenharmony_ci	    (cond[1] == 'g' || cond[1] == 'l') &&
11362306a36Sopenharmony_ci	    cond[2] == 'e' &&
11462306a36Sopenharmony_ci	    cond[3] == '\0')
11562306a36Sopenharmony_ci		return 1;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	return 0;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct ins_ops *ops = NULL;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (!strcmp(name, "call") ||
12562306a36Sopenharmony_ci	    !strcmp(name, "jmp") ||
12662306a36Sopenharmony_ci	    !strcmp(name, "jmpl")) {
12762306a36Sopenharmony_ci		ops = &call_ops;
12862306a36Sopenharmony_ci	} else if (!strcmp(name, "ret") ||
12962306a36Sopenharmony_ci		   !strcmp(name, "retl") ||
13062306a36Sopenharmony_ci		   !strcmp(name, "return")) {
13162306a36Sopenharmony_ci		ops = &ret_ops;
13262306a36Sopenharmony_ci	} else if (!strcmp(name, "mov")) {
13362306a36Sopenharmony_ci		ops = &mov_ops;
13462306a36Sopenharmony_ci	} else {
13562306a36Sopenharmony_ci		if (name[0] == 'c' &&
13662306a36Sopenharmony_ci		    (name[1] == 'w' || name[1] == 'x'))
13762306a36Sopenharmony_ci			name += 2;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		if (name[0] == 'b') {
14062306a36Sopenharmony_ci			const char *cond = name + 1;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci			if (cond[0] == 'r') {
14362306a36Sopenharmony_ci				if (is_branch_reg_cond(cond + 1))
14462306a36Sopenharmony_ci					ops = &jump_ops;
14562306a36Sopenharmony_ci			} else if (is_branch_cond(cond)) {
14662306a36Sopenharmony_ci				ops = &jump_ops;
14762306a36Sopenharmony_ci			}
14862306a36Sopenharmony_ci		} else if (name[0] == 'f' && name[1] == 'b') {
14962306a36Sopenharmony_ci			if (is_branch_float_cond(name + 2))
15062306a36Sopenharmony_ci				ops = &jump_ops;
15162306a36Sopenharmony_ci		}
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	if (ops)
15562306a36Sopenharmony_ci		arch__associate_ins_ops(arch, name, ops);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	return ops;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	if (!arch->initialized) {
16362306a36Sopenharmony_ci		arch->initialized = true;
16462306a36Sopenharmony_ci		arch->associate_instruction_ops = sparc__associate_instruction_ops;
16562306a36Sopenharmony_ci		arch->objdump.comment_char = '#';
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	return 0;
16962306a36Sopenharmony_ci}
170