1#!/usr/bin/env python3 2 3## 4## Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. 5## 6## This program is free software; you can redistribute it and/or modify 7## it under the terms of the GNU General Public License as published by 8## the Free Software Foundation; either version 2 of the License, or 9## (at your option) any later version. 10## 11## This program is distributed in the hope that it will be useful, 12## but WITHOUT ANY WARRANTY; without even the implied warranty of 13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14## GNU General Public License for more details. 15## 16## You should have received a copy of the GNU General Public License 17## along with this program; if not, see <http://www.gnu.org/licenses/>. 18## 19 20import sys 21import re 22import string 23import hex_common 24 25## 26## Helpers for gen_helper_function 27## 28def gen_decl_ea(f): 29 f.write(" uint32_t EA;\n") 30 31def gen_helper_return_type(f,regtype,regid,regno): 32 if regno > 1 : f.write(", ") 33 f.write("int32_t") 34 35def gen_helper_return_type_pair(f,regtype,regid,regno): 36 if regno > 1 : f.write(", ") 37 f.write("int64_t") 38 39def gen_helper_arg(f,regtype,regid,regno): 40 if regno > 0 : f.write(", " ) 41 f.write("int32_t %s%sV" % (regtype,regid)) 42 43def gen_helper_arg_new(f,regtype,regid,regno): 44 if regno >= 0 : f.write(", " ) 45 f.write("int32_t %s%sN" % (regtype,regid)) 46 47def gen_helper_arg_pair(f,regtype,regid,regno): 48 if regno >= 0 : f.write(", ") 49 f.write("int64_t %s%sV" % (regtype,regid)) 50 51def gen_helper_arg_ext(f,regtype,regid,regno): 52 if regno > 0 : f.write(", ") 53 f.write("void *%s%sV_void" % (regtype,regid)) 54 55def gen_helper_arg_ext_pair(f,regtype,regid,regno): 56 if regno > 0 : f.write(", ") 57 f.write("void *%s%sV_void" % (regtype,regid)) 58 59def gen_helper_arg_opn(f,regtype,regid,i,tag): 60 if (hex_common.is_pair(regid)): 61 if (hex_common.is_hvx_reg(regtype)): 62 gen_helper_arg_ext_pair(f,regtype,regid,i) 63 else: 64 gen_helper_arg_pair(f,regtype,regid,i) 65 elif (hex_common.is_single(regid)): 66 if hex_common.is_old_val(regtype, regid, tag): 67 if (hex_common.is_hvx_reg(regtype)): 68 gen_helper_arg_ext(f,regtype,regid,i) 69 else: 70 gen_helper_arg(f,regtype,regid,i) 71 elif hex_common.is_new_val(regtype, regid, tag): 72 gen_helper_arg_new(f,regtype,regid,i) 73 else: 74 print("Bad register parse: ",regtype,regid,toss,numregs) 75 else: 76 print("Bad register parse: ",regtype,regid,toss,numregs) 77 78def gen_helper_arg_imm(f,immlett): 79 f.write(", int32_t %s" % (hex_common.imm_name(immlett))) 80 81def gen_helper_dest_decl(f,regtype,regid,regno,subfield=""): 82 f.write(" int32_t %s%sV%s = 0;\n" % \ 83 (regtype,regid,subfield)) 84 85def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""): 86 f.write(" int64_t %s%sV%s = 0;\n" % \ 87 (regtype,regid,subfield)) 88 89def gen_helper_dest_decl_ext(f,regtype,regid): 90 if (regtype == "Q"): 91 f.write(" /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \ 92 (regtype,regid,regtype,regid)) 93 else: 94 f.write(" /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \ 95 (regtype,regid,regtype,regid)) 96 97def gen_helper_dest_decl_ext_pair(f,regtype,regid,regno): 98 f.write(" /* %s%sV is *(MMVectorPair *))%s%sV_void) */\n" % \ 99 (regtype,regid,regtype, regid)) 100 101def gen_helper_dest_decl_opn(f,regtype,regid,i): 102 if (hex_common.is_pair(regid)): 103 if (hex_common.is_hvx_reg(regtype)): 104 gen_helper_dest_decl_ext_pair(f,regtype,regid, i) 105 else: 106 gen_helper_dest_decl_pair(f,regtype,regid,i) 107 elif (hex_common.is_single(regid)): 108 if (hex_common.is_hvx_reg(regtype)): 109 gen_helper_dest_decl_ext(f,regtype,regid) 110 else: 111 gen_helper_dest_decl(f,regtype,regid,i) 112 else: 113 print("Bad register parse: ",regtype,regid,toss,numregs) 114 115def gen_helper_src_var_ext(f,regtype,regid): 116 if (regtype == "Q"): 117 f.write(" /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \ 118 (regtype,regid,regtype,regid)) 119 else: 120 f.write(" /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \ 121 (regtype,regid,regtype,regid)) 122 123def gen_helper_src_var_ext_pair(f,regtype,regid,regno): 124 f.write(" /* %s%sV%s is *(MMVectorPair *)(%s%sV%s_void) */\n" % \ 125 (regtype,regid,regno,regtype,regid,regno)) 126 127def gen_helper_return(f,regtype,regid,regno): 128 f.write(" return %s%sV;\n" % (regtype,regid)) 129 130def gen_helper_return_pair(f,regtype,regid,regno): 131 f.write(" return %s%sV;\n" % (regtype,regid)) 132 133def gen_helper_dst_write_ext(f,regtype,regid): 134 return 135 136def gen_helper_dst_write_ext_pair(f,regtype,regid): 137 return 138 139def gen_helper_return_opn(f, regtype, regid, i): 140 if (hex_common.is_pair(regid)): 141 if (hex_common.is_hvx_reg(regtype)): 142 gen_helper_dst_write_ext_pair(f,regtype,regid) 143 else: 144 gen_helper_return_pair(f,regtype,regid,i) 145 elif (hex_common.is_single(regid)): 146 if (hex_common.is_hvx_reg(regtype)): 147 gen_helper_dst_write_ext(f,regtype,regid) 148 else: 149 gen_helper_return(f,regtype,regid,i) 150 else: 151 print("Bad register parse: ",regtype,regid,toss,numregs) 152 153## 154## Generate the TCG code to call the helper 155## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;} 156## We produce: 157## int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV) 158## { 159## uint32_t slot __attribute__(unused)) = 4; 160## int32_t RdV = 0; 161## { RdV=RsV+RtV;} 162## COUNT_HELPER(A2_add); 163## return RdV; 164## } 165## 166def gen_helper_function(f, tag, tagregs, tagimms): 167 regs = tagregs[tag] 168 imms = tagimms[tag] 169 170 numresults = 0 171 numscalarresults = 0 172 numscalarreadwrite = 0 173 for regtype,regid,toss,numregs in regs: 174 if (hex_common.is_written(regid)): 175 numresults += 1 176 if (hex_common.is_scalar_reg(regtype)): 177 numscalarresults += 1 178 if (hex_common.is_readwrite(regid)): 179 if (hex_common.is_scalar_reg(regtype)): 180 numscalarreadwrite += 1 181 182 if (numscalarresults > 1): 183 ## The helper is bogus when there is more than one result 184 f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s); }\n" 185 % (tag, tag)) 186 else: 187 ## The return type of the function is the type of the destination 188 ## register (if scalar) 189 i=0 190 for regtype,regid,toss,numregs in regs: 191 if (hex_common.is_written(regid)): 192 if (hex_common.is_pair(regid)): 193 if (hex_common.is_hvx_reg(regtype)): 194 continue 195 else: 196 gen_helper_return_type_pair(f,regtype,regid,i) 197 elif (hex_common.is_single(regid)): 198 if (hex_common.is_hvx_reg(regtype)): 199 continue 200 else: 201 gen_helper_return_type(f,regtype,regid,i) 202 else: 203 print("Bad register parse: ",regtype,regid,toss,numregs) 204 i += 1 205 206 if (numscalarresults == 0): 207 f.write("void") 208 f.write(" HELPER(%s)(CPUHexagonState *env" % tag) 209 210 ## Arguments include the vector destination operands 211 i = 1 212 for regtype,regid,toss,numregs in regs: 213 if (hex_common.is_written(regid)): 214 if (hex_common.is_pair(regid)): 215 if (hex_common.is_hvx_reg(regtype)): 216 gen_helper_arg_ext_pair(f,regtype,regid,i) 217 else: 218 continue 219 elif (hex_common.is_single(regid)): 220 if (hex_common.is_hvx_reg(regtype)): 221 gen_helper_arg_ext(f,regtype,regid,i) 222 else: 223 # This is the return value of the function 224 continue 225 else: 226 print("Bad register parse: ",regtype,regid,toss,numregs) 227 i += 1 228 229 ## Arguments to the helper function are the source regs and immediates 230 for regtype,regid,toss,numregs in regs: 231 if (hex_common.is_read(regid)): 232 if (hex_common.is_hvx_reg(regtype) and 233 hex_common.is_readwrite(regid)): 234 continue 235 gen_helper_arg_opn(f,regtype,regid,i,tag) 236 i += 1 237 for immlett,bits,immshift in imms: 238 gen_helper_arg_imm(f,immlett) 239 i += 1 240 241 if (hex_common.need_pkt_has_multi_cof(tag)): 242 f.write(", uint32_t pkt_has_multi_cof") 243 244 if hex_common.need_PC(tag): 245 if i > 0: f.write(", ") 246 f.write("target_ulong PC") 247 i += 1 248 if hex_common.helper_needs_next_PC(tag): 249 if i > 0: f.write(", ") 250 f.write("target_ulong next_PC") 251 i += 1 252 if hex_common.need_slot(tag): 253 if i > 0: f.write(", ") 254 f.write("uint32_t slot") 255 i += 1 256 if hex_common.need_part1(tag): 257 if i > 0: f.write(", ") 258 f.write("uint32_t part1") 259 f.write(")\n{\n") 260 if (not hex_common.need_slot(tag)): 261 f.write(" uint32_t slot __attribute__((unused)) = 4;\n" ) 262 if hex_common.need_ea(tag): gen_decl_ea(f) 263 ## Declare the return variable 264 i=0 265 for regtype,regid,toss,numregs in regs: 266 if (hex_common.is_writeonly(regid)): 267 gen_helper_dest_decl_opn(f,regtype,regid,i) 268 i += 1 269 270 for regtype,regid,toss,numregs in regs: 271 if (hex_common.is_read(regid)): 272 if (hex_common.is_pair(regid)): 273 if (hex_common.is_hvx_reg(regtype)): 274 gen_helper_src_var_ext_pair(f,regtype,regid,i) 275 elif (hex_common.is_single(regid)): 276 if (hex_common.is_hvx_reg(regtype)): 277 gen_helper_src_var_ext(f,regtype,regid) 278 else: 279 print("Bad register parse: ",regtype,regid,toss,numregs) 280 281 if 'A_FPOP' in hex_common.attribdict[tag]: 282 f.write(' arch_fpop_start(env);\n'); 283 284 f.write(" %s\n" % hex_common.semdict[tag]) 285 286 if 'A_FPOP' in hex_common.attribdict[tag]: 287 f.write(' arch_fpop_end(env);\n'); 288 289 ## Save/return the return variable 290 for regtype,regid,toss,numregs in regs: 291 if (hex_common.is_written(regid)): 292 gen_helper_return_opn(f, regtype, regid, i) 293 f.write("}\n\n") 294 ## End of the helper definition 295 296def main(): 297 hex_common.read_semantics_file(sys.argv[1]) 298 hex_common.read_attribs_file(sys.argv[2]) 299 hex_common.read_overrides_file(sys.argv[3]) 300 hex_common.read_overrides_file(sys.argv[4]) 301 ## Whether or not idef-parser is enabled is 302 ## determined by the number of arguments to 303 ## this script: 304 ## 305 ## 5 args. -> not enabled, 306 ## 6 args. -> idef-parser enabled. 307 ## 308 ## The 6:th arg. then holds a list of the successfully 309 ## parsed instructions. 310 is_idef_parser_enabled = len(sys.argv) > 6 311 if is_idef_parser_enabled: 312 hex_common.read_idef_parser_enabled_file(sys.argv[5]) 313 hex_common.calculate_attribs() 314 tagregs = hex_common.get_tagregs() 315 tagimms = hex_common.get_tagimms() 316 317 output_file = sys.argv[-1] 318 with open(output_file, 'w') as f: 319 for tag in hex_common.tags: 320 ## Skip the priv instructions 321 if ( "A_PRIV" in hex_common.attribdict[tag] ) : 322 continue 323 ## Skip the guest instructions 324 if ( "A_GUEST" in hex_common.attribdict[tag] ) : 325 continue 326 ## Skip the diag instructions 327 if ( tag == "Y6_diag" ) : 328 continue 329 if ( tag == "Y6_diag0" ) : 330 continue 331 if ( tag == "Y6_diag1" ) : 332 continue 333 if ( hex_common.skip_qemu_helper(tag) ): 334 continue 335 if ( hex_common.is_idef_parser_enabled(tag) ): 336 continue 337 338 gen_helper_function(f, tag, tagregs, tagimms) 339 340if __name__ == "__main__": 341 main() 342