xref: /linux/tools/perf/util/annotate-arch/annotate-sparc.c (revision c7decec2f2d2ab0366567f9e30c0e1418cece43f)
107b972ffSIan Rogers // SPDX-License-Identifier: GPL-2.0
207b972ffSIan Rogers #include <string.h>
307b972ffSIan Rogers #include <linux/compiler.h>
4*0e26ba5aSIan Rogers #include <linux/zalloc.h>
507b972ffSIan Rogers #include "../../util/disasm.h"
607b972ffSIan Rogers 
is_branch_cond(const char * cond)707b972ffSIan Rogers static int is_branch_cond(const char *cond)
807b972ffSIan Rogers {
907b972ffSIan Rogers 	if (cond[0] == '\0')
1007b972ffSIan Rogers 		return 1;
1107b972ffSIan Rogers 
1207b972ffSIan Rogers 	if (cond[0] == 'a' && cond[1] == '\0')
1307b972ffSIan Rogers 		return 1;
1407b972ffSIan Rogers 
1507b972ffSIan Rogers 	if (cond[0] == 'c' &&
1607b972ffSIan Rogers 	    (cond[1] == 'c' || cond[1] == 's') &&
1707b972ffSIan Rogers 	    cond[2] == '\0')
1807b972ffSIan Rogers 		return 1;
1907b972ffSIan Rogers 
2007b972ffSIan Rogers 	if (cond[0] == 'e' &&
2107b972ffSIan Rogers 	    (cond[1] == '\0' ||
2207b972ffSIan Rogers 	     (cond[1] == 'q' && cond[2] == '\0')))
2307b972ffSIan Rogers 		return 1;
2407b972ffSIan Rogers 
2507b972ffSIan Rogers 	if (cond[0] == 'g' &&
2607b972ffSIan Rogers 	    (cond[1] == '\0' ||
2707b972ffSIan Rogers 	     (cond[1] == 't' && cond[2] == '\0') ||
2807b972ffSIan Rogers 	     (cond[1] == 'e' && cond[2] == '\0') ||
2907b972ffSIan Rogers 	     (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
3007b972ffSIan Rogers 		return 1;
3107b972ffSIan Rogers 
3207b972ffSIan Rogers 	if (cond[0] == 'l' &&
3307b972ffSIan Rogers 	    (cond[1] == '\0' ||
3407b972ffSIan Rogers 	     (cond[1] == 't' && cond[2] == '\0') ||
3507b972ffSIan Rogers 	     (cond[1] == 'u' && cond[2] == '\0') ||
3607b972ffSIan Rogers 	     (cond[1] == 'e' && cond[2] == '\0') ||
3707b972ffSIan Rogers 	     (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
3807b972ffSIan Rogers 		return 1;
3907b972ffSIan Rogers 
4007b972ffSIan Rogers 	if (cond[0] == 'n' &&
4107b972ffSIan Rogers 	    (cond[1] == '\0' ||
4207b972ffSIan Rogers 	     (cond[1] == 'e' && cond[2] == '\0') ||
4307b972ffSIan Rogers 	     (cond[1] == 'z' && cond[2] == '\0') ||
4407b972ffSIan Rogers 	     (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
4507b972ffSIan Rogers 		return 1;
4607b972ffSIan Rogers 
4707b972ffSIan Rogers 	if (cond[0] == 'b' &&
4807b972ffSIan Rogers 	    cond[1] == 'p' &&
4907b972ffSIan Rogers 	    cond[2] == 'o' &&
5007b972ffSIan Rogers 	    cond[3] == 's' &&
5107b972ffSIan Rogers 	    cond[4] == '\0')
5207b972ffSIan Rogers 		return 1;
5307b972ffSIan Rogers 
5407b972ffSIan Rogers 	if (cond[0] == 'v' &&
5507b972ffSIan Rogers 	    (cond[1] == 'c' || cond[1] == 's') &&
5607b972ffSIan Rogers 	    cond[2] == '\0')
5707b972ffSIan Rogers 		return 1;
5807b972ffSIan Rogers 
5907b972ffSIan Rogers 	if (cond[0] == 'b' &&
6007b972ffSIan Rogers 	    cond[1] == 'z' &&
6107b972ffSIan Rogers 	    cond[2] == '\0')
6207b972ffSIan Rogers 		return 1;
6307b972ffSIan Rogers 
6407b972ffSIan Rogers 	return 0;
6507b972ffSIan Rogers }
6607b972ffSIan Rogers 
is_branch_reg_cond(const char * cond)6707b972ffSIan Rogers static int is_branch_reg_cond(const char *cond)
6807b972ffSIan Rogers {
6907b972ffSIan Rogers 	if ((cond[0] == 'n' || cond[0] == 'l') &&
7007b972ffSIan Rogers 	    cond[1] == 'z' &&
7107b972ffSIan Rogers 	    cond[2] == '\0')
7207b972ffSIan Rogers 		return 1;
7307b972ffSIan Rogers 
7407b972ffSIan Rogers 	if (cond[0] == 'z' &&
7507b972ffSIan Rogers 	    cond[1] == '\0')
7607b972ffSIan Rogers 		return 1;
7707b972ffSIan Rogers 
7807b972ffSIan Rogers 	if ((cond[0] == 'g' || cond[0] == 'l') &&
7907b972ffSIan Rogers 	    cond[1] == 'e' &&
8007b972ffSIan Rogers 	    cond[2] == 'z' &&
8107b972ffSIan Rogers 	    cond[3] == '\0')
8207b972ffSIan Rogers 		return 1;
8307b972ffSIan Rogers 
8407b972ffSIan Rogers 	if (cond[0] == 'g' &&
8507b972ffSIan Rogers 	    cond[1] == 'z' &&
8607b972ffSIan Rogers 	    cond[2] == '\0')
8707b972ffSIan Rogers 		return 1;
8807b972ffSIan Rogers 
8907b972ffSIan Rogers 	return 0;
9007b972ffSIan Rogers }
9107b972ffSIan Rogers 
is_branch_float_cond(const char * cond)9207b972ffSIan Rogers static int is_branch_float_cond(const char *cond)
9307b972ffSIan Rogers {
9407b972ffSIan Rogers 	if (cond[0] == '\0')
9507b972ffSIan Rogers 		return 1;
9607b972ffSIan Rogers 
9707b972ffSIan Rogers 	if ((cond[0] == 'a' || cond[0] == 'e' ||
9807b972ffSIan Rogers 	     cond[0] == 'z' || cond[0] == 'g' ||
9907b972ffSIan Rogers 	     cond[0] == 'l' || cond[0] == 'n' ||
10007b972ffSIan Rogers 	     cond[0] == 'o' || cond[0] == 'u') &&
10107b972ffSIan Rogers 	    cond[1] == '\0')
10207b972ffSIan Rogers 		return 1;
10307b972ffSIan Rogers 
10407b972ffSIan Rogers 	if (((cond[0] == 'g' && cond[1] == 'e') ||
10507b972ffSIan Rogers 	     (cond[0] == 'l' && (cond[1] == 'e' ||
10607b972ffSIan Rogers 				 cond[1] == 'g')) ||
10707b972ffSIan Rogers 	     (cond[0] == 'n' && (cond[1] == 'e' ||
10807b972ffSIan Rogers 				 cond[1] == 'z')) ||
10907b972ffSIan Rogers 	     (cond[0] == 'u' && (cond[1] == 'e' ||
11007b972ffSIan Rogers 				 cond[1] == 'g' ||
11107b972ffSIan Rogers 				 cond[1] == 'l'))) &&
11207b972ffSIan Rogers 	    cond[2] == '\0')
11307b972ffSIan Rogers 		return 1;
11407b972ffSIan Rogers 
11507b972ffSIan Rogers 	if (cond[0] == 'u' &&
11607b972ffSIan Rogers 	    (cond[1] == 'g' || cond[1] == 'l') &&
11707b972ffSIan Rogers 	    cond[2] == 'e' &&
11807b972ffSIan Rogers 	    cond[3] == '\0')
11907b972ffSIan Rogers 		return 1;
12007b972ffSIan Rogers 
12107b972ffSIan Rogers 	return 0;
12207b972ffSIan Rogers }
12307b972ffSIan Rogers 
sparc__associate_instruction_ops(struct arch * arch,const char * name)12407b972ffSIan Rogers static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
12507b972ffSIan Rogers {
12607b972ffSIan Rogers 	const struct ins_ops *ops = NULL;
12707b972ffSIan Rogers 
12807b972ffSIan Rogers 	if (!strcmp(name, "call") ||
12907b972ffSIan Rogers 	    !strcmp(name, "jmp") ||
13007b972ffSIan Rogers 	    !strcmp(name, "jmpl")) {
13107b972ffSIan Rogers 		ops = &call_ops;
13207b972ffSIan Rogers 	} else if (!strcmp(name, "ret") ||
13307b972ffSIan Rogers 		   !strcmp(name, "retl") ||
13407b972ffSIan Rogers 		   !strcmp(name, "return")) {
13507b972ffSIan Rogers 		ops = &ret_ops;
13607b972ffSIan Rogers 	} else if (!strcmp(name, "mov")) {
13707b972ffSIan Rogers 		ops = &mov_ops;
13807b972ffSIan Rogers 	} else {
13907b972ffSIan Rogers 		if (name[0] == 'c' &&
14007b972ffSIan Rogers 		    (name[1] == 'w' || name[1] == 'x'))
14107b972ffSIan Rogers 			name += 2;
14207b972ffSIan Rogers 
14307b972ffSIan Rogers 		if (name[0] == 'b') {
14407b972ffSIan Rogers 			const char *cond = name + 1;
14507b972ffSIan Rogers 
14607b972ffSIan Rogers 			if (cond[0] == 'r') {
14707b972ffSIan Rogers 				if (is_branch_reg_cond(cond + 1))
14807b972ffSIan Rogers 					ops = &jump_ops;
14907b972ffSIan Rogers 			} else if (is_branch_cond(cond)) {
15007b972ffSIan Rogers 				ops = &jump_ops;
15107b972ffSIan Rogers 			}
15207b972ffSIan Rogers 		} else if (name[0] == 'f' && name[1] == 'b') {
15307b972ffSIan Rogers 			if (is_branch_float_cond(name + 2))
15407b972ffSIan Rogers 				ops = &jump_ops;
15507b972ffSIan Rogers 		}
15607b972ffSIan Rogers 	}
15707b972ffSIan Rogers 
15807b972ffSIan Rogers 	if (ops)
15907b972ffSIan Rogers 		arch__associate_ins_ops(arch, name, ops);
16007b972ffSIan Rogers 
16107b972ffSIan Rogers 	return ops;
16207b972ffSIan Rogers }
16307b972ffSIan Rogers 
arch__new_sparc(const struct e_machine_and_e_flags * id,const char * cpuid __maybe_unused)164*0e26ba5aSIan Rogers const struct arch *arch__new_sparc(const struct e_machine_and_e_flags *id,
165*0e26ba5aSIan Rogers 				   const char *cpuid __maybe_unused)
16607b972ffSIan Rogers {
167*0e26ba5aSIan Rogers 	struct arch *arch = zalloc(sizeof(*arch));
168*0e26ba5aSIan Rogers 
169*0e26ba5aSIan Rogers 	if (!arch)
170*0e26ba5aSIan Rogers 		return NULL;
171*0e26ba5aSIan Rogers 
172*0e26ba5aSIan Rogers 	arch->name = "sparc";
173*0e26ba5aSIan Rogers 	arch->id = *id;
17407b972ffSIan Rogers 	arch->associate_instruction_ops = sparc__associate_instruction_ops;
17507b972ffSIan Rogers 	arch->objdump.comment_char = '#';
176*0e26ba5aSIan Rogers 	return arch;
17707b972ffSIan Rogers }
178