1#!/usr/bin/env python3 2 3## 4## Copyright(c) 2019-2021 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_slot(tag): 242 if i > 0: f.write(", ") 243 f.write("uint32_t slot") 244 i += 1 245 if hex_common.need_part1(tag): 246 if i > 0: f.write(", ") 247 f.write("uint32_t part1") 248 f.write(")\n{\n") 249 if (not hex_common.need_slot(tag)): 250 f.write(" uint32_t slot __attribute__((unused)) = 4;\n" ) 251 if hex_common.need_ea(tag): gen_decl_ea(f) 252 ## Declare the return variable 253 i=0 254 for regtype,regid,toss,numregs in regs: 255 if (hex_common.is_writeonly(regid)): 256 gen_helper_dest_decl_opn(f,regtype,regid,i) 257 i += 1 258 259 for regtype,regid,toss,numregs in regs: 260 if (hex_common.is_read(regid)): 261 if (hex_common.is_pair(regid)): 262 if (hex_common.is_hvx_reg(regtype)): 263 gen_helper_src_var_ext_pair(f,regtype,regid,i) 264 elif (hex_common.is_single(regid)): 265 if (hex_common.is_hvx_reg(regtype)): 266 gen_helper_src_var_ext(f,regtype,regid) 267 else: 268 print("Bad register parse: ",regtype,regid,toss,numregs) 269 270 if 'A_FPOP' in hex_common.attribdict[tag]: 271 f.write(' arch_fpop_start(env);\n'); 272 273 f.write(" %s\n" % hex_common.semdict[tag]) 274 275 if 'A_FPOP' in hex_common.attribdict[tag]: 276 f.write(' arch_fpop_end(env);\n'); 277 278 ## Save/return the return variable 279 for regtype,regid,toss,numregs in regs: 280 if (hex_common.is_written(regid)): 281 gen_helper_return_opn(f, regtype, regid, i) 282 f.write("}\n\n") 283 ## End of the helper definition 284 285def main(): 286 hex_common.read_semantics_file(sys.argv[1]) 287 hex_common.read_attribs_file(sys.argv[2]) 288 hex_common.read_overrides_file(sys.argv[3]) 289 hex_common.read_overrides_file(sys.argv[4]) 290 hex_common.calculate_attribs() 291 tagregs = hex_common.get_tagregs() 292 tagimms = hex_common.get_tagimms() 293 294 with open(sys.argv[5], 'w') as f: 295 for tag in hex_common.tags: 296 ## Skip the priv instructions 297 if ( "A_PRIV" in hex_common.attribdict[tag] ) : 298 continue 299 ## Skip the guest instructions 300 if ( "A_GUEST" in hex_common.attribdict[tag] ) : 301 continue 302 ## Skip the diag instructions 303 if ( tag == "Y6_diag" ) : 304 continue 305 if ( tag == "Y6_diag0" ) : 306 continue 307 if ( tag == "Y6_diag1" ) : 308 continue 309 if ( hex_common.skip_qemu_helper(tag) ): 310 continue 311 312 gen_helper_function(f, tag, tagregs, tagimms) 313 314if __name__ == "__main__": 315 main() 316