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