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