1 // SPDX-License-Identifier: GPL-2.0 2 #include <string.h> 3 #include <linux/compiler.h> 4 #include "../../util/disasm.h" 5 6 static int is_branch_cond(const char *cond) 7 { 8 if (cond[0] == '\0') 9 return 1; 10 11 if (cond[0] == 'a' && cond[1] == '\0') 12 return 1; 13 14 if (cond[0] == 'c' && 15 (cond[1] == 'c' || cond[1] == 's') && 16 cond[2] == '\0') 17 return 1; 18 19 if (cond[0] == 'e' && 20 (cond[1] == '\0' || 21 (cond[1] == 'q' && cond[2] == '\0'))) 22 return 1; 23 24 if (cond[0] == 'g' && 25 (cond[1] == '\0' || 26 (cond[1] == 't' && cond[2] == '\0') || 27 (cond[1] == 'e' && cond[2] == '\0') || 28 (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0'))) 29 return 1; 30 31 if (cond[0] == 'l' && 32 (cond[1] == '\0' || 33 (cond[1] == 't' && cond[2] == '\0') || 34 (cond[1] == 'u' && cond[2] == '\0') || 35 (cond[1] == 'e' && cond[2] == '\0') || 36 (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0'))) 37 return 1; 38 39 if (cond[0] == 'n' && 40 (cond[1] == '\0' || 41 (cond[1] == 'e' && cond[2] == '\0') || 42 (cond[1] == 'z' && cond[2] == '\0') || 43 (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0'))) 44 return 1; 45 46 if (cond[0] == 'b' && 47 cond[1] == 'p' && 48 cond[2] == 'o' && 49 cond[3] == 's' && 50 cond[4] == '\0') 51 return 1; 52 53 if (cond[0] == 'v' && 54 (cond[1] == 'c' || cond[1] == 's') && 55 cond[2] == '\0') 56 return 1; 57 58 if (cond[0] == 'b' && 59 cond[1] == 'z' && 60 cond[2] == '\0') 61 return 1; 62 63 return 0; 64 } 65 66 static int is_branch_reg_cond(const char *cond) 67 { 68 if ((cond[0] == 'n' || cond[0] == 'l') && 69 cond[1] == 'z' && 70 cond[2] == '\0') 71 return 1; 72 73 if (cond[0] == 'z' && 74 cond[1] == '\0') 75 return 1; 76 77 if ((cond[0] == 'g' || cond[0] == 'l') && 78 cond[1] == 'e' && 79 cond[2] == 'z' && 80 cond[3] == '\0') 81 return 1; 82 83 if (cond[0] == 'g' && 84 cond[1] == 'z' && 85 cond[2] == '\0') 86 return 1; 87 88 return 0; 89 } 90 91 static int is_branch_float_cond(const char *cond) 92 { 93 if (cond[0] == '\0') 94 return 1; 95 96 if ((cond[0] == 'a' || cond[0] == 'e' || 97 cond[0] == 'z' || cond[0] == 'g' || 98 cond[0] == 'l' || cond[0] == 'n' || 99 cond[0] == 'o' || cond[0] == 'u') && 100 cond[1] == '\0') 101 return 1; 102 103 if (((cond[0] == 'g' && cond[1] == 'e') || 104 (cond[0] == 'l' && (cond[1] == 'e' || 105 cond[1] == 'g')) || 106 (cond[0] == 'n' && (cond[1] == 'e' || 107 cond[1] == 'z')) || 108 (cond[0] == 'u' && (cond[1] == 'e' || 109 cond[1] == 'g' || 110 cond[1] == 'l'))) && 111 cond[2] == '\0') 112 return 1; 113 114 if (cond[0] == 'u' && 115 (cond[1] == 'g' || cond[1] == 'l') && 116 cond[2] == 'e' && 117 cond[3] == '\0') 118 return 1; 119 120 return 0; 121 } 122 123 static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name) 124 { 125 const struct ins_ops *ops = NULL; 126 127 if (!strcmp(name, "call") || 128 !strcmp(name, "jmp") || 129 !strcmp(name, "jmpl")) { 130 ops = &call_ops; 131 } else if (!strcmp(name, "ret") || 132 !strcmp(name, "retl") || 133 !strcmp(name, "return")) { 134 ops = &ret_ops; 135 } else if (!strcmp(name, "mov")) { 136 ops = &mov_ops; 137 } else { 138 if (name[0] == 'c' && 139 (name[1] == 'w' || name[1] == 'x')) 140 name += 2; 141 142 if (name[0] == 'b') { 143 const char *cond = name + 1; 144 145 if (cond[0] == 'r') { 146 if (is_branch_reg_cond(cond + 1)) 147 ops = &jump_ops; 148 } else if (is_branch_cond(cond)) { 149 ops = &jump_ops; 150 } 151 } else if (name[0] == 'f' && name[1] == 'b') { 152 if (is_branch_float_cond(name + 2)) 153 ops = &jump_ops; 154 } 155 } 156 157 if (ops) 158 arch__associate_ins_ops(arch, name, ops); 159 160 return ops; 161 } 162 163 int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused) 164 { 165 if (!arch->initialized) { 166 arch->initialized = true; 167 arch->associate_instruction_ops = sparc__associate_instruction_ops; 168 arch->objdump.comment_char = '#'; 169 } 170 171 return 0; 172 } 173