1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/adlc/output_c.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,4049 @@ 1.4 +/* 1.5 + * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// output_c.cpp - Class CPP file output routines for architecture definition 1.29 + 1.30 +#include "adlc.hpp" 1.31 + 1.32 +// Utilities to characterize effect statements 1.33 +static bool is_def(int usedef) { 1.34 + switch(usedef) { 1.35 + case Component::DEF: 1.36 + case Component::USE_DEF: return true; break; 1.37 + } 1.38 + return false; 1.39 +} 1.40 + 1.41 +static bool is_use(int usedef) { 1.42 + switch(usedef) { 1.43 + case Component::USE: 1.44 + case Component::USE_DEF: 1.45 + case Component::USE_KILL: return true; break; 1.46 + } 1.47 + return false; 1.48 +} 1.49 + 1.50 +static bool is_kill(int usedef) { 1.51 + switch(usedef) { 1.52 + case Component::KILL: 1.53 + case Component::USE_KILL: return true; break; 1.54 + } 1.55 + return false; 1.56 +} 1.57 + 1.58 +// Define an array containing the machine register names, strings. 1.59 +static void defineRegNames(FILE *fp, RegisterForm *registers) { 1.60 + if (registers) { 1.61 + fprintf(fp,"\n"); 1.62 + fprintf(fp,"// An array of character pointers to machine register names.\n"); 1.63 + fprintf(fp,"const char *Matcher::regName[REG_COUNT] = {\n"); 1.64 + 1.65 + // Output the register name for each register in the allocation classes 1.66 + RegDef *reg_def = NULL; 1.67 + RegDef *next = NULL; 1.68 + registers->reset_RegDefs(); 1.69 + for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { 1.70 + next = registers->iter_RegDefs(); 1.71 + const char *comma = (next != NULL) ? "," : " // no trailing comma"; 1.72 + fprintf(fp," \"%s\"%s\n", 1.73 + reg_def->_regname, comma ); 1.74 + } 1.75 + 1.76 + // Finish defining enumeration 1.77 + fprintf(fp,"};\n"); 1.78 + 1.79 + fprintf(fp,"\n"); 1.80 + fprintf(fp,"// An array of character pointers to machine register names.\n"); 1.81 + fprintf(fp,"const VMReg OptoReg::opto2vm[REG_COUNT] = {\n"); 1.82 + reg_def = NULL; 1.83 + next = NULL; 1.84 + registers->reset_RegDefs(); 1.85 + for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { 1.86 + next = registers->iter_RegDefs(); 1.87 + const char *comma = (next != NULL) ? "," : " // no trailing comma"; 1.88 + fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma ); 1.89 + } 1.90 + // Finish defining array 1.91 + fprintf(fp,"\t};\n"); 1.92 + fprintf(fp,"\n"); 1.93 + 1.94 + fprintf(fp," OptoReg::Name OptoReg::vm2opto[ConcreteRegisterImpl::number_of_registers];\n"); 1.95 + 1.96 + } 1.97 +} 1.98 + 1.99 +// Define an array containing the machine register encoding values 1.100 +static void defineRegEncodes(FILE *fp, RegisterForm *registers) { 1.101 + if (registers) { 1.102 + fprintf(fp,"\n"); 1.103 + fprintf(fp,"// An array of the machine register encode values\n"); 1.104 + fprintf(fp,"const unsigned char Matcher::_regEncode[REG_COUNT] = {\n"); 1.105 + 1.106 + // Output the register encoding for each register in the allocation classes 1.107 + RegDef *reg_def = NULL; 1.108 + RegDef *next = NULL; 1.109 + registers->reset_RegDefs(); 1.110 + for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { 1.111 + next = registers->iter_RegDefs(); 1.112 + const char* register_encode = reg_def->register_encode(); 1.113 + const char *comma = (next != NULL) ? "," : " // no trailing comma"; 1.114 + int encval; 1.115 + if (!ADLParser::is_int_token(register_encode, encval)) { 1.116 + fprintf(fp," %s%s // %s\n", 1.117 + register_encode, comma, reg_def->_regname ); 1.118 + } else { 1.119 + // Output known constants in hex char format (backward compatibility). 1.120 + assert(encval < 256, "Exceeded supported width for register encoding"); 1.121 + fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", 1.122 + encval, comma, reg_def->_regname ); 1.123 + } 1.124 + } 1.125 + // Finish defining enumeration 1.126 + fprintf(fp,"};\n"); 1.127 + 1.128 + } // Done defining array 1.129 +} 1.130 + 1.131 +// Output an enumeration of register class names 1.132 +static void defineRegClassEnum(FILE *fp, RegisterForm *registers) { 1.133 + if (registers) { 1.134 + // Output an enumeration of register class names 1.135 + fprintf(fp,"\n"); 1.136 + fprintf(fp,"// Enumeration of register class names\n"); 1.137 + fprintf(fp, "enum machRegisterClass {\n"); 1.138 + registers->_rclasses.reset(); 1.139 + for( const char *class_name = NULL; 1.140 + (class_name = registers->_rclasses.iter()) != NULL; ) { 1.141 + fprintf(fp," %s,\n", toUpper( class_name )); 1.142 + } 1.143 + // Finish defining enumeration 1.144 + fprintf(fp, " _last_Mach_Reg_Class\n"); 1.145 + fprintf(fp, "};\n"); 1.146 + } 1.147 +} 1.148 + 1.149 +// Declare an enumeration of user-defined register classes 1.150 +// and a list of register masks, one for each class. 1.151 +void ArchDesc::declare_register_masks(FILE *fp_hpp) { 1.152 + const char *rc_name; 1.153 + 1.154 + if( _register ) { 1.155 + // Build enumeration of user-defined register classes. 1.156 + defineRegClassEnum(fp_hpp, _register); 1.157 + 1.158 + // Generate a list of register masks, one for each class. 1.159 + fprintf(fp_hpp,"\n"); 1.160 + fprintf(fp_hpp,"// Register masks, one for each register class.\n"); 1.161 + _register->_rclasses.reset(); 1.162 + for( rc_name = NULL; 1.163 + (rc_name = _register->_rclasses.iter()) != NULL; ) { 1.164 + const char *prefix = ""; 1.165 + RegClass *reg_class = _register->getRegClass(rc_name); 1.166 + assert( reg_class, "Using an undefined register class"); 1.167 + 1.168 + int len = RegisterForm::RegMask_Size(); 1.169 + fprintf(fp_hpp, "extern const RegMask %s%s_mask;\n", prefix, toUpper( rc_name ) ); 1.170 + 1.171 + if( reg_class->_stack_or_reg ) { 1.172 + fprintf(fp_hpp, "extern const RegMask %sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) ); 1.173 + } 1.174 + } 1.175 + } 1.176 +} 1.177 + 1.178 +// Generate an enumeration of user-defined register classes 1.179 +// and a list of register masks, one for each class. 1.180 +void ArchDesc::build_register_masks(FILE *fp_cpp) { 1.181 + const char *rc_name; 1.182 + 1.183 + if( _register ) { 1.184 + // Generate a list of register masks, one for each class. 1.185 + fprintf(fp_cpp,"\n"); 1.186 + fprintf(fp_cpp,"// Register masks, one for each register class.\n"); 1.187 + _register->_rclasses.reset(); 1.188 + for( rc_name = NULL; 1.189 + (rc_name = _register->_rclasses.iter()) != NULL; ) { 1.190 + const char *prefix = ""; 1.191 + RegClass *reg_class = _register->getRegClass(rc_name); 1.192 + assert( reg_class, "Using an undefined register class"); 1.193 + 1.194 + int len = RegisterForm::RegMask_Size(); 1.195 + fprintf(fp_cpp, "const RegMask %s%s_mask(", prefix, toUpper( rc_name ) ); 1.196 + { int i; 1.197 + for( i = 0; i < len-1; i++ ) 1.198 + fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false)); 1.199 + fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false)); 1.200 + } 1.201 + 1.202 + if( reg_class->_stack_or_reg ) { 1.203 + int i; 1.204 + fprintf(fp_cpp, "const RegMask %sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); 1.205 + for( i = 0; i < len-1; i++ ) 1.206 + fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true)); 1.207 + fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true)); 1.208 + } 1.209 + } 1.210 + } 1.211 +} 1.212 + 1.213 +// Compute an index for an array in the pipeline_reads_NNN arrays 1.214 +static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, PipeClassForm *pipeclass) 1.215 +{ 1.216 + int templen = 1; 1.217 + int paramcount = 0; 1.218 + const char *paramname; 1.219 + 1.220 + if (pipeclass->_parameters.count() == 0) 1.221 + return -1; 1.222 + 1.223 + pipeclass->_parameters.reset(); 1.224 + paramname = pipeclass->_parameters.iter(); 1.225 + const PipeClassOperandForm *pipeopnd = 1.226 + (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; 1.227 + if (pipeopnd && !pipeopnd->isWrite() && strcmp(pipeopnd->_stage, "Universal")) 1.228 + pipeclass->_parameters.reset(); 1.229 + 1.230 + while ( (paramname = pipeclass->_parameters.iter()) != NULL ) { 1.231 + const PipeClassOperandForm *pipeopnd = 1.232 + (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; 1.233 + 1.234 + if (pipeopnd) 1.235 + templen += 10 + (int)strlen(pipeopnd->_stage); 1.236 + else 1.237 + templen += 19; 1.238 + 1.239 + paramcount++; 1.240 + } 1.241 + 1.242 + // See if the count is zero 1.243 + if (paramcount == 0) { 1.244 + return -1; 1.245 + } 1.246 + 1.247 + char *operand_stages = new char [templen]; 1.248 + operand_stages[0] = 0; 1.249 + int i = 0; 1.250 + templen = 0; 1.251 + 1.252 + pipeclass->_parameters.reset(); 1.253 + paramname = pipeclass->_parameters.iter(); 1.254 + pipeopnd = (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; 1.255 + if (pipeopnd && !pipeopnd->isWrite() && strcmp(pipeopnd->_stage, "Universal")) 1.256 + pipeclass->_parameters.reset(); 1.257 + 1.258 + while ( (paramname = pipeclass->_parameters.iter()) != NULL ) { 1.259 + const PipeClassOperandForm *pipeopnd = 1.260 + (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; 1.261 + templen += sprintf(&operand_stages[templen], " stage_%s%c\n", 1.262 + pipeopnd ? pipeopnd->_stage : "undefined", 1.263 + (++i < paramcount ? ',' : ' ') ); 1.264 + } 1.265 + 1.266 + // See if the same string is in the table 1.267 + int ndx = pipeline_reads.index(operand_stages); 1.268 + 1.269 + // No, add it to the table 1.270 + if (ndx < 0) { 1.271 + pipeline_reads.addName(operand_stages); 1.272 + ndx = pipeline_reads.index(operand_stages); 1.273 + 1.274 + fprintf(fp_cpp, "static const enum machPipelineStages pipeline_reads_%03d[%d] = {\n%s};\n\n", 1.275 + ndx+1, paramcount, operand_stages); 1.276 + } 1.277 + else 1.278 + delete [] operand_stages; 1.279 + 1.280 + return (ndx); 1.281 +} 1.282 + 1.283 +// Compute an index for an array in the pipeline_res_stages_NNN arrays 1.284 +static int pipeline_res_stages_initializer( 1.285 + FILE *fp_cpp, 1.286 + PipelineForm *pipeline, 1.287 + NameList &pipeline_res_stages, 1.288 + PipeClassForm *pipeclass) 1.289 +{ 1.290 + const PipeClassResourceForm *piperesource; 1.291 + int * res_stages = new int [pipeline->_rescount]; 1.292 + int i; 1.293 + 1.294 + for (i = 0; i < pipeline->_rescount; i++) 1.295 + res_stages[i] = 0; 1.296 + 1.297 + for (pipeclass->_resUsage.reset(); 1.298 + (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL; ) { 1.299 + int used_mask = pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); 1.300 + for (i = 0; i < pipeline->_rescount; i++) 1.301 + if ((1 << i) & used_mask) { 1.302 + int stage = pipeline->_stages.index(piperesource->_stage); 1.303 + if (res_stages[i] < stage+1) 1.304 + res_stages[i] = stage+1; 1.305 + } 1.306 + } 1.307 + 1.308 + // Compute the length needed for the resource list 1.309 + int commentlen = 0; 1.310 + int max_stage = 0; 1.311 + for (i = 0; i < pipeline->_rescount; i++) { 1.312 + if (res_stages[i] == 0) { 1.313 + if (max_stage < 9) 1.314 + max_stage = 9; 1.315 + } 1.316 + else { 1.317 + int stagelen = (int)strlen(pipeline->_stages.name(res_stages[i]-1)); 1.318 + if (max_stage < stagelen) 1.319 + max_stage = stagelen; 1.320 + } 1.321 + 1.322 + commentlen += (int)strlen(pipeline->_reslist.name(i)); 1.323 + } 1.324 + 1.325 + int templen = 1 + commentlen + pipeline->_rescount * (max_stage + 14); 1.326 + 1.327 + // Allocate space for the resource list 1.328 + char * resource_stages = new char [templen]; 1.329 + 1.330 + templen = 0; 1.331 + for (i = 0; i < pipeline->_rescount; i++) { 1.332 + const char * const resname = 1.333 + res_stages[i] == 0 ? "undefined" : pipeline->_stages.name(res_stages[i]-1); 1.334 + 1.335 + templen += sprintf(&resource_stages[templen], " stage_%s%-*s // %s\n", 1.336 + resname, max_stage - (int)strlen(resname) + 1, 1.337 + (i < pipeline->_rescount-1) ? "," : "", 1.338 + pipeline->_reslist.name(i)); 1.339 + } 1.340 + 1.341 + // See if the same string is in the table 1.342 + int ndx = pipeline_res_stages.index(resource_stages); 1.343 + 1.344 + // No, add it to the table 1.345 + if (ndx < 0) { 1.346 + pipeline_res_stages.addName(resource_stages); 1.347 + ndx = pipeline_res_stages.index(resource_stages); 1.348 + 1.349 + fprintf(fp_cpp, "static const enum machPipelineStages pipeline_res_stages_%03d[%d] = {\n%s};\n\n", 1.350 + ndx+1, pipeline->_rescount, resource_stages); 1.351 + } 1.352 + else 1.353 + delete [] resource_stages; 1.354 + 1.355 + delete [] res_stages; 1.356 + 1.357 + return (ndx); 1.358 +} 1.359 + 1.360 +// Compute an index for an array in the pipeline_res_cycles_NNN arrays 1.361 +static int pipeline_res_cycles_initializer( 1.362 + FILE *fp_cpp, 1.363 + PipelineForm *pipeline, 1.364 + NameList &pipeline_res_cycles, 1.365 + PipeClassForm *pipeclass) 1.366 +{ 1.367 + const PipeClassResourceForm *piperesource; 1.368 + int * res_cycles = new int [pipeline->_rescount]; 1.369 + int i; 1.370 + 1.371 + for (i = 0; i < pipeline->_rescount; i++) 1.372 + res_cycles[i] = 0; 1.373 + 1.374 + for (pipeclass->_resUsage.reset(); 1.375 + (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL; ) { 1.376 + int used_mask = pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); 1.377 + for (i = 0; i < pipeline->_rescount; i++) 1.378 + if ((1 << i) & used_mask) { 1.379 + int cycles = piperesource->_cycles; 1.380 + if (res_cycles[i] < cycles) 1.381 + res_cycles[i] = cycles; 1.382 + } 1.383 + } 1.384 + 1.385 + // Pre-compute the string length 1.386 + int templen; 1.387 + int cyclelen = 0, commentlen = 0; 1.388 + int max_cycles = 0; 1.389 + char temp[32]; 1.390 + 1.391 + for (i = 0; i < pipeline->_rescount; i++) { 1.392 + if (max_cycles < res_cycles[i]) 1.393 + max_cycles = res_cycles[i]; 1.394 + templen = sprintf(temp, "%d", res_cycles[i]); 1.395 + if (cyclelen < templen) 1.396 + cyclelen = templen; 1.397 + commentlen += (int)strlen(pipeline->_reslist.name(i)); 1.398 + } 1.399 + 1.400 + templen = 1 + commentlen + (cyclelen + 8) * pipeline->_rescount; 1.401 + 1.402 + // Allocate space for the resource list 1.403 + char * resource_cycles = new char [templen]; 1.404 + 1.405 + templen = 0; 1.406 + 1.407 + for (i = 0; i < pipeline->_rescount; i++) { 1.408 + templen += sprintf(&resource_cycles[templen], " %*d%c // %s\n", 1.409 + cyclelen, res_cycles[i], (i < pipeline->_rescount-1) ? ',' : ' ', pipeline->_reslist.name(i)); 1.410 + } 1.411 + 1.412 + // See if the same string is in the table 1.413 + int ndx = pipeline_res_cycles.index(resource_cycles); 1.414 + 1.415 + // No, add it to the table 1.416 + if (ndx < 0) { 1.417 + pipeline_res_cycles.addName(resource_cycles); 1.418 + ndx = pipeline_res_cycles.index(resource_cycles); 1.419 + 1.420 + fprintf(fp_cpp, "static const uint pipeline_res_cycles_%03d[%d] = {\n%s};\n\n", 1.421 + ndx+1, pipeline->_rescount, resource_cycles); 1.422 + } 1.423 + else 1.424 + delete [] resource_cycles; 1.425 + 1.426 + delete [] res_cycles; 1.427 + 1.428 + return (ndx); 1.429 +} 1.430 + 1.431 +//typedef unsigned long long uint64_t; 1.432 + 1.433 +// Compute an index for an array in the pipeline_res_mask_NNN arrays 1.434 +static int pipeline_res_mask_initializer( 1.435 + FILE *fp_cpp, 1.436 + PipelineForm *pipeline, 1.437 + NameList &pipeline_res_mask, 1.438 + NameList &pipeline_res_args, 1.439 + PipeClassForm *pipeclass) 1.440 +{ 1.441 + const PipeClassResourceForm *piperesource; 1.442 + const uint rescount = pipeline->_rescount; 1.443 + const uint maxcycleused = pipeline->_maxcycleused; 1.444 + const uint cyclemasksize = (maxcycleused + 31) >> 5; 1.445 + 1.446 + int i, j; 1.447 + int element_count = 0; 1.448 + uint *res_mask = new uint [cyclemasksize]; 1.449 + uint resources_used = 0; 1.450 + uint resources_used_exclusively = 0; 1.451 + 1.452 + for (pipeclass->_resUsage.reset(); 1.453 + (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL; ) 1.454 + element_count++; 1.455 + 1.456 + // Pre-compute the string length 1.457 + int templen; 1.458 + int commentlen = 0; 1.459 + int max_cycles = 0; 1.460 + 1.461 + int cyclelen = ((maxcycleused + 3) >> 2); 1.462 + int masklen = (rescount + 3) >> 2; 1.463 + 1.464 + int cycledigit = 0; 1.465 + for (i = maxcycleused; i > 0; i /= 10) 1.466 + cycledigit++; 1.467 + 1.468 + int maskdigit = 0; 1.469 + for (i = rescount; i > 0; i /= 10) 1.470 + maskdigit++; 1.471 + 1.472 + static const char * pipeline_use_cycle_mask = "Pipeline_Use_Cycle_Mask"; 1.473 + static const char * pipeline_use_element = "Pipeline_Use_Element"; 1.474 + 1.475 + templen = 1 + 1.476 + (int)(strlen(pipeline_use_cycle_mask) + (int)strlen(pipeline_use_element) + 1.477 + (cyclemasksize * 12) + masklen + (cycledigit * 2) + 30) * element_count; 1.478 + 1.479 + // Allocate space for the resource list 1.480 + char * resource_mask = new char [templen]; 1.481 + char * last_comma = NULL; 1.482 + 1.483 + templen = 0; 1.484 + 1.485 + for (pipeclass->_resUsage.reset(); 1.486 + (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL; ) { 1.487 + int used_mask = pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); 1.488 + 1.489 + if (!used_mask) 1.490 + fprintf(stderr, "*** used_mask is 0 ***\n"); 1.491 + 1.492 + resources_used |= used_mask; 1.493 + 1.494 + uint lb, ub; 1.495 + 1.496 + for (lb = 0; (used_mask & (1 << lb)) == 0; lb++); 1.497 + for (ub = 31; (used_mask & (1 << ub)) == 0; ub--); 1.498 + 1.499 + if (lb == ub) 1.500 + resources_used_exclusively |= used_mask; 1.501 + 1.502 + int formatlen = 1.503 + sprintf(&resource_mask[templen], " %s(0x%0*x, %*d, %*d, %s %s(", 1.504 + pipeline_use_element, 1.505 + masklen, used_mask, 1.506 + cycledigit, lb, cycledigit, ub, 1.507 + ((used_mask & (used_mask-1)) != 0) ? "true, " : "false,", 1.508 + pipeline_use_cycle_mask); 1.509 + 1.510 + templen += formatlen; 1.511 + 1.512 + memset(res_mask, 0, cyclemasksize * sizeof(uint)); 1.513 + 1.514 + int cycles = piperesource->_cycles; 1.515 + uint stage = pipeline->_stages.index(piperesource->_stage); 1.516 + uint upper_limit = stage+cycles-1; 1.517 + uint lower_limit = stage-1; 1.518 + uint upper_idx = upper_limit >> 5; 1.519 + uint lower_idx = lower_limit >> 5; 1.520 + uint upper_position = upper_limit & 0x1f; 1.521 + uint lower_position = lower_limit & 0x1f; 1.522 + 1.523 + uint mask = (((uint)1) << upper_position) - 1; 1.524 + 1.525 + while ( upper_idx > lower_idx ) { 1.526 + res_mask[upper_idx--] |= mask; 1.527 + mask = (uint)-1; 1.528 + } 1.529 + 1.530 + mask -= (((uint)1) << lower_position) - 1; 1.531 + res_mask[upper_idx] |= mask; 1.532 + 1.533 + for (j = cyclemasksize-1; j >= 0; j--) { 1.534 + formatlen = 1.535 + sprintf(&resource_mask[templen], "0x%08x%s", res_mask[j], j > 0 ? ", " : ""); 1.536 + templen += formatlen; 1.537 + } 1.538 + 1.539 + resource_mask[templen++] = ')'; 1.540 + resource_mask[templen++] = ')'; 1.541 + last_comma = &resource_mask[templen]; 1.542 + resource_mask[templen++] = ','; 1.543 + resource_mask[templen++] = '\n'; 1.544 + } 1.545 + 1.546 + resource_mask[templen] = 0; 1.547 + if (last_comma) 1.548 + last_comma[0] = ' '; 1.549 + 1.550 + // See if the same string is in the table 1.551 + int ndx = pipeline_res_mask.index(resource_mask); 1.552 + 1.553 + // No, add it to the table 1.554 + if (ndx < 0) { 1.555 + pipeline_res_mask.addName(resource_mask); 1.556 + ndx = pipeline_res_mask.index(resource_mask); 1.557 + 1.558 + if (strlen(resource_mask) > 0) 1.559 + fprintf(fp_cpp, "static const Pipeline_Use_Element pipeline_res_mask_%03d[%d] = {\n%s};\n\n", 1.560 + ndx+1, element_count, resource_mask); 1.561 + 1.562 + char * args = new char [9 + 2*masklen + maskdigit]; 1.563 + 1.564 + sprintf(args, "0x%0*x, 0x%0*x, %*d", 1.565 + masklen, resources_used, 1.566 + masklen, resources_used_exclusively, 1.567 + maskdigit, element_count); 1.568 + 1.569 + pipeline_res_args.addName(args); 1.570 + } 1.571 + else 1.572 + delete [] resource_mask; 1.573 + 1.574 + delete [] res_mask; 1.575 +//delete [] res_masks; 1.576 + 1.577 + return (ndx); 1.578 +} 1.579 + 1.580 +void ArchDesc::build_pipe_classes(FILE *fp_cpp) { 1.581 + const char *classname; 1.582 + const char *resourcename; 1.583 + int resourcenamelen = 0; 1.584 + NameList pipeline_reads; 1.585 + NameList pipeline_res_stages; 1.586 + NameList pipeline_res_cycles; 1.587 + NameList pipeline_res_masks; 1.588 + NameList pipeline_res_args; 1.589 + const int default_latency = 1; 1.590 + const int non_operand_latency = 0; 1.591 + const int node_latency = 0; 1.592 + 1.593 + if (!_pipeline) { 1.594 + fprintf(fp_cpp, "uint Node::latency(uint i) const {\n"); 1.595 + fprintf(fp_cpp, " // assert(false, \"pipeline functionality is not defined\");\n"); 1.596 + fprintf(fp_cpp, " return %d;\n", non_operand_latency); 1.597 + fprintf(fp_cpp, "}\n"); 1.598 + return; 1.599 + } 1.600 + 1.601 + fprintf(fp_cpp, "\n"); 1.602 + fprintf(fp_cpp, "//------------------Pipeline Methods-----------------------------------------\n"); 1.603 + fprintf(fp_cpp, "#ifndef PRODUCT\n"); 1.604 + fprintf(fp_cpp, "const char * Pipeline::stageName(uint s) {\n"); 1.605 + fprintf(fp_cpp, " static const char * const _stage_names[] = {\n"); 1.606 + fprintf(fp_cpp, " \"undefined\""); 1.607 + 1.608 + for (int s = 0; s < _pipeline->_stagecnt; s++) 1.609 + fprintf(fp_cpp, ", \"%s\"", _pipeline->_stages.name(s)); 1.610 + 1.611 + fprintf(fp_cpp, "\n };\n\n"); 1.612 + fprintf(fp_cpp, " return (s <= %d ? _stage_names[s] : \"???\");\n", 1.613 + _pipeline->_stagecnt); 1.614 + fprintf(fp_cpp, "}\n"); 1.615 + fprintf(fp_cpp, "#endif\n\n"); 1.616 + 1.617 + fprintf(fp_cpp, "uint Pipeline::functional_unit_latency(uint start, const Pipeline *pred) const {\n"); 1.618 + fprintf(fp_cpp, " // See if the functional units overlap\n"); 1.619 +#if 0 1.620 + fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); 1.621 + fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); 1.622 + fprintf(fp_cpp, " tty->print(\"# functional_unit_latency: start == %%d, this->exclusively == 0x%%03x, pred->exclusively == 0x%%03x\\n\", start, resourcesUsedExclusively(), pred->resourcesUsedExclusively());\n"); 1.623 + fprintf(fp_cpp, " }\n"); 1.624 + fprintf(fp_cpp, "#endif\n\n"); 1.625 +#endif 1.626 + fprintf(fp_cpp, " uint mask = resourcesUsedExclusively() & pred->resourcesUsedExclusively();\n"); 1.627 + fprintf(fp_cpp, " if (mask == 0)\n return (start);\n\n"); 1.628 +#if 0 1.629 + fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); 1.630 + fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); 1.631 + fprintf(fp_cpp, " tty->print(\"# functional_unit_latency: mask == 0x%%x\\n\", mask);\n"); 1.632 + fprintf(fp_cpp, " }\n"); 1.633 + fprintf(fp_cpp, "#endif\n\n"); 1.634 +#endif 1.635 + fprintf(fp_cpp, " for (uint i = 0; i < pred->resourceUseCount(); i++) {\n"); 1.636 + fprintf(fp_cpp, " const Pipeline_Use_Element *predUse = pred->resourceUseElement(i);\n"); 1.637 + fprintf(fp_cpp, " if (predUse->multiple())\n"); 1.638 + fprintf(fp_cpp, " continue;\n\n"); 1.639 + fprintf(fp_cpp, " for (uint j = 0; j < resourceUseCount(); j++) {\n"); 1.640 + fprintf(fp_cpp, " const Pipeline_Use_Element *currUse = resourceUseElement(j);\n"); 1.641 + fprintf(fp_cpp, " if (currUse->multiple())\n"); 1.642 + fprintf(fp_cpp, " continue;\n\n"); 1.643 + fprintf(fp_cpp, " if (predUse->used() & currUse->used()) {\n"); 1.644 + fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask x = predUse->mask();\n"); 1.645 + fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask y = currUse->mask();\n\n"); 1.646 + fprintf(fp_cpp, " for ( y <<= start; x.overlaps(y); start++ )\n"); 1.647 + fprintf(fp_cpp, " y <<= 1;\n"); 1.648 + fprintf(fp_cpp, " }\n"); 1.649 + fprintf(fp_cpp, " }\n"); 1.650 + fprintf(fp_cpp, " }\n\n"); 1.651 + fprintf(fp_cpp, " // There is the potential for overlap\n"); 1.652 + fprintf(fp_cpp, " return (start);\n"); 1.653 + fprintf(fp_cpp, "}\n\n"); 1.654 + fprintf(fp_cpp, "// The following two routines assume that the root Pipeline_Use entity\n"); 1.655 + fprintf(fp_cpp, "// consists of exactly 1 element for each functional unit\n"); 1.656 + fprintf(fp_cpp, "// start is relative to the current cycle; used for latency-based info\n"); 1.657 + fprintf(fp_cpp, "uint Pipeline_Use::full_latency(uint delay, const Pipeline_Use &pred) const {\n"); 1.658 + fprintf(fp_cpp, " for (uint i = 0; i < pred._count; i++) {\n"); 1.659 + fprintf(fp_cpp, " const Pipeline_Use_Element *predUse = pred.element(i);\n"); 1.660 + fprintf(fp_cpp, " if (predUse->_multiple) {\n"); 1.661 + fprintf(fp_cpp, " uint min_delay = %d;\n", 1.662 + _pipeline->_maxcycleused+1); 1.663 + fprintf(fp_cpp, " // Multiple possible functional units, choose first unused one\n"); 1.664 + fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); 1.665 + fprintf(fp_cpp, " const Pipeline_Use_Element *currUse = element(j);\n"); 1.666 + fprintf(fp_cpp, " uint curr_delay = delay;\n"); 1.667 + fprintf(fp_cpp, " if (predUse->_used & currUse->_used) {\n"); 1.668 + fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask x = predUse->_mask;\n"); 1.669 + fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask y = currUse->_mask;\n\n"); 1.670 + fprintf(fp_cpp, " for ( y <<= curr_delay; x.overlaps(y); curr_delay++ )\n"); 1.671 + fprintf(fp_cpp, " y <<= 1;\n"); 1.672 + fprintf(fp_cpp, " }\n"); 1.673 + fprintf(fp_cpp, " if (min_delay > curr_delay)\n min_delay = curr_delay;\n"); 1.674 + fprintf(fp_cpp, " }\n"); 1.675 + fprintf(fp_cpp, " if (delay < min_delay)\n delay = min_delay;\n"); 1.676 + fprintf(fp_cpp, " }\n"); 1.677 + fprintf(fp_cpp, " else {\n"); 1.678 + fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); 1.679 + fprintf(fp_cpp, " const Pipeline_Use_Element *currUse = element(j);\n"); 1.680 + fprintf(fp_cpp, " if (predUse->_used & currUse->_used) {\n"); 1.681 + fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask x = predUse->_mask;\n"); 1.682 + fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask y = currUse->_mask;\n\n"); 1.683 + fprintf(fp_cpp, " for ( y <<= delay; x.overlaps(y); delay++ )\n"); 1.684 + fprintf(fp_cpp, " y <<= 1;\n"); 1.685 + fprintf(fp_cpp, " }\n"); 1.686 + fprintf(fp_cpp, " }\n"); 1.687 + fprintf(fp_cpp, " }\n"); 1.688 + fprintf(fp_cpp, " }\n\n"); 1.689 + fprintf(fp_cpp, " return (delay);\n"); 1.690 + fprintf(fp_cpp, "}\n\n"); 1.691 + fprintf(fp_cpp, "void Pipeline_Use::add_usage(const Pipeline_Use &pred) {\n"); 1.692 + fprintf(fp_cpp, " for (uint i = 0; i < pred._count; i++) {\n"); 1.693 + fprintf(fp_cpp, " const Pipeline_Use_Element *predUse = pred.element(i);\n"); 1.694 + fprintf(fp_cpp, " if (predUse->_multiple) {\n"); 1.695 + fprintf(fp_cpp, " // Multiple possible functional units, choose first unused one\n"); 1.696 + fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); 1.697 + fprintf(fp_cpp, " Pipeline_Use_Element *currUse = element(j);\n"); 1.698 + fprintf(fp_cpp, " if ( !predUse->_mask.overlaps(currUse->_mask) ) {\n"); 1.699 + fprintf(fp_cpp, " currUse->_used |= (1 << j);\n"); 1.700 + fprintf(fp_cpp, " _resources_used |= (1 << j);\n"); 1.701 + fprintf(fp_cpp, " currUse->_mask.Or(predUse->_mask);\n"); 1.702 + fprintf(fp_cpp, " break;\n"); 1.703 + fprintf(fp_cpp, " }\n"); 1.704 + fprintf(fp_cpp, " }\n"); 1.705 + fprintf(fp_cpp, " }\n"); 1.706 + fprintf(fp_cpp, " else {\n"); 1.707 + fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); 1.708 + fprintf(fp_cpp, " Pipeline_Use_Element *currUse = element(j);\n"); 1.709 + fprintf(fp_cpp, " currUse->_used |= (1 << j);\n"); 1.710 + fprintf(fp_cpp, " _resources_used |= (1 << j);\n"); 1.711 + fprintf(fp_cpp, " currUse->_mask.Or(predUse->_mask);\n"); 1.712 + fprintf(fp_cpp, " }\n"); 1.713 + fprintf(fp_cpp, " }\n"); 1.714 + fprintf(fp_cpp, " }\n"); 1.715 + fprintf(fp_cpp, "}\n\n"); 1.716 + 1.717 + fprintf(fp_cpp, "uint Pipeline::operand_latency(uint opnd, const Pipeline *pred) const {\n"); 1.718 + fprintf(fp_cpp, " int const default_latency = 1;\n"); 1.719 + fprintf(fp_cpp, "\n"); 1.720 +#if 0 1.721 + fprintf(fp_cpp, "#ifndef PRODUCT\n"); 1.722 + fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); 1.723 + fprintf(fp_cpp, " tty->print(\"# operand_latency(%%d), _read_stage_count = %%d\\n\", opnd, _read_stage_count);\n"); 1.724 + fprintf(fp_cpp, " }\n"); 1.725 + fprintf(fp_cpp, "#endif\n\n"); 1.726 +#endif 1.727 + fprintf(fp_cpp, " assert(this, \"NULL pipeline info\")\n"); 1.728 + fprintf(fp_cpp, " assert(pred, \"NULL predecessor pipline info\")\n\n"); 1.729 + fprintf(fp_cpp, " if (pred->hasFixedLatency())\n return (pred->fixedLatency());\n\n"); 1.730 + fprintf(fp_cpp, " // If this is not an operand, then assume a dependence with 0 latency\n"); 1.731 + fprintf(fp_cpp, " if (opnd > _read_stage_count)\n return (0);\n\n"); 1.732 + fprintf(fp_cpp, " uint writeStage = pred->_write_stage;\n"); 1.733 + fprintf(fp_cpp, " uint readStage = _read_stages[opnd-1];\n"); 1.734 +#if 0 1.735 + fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); 1.736 + fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); 1.737 + fprintf(fp_cpp, " tty->print(\"# operand_latency: writeStage=%%s readStage=%%s, opnd=%%d\\n\", stageName(writeStage), stageName(readStage), opnd);\n"); 1.738 + fprintf(fp_cpp, " }\n"); 1.739 + fprintf(fp_cpp, "#endif\n\n"); 1.740 +#endif 1.741 + fprintf(fp_cpp, "\n"); 1.742 + fprintf(fp_cpp, " if (writeStage == stage_undefined || readStage == stage_undefined)\n"); 1.743 + fprintf(fp_cpp, " return (default_latency);\n"); 1.744 + fprintf(fp_cpp, "\n"); 1.745 + fprintf(fp_cpp, " int delta = writeStage - readStage;\n"); 1.746 + fprintf(fp_cpp, " if (delta < 0) delta = 0;\n\n"); 1.747 +#if 0 1.748 + fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); 1.749 + fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); 1.750 + fprintf(fp_cpp, " tty->print(\"# operand_latency: delta=%%d\\n\", delta);\n"); 1.751 + fprintf(fp_cpp, " }\n"); 1.752 + fprintf(fp_cpp, "#endif\n\n"); 1.753 +#endif 1.754 + fprintf(fp_cpp, " return (delta);\n"); 1.755 + fprintf(fp_cpp, "}\n\n"); 1.756 + 1.757 + if (!_pipeline) 1.758 + /* Do Nothing */; 1.759 + 1.760 + else if (_pipeline->_maxcycleused <= 1.761 +#ifdef SPARC 1.762 + 64 1.763 +#else 1.764 + 32 1.765 +#endif 1.766 + ) { 1.767 + fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); 1.768 + fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask(in1._mask & in2._mask);\n"); 1.769 + fprintf(fp_cpp, "}\n\n"); 1.770 + fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); 1.771 + fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask(in1._mask | in2._mask);\n"); 1.772 + fprintf(fp_cpp, "}\n\n"); 1.773 + } 1.774 + else { 1.775 + uint l; 1.776 + uint masklen = (_pipeline->_maxcycleused + 31) >> 5; 1.777 + fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); 1.778 + fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask("); 1.779 + for (l = 1; l <= masklen; l++) 1.780 + fprintf(fp_cpp, "in1._mask%d & in2._mask%d%s\n", l, l, l < masklen ? ", " : ""); 1.781 + fprintf(fp_cpp, ");\n"); 1.782 + fprintf(fp_cpp, "}\n\n"); 1.783 + fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); 1.784 + fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask("); 1.785 + for (l = 1; l <= masklen; l++) 1.786 + fprintf(fp_cpp, "in1._mask%d | in2._mask%d%s", l, l, l < masklen ? ", " : ""); 1.787 + fprintf(fp_cpp, ");\n"); 1.788 + fprintf(fp_cpp, "}\n\n"); 1.789 + fprintf(fp_cpp, "void Pipeline_Use_Cycle_Mask::Or(const Pipeline_Use_Cycle_Mask &in2) {\n "); 1.790 + for (l = 1; l <= masklen; l++) 1.791 + fprintf(fp_cpp, " _mask%d |= in2._mask%d;", l, l); 1.792 + fprintf(fp_cpp, "\n}\n\n"); 1.793 + } 1.794 + 1.795 + /* Get the length of all the resource names */ 1.796 + for (_pipeline->_reslist.reset(), resourcenamelen = 0; 1.797 + (resourcename = _pipeline->_reslist.iter()) != NULL; 1.798 + resourcenamelen += (int)strlen(resourcename)); 1.799 + 1.800 + // Create the pipeline class description 1.801 + 1.802 + fprintf(fp_cpp, "static const Pipeline pipeline_class_Zero_Instructions(0, 0, true, 0, 0, false, false, false, false, NULL, NULL, NULL, Pipeline_Use(0, 0, 0, NULL));\n\n"); 1.803 + fprintf(fp_cpp, "static const Pipeline pipeline_class_Unknown_Instructions(0, 0, true, 0, 0, false, true, true, false, NULL, NULL, NULL, Pipeline_Use(0, 0, 0, NULL));\n\n"); 1.804 + 1.805 + fprintf(fp_cpp, "const Pipeline_Use_Element Pipeline_Use::elaborated_elements[%d] = {\n", _pipeline->_rescount); 1.806 + for (int i1 = 0; i1 < _pipeline->_rescount; i1++) { 1.807 + fprintf(fp_cpp, " Pipeline_Use_Element(0, %d, %d, false, Pipeline_Use_Cycle_Mask(", i1, i1); 1.808 + uint masklen = (_pipeline->_maxcycleused + 31) >> 5; 1.809 + for (int i2 = masklen-1; i2 >= 0; i2--) 1.810 + fprintf(fp_cpp, "0%s", i2 > 0 ? ", " : ""); 1.811 + fprintf(fp_cpp, "))%s\n", i1 < (_pipeline->_rescount-1) ? "," : ""); 1.812 + } 1.813 + fprintf(fp_cpp, "};\n\n"); 1.814 + 1.815 + fprintf(fp_cpp, "const Pipeline_Use Pipeline_Use::elaborated_use(0, 0, %d, (Pipeline_Use_Element *)&elaborated_elements[0]);\n\n", 1.816 + _pipeline->_rescount); 1.817 + 1.818 + for (_pipeline->_classlist.reset(); (classname = _pipeline->_classlist.iter()) != NULL; ) { 1.819 + fprintf(fp_cpp, "\n"); 1.820 + fprintf(fp_cpp, "// Pipeline Class \"%s\"\n", classname); 1.821 + PipeClassForm *pipeclass = _pipeline->_classdict[classname]->is_pipeclass(); 1.822 + int maxWriteStage = -1; 1.823 + int maxMoreInstrs = 0; 1.824 + int paramcount = 0; 1.825 + int i = 0; 1.826 + const char *paramname; 1.827 + int resource_count = (_pipeline->_rescount + 3) >> 2; 1.828 + 1.829 + // Scan the operands, looking for last output stage and number of inputs 1.830 + for (pipeclass->_parameters.reset(); (paramname = pipeclass->_parameters.iter()) != NULL; ) { 1.831 + const PipeClassOperandForm *pipeopnd = 1.832 + (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; 1.833 + if (pipeopnd) { 1.834 + if (pipeopnd->_iswrite) { 1.835 + int stagenum = _pipeline->_stages.index(pipeopnd->_stage); 1.836 + int moreinsts = pipeopnd->_more_instrs; 1.837 + if ((maxWriteStage+maxMoreInstrs) < (stagenum+moreinsts)) { 1.838 + maxWriteStage = stagenum; 1.839 + maxMoreInstrs = moreinsts; 1.840 + } 1.841 + } 1.842 + } 1.843 + 1.844 + if (i++ > 0 || (pipeopnd && !pipeopnd->isWrite())) 1.845 + paramcount++; 1.846 + } 1.847 + 1.848 + // Create the list of stages for the operands that are read 1.849 + // Note that we will build a NameList to reduce the number of copies 1.850 + 1.851 + int pipeline_reads_index = pipeline_reads_initializer(fp_cpp, pipeline_reads, pipeclass); 1.852 + 1.853 + int pipeline_res_stages_index = pipeline_res_stages_initializer( 1.854 + fp_cpp, _pipeline, pipeline_res_stages, pipeclass); 1.855 + 1.856 + int pipeline_res_cycles_index = pipeline_res_cycles_initializer( 1.857 + fp_cpp, _pipeline, pipeline_res_cycles, pipeclass); 1.858 + 1.859 + int pipeline_res_mask_index = pipeline_res_mask_initializer( 1.860 + fp_cpp, _pipeline, pipeline_res_masks, pipeline_res_args, pipeclass); 1.861 + 1.862 +#if 0 1.863 + // Process the Resources 1.864 + const PipeClassResourceForm *piperesource; 1.865 + 1.866 + unsigned resources_used = 0; 1.867 + unsigned exclusive_resources_used = 0; 1.868 + unsigned resource_groups = 0; 1.869 + for (pipeclass->_resUsage.reset(); 1.870 + (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL; ) { 1.871 + int used_mask = _pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); 1.872 + if (used_mask) 1.873 + resource_groups++; 1.874 + resources_used |= used_mask; 1.875 + if ((used_mask & (used_mask-1)) == 0) 1.876 + exclusive_resources_used |= used_mask; 1.877 + } 1.878 + 1.879 + if (resource_groups > 0) { 1.880 + fprintf(fp_cpp, "static const uint pipeline_res_or_masks_%03d[%d] = {", 1.881 + pipeclass->_num, resource_groups); 1.882 + for (pipeclass->_resUsage.reset(), i = 1; 1.883 + (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL; 1.884 + i++ ) { 1.885 + int used_mask = _pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); 1.886 + if (used_mask) { 1.887 + fprintf(fp_cpp, " 0x%0*x%c", resource_count, used_mask, i < (int)resource_groups ? ',' : ' '); 1.888 + } 1.889 + } 1.890 + fprintf(fp_cpp, "};\n\n"); 1.891 + } 1.892 +#endif 1.893 + 1.894 + // Create the pipeline class description 1.895 + fprintf(fp_cpp, "static const Pipeline pipeline_class_%03d(", 1.896 + pipeclass->_num); 1.897 + if (maxWriteStage < 0) 1.898 + fprintf(fp_cpp, "(uint)stage_undefined"); 1.899 + else if (maxMoreInstrs == 0) 1.900 + fprintf(fp_cpp, "(uint)stage_%s", _pipeline->_stages.name(maxWriteStage)); 1.901 + else 1.902 + fprintf(fp_cpp, "((uint)stage_%s)+%d", _pipeline->_stages.name(maxWriteStage), maxMoreInstrs); 1.903 + fprintf(fp_cpp, ", %d, %s, %d, %d, %s, %s, %s, %s,\n", 1.904 + paramcount, 1.905 + pipeclass->hasFixedLatency() ? "true" : "false", 1.906 + pipeclass->fixedLatency(), 1.907 + pipeclass->InstructionCount(), 1.908 + pipeclass->hasBranchDelay() ? "true" : "false", 1.909 + pipeclass->hasMultipleBundles() ? "true" : "false", 1.910 + pipeclass->forceSerialization() ? "true" : "false", 1.911 + pipeclass->mayHaveNoCode() ? "true" : "false" ); 1.912 + if (paramcount > 0) { 1.913 + fprintf(fp_cpp, "\n (enum machPipelineStages * const) pipeline_reads_%03d,\n ", 1.914 + pipeline_reads_index+1); 1.915 + } 1.916 + else 1.917 + fprintf(fp_cpp, " NULL,"); 1.918 + fprintf(fp_cpp, " (enum machPipelineStages * const) pipeline_res_stages_%03d,\n", 1.919 + pipeline_res_stages_index+1); 1.920 + fprintf(fp_cpp, " (uint * const) pipeline_res_cycles_%03d,\n", 1.921 + pipeline_res_cycles_index+1); 1.922 + fprintf(fp_cpp, " Pipeline_Use(%s, (Pipeline_Use_Element *)", 1.923 + pipeline_res_args.name(pipeline_res_mask_index)); 1.924 + if (strlen(pipeline_res_masks.name(pipeline_res_mask_index)) > 0) 1.925 + fprintf(fp_cpp, "&pipeline_res_mask_%03d[0]", 1.926 + pipeline_res_mask_index+1); 1.927 + else 1.928 + fprintf(fp_cpp, "NULL"); 1.929 + fprintf(fp_cpp, "));\n"); 1.930 + } 1.931 + 1.932 + // Generate the Node::latency method if _pipeline defined 1.933 + fprintf(fp_cpp, "\n"); 1.934 + fprintf(fp_cpp, "//------------------Inter-Instruction Latency--------------------------------\n"); 1.935 + fprintf(fp_cpp, "uint Node::latency(uint i) {\n"); 1.936 + if (_pipeline) { 1.937 +#if 0 1.938 + fprintf(fp_cpp, "#ifndef PRODUCT\n"); 1.939 + fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); 1.940 + fprintf(fp_cpp, " tty->print(\"# %%4d->latency(%%d)\\n\", _idx, i);\n"); 1.941 + fprintf(fp_cpp, " }\n"); 1.942 + fprintf(fp_cpp, "#endif\n"); 1.943 +#endif 1.944 + fprintf(fp_cpp, " uint j;\n"); 1.945 + fprintf(fp_cpp, " // verify in legal range for inputs\n"); 1.946 + fprintf(fp_cpp, " assert(i < len(), \"index not in range\");\n\n"); 1.947 + fprintf(fp_cpp, " // verify input is not null\n"); 1.948 + fprintf(fp_cpp, " Node *pred = in(i);\n"); 1.949 + fprintf(fp_cpp, " if (!pred)\n return %d;\n\n", 1.950 + non_operand_latency); 1.951 + fprintf(fp_cpp, " if (pred->is_Proj())\n pred = pred->in(0);\n\n"); 1.952 + fprintf(fp_cpp, " // if either node does not have pipeline info, use default\n"); 1.953 + fprintf(fp_cpp, " const Pipeline *predpipe = pred->pipeline();\n"); 1.954 + fprintf(fp_cpp, " assert(predpipe, \"no predecessor pipeline info\");\n\n"); 1.955 + fprintf(fp_cpp, " if (predpipe->hasFixedLatency())\n return predpipe->fixedLatency();\n\n"); 1.956 + fprintf(fp_cpp, " const Pipeline *currpipe = pipeline();\n"); 1.957 + fprintf(fp_cpp, " assert(currpipe, \"no pipeline info\");\n\n"); 1.958 + fprintf(fp_cpp, " if (!is_Mach())\n return %d;\n\n", 1.959 + node_latency); 1.960 + fprintf(fp_cpp, " const MachNode *m = as_Mach();\n"); 1.961 + fprintf(fp_cpp, " j = m->oper_input_base();\n"); 1.962 + fprintf(fp_cpp, " if (i < j)\n return currpipe->functional_unit_latency(%d, predpipe);\n\n", 1.963 + non_operand_latency); 1.964 + fprintf(fp_cpp, " // determine which operand this is in\n"); 1.965 + fprintf(fp_cpp, " uint n = m->num_opnds();\n"); 1.966 + fprintf(fp_cpp, " int delta = %d;\n\n", 1.967 + non_operand_latency); 1.968 + fprintf(fp_cpp, " uint k;\n"); 1.969 + fprintf(fp_cpp, " for (k = 1; k < n; k++) {\n"); 1.970 + fprintf(fp_cpp, " j += m->_opnds[k]->num_edges();\n"); 1.971 + fprintf(fp_cpp, " if (i < j)\n"); 1.972 + fprintf(fp_cpp, " break;\n"); 1.973 + fprintf(fp_cpp, " }\n"); 1.974 + fprintf(fp_cpp, " if (k < n)\n"); 1.975 + fprintf(fp_cpp, " delta = currpipe->operand_latency(k,predpipe);\n\n"); 1.976 + fprintf(fp_cpp, " return currpipe->functional_unit_latency(delta, predpipe);\n"); 1.977 + } 1.978 + else { 1.979 + fprintf(fp_cpp, " // assert(false, \"pipeline functionality is not defined\");\n"); 1.980 + fprintf(fp_cpp, " return %d;\n", 1.981 + non_operand_latency); 1.982 + } 1.983 + fprintf(fp_cpp, "}\n\n"); 1.984 + 1.985 + // Output the list of nop nodes 1.986 + fprintf(fp_cpp, "// Descriptions for emitting different functional unit nops\n"); 1.987 + const char *nop; 1.988 + int nopcnt = 0; 1.989 + for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; nopcnt++ ); 1.990 + 1.991 + fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d], Compile *C) {\n", nopcnt); 1.992 + int i = 0; 1.993 + for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; i++ ) { 1.994 + fprintf(fp_cpp, " nop_list[%d] = (MachNode *) new (C) %sNode();\n", i, nop); 1.995 + } 1.996 + fprintf(fp_cpp, "};\n\n"); 1.997 + fprintf(fp_cpp, "#ifndef PRODUCT\n"); 1.998 + fprintf(fp_cpp, "void Bundle::dump() const {\n"); 1.999 + fprintf(fp_cpp, " static const char * bundle_flags[] = {\n"); 1.1000 + fprintf(fp_cpp, " \"\",\n"); 1.1001 + fprintf(fp_cpp, " \"use nop delay\",\n"); 1.1002 + fprintf(fp_cpp, " \"use unconditional delay\",\n"); 1.1003 + fprintf(fp_cpp, " \"use conditional delay\",\n"); 1.1004 + fprintf(fp_cpp, " \"used in conditional delay\",\n"); 1.1005 + fprintf(fp_cpp, " \"used in unconditional delay\",\n"); 1.1006 + fprintf(fp_cpp, " \"used in all conditional delays\",\n"); 1.1007 + fprintf(fp_cpp, " };\n\n"); 1.1008 + 1.1009 + fprintf(fp_cpp, " static const char *resource_names[%d] = {", _pipeline->_rescount); 1.1010 + for (i = 0; i < _pipeline->_rescount; i++) 1.1011 + fprintf(fp_cpp, " \"%s\"%c", _pipeline->_reslist.name(i), i < _pipeline->_rescount-1 ? ',' : ' '); 1.1012 + fprintf(fp_cpp, "};\n\n"); 1.1013 + 1.1014 + // See if the same string is in the table 1.1015 + fprintf(fp_cpp, " bool needs_comma = false;\n\n"); 1.1016 + fprintf(fp_cpp, " if (_flags) {\n"); 1.1017 + fprintf(fp_cpp, " tty->print(\"%%s\", bundle_flags[_flags]);\n"); 1.1018 + fprintf(fp_cpp, " needs_comma = true;\n"); 1.1019 + fprintf(fp_cpp, " };\n"); 1.1020 + fprintf(fp_cpp, " if (instr_count()) {\n"); 1.1021 + fprintf(fp_cpp, " tty->print(\"%%s%%d instr%%s\", needs_comma ? \", \" : \"\", instr_count(), instr_count() != 1 ? \"s\" : \"\");\n"); 1.1022 + fprintf(fp_cpp, " needs_comma = true;\n"); 1.1023 + fprintf(fp_cpp, " };\n"); 1.1024 + fprintf(fp_cpp, " uint r = resources_used();\n"); 1.1025 + fprintf(fp_cpp, " if (r) {\n"); 1.1026 + fprintf(fp_cpp, " tty->print(\"%%sresource%%s:\", needs_comma ? \", \" : \"\", (r & (r-1)) != 0 ? \"s\" : \"\");\n"); 1.1027 + fprintf(fp_cpp, " for (uint i = 0; i < %d; i++)\n", _pipeline->_rescount); 1.1028 + fprintf(fp_cpp, " if ((r & (1 << i)) != 0)\n"); 1.1029 + fprintf(fp_cpp, " tty->print(\" %%s\", resource_names[i]);\n"); 1.1030 + fprintf(fp_cpp, " needs_comma = true;\n"); 1.1031 + fprintf(fp_cpp, " };\n"); 1.1032 + fprintf(fp_cpp, " tty->print(\"\\n\");\n"); 1.1033 + fprintf(fp_cpp, "}\n"); 1.1034 + fprintf(fp_cpp, "#endif\n"); 1.1035 +} 1.1036 + 1.1037 +// --------------------------------------------------------------------------- 1.1038 +//------------------------------Utilities to build Instruction Classes-------- 1.1039 +// --------------------------------------------------------------------------- 1.1040 + 1.1041 +static void defineOut_RegMask(FILE *fp, const char *node, const char *regMask) { 1.1042 + fprintf(fp,"const RegMask &%sNode::out_RegMask() const { return (%s); }\n", 1.1043 + node, regMask); 1.1044 +} 1.1045 + 1.1046 +// Scan the peepmatch and output a test for each instruction 1.1047 +static void check_peepmatch_instruction_tree(FILE *fp, PeepMatch *pmatch, PeepConstraint *pconstraint) { 1.1048 + intptr_t parent = -1; 1.1049 + intptr_t inst_position = 0; 1.1050 + const char *inst_name = NULL; 1.1051 + intptr_t input = 0; 1.1052 + fprintf(fp, " // Check instruction sub-tree\n"); 1.1053 + pmatch->reset(); 1.1054 + for( pmatch->next_instruction( parent, inst_position, inst_name, input ); 1.1055 + inst_name != NULL; 1.1056 + pmatch->next_instruction( parent, inst_position, inst_name, input ) ) { 1.1057 + // If this is not a placeholder 1.1058 + if( ! pmatch->is_placeholder() ) { 1.1059 + // Define temporaries 'inst#', based on parent and parent's input index 1.1060 + if( parent != -1 ) { // root was initialized 1.1061 + fprintf(fp, " inst%ld = inst%ld->in(%ld);\n", 1.1062 + inst_position, parent, input); 1.1063 + } 1.1064 + 1.1065 + // When not the root 1.1066 + // Test we have the correct instruction by comparing the rule 1.1067 + if( parent != -1 ) { 1.1068 + fprintf(fp, " matches = matches && ( inst%ld->rule() == %s_rule );", 1.1069 + inst_position, inst_name); 1.1070 + } 1.1071 + } else { 1.1072 + // Check that user did not try to constrain a placeholder 1.1073 + assert( ! pconstraint->constrains_instruction(inst_position), 1.1074 + "fatal(): Can not constrain a placeholder instruction"); 1.1075 + } 1.1076 + } 1.1077 +} 1.1078 + 1.1079 +static void print_block_index(FILE *fp, intptr_t inst_position) { 1.1080 + assert( inst_position >= 0, "Instruction number less than zero"); 1.1081 + fprintf(fp, "block_index"); 1.1082 + if( inst_position != 0 ) { 1.1083 + fprintf(fp, " - %ld", inst_position); 1.1084 + } 1.1085 +} 1.1086 + 1.1087 +// Scan the peepmatch and output a test for each instruction 1.1088 +static void check_peepmatch_instruction_sequence(FILE *fp, PeepMatch *pmatch, PeepConstraint *pconstraint) { 1.1089 + intptr_t parent = -1; 1.1090 + intptr_t inst_position = 0; 1.1091 + const char *inst_name = NULL; 1.1092 + intptr_t input = 0; 1.1093 + fprintf(fp, " // Check instruction sub-tree\n"); 1.1094 + pmatch->reset(); 1.1095 + for( pmatch->next_instruction( parent, inst_position, inst_name, input ); 1.1096 + inst_name != NULL; 1.1097 + pmatch->next_instruction( parent, inst_position, inst_name, input ) ) { 1.1098 + // If this is not a placeholder 1.1099 + if( ! pmatch->is_placeholder() ) { 1.1100 + // Define temporaries 'inst#', based on parent and parent's input index 1.1101 + if( parent != -1 ) { // root was initialized 1.1102 + fprintf(fp, " // Identify previous instruction if inside this block\n"); 1.1103 + fprintf(fp, " if( "); 1.1104 + print_block_index(fp, inst_position); 1.1105 + fprintf(fp, " > 0 ) {\n Node *n = block->_nodes.at("); 1.1106 + print_block_index(fp, inst_position); 1.1107 + fprintf(fp, ");\n inst%ld = (n->is_Mach()) ? ", inst_position); 1.1108 + fprintf(fp, "n->as_Mach() : NULL;\n }\n"); 1.1109 + } 1.1110 + 1.1111 + // When not the root 1.1112 + // Test we have the correct instruction by comparing the rule. 1.1113 + if( parent != -1 ) { 1.1114 + fprintf(fp, " matches = matches && (inst%ld != NULL) && (inst%ld->rule() == %s_rule);\n", 1.1115 + inst_position, inst_position, inst_name); 1.1116 + } 1.1117 + } else { 1.1118 + // Check that user did not try to constrain a placeholder 1.1119 + assert( ! pconstraint->constrains_instruction(inst_position), 1.1120 + "fatal(): Can not constrain a placeholder instruction"); 1.1121 + } 1.1122 + } 1.1123 +} 1.1124 + 1.1125 +// Build mapping for register indices, num_edges to input 1.1126 +static void build_instruction_index_mapping( FILE *fp, FormDict &globals, PeepMatch *pmatch ) { 1.1127 + intptr_t parent = -1; 1.1128 + intptr_t inst_position = 0; 1.1129 + const char *inst_name = NULL; 1.1130 + intptr_t input = 0; 1.1131 + fprintf(fp, " // Build map to register info\n"); 1.1132 + pmatch->reset(); 1.1133 + for( pmatch->next_instruction( parent, inst_position, inst_name, input ); 1.1134 + inst_name != NULL; 1.1135 + pmatch->next_instruction( parent, inst_position, inst_name, input ) ) { 1.1136 + // If this is not a placeholder 1.1137 + if( ! pmatch->is_placeholder() ) { 1.1138 + // Define temporaries 'inst#', based on self's inst_position 1.1139 + InstructForm *inst = globals[inst_name]->is_instruction(); 1.1140 + if( inst != NULL ) { 1.1141 + char inst_prefix[] = "instXXXX_"; 1.1142 + sprintf(inst_prefix, "inst%ld_", inst_position); 1.1143 + char receiver[] = "instXXXX->"; 1.1144 + sprintf(receiver, "inst%ld->", inst_position); 1.1145 + inst->index_temps( fp, globals, inst_prefix, receiver ); 1.1146 + } 1.1147 + } 1.1148 + } 1.1149 +} 1.1150 + 1.1151 +// Generate tests for the constraints 1.1152 +static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch, PeepConstraint *pconstraint) { 1.1153 + fprintf(fp, "\n"); 1.1154 + fprintf(fp, " // Check constraints on sub-tree-leaves\n"); 1.1155 + 1.1156 + // Build mapping from num_edges to local variables 1.1157 + build_instruction_index_mapping( fp, globals, pmatch ); 1.1158 + 1.1159 + // Build constraint tests 1.1160 + if( pconstraint != NULL ) { 1.1161 + fprintf(fp, " matches = matches &&"); 1.1162 + bool first_constraint = true; 1.1163 + while( pconstraint != NULL ) { 1.1164 + // indentation and connecting '&&' 1.1165 + const char *indentation = " "; 1.1166 + fprintf(fp, "\n%s%s", indentation, (!first_constraint ? "&& " : " ")); 1.1167 + 1.1168 + // Only have '==' relation implemented 1.1169 + if( strcmp(pconstraint->_relation,"==") != 0 ) { 1.1170 + assert( false, "Unimplemented()" ); 1.1171 + } 1.1172 + 1.1173 + // LEFT 1.1174 + intptr_t left_index = pconstraint->_left_inst; 1.1175 + const char *left_op = pconstraint->_left_op; 1.1176 + // Access info on the instructions whose operands are compared 1.1177 + InstructForm *inst_left = globals[pmatch->instruction_name(left_index)]->is_instruction(); 1.1178 + assert( inst_left, "Parser should guaranty this is an instruction"); 1.1179 + int left_op_base = inst_left->oper_input_base(globals); 1.1180 + // Access info on the operands being compared 1.1181 + int left_op_index = inst_left->operand_position(left_op, Component::USE); 1.1182 + if( left_op_index == -1 ) { 1.1183 + left_op_index = inst_left->operand_position(left_op, Component::DEF); 1.1184 + if( left_op_index == -1 ) { 1.1185 + left_op_index = inst_left->operand_position(left_op, Component::USE_DEF); 1.1186 + } 1.1187 + } 1.1188 + assert( left_op_index != NameList::Not_in_list, "Did not find operand in instruction"); 1.1189 + ComponentList components_left = inst_left->_components; 1.1190 + const char *left_comp_type = components_left.at(left_op_index)->_type; 1.1191 + OpClassForm *left_opclass = globals[left_comp_type]->is_opclass(); 1.1192 + Form::InterfaceType left_interface_type = left_opclass->interface_type(globals); 1.1193 + 1.1194 + 1.1195 + // RIGHT 1.1196 + int right_op_index = -1; 1.1197 + intptr_t right_index = pconstraint->_right_inst; 1.1198 + const char *right_op = pconstraint->_right_op; 1.1199 + if( right_index != -1 ) { // Match operand 1.1200 + // Access info on the instructions whose operands are compared 1.1201 + InstructForm *inst_right = globals[pmatch->instruction_name(right_index)]->is_instruction(); 1.1202 + assert( inst_right, "Parser should guaranty this is an instruction"); 1.1203 + int right_op_base = inst_right->oper_input_base(globals); 1.1204 + // Access info on the operands being compared 1.1205 + right_op_index = inst_right->operand_position(right_op, Component::USE); 1.1206 + if( right_op_index == -1 ) { 1.1207 + right_op_index = inst_right->operand_position(right_op, Component::DEF); 1.1208 + if( right_op_index == -1 ) { 1.1209 + right_op_index = inst_right->operand_position(right_op, Component::USE_DEF); 1.1210 + } 1.1211 + } 1.1212 + assert( right_op_index != NameList::Not_in_list, "Did not find operand in instruction"); 1.1213 + ComponentList components_right = inst_right->_components; 1.1214 + const char *right_comp_type = components_right.at(right_op_index)->_type; 1.1215 + OpClassForm *right_opclass = globals[right_comp_type]->is_opclass(); 1.1216 + Form::InterfaceType right_interface_type = right_opclass->interface_type(globals); 1.1217 + assert( right_interface_type == left_interface_type, "Both must be same interface"); 1.1218 + 1.1219 + } else { // Else match register 1.1220 + // assert( false, "should be a register" ); 1.1221 + } 1.1222 + 1.1223 + // 1.1224 + // Check for equivalence 1.1225 + // 1.1226 + // fprintf(fp, "phase->eqv( "); 1.1227 + // fprintf(fp, "inst%d->in(%d+%d) /* %s */, inst%d->in(%d+%d) /* %s */", 1.1228 + // left_index, left_op_base, left_op_index, left_op, 1.1229 + // right_index, right_op_base, right_op_index, right_op ); 1.1230 + // fprintf(fp, ")"); 1.1231 + // 1.1232 + switch( left_interface_type ) { 1.1233 + case Form::register_interface: { 1.1234 + // Check that they are allocated to the same register 1.1235 + // Need parameter for index position if not result operand 1.1236 + char left_reg_index[] = ",instXXXX_idxXXXX"; 1.1237 + if( left_op_index != 0 ) { 1.1238 + assert( (left_index <= 9999) && (left_op_index <= 9999), "exceed string size"); 1.1239 + // Must have index into operands 1.1240 + sprintf(left_reg_index,",inst%d_idx%d", left_index, left_op_index); 1.1241 + } else { 1.1242 + strcpy(left_reg_index, ""); 1.1243 + } 1.1244 + fprintf(fp, "(inst%d->_opnds[%d]->reg(ra_,inst%d%s) /* %d.%s */", 1.1245 + left_index, left_op_index, left_index, left_reg_index, left_index, left_op ); 1.1246 + fprintf(fp, " == "); 1.1247 + 1.1248 + if( right_index != -1 ) { 1.1249 + char right_reg_index[18] = ",instXXXX_idxXXXX"; 1.1250 + if( right_op_index != 0 ) { 1.1251 + assert( (right_index <= 9999) && (right_op_index <= 9999), "exceed string size"); 1.1252 + // Must have index into operands 1.1253 + sprintf(right_reg_index,",inst%d_idx%d", right_index, right_op_index); 1.1254 + } else { 1.1255 + strcpy(right_reg_index, ""); 1.1256 + } 1.1257 + fprintf(fp, "/* %d.%s */ inst%d->_opnds[%d]->reg(ra_,inst%d%s)", 1.1258 + right_index, right_op, right_index, right_op_index, right_index, right_reg_index ); 1.1259 + } else { 1.1260 + fprintf(fp, "%s_enc", right_op ); 1.1261 + } 1.1262 + fprintf(fp,")"); 1.1263 + break; 1.1264 + } 1.1265 + case Form::constant_interface: { 1.1266 + // Compare the '->constant()' values 1.1267 + fprintf(fp, "(inst%d->_opnds[%d]->constant() /* %d.%s */", 1.1268 + left_index, left_op_index, left_index, left_op ); 1.1269 + fprintf(fp, " == "); 1.1270 + fprintf(fp, "/* %d.%s */ inst%d->_opnds[%d]->constant())", 1.1271 + right_index, right_op, right_index, right_op_index ); 1.1272 + break; 1.1273 + } 1.1274 + case Form::memory_interface: { 1.1275 + // Compare 'base', 'index', 'scale', and 'disp' 1.1276 + // base 1.1277 + fprintf(fp, "( \n"); 1.1278 + fprintf(fp, " (inst%d->_opnds[%d]->base(ra_,inst%d,inst%d_idx%d) /* %d.%s$$base */", 1.1279 + left_index, left_op_index, left_index, left_index, left_op_index, left_index, left_op ); 1.1280 + fprintf(fp, " == "); 1.1281 + fprintf(fp, "/* %d.%s$$base */ inst%d->_opnds[%d]->base(ra_,inst%d,inst%d_idx%d)) &&\n", 1.1282 + right_index, right_op, right_index, right_op_index, right_index, right_index, right_op_index ); 1.1283 + // index 1.1284 + fprintf(fp, " (inst%d->_opnds[%d]->index(ra_,inst%d,inst%d_idx%d) /* %d.%s$$index */", 1.1285 + left_index, left_op_index, left_index, left_index, left_op_index, left_index, left_op ); 1.1286 + fprintf(fp, " == "); 1.1287 + fprintf(fp, "/* %d.%s$$index */ inst%d->_opnds[%d]->index(ra_,inst%d,inst%d_idx%d)) &&\n", 1.1288 + right_index, right_op, right_index, right_op_index, right_index, right_index, right_op_index ); 1.1289 + // scale 1.1290 + fprintf(fp, " (inst%d->_opnds[%d]->scale() /* %d.%s$$scale */", 1.1291 + left_index, left_op_index, left_index, left_op ); 1.1292 + fprintf(fp, " == "); 1.1293 + fprintf(fp, "/* %d.%s$$scale */ inst%d->_opnds[%d]->scale()) &&\n", 1.1294 + right_index, right_op, right_index, right_op_index ); 1.1295 + // disp 1.1296 + fprintf(fp, " (inst%d->_opnds[%d]->disp(ra_,inst%d,inst%d_idx%d) /* %d.%s$$disp */", 1.1297 + left_index, left_op_index, left_index, left_index, left_op_index, left_index, left_op ); 1.1298 + fprintf(fp, " == "); 1.1299 + fprintf(fp, "/* %d.%s$$disp */ inst%d->_opnds[%d]->disp(ra_,inst%d,inst%d_idx%d))\n", 1.1300 + right_index, right_op, right_index, right_op_index, right_index, right_index, right_op_index ); 1.1301 + fprintf(fp, ") \n"); 1.1302 + break; 1.1303 + } 1.1304 + case Form::conditional_interface: { 1.1305 + // Compare the condition code being tested 1.1306 + assert( false, "Unimplemented()" ); 1.1307 + break; 1.1308 + } 1.1309 + default: { 1.1310 + assert( false, "ShouldNotReachHere()" ); 1.1311 + break; 1.1312 + } 1.1313 + } 1.1314 + 1.1315 + // Advance to next constraint 1.1316 + pconstraint = pconstraint->next(); 1.1317 + first_constraint = false; 1.1318 + } 1.1319 + 1.1320 + fprintf(fp, ";\n"); 1.1321 + } 1.1322 +} 1.1323 + 1.1324 +// // EXPERIMENTAL -- TEMPORARY code 1.1325 +// static Form::DataType get_operand_type(FormDict &globals, InstructForm *instr, const char *op_name ) { 1.1326 +// int op_index = instr->operand_position(op_name, Component::USE); 1.1327 +// if( op_index == -1 ) { 1.1328 +// op_index = instr->operand_position(op_name, Component::DEF); 1.1329 +// if( op_index == -1 ) { 1.1330 +// op_index = instr->operand_position(op_name, Component::USE_DEF); 1.1331 +// } 1.1332 +// } 1.1333 +// assert( op_index != NameList::Not_in_list, "Did not find operand in instruction"); 1.1334 +// 1.1335 +// ComponentList components_right = instr->_components; 1.1336 +// char *right_comp_type = components_right.at(op_index)->_type; 1.1337 +// OpClassForm *right_opclass = globals[right_comp_type]->is_opclass(); 1.1338 +// Form::InterfaceType right_interface_type = right_opclass->interface_type(globals); 1.1339 +// 1.1340 +// return; 1.1341 +// } 1.1342 + 1.1343 +// Construct the new sub-tree 1.1344 +static void generate_peepreplace( FILE *fp, FormDict &globals, PeepMatch *pmatch, PeepConstraint *pconstraint, PeepReplace *preplace, int max_position ) { 1.1345 + fprintf(fp, " // IF instructions and constraints matched\n"); 1.1346 + fprintf(fp, " if( matches ) {\n"); 1.1347 + fprintf(fp, " // generate the new sub-tree\n"); 1.1348 + fprintf(fp, " assert( true, \"Debug stopping point\");\n"); 1.1349 + if( preplace != NULL ) { 1.1350 + // Get the root of the new sub-tree 1.1351 + const char *root_inst = NULL; 1.1352 + preplace->next_instruction(root_inst); 1.1353 + InstructForm *root_form = globals[root_inst]->is_instruction(); 1.1354 + assert( root_form != NULL, "Replacement instruction was not previously defined"); 1.1355 + fprintf(fp, " %sNode *root = new (C) %sNode();\n", root_inst, root_inst); 1.1356 + 1.1357 + intptr_t inst_num; 1.1358 + const char *op_name; 1.1359 + int opnds_index = 0; // define result operand 1.1360 + // Then install the use-operands for the new sub-tree 1.1361 + // preplace->reset(); // reset breaks iteration 1.1362 + for( preplace->next_operand( inst_num, op_name ); 1.1363 + op_name != NULL; 1.1364 + preplace->next_operand( inst_num, op_name ) ) { 1.1365 + InstructForm *inst_form; 1.1366 + inst_form = globals[pmatch->instruction_name(inst_num)]->is_instruction(); 1.1367 + assert( inst_form, "Parser should guaranty this is an instruction"); 1.1368 + int op_base = inst_form->oper_input_base(globals); 1.1369 + int inst_op_num = inst_form->operand_position(op_name, Component::USE); 1.1370 + if( inst_op_num == NameList::Not_in_list ) 1.1371 + inst_op_num = inst_form->operand_position(op_name, Component::USE_DEF); 1.1372 + assert( inst_op_num != NameList::Not_in_list, "Did not find operand as USE"); 1.1373 + // find the name of the OperandForm from the local name 1.1374 + const Form *form = inst_form->_localNames[op_name]; 1.1375 + OperandForm *op_form = form->is_operand(); 1.1376 + if( opnds_index == 0 ) { 1.1377 + // Initial setup of new instruction 1.1378 + fprintf(fp, " // ----- Initial setup -----\n"); 1.1379 + // 1.1380 + // Add control edge for this node 1.1381 + fprintf(fp, " root->add_req(_in[0]); // control edge\n"); 1.1382 + // Add unmatched edges from root of match tree 1.1383 + int op_base = root_form->oper_input_base(globals); 1.1384 + for( int unmatched_edge = 1; unmatched_edge < op_base; ++unmatched_edge ) { 1.1385 + fprintf(fp, " root->add_req(inst%ld->in(%d)); // unmatched ideal edge\n", 1.1386 + inst_num, unmatched_edge); 1.1387 + } 1.1388 + // If new instruction captures bottom type 1.1389 + if( root_form->captures_bottom_type() ) { 1.1390 + // Get bottom type from instruction whose result we are replacing 1.1391 + fprintf(fp, " root->_bottom_type = inst%ld->bottom_type();\n", inst_num); 1.1392 + } 1.1393 + // Define result register and result operand 1.1394 + fprintf(fp, " ra_->add_reference(root, inst%ld);\n", inst_num); 1.1395 + fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%ld));\n", inst_num); 1.1396 + fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%ld), ra_->get_reg_first(inst%ld));\n", inst_num, inst_num); 1.1397 + fprintf(fp, " root->_opnds[0] = inst%ld->_opnds[0]->clone(C); // result\n", inst_num); 1.1398 + fprintf(fp, " // ----- Done with initial setup -----\n"); 1.1399 + } else { 1.1400 + if( (op_form == NULL) || (op_form->is_base_constant(globals) == Form::none) ) { 1.1401 + // Do not have ideal edges for constants after matching 1.1402 + fprintf(fp, " for( unsigned x%d = inst%ld_idx%d; x%d < inst%ld_idx%d; x%d++ )\n", 1.1403 + inst_op_num, inst_num, inst_op_num, 1.1404 + inst_op_num, inst_num, inst_op_num+1, inst_op_num ); 1.1405 + fprintf(fp, " root->add_req( inst%ld->in(x%d) );\n", 1.1406 + inst_num, inst_op_num ); 1.1407 + } else { 1.1408 + fprintf(fp, " // no ideal edge for constants after matching\n"); 1.1409 + } 1.1410 + fprintf(fp, " root->_opnds[%d] = inst%ld->_opnds[%d]->clone(C);\n", 1.1411 + opnds_index, inst_num, inst_op_num ); 1.1412 + } 1.1413 + ++opnds_index; 1.1414 + } 1.1415 + }else { 1.1416 + // Replacing subtree with empty-tree 1.1417 + assert( false, "ShouldNotReachHere();"); 1.1418 + } 1.1419 + 1.1420 + // Return the new sub-tree 1.1421 + fprintf(fp, " deleted = %d;\n", max_position+1 /*zero to one based*/); 1.1422 + fprintf(fp, " return root; // return new root;\n"); 1.1423 + fprintf(fp, " }\n"); 1.1424 +} 1.1425 + 1.1426 + 1.1427 +// Define the Peephole method for an instruction node 1.1428 +void ArchDesc::definePeephole(FILE *fp, InstructForm *node) { 1.1429 + // Generate Peephole function header 1.1430 + fprintf(fp, "MachNode *%sNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {\n", node->_ident); 1.1431 + fprintf(fp, " bool matches = true;\n"); 1.1432 + 1.1433 + // Identify the maximum instruction position, 1.1434 + // generate temporaries that hold current instruction 1.1435 + // 1.1436 + // MachNode *inst0 = NULL; 1.1437 + // ... 1.1438 + // MachNode *instMAX = NULL; 1.1439 + // 1.1440 + int max_position = 0; 1.1441 + Peephole *peep; 1.1442 + for( peep = node->peepholes(); peep != NULL; peep = peep->next() ) { 1.1443 + PeepMatch *pmatch = peep->match(); 1.1444 + assert( pmatch != NULL, "fatal(), missing peepmatch rule"); 1.1445 + if( max_position < pmatch->max_position() ) max_position = pmatch->max_position(); 1.1446 + } 1.1447 + for( int i = 0; i <= max_position; ++i ) { 1.1448 + if( i == 0 ) { 1.1449 + fprintf(fp, " MachNode *inst0 = this;\n", i); 1.1450 + } else { 1.1451 + fprintf(fp, " MachNode *inst%d = NULL;\n", i); 1.1452 + } 1.1453 + } 1.1454 + 1.1455 + // For each peephole rule in architecture description 1.1456 + // Construct a test for the desired instruction sub-tree 1.1457 + // then check the constraints 1.1458 + // If these match, Generate the new subtree 1.1459 + for( peep = node->peepholes(); peep != NULL; peep = peep->next() ) { 1.1460 + int peephole_number = peep->peephole_number(); 1.1461 + PeepMatch *pmatch = peep->match(); 1.1462 + PeepConstraint *pconstraint = peep->constraints(); 1.1463 + PeepReplace *preplace = peep->replacement(); 1.1464 + 1.1465 + // Root of this peephole is the current MachNode 1.1466 + assert( true, // %%name?%% strcmp( node->_ident, pmatch->name(0) ) == 0, 1.1467 + "root of PeepMatch does not match instruction"); 1.1468 + 1.1469 + // Make each peephole rule individually selectable 1.1470 + fprintf(fp, " if( (OptoPeepholeAt == -1) || (OptoPeepholeAt==%d) ) {\n", peephole_number); 1.1471 + fprintf(fp, " matches = true;\n"); 1.1472 + // Scan the peepmatch and output a test for each instruction 1.1473 + check_peepmatch_instruction_sequence( fp, pmatch, pconstraint ); 1.1474 + 1.1475 + // Check constraints and build replacement inside scope 1.1476 + fprintf(fp, " // If instruction subtree matches\n"); 1.1477 + fprintf(fp, " if( matches ) {\n"); 1.1478 + 1.1479 + // Generate tests for the constraints 1.1480 + check_peepconstraints( fp, _globalNames, pmatch, pconstraint ); 1.1481 + 1.1482 + // Construct the new sub-tree 1.1483 + generate_peepreplace( fp, _globalNames, pmatch, pconstraint, preplace, max_position ); 1.1484 + 1.1485 + // End of scope for this peephole's constraints 1.1486 + fprintf(fp, " }\n"); 1.1487 + // Closing brace '}' to make each peephole rule individually selectable 1.1488 + fprintf(fp, " } // end of peephole rule #%d\n", peephole_number); 1.1489 + fprintf(fp, "\n"); 1.1490 + } 1.1491 + 1.1492 + fprintf(fp, " return NULL; // No peephole rules matched\n"); 1.1493 + fprintf(fp, "}\n"); 1.1494 + fprintf(fp, "\n"); 1.1495 +} 1.1496 + 1.1497 +// Define the Expand method for an instruction node 1.1498 +void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { 1.1499 + unsigned cnt = 0; // Count nodes we have expand into 1.1500 + unsigned i; 1.1501 + 1.1502 + // Generate Expand function header 1.1503 + fprintf(fp,"MachNode *%sNode::Expand(State *state, Node_List &proj_list) {\n", node->_ident); 1.1504 + fprintf(fp,"Compile* C = Compile::current();\n"); 1.1505 + // Generate expand code 1.1506 + if( node->expands() ) { 1.1507 + const char *opid; 1.1508 + int new_pos, exp_pos; 1.1509 + const char *new_id = NULL; 1.1510 + const Form *frm = NULL; 1.1511 + InstructForm *new_inst = NULL; 1.1512 + OperandForm *new_oper = NULL; 1.1513 + unsigned numo = node->num_opnds() + 1.1514 + node->_exprule->_newopers.count(); 1.1515 + 1.1516 + // If necessary, generate any operands created in expand rule 1.1517 + if (node->_exprule->_newopers.count()) { 1.1518 + for(node->_exprule->_newopers.reset(); 1.1519 + (new_id = node->_exprule->_newopers.iter()) != NULL; cnt++) { 1.1520 + frm = node->_localNames[new_id]; 1.1521 + assert(frm, "Invalid entry in new operands list of expand rule"); 1.1522 + new_oper = frm->is_operand(); 1.1523 + char *tmp = (char *)node->_exprule->_newopconst[new_id]; 1.1524 + if (tmp == NULL) { 1.1525 + fprintf(fp," MachOper *op%d = new (C) %sOper();\n", 1.1526 + cnt, new_oper->_ident); 1.1527 + } 1.1528 + else { 1.1529 + fprintf(fp," MachOper *op%d = new (C) %sOper(%s);\n", 1.1530 + cnt, new_oper->_ident, tmp); 1.1531 + } 1.1532 + } 1.1533 + } 1.1534 + cnt = 0; 1.1535 + // Generate the temps to use for DAG building 1.1536 + for(i = 0; i < numo; i++) { 1.1537 + if (i < node->num_opnds()) { 1.1538 + fprintf(fp," MachNode *tmp%d = this;\n", i); 1.1539 + } 1.1540 + else { 1.1541 + fprintf(fp," MachNode *tmp%d = NULL;\n", i); 1.1542 + } 1.1543 + } 1.1544 + // Build mapping from num_edges to local variables 1.1545 + fprintf(fp," unsigned num0 = 0;\n"); 1.1546 + for( i = 1; i < node->num_opnds(); i++ ) { 1.1547 + fprintf(fp," unsigned num%d = opnd_array(%d)->num_edges();\n",i,i); 1.1548 + } 1.1549 + 1.1550 + // Build a mapping from operand index to input edges 1.1551 + fprintf(fp," unsigned idx0 = oper_input_base();\n"); 1.1552 + for( i = 0; i < node->num_opnds(); i++ ) { 1.1553 + fprintf(fp," unsigned idx%d = idx%d + num%d;\n", 1.1554 + i+1,i,i); 1.1555 + } 1.1556 + 1.1557 + // Declare variable to hold root of expansion 1.1558 + fprintf(fp," MachNode *result = NULL;\n"); 1.1559 + 1.1560 + // Iterate over the instructions 'node' expands into 1.1561 + ExpandRule *expand = node->_exprule; 1.1562 + NameAndList *expand_instr = NULL; 1.1563 + for(expand->reset_instructions(); 1.1564 + (expand_instr = expand->iter_instructions()) != NULL; cnt++) { 1.1565 + new_id = expand_instr->name(); 1.1566 + 1.1567 + InstructForm* expand_instruction = (InstructForm*)globalAD->globalNames()[new_id]; 1.1568 + if (expand_instruction->has_temps()) { 1.1569 + globalAD->syntax_err(node->_linenum, "In %s: expand rules using instructs with TEMPs aren't supported: %s", 1.1570 + node->_ident, new_id); 1.1571 + } 1.1572 + 1.1573 + // Build the node for the instruction 1.1574 + fprintf(fp,"\n %sNode *n%d = new (C) %sNode();\n", new_id, cnt, new_id); 1.1575 + // Add control edge for this node 1.1576 + fprintf(fp," n%d->add_req(_in[0]);\n", cnt); 1.1577 + // Build the operand for the value this node defines. 1.1578 + Form *form = (Form*)_globalNames[new_id]; 1.1579 + assert( form, "'new_id' must be a defined form name"); 1.1580 + // Grab the InstructForm for the new instruction 1.1581 + new_inst = form->is_instruction(); 1.1582 + assert( new_inst, "'new_id' must be an instruction name"); 1.1583 + if( node->is_ideal_if() && new_inst->is_ideal_if() ) { 1.1584 + fprintf(fp, " ((MachIfNode*)n%d)->_prob = _prob;\n",cnt); 1.1585 + fprintf(fp, " ((MachIfNode*)n%d)->_fcnt = _fcnt;\n",cnt); 1.1586 + } 1.1587 + 1.1588 + if( node->is_ideal_fastlock() && new_inst->is_ideal_fastlock() ) { 1.1589 + fprintf(fp, " ((MachFastLockNode*)n%d)->_counters = _counters;\n",cnt); 1.1590 + } 1.1591 + 1.1592 + const char *resultOper = new_inst->reduce_result(); 1.1593 + fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator( %s, C ));\n", 1.1594 + cnt, machOperEnum(resultOper)); 1.1595 + 1.1596 + // get the formal operand NameList 1.1597 + NameList *formal_lst = &new_inst->_parameters; 1.1598 + formal_lst->reset(); 1.1599 + 1.1600 + // Handle any memory operand 1.1601 + int memory_operand = new_inst->memory_operand(_globalNames); 1.1602 + if( memory_operand != InstructForm::NO_MEMORY_OPERAND ) { 1.1603 + int node_mem_op = node->memory_operand(_globalNames); 1.1604 + assert( node_mem_op != InstructForm::NO_MEMORY_OPERAND, 1.1605 + "expand rule member needs memory but top-level inst doesn't have any" ); 1.1606 + // Copy memory edge 1.1607 + fprintf(fp," n%d->add_req(_in[1]);\t// Add memory edge\n", cnt); 1.1608 + } 1.1609 + 1.1610 + // Iterate over the new instruction's operands 1.1611 + for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) { 1.1612 + // Use 'parameter' at current position in list of new instruction's formals 1.1613 + // instead of 'opid' when looking up info internal to new_inst 1.1614 + const char *parameter = formal_lst->iter(); 1.1615 + // Check for an operand which is created in the expand rule 1.1616 + if ((exp_pos = node->_exprule->_newopers.index(opid)) != -1) { 1.1617 + new_pos = new_inst->operand_position(parameter,Component::USE); 1.1618 + exp_pos += node->num_opnds(); 1.1619 + // If there is no use of the created operand, just skip it 1.1620 + if (new_pos != -1) { 1.1621 + //Copy the operand from the original made above 1.1622 + fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n", 1.1623 + cnt, new_pos, exp_pos-node->num_opnds(), opid); 1.1624 + // Check for who defines this operand & add edge if needed 1.1625 + fprintf(fp," if(tmp%d != NULL)\n", exp_pos); 1.1626 + fprintf(fp," n%d->add_req(tmp%d);\n", cnt, exp_pos); 1.1627 + } 1.1628 + } 1.1629 + else { 1.1630 + // Use operand name to get an index into instruction component list 1.1631 + // ins = (InstructForm *) _globalNames[new_id]; 1.1632 + exp_pos = node->operand_position_format(opid); 1.1633 + assert(exp_pos != -1, "Bad expand rule"); 1.1634 + 1.1635 + new_pos = new_inst->operand_position(parameter,Component::USE); 1.1636 + if (new_pos != -1) { 1.1637 + // Copy the operand from the ExpandNode to the new node 1.1638 + fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n", 1.1639 + cnt, new_pos, exp_pos, opid); 1.1640 + // For each operand add appropriate input edges by looking at tmp's 1.1641 + fprintf(fp," if(tmp%d == this) {\n", exp_pos); 1.1642 + // Grab corresponding edges from ExpandNode and insert them here 1.1643 + fprintf(fp," for(unsigned i = 0; i < num%d; i++) {\n", exp_pos); 1.1644 + fprintf(fp," n%d->add_req(_in[i + idx%d]);\n", cnt, exp_pos); 1.1645 + fprintf(fp," }\n"); 1.1646 + fprintf(fp," }\n"); 1.1647 + // This value is generated by one of the new instructions 1.1648 + fprintf(fp," else n%d->add_req(tmp%d);\n", cnt, exp_pos); 1.1649 + } 1.1650 + } 1.1651 + 1.1652 + // Update the DAG tmp's for values defined by this instruction 1.1653 + int new_def_pos = new_inst->operand_position(parameter,Component::DEF); 1.1654 + Effect *eform = (Effect *)new_inst->_effects[parameter]; 1.1655 + // If this operand is a definition in either an effects rule 1.1656 + // or a match rule 1.1657 + if((eform) && (is_def(eform->_use_def))) { 1.1658 + // Update the temp associated with this operand 1.1659 + fprintf(fp," tmp%d = n%d;\n", exp_pos, cnt); 1.1660 + } 1.1661 + else if( new_def_pos != -1 ) { 1.1662 + // Instruction defines a value but user did not declare it 1.1663 + // in the 'effect' clause 1.1664 + fprintf(fp," tmp%d = n%d;\n", exp_pos, cnt); 1.1665 + } 1.1666 + } // done iterating over a new instruction's operands 1.1667 + 1.1668 + // Invoke Expand() for the newly created instruction. 1.1669 + fprintf(fp," result = n%d->Expand( state, proj_list );\n", cnt); 1.1670 + assert( !new_inst->expands(), "Do not have complete support for recursive expansion"); 1.1671 + } // done iterating over new instructions 1.1672 + fprintf(fp,"\n"); 1.1673 + } // done generating expand rule 1.1674 + 1.1675 + else if( node->_matrule != NULL ) { 1.1676 + // Remove duplicated operands and inputs which use the same name. 1.1677 + // Seach through match operands for the same name usage. 1.1678 + uint cur_num_opnds = node->num_opnds(); 1.1679 + if( cur_num_opnds > 1 && cur_num_opnds != node->num_unique_opnds() ) { 1.1680 + Component *comp = NULL; 1.1681 + // Build mapping from num_edges to local variables 1.1682 + fprintf(fp," unsigned num0 = 0;\n"); 1.1683 + for( i = 1; i < cur_num_opnds; i++ ) { 1.1684 + fprintf(fp," unsigned num%d = opnd_array(%d)->num_edges();\n",i,i); 1.1685 + } 1.1686 + // Build a mapping from operand index to input edges 1.1687 + fprintf(fp," unsigned idx0 = oper_input_base();\n"); 1.1688 + for( i = 0; i < cur_num_opnds; i++ ) { 1.1689 + fprintf(fp," unsigned idx%d = idx%d + num%d;\n", 1.1690 + i+1,i,i); 1.1691 + } 1.1692 + 1.1693 + uint new_num_opnds = 1; 1.1694 + node->_components.reset(); 1.1695 + // Skip first unique operands. 1.1696 + for( i = 1; i < cur_num_opnds; i++ ) { 1.1697 + comp = node->_components.iter(); 1.1698 + if( (int)i != node->unique_opnds_idx(i) ) { 1.1699 + break; 1.1700 + } 1.1701 + new_num_opnds++; 1.1702 + } 1.1703 + // Replace not unique operands with next unique operands. 1.1704 + for( ; i < cur_num_opnds; i++ ) { 1.1705 + comp = node->_components.iter(); 1.1706 + int j = node->unique_opnds_idx(i); 1.1707 + // unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique. 1.1708 + if( j != node->unique_opnds_idx(j) ) { 1.1709 + fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n", 1.1710 + new_num_opnds, i, comp->_name); 1.1711 + // delete not unique edges here 1.1712 + fprintf(fp," for(unsigned i = 0; i < num%d; i++) {\n", i); 1.1713 + fprintf(fp," set_req(i + idx%d, _in[i + idx%d]);\n", new_num_opnds, i); 1.1714 + fprintf(fp," }\n"); 1.1715 + fprintf(fp," num%d = num%d;\n", new_num_opnds, i); 1.1716 + fprintf(fp," idx%d = idx%d + num%d;\n", new_num_opnds+1, new_num_opnds, new_num_opnds); 1.1717 + new_num_opnds++; 1.1718 + } 1.1719 + } 1.1720 + // delete the rest of edges 1.1721 + fprintf(fp," for(int i = idx%d - 1; i >= (int)idx%d; i--) {\n", cur_num_opnds, new_num_opnds); 1.1722 + fprintf(fp," del_req(i);\n", i); 1.1723 + fprintf(fp," }\n"); 1.1724 + fprintf(fp," _num_opnds = %d;\n", new_num_opnds); 1.1725 + } 1.1726 + } 1.1727 + 1.1728 + 1.1729 + // Generate projections for instruction's additional DEFs and KILLs 1.1730 + if( ! node->expands() && (node->needs_projections() || node->has_temps())) { 1.1731 + // Get string representing the MachNode that projections point at 1.1732 + const char *machNode = "this"; 1.1733 + // Generate the projections 1.1734 + fprintf(fp," // Add projection edges for additional defs or kills\n"); 1.1735 + 1.1736 + // Examine each component to see if it is a DEF or KILL 1.1737 + node->_components.reset(); 1.1738 + // Skip the first component, if already handled as (SET dst (...)) 1.1739 + Component *comp = NULL; 1.1740 + // For kills, the choice of projection numbers is arbitrary 1.1741 + int proj_no = 1; 1.1742 + bool declared_def = false; 1.1743 + bool declared_kill = false; 1.1744 + 1.1745 + while( (comp = node->_components.iter()) != NULL ) { 1.1746 + // Lookup register class associated with operand type 1.1747 + Form *form = (Form*)_globalNames[comp->_type]; 1.1748 + assert( form, "component type must be a defined form"); 1.1749 + OperandForm *op = form->is_operand(); 1.1750 + 1.1751 + if (comp->is(Component::TEMP)) { 1.1752 + fprintf(fp, " // TEMP %s\n", comp->_name); 1.1753 + if (!declared_def) { 1.1754 + // Define the variable "def" to hold new MachProjNodes 1.1755 + fprintf(fp, " MachTempNode *def;\n"); 1.1756 + declared_def = true; 1.1757 + } 1.1758 + if (op && op->_interface && op->_interface->is_RegInterface()) { 1.1759 + fprintf(fp," def = new (C) MachTempNode(state->MachOperGenerator( %s, C ));\n", 1.1760 + machOperEnum(op->_ident)); 1.1761 + fprintf(fp," add_req(def);\n"); 1.1762 + int idx = node->operand_position_format(comp->_name); 1.1763 + fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n", 1.1764 + idx, machOperEnum(op->_ident)); 1.1765 + } else { 1.1766 + assert(false, "can't have temps which aren't registers"); 1.1767 + } 1.1768 + } else if (comp->isa(Component::KILL)) { 1.1769 + fprintf(fp, " // DEF/KILL %s\n", comp->_name); 1.1770 + 1.1771 + if (!declared_kill) { 1.1772 + // Define the variable "kill" to hold new MachProjNodes 1.1773 + fprintf(fp, " MachProjNode *kill;\n"); 1.1774 + declared_kill = true; 1.1775 + } 1.1776 + 1.1777 + assert( op, "Support additional KILLS for base operands"); 1.1778 + const char *regmask = reg_mask(*op); 1.1779 + const char *ideal_type = op->ideal_type(_globalNames, _register); 1.1780 + 1.1781 + if (!op->is_bound_register()) { 1.1782 + syntax_err(node->_linenum, "In %s only bound registers can be killed: %s %s\n", 1.1783 + node->_ident, comp->_type, comp->_name); 1.1784 + } 1.1785 + 1.1786 + fprintf(fp," kill = "); 1.1787 + fprintf(fp,"new (C, 1) MachProjNode( %s, %d, (%s), Op_%s );\n", 1.1788 + machNode, proj_no++, regmask, ideal_type); 1.1789 + fprintf(fp," proj_list.push(kill);\n"); 1.1790 + } 1.1791 + } 1.1792 + } 1.1793 + 1.1794 + fprintf(fp,"\n"); 1.1795 + if( node->expands() ) { 1.1796 + fprintf(fp," return result;\n",cnt-1); 1.1797 + } else { 1.1798 + fprintf(fp," return this;\n"); 1.1799 + } 1.1800 + fprintf(fp,"}\n"); 1.1801 + fprintf(fp,"\n"); 1.1802 +} 1.1803 + 1.1804 + 1.1805 +//------------------------------Emit Routines---------------------------------- 1.1806 +// Special classes and routines for defining node emit routines which output 1.1807 +// target specific instruction object encodings. 1.1808 +// Define the ___Node::emit() routine 1.1809 +// 1.1810 +// (1) void ___Node::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 1.1811 +// (2) // ... encoding defined by user 1.1812 +// (3) 1.1813 +// (4) } 1.1814 +// 1.1815 + 1.1816 +class DefineEmitState { 1.1817 +private: 1.1818 + enum reloc_format { RELOC_NONE = -1, 1.1819 + RELOC_IMMEDIATE = 0, 1.1820 + RELOC_DISP = 1, 1.1821 + RELOC_CALL_DISP = 2 }; 1.1822 + enum literal_status{ LITERAL_NOT_SEEN = 0, 1.1823 + LITERAL_SEEN = 1, 1.1824 + LITERAL_ACCESSED = 2, 1.1825 + LITERAL_OUTPUT = 3 }; 1.1826 + // Temporaries that describe current operand 1.1827 + bool _cleared; 1.1828 + OpClassForm *_opclass; 1.1829 + OperandForm *_operand; 1.1830 + int _operand_idx; 1.1831 + const char *_local_name; 1.1832 + const char *_operand_name; 1.1833 + bool _doing_disp; 1.1834 + bool _doing_constant; 1.1835 + Form::DataType _constant_type; 1.1836 + DefineEmitState::literal_status _constant_status; 1.1837 + DefineEmitState::literal_status _reg_status; 1.1838 + bool _doing_emit8; 1.1839 + bool _doing_emit_d32; 1.1840 + bool _doing_emit_d16; 1.1841 + bool _doing_emit_hi; 1.1842 + bool _doing_emit_lo; 1.1843 + bool _may_reloc; 1.1844 + bool _must_reloc; 1.1845 + reloc_format _reloc_form; 1.1846 + const char * _reloc_type; 1.1847 + bool _processing_noninput; 1.1848 + 1.1849 + NameList _strings_to_emit; 1.1850 + 1.1851 + // Stable state, set by constructor 1.1852 + ArchDesc &_AD; 1.1853 + FILE *_fp; 1.1854 + EncClass &_encoding; 1.1855 + InsEncode &_ins_encode; 1.1856 + InstructForm &_inst; 1.1857 + 1.1858 +public: 1.1859 + DefineEmitState(FILE *fp, ArchDesc &AD, EncClass &encoding, 1.1860 + InsEncode &ins_encode, InstructForm &inst) 1.1861 + : _AD(AD), _fp(fp), _encoding(encoding), _ins_encode(ins_encode), _inst(inst) { 1.1862 + clear(); 1.1863 + } 1.1864 + 1.1865 + void clear() { 1.1866 + _cleared = true; 1.1867 + _opclass = NULL; 1.1868 + _operand = NULL; 1.1869 + _operand_idx = 0; 1.1870 + _local_name = ""; 1.1871 + _operand_name = ""; 1.1872 + _doing_disp = false; 1.1873 + _doing_constant= false; 1.1874 + _constant_type = Form::none; 1.1875 + _constant_status = LITERAL_NOT_SEEN; 1.1876 + _reg_status = LITERAL_NOT_SEEN; 1.1877 + _doing_emit8 = false; 1.1878 + _doing_emit_d32= false; 1.1879 + _doing_emit_d16= false; 1.1880 + _doing_emit_hi = false; 1.1881 + _doing_emit_lo = false; 1.1882 + _may_reloc = false; 1.1883 + _must_reloc = false; 1.1884 + _reloc_form = RELOC_NONE; 1.1885 + _reloc_type = AdlcVMDeps::none_reloc_type(); 1.1886 + _strings_to_emit.clear(); 1.1887 + } 1.1888 + 1.1889 + // Track necessary state when identifying a replacement variable 1.1890 + void update_state(const char *rep_var) { 1.1891 + // A replacement variable or one of its subfields 1.1892 + // Obtain replacement variable from list 1.1893 + if ( (*rep_var) != '$' ) { 1.1894 + // A replacement variable, '$' prefix 1.1895 + // check_rep_var( rep_var ); 1.1896 + if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { 1.1897 + // No state needed. 1.1898 + assert( _opclass == NULL, 1.1899 + "'primary', 'secondary' and 'tertiary' don't follow operand."); 1.1900 + } else { 1.1901 + // Lookup its position in parameter list 1.1902 + int param_no = _encoding.rep_var_index(rep_var); 1.1903 + if ( param_no == -1 ) { 1.1904 + _AD.syntax_err( _encoding._linenum, 1.1905 + "Replacement variable %s not found in enc_class %s.\n", 1.1906 + rep_var, _encoding._name); 1.1907 + } 1.1908 + 1.1909 + // Lookup the corresponding ins_encode parameter 1.1910 + const char *inst_rep_var = _ins_encode.rep_var_name(_inst, param_no); 1.1911 + if (inst_rep_var == NULL) { 1.1912 + _AD.syntax_err( _ins_encode._linenum, 1.1913 + "Parameter %s not passed to enc_class %s from instruct %s.\n", 1.1914 + rep_var, _encoding._name, _inst._ident); 1.1915 + } 1.1916 + 1.1917 + // Check if instruction's actual parameter is a local name in the instruction 1.1918 + const Form *local = _inst._localNames[inst_rep_var]; 1.1919 + OpClassForm *opc = (local != NULL) ? local->is_opclass() : NULL; 1.1920 + // Note: assert removed to allow constant and symbolic parameters 1.1921 + // assert( opc, "replacement variable was not found in local names"); 1.1922 + // Lookup the index position iff the replacement variable is a localName 1.1923 + int idx = (opc != NULL) ? _inst.operand_position_format(inst_rep_var) : -1; 1.1924 + 1.1925 + if ( idx != -1 ) { 1.1926 + // This is a local in the instruction 1.1927 + // Update local state info. 1.1928 + _opclass = opc; 1.1929 + _operand_idx = idx; 1.1930 + _local_name = rep_var; 1.1931 + _operand_name = inst_rep_var; 1.1932 + 1.1933 + // !!!!! 1.1934 + // Do not support consecutive operands. 1.1935 + assert( _operand == NULL, "Unimplemented()"); 1.1936 + _operand = opc->is_operand(); 1.1937 + } 1.1938 + else if( ADLParser::is_literal_constant(inst_rep_var) ) { 1.1939 + // Instruction provided a constant expression 1.1940 + // Check later that encoding specifies $$$constant to resolve as constant 1.1941 + _constant_status = LITERAL_SEEN; 1.1942 + } 1.1943 + else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) { 1.1944 + // Instruction provided an opcode: "primary", "secondary", "tertiary" 1.1945 + // Check later that encoding specifies $$$constant to resolve as constant 1.1946 + _constant_status = LITERAL_SEEN; 1.1947 + } 1.1948 + else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) { 1.1949 + // Instruction provided a literal register name for this parameter 1.1950 + // Check that encoding specifies $$$reg to resolve.as register. 1.1951 + _reg_status = LITERAL_SEEN; 1.1952 + } 1.1953 + else { 1.1954 + // Check for unimplemented functionality before hard failure 1.1955 + assert( strcmp(opc->_ident,"label")==0, "Unimplemented() Label"); 1.1956 + assert( false, "ShouldNotReachHere()"); 1.1957 + } 1.1958 + } // done checking which operand this is. 1.1959 + } else { 1.1960 + // 1.1961 + // A subfield variable, '$$' prefix 1.1962 + // Check for fields that may require relocation information. 1.1963 + // Then check that literal register parameters are accessed with 'reg' or 'constant' 1.1964 + // 1.1965 + if ( strcmp(rep_var,"$disp") == 0 ) { 1.1966 + _doing_disp = true; 1.1967 + assert( _opclass, "Must use operand or operand class before '$disp'"); 1.1968 + if( _operand == NULL ) { 1.1969 + // Only have an operand class, generate run-time check for relocation 1.1970 + _may_reloc = true; 1.1971 + _reloc_form = RELOC_DISP; 1.1972 + _reloc_type = AdlcVMDeps::oop_reloc_type(); 1.1973 + } else { 1.1974 + // Do precise check on operand: is it a ConP or not 1.1975 + // 1.1976 + // Check interface for value of displacement 1.1977 + assert( ( _operand->_interface != NULL ), 1.1978 + "$disp can only follow memory interface operand"); 1.1979 + MemInterface *mem_interface= _operand->_interface->is_MemInterface(); 1.1980 + assert( mem_interface != NULL, 1.1981 + "$disp can only follow memory interface operand"); 1.1982 + const char *disp = mem_interface->_disp; 1.1983 + 1.1984 + if( disp != NULL && (*disp == '$') ) { 1.1985 + // MemInterface::disp contains a replacement variable, 1.1986 + // Check if this matches a ConP 1.1987 + // 1.1988 + // Lookup replacement variable, in operand's component list 1.1989 + const char *rep_var_name = disp + 1; // Skip '$' 1.1990 + const Component *comp = _operand->_components.search(rep_var_name); 1.1991 + assert( comp != NULL,"Replacement variable not found in components"); 1.1992 + const char *type = comp->_type; 1.1993 + // Lookup operand form for replacement variable's type 1.1994 + const Form *form = _AD.globalNames()[type]; 1.1995 + assert( form != NULL, "Replacement variable's type not found"); 1.1996 + OperandForm *op = form->is_operand(); 1.1997 + assert( op, "Attempting to emit a non-register or non-constant"); 1.1998 + // Check if this is a constant 1.1999 + if (op->_matrule && op->_matrule->is_base_constant(_AD.globalNames())) { 1.2000 + // Check which constant this name maps to: _c0, _c1, ..., _cn 1.2001 + // const int idx = _operand.constant_position(_AD.globalNames(), comp); 1.2002 + // assert( idx != -1, "Constant component not found in operand"); 1.2003 + Form::DataType dtype = op->is_base_constant(_AD.globalNames()); 1.2004 + if ( dtype == Form::idealP ) { 1.2005 + _may_reloc = true; 1.2006 + // No longer true that idealP is always an oop 1.2007 + _reloc_form = RELOC_DISP; 1.2008 + _reloc_type = AdlcVMDeps::oop_reloc_type(); 1.2009 + } 1.2010 + } 1.2011 + 1.2012 + else if( _operand->is_user_name_for_sReg() != Form::none ) { 1.2013 + // The only non-constant allowed access to disp is an operand sRegX in a stackSlotX 1.2014 + assert( op->ideal_to_sReg_type(type) != Form::none, "StackSlots access displacements using 'sRegs'"); 1.2015 + _may_reloc = false; 1.2016 + } else { 1.2017 + assert( false, "fatal(); Only stackSlots can access a non-constant using 'disp'"); 1.2018 + } 1.2019 + } 1.2020 + } // finished with precise check of operand for relocation. 1.2021 + } // finished with subfield variable 1.2022 + else if ( strcmp(rep_var,"$constant") == 0 ) { 1.2023 + _doing_constant = true; 1.2024 + if ( _constant_status == LITERAL_NOT_SEEN ) { 1.2025 + // Check operand for type of constant 1.2026 + assert( _operand, "Must use operand before '$$constant'"); 1.2027 + Form::DataType dtype = _operand->is_base_constant(_AD.globalNames()); 1.2028 + _constant_type = dtype; 1.2029 + if ( dtype == Form::idealP ) { 1.2030 + _may_reloc = true; 1.2031 + // No longer true that idealP is always an oop 1.2032 + // // _must_reloc = true; 1.2033 + _reloc_form = RELOC_IMMEDIATE; 1.2034 + _reloc_type = AdlcVMDeps::oop_reloc_type(); 1.2035 + } else { 1.2036 + // No relocation information needed 1.2037 + } 1.2038 + } else { 1.2039 + // User-provided literals may not require relocation information !!!!! 1.2040 + assert( _constant_status == LITERAL_SEEN, "Must know we are processing a user-provided literal"); 1.2041 + } 1.2042 + } 1.2043 + else if ( strcmp(rep_var,"$label") == 0 ) { 1.2044 + // Calls containing labels require relocation 1.2045 + if ( _inst.is_ideal_call() ) { 1.2046 + _may_reloc = true; 1.2047 + // !!!!! !!!!! 1.2048 + _reloc_type = AdlcVMDeps::none_reloc_type(); 1.2049 + } 1.2050 + } 1.2051 + 1.2052 + // literal register parameter must be accessed as a 'reg' field. 1.2053 + if ( _reg_status != LITERAL_NOT_SEEN ) { 1.2054 + assert( _reg_status == LITERAL_SEEN, "Must have seen register literal before now"); 1.2055 + if (strcmp(rep_var,"$reg") == 0 || reg_conversion(rep_var) != NULL) { 1.2056 + _reg_status = LITERAL_ACCESSED; 1.2057 + } else { 1.2058 + assert( false, "invalid access to literal register parameter"); 1.2059 + } 1.2060 + } 1.2061 + // literal constant parameters must be accessed as a 'constant' field 1.2062 + if ( _constant_status != LITERAL_NOT_SEEN ) { 1.2063 + assert( _constant_status == LITERAL_SEEN, "Must have seen constant literal before now"); 1.2064 + if( strcmp(rep_var,"$constant") == 0 ) { 1.2065 + _constant_status = LITERAL_ACCESSED; 1.2066 + } else { 1.2067 + assert( false, "invalid access to literal constant parameter"); 1.2068 + } 1.2069 + } 1.2070 + } // end replacement and/or subfield 1.2071 + 1.2072 + } 1.2073 + 1.2074 + void add_rep_var(const char *rep_var) { 1.2075 + // Handle subfield and replacement variables. 1.2076 + if ( ( *rep_var == '$' ) && ( *(rep_var+1) == '$' ) ) { 1.2077 + // Check for emit prefix, '$$emit32' 1.2078 + assert( _cleared, "Can not nest $$$emit32"); 1.2079 + if ( strcmp(rep_var,"$$emit32") == 0 ) { 1.2080 + _doing_emit_d32 = true; 1.2081 + } 1.2082 + else if ( strcmp(rep_var,"$$emit16") == 0 ) { 1.2083 + _doing_emit_d16 = true; 1.2084 + } 1.2085 + else if ( strcmp(rep_var,"$$emit_hi") == 0 ) { 1.2086 + _doing_emit_hi = true; 1.2087 + } 1.2088 + else if ( strcmp(rep_var,"$$emit_lo") == 0 ) { 1.2089 + _doing_emit_lo = true; 1.2090 + } 1.2091 + else if ( strcmp(rep_var,"$$emit8") == 0 ) { 1.2092 + _doing_emit8 = true; 1.2093 + } 1.2094 + else { 1.2095 + _AD.syntax_err(_encoding._linenum, "Unsupported $$operation '%s'\n",rep_var); 1.2096 + assert( false, "fatal();"); 1.2097 + } 1.2098 + } 1.2099 + else { 1.2100 + // Update state for replacement variables 1.2101 + update_state( rep_var ); 1.2102 + _strings_to_emit.addName(rep_var); 1.2103 + } 1.2104 + _cleared = false; 1.2105 + } 1.2106 + 1.2107 + void emit_replacement() { 1.2108 + // A replacement variable or one of its subfields 1.2109 + // Obtain replacement variable from list 1.2110 + // const char *ec_rep_var = encoding->_rep_vars.iter(); 1.2111 + const char *rep_var; 1.2112 + _strings_to_emit.reset(); 1.2113 + while ( (rep_var = _strings_to_emit.iter()) != NULL ) { 1.2114 + 1.2115 + if ( (*rep_var) == '$' ) { 1.2116 + // A subfield variable, '$$' prefix 1.2117 + emit_field( rep_var ); 1.2118 + } else { 1.2119 + // A replacement variable, '$' prefix 1.2120 + emit_rep_var( rep_var ); 1.2121 + } // end replacement and/or subfield 1.2122 + } 1.2123 + } 1.2124 + 1.2125 + void emit_reloc_type(const char* type) { 1.2126 + fprintf(_fp, "%s", type) 1.2127 + ; 1.2128 + } 1.2129 + 1.2130 + 1.2131 + void gen_emit_x_reloc(const char *d32_lo_hi ) { 1.2132 + fprintf(_fp,"emit_%s_reloc(cbuf, ", d32_lo_hi ); 1.2133 + emit_replacement(); fprintf(_fp,", "); 1.2134 + emit_reloc_type( _reloc_type ); fprintf(_fp,", "); 1.2135 + fprintf(_fp, "%d", _reloc_form);fprintf(_fp, ");"); 1.2136 + } 1.2137 + 1.2138 + 1.2139 + void emit() { 1.2140 + // 1.2141 + // "emit_d32_reloc(" or "emit_hi_reloc" or "emit_lo_reloc" 1.2142 + // 1.2143 + // Emit the function name when generating an emit function 1.2144 + if ( _doing_emit_d32 || _doing_emit_hi || _doing_emit_lo ) { 1.2145 + const char *d32_hi_lo = _doing_emit_d32 ? "d32" : (_doing_emit_hi ? "hi" : "lo"); 1.2146 + // In general, relocatable isn't known at compiler compile time. 1.2147 + // Check results of prior scan 1.2148 + if ( ! _may_reloc ) { 1.2149 + // Definitely don't need relocation information 1.2150 + fprintf( _fp, "emit_%s(cbuf, ", d32_hi_lo ); 1.2151 + emit_replacement(); fprintf(_fp, ")"); 1.2152 + } 1.2153 + else if ( _must_reloc ) { 1.2154 + // Must emit relocation information 1.2155 + gen_emit_x_reloc( d32_hi_lo ); 1.2156 + } 1.2157 + else { 1.2158 + // Emit RUNTIME CHECK to see if value needs relocation info 1.2159 + // If emitting a relocatable address, use 'emit_d32_reloc' 1.2160 + const char *disp_constant = _doing_disp ? "disp" : _doing_constant ? "constant" : "INVALID"; 1.2161 + assert( (_doing_disp || _doing_constant) 1.2162 + && !(_doing_disp && _doing_constant), 1.2163 + "Must be emitting either a displacement or a constant"); 1.2164 + fprintf(_fp,"\n"); 1.2165 + fprintf(_fp,"if ( opnd_array(%d)->%s_is_oop() ) {\n", 1.2166 + _operand_idx, disp_constant); 1.2167 + fprintf(_fp," "); 1.2168 + gen_emit_x_reloc( d32_hi_lo ); fprintf(_fp,"\n"); 1.2169 + fprintf(_fp,"} else {\n"); 1.2170 + fprintf(_fp," emit_%s(cbuf, ", d32_hi_lo); 1.2171 + emit_replacement(); fprintf(_fp, ");\n"); fprintf(_fp,"}"); 1.2172 + } 1.2173 + } 1.2174 + else if ( _doing_emit_d16 ) { 1.2175 + // Relocation of 16-bit values is not supported 1.2176 + fprintf(_fp,"emit_d16(cbuf, "); 1.2177 + emit_replacement(); fprintf(_fp, ")"); 1.2178 + // No relocation done for 16-bit values 1.2179 + } 1.2180 + else if ( _doing_emit8 ) { 1.2181 + // Relocation of 8-bit values is not supported 1.2182 + fprintf(_fp,"emit_d8(cbuf, "); 1.2183 + emit_replacement(); fprintf(_fp, ")"); 1.2184 + // No relocation done for 8-bit values 1.2185 + } 1.2186 + else { 1.2187 + // Not an emit# command, just output the replacement string. 1.2188 + emit_replacement(); 1.2189 + } 1.2190 + 1.2191 + // Get ready for next state collection. 1.2192 + clear(); 1.2193 + } 1.2194 + 1.2195 +private: 1.2196 + 1.2197 + // recognizes names which represent MacroAssembler register types 1.2198 + // and return the conversion function to build them from OptoReg 1.2199 + const char* reg_conversion(const char* rep_var) { 1.2200 + if (strcmp(rep_var,"$Register") == 0) return "as_Register"; 1.2201 + if (strcmp(rep_var,"$FloatRegister") == 0) return "as_FloatRegister"; 1.2202 +#if defined(IA32) || defined(AMD64) 1.2203 + if (strcmp(rep_var,"$XMMRegister") == 0) return "as_XMMRegister"; 1.2204 +#endif 1.2205 + return NULL; 1.2206 + } 1.2207 + 1.2208 + void emit_field(const char *rep_var) { 1.2209 + const char* reg_convert = reg_conversion(rep_var); 1.2210 + 1.2211 + // A subfield variable, '$$subfield' 1.2212 + if ( strcmp(rep_var, "$reg") == 0 || reg_convert != NULL) { 1.2213 + // $reg form or the $Register MacroAssembler type conversions 1.2214 + assert( _operand_idx != -1, 1.2215 + "Must use this subfield after operand"); 1.2216 + if( _reg_status == LITERAL_NOT_SEEN ) { 1.2217 + if (_processing_noninput) { 1.2218 + const Form *local = _inst._localNames[_operand_name]; 1.2219 + OperandForm *oper = local->is_operand(); 1.2220 + const RegDef* first = oper->get_RegClass()->find_first_elem(); 1.2221 + if (reg_convert != NULL) { 1.2222 + fprintf(_fp, "%s(%s_enc)", reg_convert, first->_regname); 1.2223 + } else { 1.2224 + fprintf(_fp, "%s_enc", first->_regname); 1.2225 + } 1.2226 + } else { 1.2227 + fprintf(_fp,"->%s(ra_,this", reg_convert != NULL ? reg_convert : "reg"); 1.2228 + // Add parameter for index position, if not result operand 1.2229 + if( _operand_idx != 0 ) fprintf(_fp,",idx%d", _operand_idx); 1.2230 + fprintf(_fp,")"); 1.2231 + } 1.2232 + } else { 1.2233 + assert( _reg_status == LITERAL_OUTPUT, "should have output register literal in emit_rep_var"); 1.2234 + // Register literal has already been sent to output file, nothing more needed 1.2235 + } 1.2236 + } 1.2237 + else if ( strcmp(rep_var,"$base") == 0 ) { 1.2238 + assert( _operand_idx != -1, 1.2239 + "Must use this subfield after operand"); 1.2240 + assert( ! _may_reloc, "UnImplemented()"); 1.2241 + fprintf(_fp,"->base(ra_,this,idx%d)", _operand_idx); 1.2242 + } 1.2243 + else if ( strcmp(rep_var,"$index") == 0 ) { 1.2244 + assert( _operand_idx != -1, 1.2245 + "Must use this subfield after operand"); 1.2246 + assert( ! _may_reloc, "UnImplemented()"); 1.2247 + fprintf(_fp,"->index(ra_,this,idx%d)", _operand_idx); 1.2248 + } 1.2249 + else if ( strcmp(rep_var,"$scale") == 0 ) { 1.2250 + assert( ! _may_reloc, "UnImplemented()"); 1.2251 + fprintf(_fp,"->scale()"); 1.2252 + } 1.2253 + else if ( strcmp(rep_var,"$cmpcode") == 0 ) { 1.2254 + assert( ! _may_reloc, "UnImplemented()"); 1.2255 + fprintf(_fp,"->ccode()"); 1.2256 + } 1.2257 + else if ( strcmp(rep_var,"$constant") == 0 ) { 1.2258 + if( _constant_status == LITERAL_NOT_SEEN ) { 1.2259 + if ( _constant_type == Form::idealD ) { 1.2260 + fprintf(_fp,"->constantD()"); 1.2261 + } else if ( _constant_type == Form::idealF ) { 1.2262 + fprintf(_fp,"->constantF()"); 1.2263 + } else if ( _constant_type == Form::idealL ) { 1.2264 + fprintf(_fp,"->constantL()"); 1.2265 + } else { 1.2266 + fprintf(_fp,"->constant()"); 1.2267 + } 1.2268 + } else { 1.2269 + assert( _constant_status == LITERAL_OUTPUT, "should have output constant literal in emit_rep_var"); 1.2270 + // Cosntant literal has already been sent to output file, nothing more needed 1.2271 + } 1.2272 + } 1.2273 + else if ( strcmp(rep_var,"$disp") == 0 ) { 1.2274 + Form::DataType stack_type = _operand ? _operand->is_user_name_for_sReg() : Form::none; 1.2275 + if( _operand && _operand_idx==0 && stack_type != Form::none ) { 1.2276 + fprintf(_fp,"->disp(ra_,this,0)"); 1.2277 + } else { 1.2278 + fprintf(_fp,"->disp(ra_,this,idx%d)", _operand_idx); 1.2279 + } 1.2280 + } 1.2281 + else if ( strcmp(rep_var,"$label") == 0 ) { 1.2282 + fprintf(_fp,"->label()"); 1.2283 + } 1.2284 + else if ( strcmp(rep_var,"$method") == 0 ) { 1.2285 + fprintf(_fp,"->method()"); 1.2286 + } 1.2287 + else { 1.2288 + printf("emit_field: %s\n",rep_var); 1.2289 + assert( false, "UnImplemented()"); 1.2290 + } 1.2291 + } 1.2292 + 1.2293 + 1.2294 + void emit_rep_var(const char *rep_var) { 1.2295 + _processing_noninput = false; 1.2296 + // A replacement variable, originally '$' 1.2297 + if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { 1.2298 + _inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) ); 1.2299 + } 1.2300 + else { 1.2301 + // Lookup its position in parameter list 1.2302 + int param_no = _encoding.rep_var_index(rep_var); 1.2303 + if ( param_no == -1 ) { 1.2304 + _AD.syntax_err( _encoding._linenum, 1.2305 + "Replacement variable %s not found in enc_class %s.\n", 1.2306 + rep_var, _encoding._name); 1.2307 + } 1.2308 + // Lookup the corresponding ins_encode parameter 1.2309 + const char *inst_rep_var = _ins_encode.rep_var_name(_inst, param_no); 1.2310 + 1.2311 + // Check if instruction's actual parameter is a local name in the instruction 1.2312 + const Form *local = _inst._localNames[inst_rep_var]; 1.2313 + OpClassForm *opc = (local != NULL) ? local->is_opclass() : NULL; 1.2314 + // Note: assert removed to allow constant and symbolic parameters 1.2315 + // assert( opc, "replacement variable was not found in local names"); 1.2316 + // Lookup the index position iff the replacement variable is a localName 1.2317 + int idx = (opc != NULL) ? _inst.operand_position_format(inst_rep_var) : -1; 1.2318 + if( idx != -1 ) { 1.2319 + if (_inst.is_noninput_operand(idx)) { 1.2320 + // This operand isn't a normal input so printing it is done 1.2321 + // specially. 1.2322 + _processing_noninput = true; 1.2323 + } else { 1.2324 + // Output the emit code for this operand 1.2325 + fprintf(_fp,"opnd_array(%d)",idx); 1.2326 + } 1.2327 + assert( _operand == opc->is_operand(), 1.2328 + "Previous emit $operand does not match current"); 1.2329 + } 1.2330 + else if( ADLParser::is_literal_constant(inst_rep_var) ) { 1.2331 + // else check if it is a constant expression 1.2332 + // Removed following assert to allow primitive C types as arguments to encodings 1.2333 + // assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); 1.2334 + fprintf(_fp,"(%s)", inst_rep_var); 1.2335 + _constant_status = LITERAL_OUTPUT; 1.2336 + } 1.2337 + else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) { 1.2338 + // else check if "primary", "secondary", "tertiary" 1.2339 + assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); 1.2340 + _inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) ); 1.2341 + _constant_status = LITERAL_OUTPUT; 1.2342 + } 1.2343 + else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) { 1.2344 + // Instruction provided a literal register name for this parameter 1.2345 + // Check that encoding specifies $$$reg to resolve.as register. 1.2346 + assert( _reg_status == LITERAL_ACCESSED, "Must be processing a literal register parameter"); 1.2347 + fprintf(_fp,"(%s_enc)", inst_rep_var); 1.2348 + _reg_status = LITERAL_OUTPUT; 1.2349 + } 1.2350 + else { 1.2351 + // Check for unimplemented functionality before hard failure 1.2352 + assert( strcmp(opc->_ident,"label")==0, "Unimplemented() Label"); 1.2353 + assert( false, "ShouldNotReachHere()"); 1.2354 + } 1.2355 + // all done 1.2356 + } 1.2357 + } 1.2358 + 1.2359 +}; // end class DefineEmitState 1.2360 + 1.2361 + 1.2362 +void ArchDesc::defineSize(FILE *fp, InstructForm &inst) { 1.2363 + 1.2364 + //(1) 1.2365 + // Output instruction's emit prototype 1.2366 + fprintf(fp,"uint %sNode::size(PhaseRegAlloc *ra_) const {\n", 1.2367 + inst._ident); 1.2368 + 1.2369 + //(2) 1.2370 + // Print the size 1.2371 + fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size); 1.2372 + 1.2373 + // (3) and (4) 1.2374 + fprintf(fp,"}\n"); 1.2375 +} 1.2376 + 1.2377 +void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) { 1.2378 + InsEncode *ins_encode = inst._insencode; 1.2379 + 1.2380 + // (1) 1.2381 + // Output instruction's emit prototype 1.2382 + fprintf(fp,"void %sNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {\n", 1.2383 + inst._ident); 1.2384 + 1.2385 + // If user did not define an encode section, 1.2386 + // provide stub that does not generate any machine code. 1.2387 + if( (_encode == NULL) || (ins_encode == NULL) ) { 1.2388 + fprintf(fp, " // User did not define an encode section.\n"); 1.2389 + fprintf(fp,"}\n"); 1.2390 + return; 1.2391 + } 1.2392 + 1.2393 + // Save current instruction's starting address (helps with relocation). 1.2394 + fprintf( fp, " cbuf.set_inst_mark();\n"); 1.2395 + 1.2396 + // // // idx0 is only needed for syntactic purposes and only by "storeSSI" 1.2397 + // fprintf( fp, " unsigned idx0 = 0;\n"); 1.2398 + 1.2399 + // Output each operand's offset into the array of registers. 1.2400 + inst.index_temps( fp, _globalNames ); 1.2401 + 1.2402 + // Output this instruction's encodings 1.2403 + const char *ec_name; 1.2404 + bool user_defined = false; 1.2405 + ins_encode->reset(); 1.2406 + while ( (ec_name = ins_encode->encode_class_iter()) != NULL ) { 1.2407 + fprintf(fp, " {"); 1.2408 + // Output user-defined encoding 1.2409 + user_defined = true; 1.2410 + 1.2411 + const char *ec_code = NULL; 1.2412 + const char *ec_rep_var = NULL; 1.2413 + EncClass *encoding = _encode->encClass(ec_name); 1.2414 + if (encoding == NULL) { 1.2415 + fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name); 1.2416 + abort(); 1.2417 + } 1.2418 + 1.2419 + if (ins_encode->current_encoding_num_args() != encoding->num_args()) { 1.2420 + globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", 1.2421 + inst._ident, ins_encode->current_encoding_num_args(), 1.2422 + ec_name, encoding->num_args()); 1.2423 + } 1.2424 + 1.2425 + DefineEmitState pending(fp, *this, *encoding, *ins_encode, inst ); 1.2426 + encoding->_code.reset(); 1.2427 + encoding->_rep_vars.reset(); 1.2428 + // Process list of user-defined strings, 1.2429 + // and occurrences of replacement variables. 1.2430 + // Replacement Vars are pushed into a list and then output 1.2431 + while ( (ec_code = encoding->_code.iter()) != NULL ) { 1.2432 + if ( ! encoding->_code.is_signal( ec_code ) ) { 1.2433 + // Emit pending code 1.2434 + pending.emit(); 1.2435 + pending.clear(); 1.2436 + // Emit this code section 1.2437 + fprintf(fp,"%s", ec_code); 1.2438 + } else { 1.2439 + // A replacement variable or one of its subfields 1.2440 + // Obtain replacement variable from list 1.2441 + ec_rep_var = encoding->_rep_vars.iter(); 1.2442 + pending.add_rep_var(ec_rep_var); 1.2443 + } 1.2444 + } 1.2445 + // Emit pending code 1.2446 + pending.emit(); 1.2447 + pending.clear(); 1.2448 + fprintf(fp, "}\n"); 1.2449 + } // end while instruction's encodings 1.2450 + 1.2451 + // Check if user stated which encoding to user 1.2452 + if ( user_defined == false ) { 1.2453 + fprintf(fp, " // User did not define which encode class to use.\n"); 1.2454 + } 1.2455 + 1.2456 + // (3) and (4) 1.2457 + fprintf(fp,"}\n"); 1.2458 +} 1.2459 + 1.2460 +// --------------------------------------------------------------------------- 1.2461 +//--------Utilities to build MachOper and MachNode derived Classes------------ 1.2462 +// --------------------------------------------------------------------------- 1.2463 + 1.2464 +//------------------------------Utilities to build Operand Classes------------ 1.2465 +static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) { 1.2466 + uint num_edges = oper.num_edges(globals); 1.2467 + if( num_edges != 0 ) { 1.2468 + // Method header 1.2469 + fprintf(fp, "const RegMask *%sOper::in_RegMask(int index) const {\n", 1.2470 + oper._ident); 1.2471 + 1.2472 + // Assert that the index is in range. 1.2473 + fprintf(fp, " assert(0 <= index && index < %d, \"index out of range\");\n", 1.2474 + num_edges); 1.2475 + 1.2476 + // Figure out if all RegMasks are the same. 1.2477 + const char* first_reg_class = oper.in_reg_class(0, globals); 1.2478 + bool all_same = true; 1.2479 + assert(first_reg_class != NULL, "did not find register mask"); 1.2480 + 1.2481 + for (uint index = 1; all_same && index < num_edges; index++) { 1.2482 + const char* some_reg_class = oper.in_reg_class(index, globals); 1.2483 + assert(some_reg_class != NULL, "did not find register mask"); 1.2484 + if (strcmp(first_reg_class, some_reg_class) != 0) { 1.2485 + all_same = false; 1.2486 + } 1.2487 + } 1.2488 + 1.2489 + if (all_same) { 1.2490 + // Return the sole RegMask. 1.2491 + if (strcmp(first_reg_class, "stack_slots") == 0) { 1.2492 + fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); 1.2493 + } else { 1.2494 + fprintf(fp," return &%s_mask;\n", toUpper(first_reg_class)); 1.2495 + } 1.2496 + } else { 1.2497 + // Build a switch statement to return the desired mask. 1.2498 + fprintf(fp," switch (index) {\n"); 1.2499 + 1.2500 + for (uint index = 0; index < num_edges; index++) { 1.2501 + const char *reg_class = oper.in_reg_class(index, globals); 1.2502 + assert(reg_class != NULL, "did not find register mask"); 1.2503 + if( !strcmp(reg_class, "stack_slots") ) { 1.2504 + fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); 1.2505 + } else { 1.2506 + fprintf(fp, " case %d: return &%s_mask;\n", index, toUpper(reg_class)); 1.2507 + } 1.2508 + } 1.2509 + fprintf(fp," }\n"); 1.2510 + fprintf(fp," ShouldNotReachHere();\n"); 1.2511 + fprintf(fp," return NULL;\n"); 1.2512 + } 1.2513 + 1.2514 + // Method close 1.2515 + fprintf(fp, "}\n\n"); 1.2516 + } 1.2517 +} 1.2518 + 1.2519 +// generate code to create a clone for a class derived from MachOper 1.2520 +// 1.2521 +// (0) MachOper *MachOperXOper::clone(Compile* C) const { 1.2522 +// (1) return new (C) MachXOper( _ccode, _c0, _c1, ..., _cn); 1.2523 +// (2) } 1.2524 +// 1.2525 +static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) { 1.2526 + fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper._ident); 1.2527 + // Check for constants that need to be copied over 1.2528 + const int num_consts = oper.num_consts(globalNames); 1.2529 + const bool is_ideal_bool = oper.is_ideal_bool(); 1.2530 + if( (num_consts > 0) ) { 1.2531 + fprintf(fp," return new (C) %sOper(", oper._ident); 1.2532 + // generate parameters for constants 1.2533 + int i = 0; 1.2534 + fprintf(fp,"_c%d", i); 1.2535 + for( i = 1; i < num_consts; ++i) { 1.2536 + fprintf(fp,", _c%d", i); 1.2537 + } 1.2538 + // finish line (1) 1.2539 + fprintf(fp,");\n"); 1.2540 + } 1.2541 + else { 1.2542 + assert( num_consts == 0, "Currently support zero or one constant per operand clone function"); 1.2543 + fprintf(fp," return new (C) %sOper();\n", oper._ident); 1.2544 + } 1.2545 + // finish method 1.2546 + fprintf(fp,"}\n"); 1.2547 +} 1.2548 + 1.2549 +static void define_hash(FILE *fp, char *operand) { 1.2550 + fprintf(fp,"uint %sOper::hash() const { return 5; }\n", operand); 1.2551 +} 1.2552 + 1.2553 +static void define_cmp(FILE *fp, char *operand) { 1.2554 + fprintf(fp,"uint %sOper::cmp( const MachOper &oper ) const { return opcode() == oper.opcode(); }\n", operand); 1.2555 +} 1.2556 + 1.2557 + 1.2558 +// Helper functions for bug 4796752, abstracted with minimal modification 1.2559 +// from define_oper_interface() 1.2560 +OperandForm *rep_var_to_operand(const char *encoding, OperandForm &oper, FormDict &globals) { 1.2561 + OperandForm *op = NULL; 1.2562 + // Check for replacement variable 1.2563 + if( *encoding == '$' ) { 1.2564 + // Replacement variable 1.2565 + const char *rep_var = encoding + 1; 1.2566 + // Lookup replacement variable, rep_var, in operand's component list 1.2567 + const Component *comp = oper._components.search(rep_var); 1.2568 + assert( comp != NULL, "Replacement variable not found in components"); 1.2569 + // Lookup operand form for replacement variable's type 1.2570 + const char *type = comp->_type; 1.2571 + Form *form = (Form*)globals[type]; 1.2572 + assert( form != NULL, "Replacement variable's type not found"); 1.2573 + op = form->is_operand(); 1.2574 + assert( op, "Attempting to emit a non-register or non-constant"); 1.2575 + } 1.2576 + 1.2577 + return op; 1.2578 +} 1.2579 + 1.2580 +int rep_var_to_constant_index(const char *encoding, OperandForm &oper, FormDict &globals) { 1.2581 + int idx = -1; 1.2582 + // Check for replacement variable 1.2583 + if( *encoding == '$' ) { 1.2584 + // Replacement variable 1.2585 + const char *rep_var = encoding + 1; 1.2586 + // Lookup replacement variable, rep_var, in operand's component list 1.2587 + const Component *comp = oper._components.search(rep_var); 1.2588 + assert( comp != NULL, "Replacement variable not found in components"); 1.2589 + // Lookup operand form for replacement variable's type 1.2590 + const char *type = comp->_type; 1.2591 + Form *form = (Form*)globals[type]; 1.2592 + assert( form != NULL, "Replacement variable's type not found"); 1.2593 + OperandForm *op = form->is_operand(); 1.2594 + assert( op, "Attempting to emit a non-register or non-constant"); 1.2595 + // Check that this is a constant and find constant's index: 1.2596 + if (op->_matrule && op->_matrule->is_base_constant(globals)) { 1.2597 + idx = oper.constant_position(globals, comp); 1.2598 + } 1.2599 + } 1.2600 + 1.2601 + return idx; 1.2602 +} 1.2603 + 1.2604 +bool is_regI(const char *encoding, OperandForm &oper, FormDict &globals ) { 1.2605 + bool is_regI = false; 1.2606 + 1.2607 + OperandForm *op = rep_var_to_operand(encoding, oper, globals); 1.2608 + if( op != NULL ) { 1.2609 + // Check that this is a register 1.2610 + if ( (op->_matrule && op->_matrule->is_base_register(globals)) ) { 1.2611 + // Register 1.2612 + const char* ideal = op->ideal_type(globals); 1.2613 + is_regI = (ideal && (op->ideal_to_Reg_type(ideal) == Form::idealI)); 1.2614 + } 1.2615 + } 1.2616 + 1.2617 + return is_regI; 1.2618 +} 1.2619 + 1.2620 +bool is_conP(const char *encoding, OperandForm &oper, FormDict &globals ) { 1.2621 + bool is_conP = false; 1.2622 + 1.2623 + OperandForm *op = rep_var_to_operand(encoding, oper, globals); 1.2624 + if( op != NULL ) { 1.2625 + // Check that this is a constant pointer 1.2626 + if (op->_matrule && op->_matrule->is_base_constant(globals)) { 1.2627 + // Constant 1.2628 + Form::DataType dtype = op->is_base_constant(globals); 1.2629 + is_conP = (dtype == Form::idealP); 1.2630 + } 1.2631 + } 1.2632 + 1.2633 + return is_conP; 1.2634 +} 1.2635 + 1.2636 + 1.2637 +// Define a MachOper interface methods 1.2638 +void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals, 1.2639 + const char *name, const char *encoding) { 1.2640 + bool emit_position = false; 1.2641 + int position = -1; 1.2642 + 1.2643 + fprintf(fp," virtual int %s", name); 1.2644 + // Generate access method for base, index, scale, disp, ... 1.2645 + if( (strcmp(name,"base") == 0) || (strcmp(name,"index") == 0) ) { 1.2646 + fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n"); 1.2647 + emit_position = true; 1.2648 + } else if ( (strcmp(name,"disp") == 0) ) { 1.2649 + fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n"); 1.2650 + } else { 1.2651 + fprintf(fp,"() const { "); 1.2652 + } 1.2653 + 1.2654 + // Check for hexadecimal value OR replacement variable 1.2655 + if( *encoding == '$' ) { 1.2656 + // Replacement variable 1.2657 + const char *rep_var = encoding + 1; 1.2658 + fprintf(fp,"// Replacement variable: %s\n", encoding+1); 1.2659 + // Lookup replacement variable, rep_var, in operand's component list 1.2660 + const Component *comp = oper._components.search(rep_var); 1.2661 + assert( comp != NULL, "Replacement variable not found in components"); 1.2662 + // Lookup operand form for replacement variable's type 1.2663 + const char *type = comp->_type; 1.2664 + Form *form = (Form*)globals[type]; 1.2665 + assert( form != NULL, "Replacement variable's type not found"); 1.2666 + OperandForm *op = form->is_operand(); 1.2667 + assert( op, "Attempting to emit a non-register or non-constant"); 1.2668 + // Check that this is a register or a constant and generate code: 1.2669 + if ( (op->_matrule && op->_matrule->is_base_register(globals)) ) { 1.2670 + // Register 1.2671 + int idx_offset = oper.register_position( globals, rep_var); 1.2672 + position = idx_offset; 1.2673 + fprintf(fp," return (int)ra_->get_encode(node->in(idx"); 1.2674 + if ( idx_offset > 0 ) fprintf(fp, "+%d",idx_offset); 1.2675 + fprintf(fp,"));\n"); 1.2676 + } else if ( op->ideal_to_sReg_type(op->_ident) != Form::none ) { 1.2677 + // StackSlot for an sReg comes either from input node or from self, when idx==0 1.2678 + fprintf(fp," if( idx != 0 ) {\n"); 1.2679 + fprintf(fp," // Access register number for input operand\n"); 1.2680 + fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node->in(idx)));/* sReg */\n"); 1.2681 + fprintf(fp," }\n"); 1.2682 + fprintf(fp," // Access register number from myself\n"); 1.2683 + fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node));/* sReg */\n"); 1.2684 + } else if (op->_matrule && op->_matrule->is_base_constant(globals)) { 1.2685 + // Constant 1.2686 + // Check which constant this name maps to: _c0, _c1, ..., _cn 1.2687 + const int idx = oper.constant_position(globals, comp); 1.2688 + assert( idx != -1, "Constant component not found in operand"); 1.2689 + // Output code for this constant, type dependent. 1.2690 + fprintf(fp," return (int)" ); 1.2691 + oper.access_constant(fp, globals, (uint)idx /* , const_type */); 1.2692 + fprintf(fp,";\n"); 1.2693 + } else { 1.2694 + assert( false, "Attempting to emit a non-register or non-constant"); 1.2695 + } 1.2696 + } 1.2697 + else if( *encoding == '0' && *(encoding+1) == 'x' ) { 1.2698 + // Hex value 1.2699 + fprintf(fp,"return %s;", encoding); 1.2700 + } else { 1.2701 + assert( false, "Do not support octal or decimal encode constants"); 1.2702 + } 1.2703 + fprintf(fp," }\n"); 1.2704 + 1.2705 + if( emit_position && (position != -1) && (oper.num_edges(globals) > 0) ) { 1.2706 + fprintf(fp," virtual int %s_position() const { return %d; }\n", name, position); 1.2707 + MemInterface *mem_interface = oper._interface->is_MemInterface(); 1.2708 + const char *base = mem_interface->_base; 1.2709 + const char *disp = mem_interface->_disp; 1.2710 + if( emit_position && (strcmp(name,"base") == 0) 1.2711 + && base != NULL && is_regI(base, oper, globals) 1.2712 + && disp != NULL && is_conP(disp, oper, globals) ) { 1.2713 + // Found a memory access using a constant pointer for a displacement 1.2714 + // and a base register containing an integer offset. 1.2715 + // In this case the base and disp are reversed with respect to what 1.2716 + // is expected by MachNode::get_base_and_disp() and MachNode::adr_type(). 1.2717 + // Provide a non-NULL return for disp_as_type() that will allow adr_type() 1.2718 + // to correctly compute the access type for alias analysis. 1.2719 + // 1.2720 + // See BugId 4796752, operand indOffset32X in i486.ad 1.2721 + int idx = rep_var_to_constant_index(disp, oper, globals); 1.2722 + fprintf(fp," virtual const TypePtr *disp_as_type() const { return _c%d; }\n", idx); 1.2723 + } 1.2724 + } 1.2725 +} 1.2726 + 1.2727 +// 1.2728 +// Construct the method to copy _idx, inputs and operands to new node. 1.2729 +static void define_fill_new_machnode(bool used, FILE *fp_cpp) { 1.2730 + fprintf(fp_cpp, "\n"); 1.2731 + fprintf(fp_cpp, "// Copy _idx, inputs and operands to new node\n"); 1.2732 + fprintf(fp_cpp, "void MachNode::fill_new_machnode( MachNode* node, Compile* C) const {\n"); 1.2733 + if( !used ) { 1.2734 + fprintf(fp_cpp, " // This architecture does not have cisc or short branch instructions\n"); 1.2735 + fprintf(fp_cpp, " ShouldNotCallThis();\n"); 1.2736 + fprintf(fp_cpp, "}\n"); 1.2737 + } else { 1.2738 + // New node must use same node index for access through allocator's tables 1.2739 + fprintf(fp_cpp, " // New node must use same node index\n"); 1.2740 + fprintf(fp_cpp, " node->set_idx( _idx );\n"); 1.2741 + // Copy machine-independent inputs 1.2742 + fprintf(fp_cpp, " // Copy machine-independent inputs\n"); 1.2743 + fprintf(fp_cpp, " for( uint j = 0; j < req(); j++ ) {\n"); 1.2744 + fprintf(fp_cpp, " node->add_req(in(j));\n"); 1.2745 + fprintf(fp_cpp, " }\n"); 1.2746 + // Copy machine operands to new MachNode 1.2747 + fprintf(fp_cpp, " // Copy my operands, except for cisc position\n"); 1.2748 + fprintf(fp_cpp, " int nopnds = num_opnds();\n"); 1.2749 + fprintf(fp_cpp, " assert( node->num_opnds() == (uint)nopnds, \"Must have same number of operands\");\n"); 1.2750 + fprintf(fp_cpp, " MachOper **to = node->_opnds;\n"); 1.2751 + fprintf(fp_cpp, " for( int i = 0; i < nopnds; i++ ) {\n"); 1.2752 + fprintf(fp_cpp, " if( i != cisc_operand() ) \n"); 1.2753 + fprintf(fp_cpp, " to[i] = _opnds[i]->clone(C);\n"); 1.2754 + fprintf(fp_cpp, " }\n"); 1.2755 + fprintf(fp_cpp, "}\n"); 1.2756 + } 1.2757 + fprintf(fp_cpp, "\n"); 1.2758 +} 1.2759 + 1.2760 +//------------------------------defineClasses---------------------------------- 1.2761 +// Define members of MachNode and MachOper classes based on 1.2762 +// operand and instruction lists 1.2763 +void ArchDesc::defineClasses(FILE *fp) { 1.2764 + 1.2765 + // Define the contents of an array containing the machine register names 1.2766 + defineRegNames(fp, _register); 1.2767 + // Define an array containing the machine register encoding values 1.2768 + defineRegEncodes(fp, _register); 1.2769 + // Generate an enumeration of user-defined register classes 1.2770 + // and a list of register masks, one for each class. 1.2771 + // Only define the RegMask value objects in the expand file. 1.2772 + // Declare each as an extern const RegMask ...; in ad_<arch>.hpp 1.2773 + declare_register_masks(_HPP_file._fp); 1.2774 + // build_register_masks(fp); 1.2775 + build_register_masks(_CPP_EXPAND_file._fp); 1.2776 + // Define the pipe_classes 1.2777 + build_pipe_classes(_CPP_PIPELINE_file._fp); 1.2778 + 1.2779 + // Generate Machine Classes for each operand defined in AD file 1.2780 + fprintf(fp,"\n"); 1.2781 + fprintf(fp,"\n"); 1.2782 + fprintf(fp,"//------------------Define classes derived from MachOper---------------------\n"); 1.2783 + // Iterate through all operands 1.2784 + _operands.reset(); 1.2785 + OperandForm *oper; 1.2786 + for( ; (oper = (OperandForm*)_operands.iter()) != NULL; ) { 1.2787 + // Ensure this is a machine-world instruction 1.2788 + if ( oper->ideal_only() ) continue; 1.2789 + // !!!!! 1.2790 + // The declaration of labelOper is in machine-independent file: machnode 1.2791 + if ( strcmp(oper->_ident,"label") == 0 ) { 1.2792 + defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); 1.2793 + 1.2794 + fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident); 1.2795 + fprintf(fp," return new (C) %sOper(_label, _block_num);\n", oper->_ident); 1.2796 + fprintf(fp,"}\n"); 1.2797 + 1.2798 + fprintf(fp,"uint %sOper::opcode() const { return %s; }\n", 1.2799 + oper->_ident, machOperEnum(oper->_ident)); 1.2800 + // // Currently all XXXOper::Hash() methods are identical (990820) 1.2801 + // define_hash(fp, oper->_ident); 1.2802 + // // Currently all XXXOper::Cmp() methods are identical (990820) 1.2803 + // define_cmp(fp, oper->_ident); 1.2804 + fprintf(fp,"\n"); 1.2805 + 1.2806 + continue; 1.2807 + } 1.2808 + 1.2809 + // The declaration of methodOper is in machine-independent file: machnode 1.2810 + if ( strcmp(oper->_ident,"method") == 0 ) { 1.2811 + defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); 1.2812 + 1.2813 + fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident); 1.2814 + fprintf(fp," return new (C) %sOper(_method);\n", oper->_ident); 1.2815 + fprintf(fp,"}\n"); 1.2816 + 1.2817 + fprintf(fp,"uint %sOper::opcode() const { return %s; }\n", 1.2818 + oper->_ident, machOperEnum(oper->_ident)); 1.2819 + // // Currently all XXXOper::Hash() methods are identical (990820) 1.2820 + // define_hash(fp, oper->_ident); 1.2821 + // // Currently all XXXOper::Cmp() methods are identical (990820) 1.2822 + // define_cmp(fp, oper->_ident); 1.2823 + fprintf(fp,"\n"); 1.2824 + 1.2825 + continue; 1.2826 + } 1.2827 + 1.2828 + defineIn_RegMask(fp, _globalNames, *oper); 1.2829 + defineClone(_CPP_CLONE_file._fp, _globalNames, *oper); 1.2830 + // // Currently all XXXOper::Hash() methods are identical (990820) 1.2831 + // define_hash(fp, oper->_ident); 1.2832 + // // Currently all XXXOper::Cmp() methods are identical (990820) 1.2833 + // define_cmp(fp, oper->_ident); 1.2834 + 1.2835 + // side-call to generate output that used to be in the header file: 1.2836 + extern void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_file); 1.2837 + gen_oper_format(_CPP_FORMAT_file._fp, _globalNames, *oper, true); 1.2838 + 1.2839 + } 1.2840 + 1.2841 + 1.2842 + // Generate Machine Classes for each instruction defined in AD file 1.2843 + fprintf(fp,"//------------------Define members for classes derived from MachNode----------\n"); 1.2844 + // Output the definitions for out_RegMask() // & kill_RegMask() 1.2845 + _instructions.reset(); 1.2846 + InstructForm *instr; 1.2847 + MachNodeForm *machnode; 1.2848 + for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.2849 + // Ensure this is a machine-world instruction 1.2850 + if ( instr->ideal_only() ) continue; 1.2851 + 1.2852 + defineOut_RegMask(_CPP_MISC_file._fp, instr->_ident, reg_mask(*instr)); 1.2853 + } 1.2854 + 1.2855 + bool used = false; 1.2856 + // Output the definitions for expand rules & peephole rules 1.2857 + _instructions.reset(); 1.2858 + for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.2859 + // Ensure this is a machine-world instruction 1.2860 + if ( instr->ideal_only() ) continue; 1.2861 + // If there are multiple defs/kills, or an explicit expand rule, build rule 1.2862 + if( instr->expands() || instr->needs_projections() || 1.2863 + instr->has_temps() || 1.2864 + instr->_matrule != NULL && 1.2865 + instr->num_opnds() != instr->num_unique_opnds() ) 1.2866 + defineExpand(_CPP_EXPAND_file._fp, instr); 1.2867 + // If there is an explicit peephole rule, build it 1.2868 + if ( instr->peepholes() ) 1.2869 + definePeephole(_CPP_PEEPHOLE_file._fp, instr); 1.2870 + 1.2871 + // Output code to convert to the cisc version, if applicable 1.2872 + used |= instr->define_cisc_version(*this, fp); 1.2873 + 1.2874 + // Output code to convert to the short branch version, if applicable 1.2875 + used |= instr->define_short_branch_methods(fp); 1.2876 + } 1.2877 + 1.2878 + // Construct the method called by cisc_version() to copy inputs and operands. 1.2879 + define_fill_new_machnode(used, fp); 1.2880 + 1.2881 + // Output the definitions for labels 1.2882 + _instructions.reset(); 1.2883 + while( (instr = (InstructForm*)_instructions.iter()) != NULL ) { 1.2884 + // Ensure this is a machine-world instruction 1.2885 + if ( instr->ideal_only() ) continue; 1.2886 + 1.2887 + // Access the fields for operand Label 1.2888 + int label_position = instr->label_position(); 1.2889 + if( label_position != -1 ) { 1.2890 + // Set the label 1.2891 + fprintf(fp,"void %sNode::label_set( Label& label, uint block_num ) {\n", instr->_ident); 1.2892 + fprintf(fp," labelOper* oper = (labelOper*)(opnd_array(%d));\n", 1.2893 + label_position ); 1.2894 + fprintf(fp," oper->_label = &label;\n"); 1.2895 + fprintf(fp," oper->_block_num = block_num;\n"); 1.2896 + fprintf(fp,"}\n"); 1.2897 + } 1.2898 + } 1.2899 + 1.2900 + // Output the definitions for methods 1.2901 + _instructions.reset(); 1.2902 + while( (instr = (InstructForm*)_instructions.iter()) != NULL ) { 1.2903 + // Ensure this is a machine-world instruction 1.2904 + if ( instr->ideal_only() ) continue; 1.2905 + 1.2906 + // Access the fields for operand Label 1.2907 + int method_position = instr->method_position(); 1.2908 + if( method_position != -1 ) { 1.2909 + // Access the method's address 1.2910 + fprintf(fp,"void %sNode::method_set( intptr_t method ) {\n", instr->_ident); 1.2911 + fprintf(fp," ((methodOper*)opnd_array(%d))->_method = method;\n", 1.2912 + method_position ); 1.2913 + fprintf(fp,"}\n"); 1.2914 + fprintf(fp,"\n"); 1.2915 + } 1.2916 + } 1.2917 + 1.2918 + // Define this instruction's number of relocation entries, base is '0' 1.2919 + _instructions.reset(); 1.2920 + while( (instr = (InstructForm*)_instructions.iter()) != NULL ) { 1.2921 + // Output the definition for number of relocation entries 1.2922 + uint reloc_size = instr->reloc(_globalNames); 1.2923 + if ( reloc_size != 0 ) { 1.2924 + fprintf(fp,"int %sNode::reloc() const {\n", instr->_ident); 1.2925 + fprintf(fp, " return %d;\n", reloc_size ); 1.2926 + fprintf(fp,"}\n"); 1.2927 + fprintf(fp,"\n"); 1.2928 + } 1.2929 + } 1.2930 + fprintf(fp,"\n"); 1.2931 + 1.2932 + // Output the definitions for code generation 1.2933 + // 1.2934 + // address ___Node::emit(address ptr, PhaseRegAlloc *ra_) const { 1.2935 + // // ... encoding defined by user 1.2936 + // return ptr; 1.2937 + // } 1.2938 + // 1.2939 + _instructions.reset(); 1.2940 + for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.2941 + // Ensure this is a machine-world instruction 1.2942 + if ( instr->ideal_only() ) continue; 1.2943 + 1.2944 + if (instr->_insencode) defineEmit(fp, *instr); 1.2945 + if (instr->_size) defineSize(fp, *instr); 1.2946 + 1.2947 + // side-call to generate output that used to be in the header file: 1.2948 + extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file); 1.2949 + gen_inst_format(_CPP_FORMAT_file._fp, _globalNames, *instr, true); 1.2950 + } 1.2951 + 1.2952 + // Output the definitions for alias analysis 1.2953 + _instructions.reset(); 1.2954 + for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.2955 + // Ensure this is a machine-world instruction 1.2956 + if ( instr->ideal_only() ) continue; 1.2957 + 1.2958 + // Analyze machine instructions that either USE or DEF memory. 1.2959 + int memory_operand = instr->memory_operand(_globalNames); 1.2960 + // Some guys kill all of memory 1.2961 + if ( instr->is_wide_memory_kill(_globalNames) ) { 1.2962 + memory_operand = InstructForm::MANY_MEMORY_OPERANDS; 1.2963 + } 1.2964 + 1.2965 + if ( memory_operand != InstructForm::NO_MEMORY_OPERAND ) { 1.2966 + if( memory_operand == InstructForm::MANY_MEMORY_OPERANDS ) { 1.2967 + fprintf(fp,"const TypePtr *%sNode::adr_type() const { return TypePtr::BOTTOM; }\n", instr->_ident); 1.2968 + fprintf(fp,"const MachOper* %sNode::memory_operand() const { return (MachOper*)-1; }\n", instr->_ident); 1.2969 + } else { 1.2970 + fprintf(fp,"const MachOper* %sNode::memory_operand() const { return _opnds[%d]; }\n", instr->_ident, memory_operand); 1.2971 + } 1.2972 + } 1.2973 + } 1.2974 + 1.2975 + // Get the length of the longest identifier 1.2976 + int max_ident_len = 0; 1.2977 + _instructions.reset(); 1.2978 + 1.2979 + for ( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.2980 + if (instr->_ins_pipe && _pipeline->_classlist.search(instr->_ins_pipe)) { 1.2981 + int ident_len = (int)strlen(instr->_ident); 1.2982 + if( max_ident_len < ident_len ) 1.2983 + max_ident_len = ident_len; 1.2984 + } 1.2985 + } 1.2986 + 1.2987 + // Emit specifically for Node(s) 1.2988 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline_class() { return %s; }\n", 1.2989 + max_ident_len, "Node", _pipeline ? "(&pipeline_class_Zero_Instructions)" : "NULL"); 1.2990 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline() const { return %s; }\n", 1.2991 + max_ident_len, "Node", _pipeline ? "(&pipeline_class_Zero_Instructions)" : "NULL"); 1.2992 + fprintf(_CPP_PIPELINE_file._fp, "\n"); 1.2993 + 1.2994 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline_class() { return %s; }\n", 1.2995 + max_ident_len, "MachNode", _pipeline ? "(&pipeline_class_Unknown_Instructions)" : "NULL"); 1.2996 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline() const { return pipeline_class(); }\n", 1.2997 + max_ident_len, "MachNode"); 1.2998 + fprintf(_CPP_PIPELINE_file._fp, "\n"); 1.2999 + 1.3000 + // Output the definitions for machine node specific pipeline data 1.3001 + _machnodes.reset(); 1.3002 + 1.3003 + for ( ; (machnode = (MachNodeForm*)_machnodes.iter()) != NULL; ) { 1.3004 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %sNode::pipeline() const { return (&pipeline_class_%03d); }\n", 1.3005 + machnode->_ident, ((class PipeClassForm *)_pipeline->_classdict[machnode->_machnode_pipe])->_num); 1.3006 + } 1.3007 + 1.3008 + fprintf(_CPP_PIPELINE_file._fp, "\n"); 1.3009 + 1.3010 + // Output the definitions for instruction pipeline static data references 1.3011 + _instructions.reset(); 1.3012 + 1.3013 + for ( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3014 + if (instr->_ins_pipe && _pipeline->_classlist.search(instr->_ins_pipe)) { 1.3015 + fprintf(_CPP_PIPELINE_file._fp, "\n"); 1.3016 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*sNode::pipeline_class() { return (&pipeline_class_%03d); }\n", 1.3017 + max_ident_len, instr->_ident, ((class PipeClassForm *)_pipeline->_classdict[instr->_ins_pipe])->_num); 1.3018 + fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*sNode::pipeline() const { return (&pipeline_class_%03d); }\n", 1.3019 + max_ident_len, instr->_ident, ((class PipeClassForm *)_pipeline->_classdict[instr->_ins_pipe])->_num); 1.3020 + } 1.3021 + } 1.3022 +} 1.3023 + 1.3024 + 1.3025 +// -------------------------------- maps ------------------------------------ 1.3026 + 1.3027 +// Information needed to generate the ReduceOp mapping for the DFA 1.3028 +class OutputReduceOp : public OutputMap { 1.3029 +public: 1.3030 + OutputReduceOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) 1.3031 + : OutputMap(hpp, cpp, globals, AD) {}; 1.3032 + 1.3033 + void declaration() { fprintf(_hpp, "extern const int reduceOp[];\n"); } 1.3034 + void definition() { fprintf(_cpp, "const int reduceOp[] = {\n"); } 1.3035 + void closing() { fprintf(_cpp, " 0 // no trailing comma\n"); 1.3036 + OutputMap::closing(); 1.3037 + } 1.3038 + void map(OpClassForm &opc) { 1.3039 + const char *reduce = opc._ident; 1.3040 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3041 + else fprintf(_cpp, " 0"); 1.3042 + } 1.3043 + void map(OperandForm &oper) { 1.3044 + // Most operands without match rules, e.g. eFlagsReg, do not have a result operand 1.3045 + const char *reduce = (oper._matrule ? oper.reduce_result() : NULL); 1.3046 + // operand stackSlot does not have a match rule, but produces a stackSlot 1.3047 + if( oper.is_user_name_for_sReg() != Form::none ) reduce = oper.reduce_result(); 1.3048 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3049 + else fprintf(_cpp, " 0"); 1.3050 + } 1.3051 + void map(InstructForm &inst) { 1.3052 + const char *reduce = (inst._matrule ? inst.reduce_result() : NULL); 1.3053 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3054 + else fprintf(_cpp, " 0"); 1.3055 + } 1.3056 + void map(char *reduce) { 1.3057 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3058 + else fprintf(_cpp, " 0"); 1.3059 + } 1.3060 +}; 1.3061 + 1.3062 +// Information needed to generate the LeftOp mapping for the DFA 1.3063 +class OutputLeftOp : public OutputMap { 1.3064 +public: 1.3065 + OutputLeftOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) 1.3066 + : OutputMap(hpp, cpp, globals, AD) {}; 1.3067 + 1.3068 + void declaration() { fprintf(_hpp, "extern const int leftOp[];\n"); } 1.3069 + void definition() { fprintf(_cpp, "const int leftOp[] = {\n"); } 1.3070 + void closing() { fprintf(_cpp, " 0 // no trailing comma\n"); 1.3071 + OutputMap::closing(); 1.3072 + } 1.3073 + void map(OpClassForm &opc) { fprintf(_cpp, " 0"); } 1.3074 + void map(OperandForm &oper) { 1.3075 + const char *reduce = oper.reduce_left(_globals); 1.3076 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3077 + else fprintf(_cpp, " 0"); 1.3078 + } 1.3079 + void map(char *name) { 1.3080 + const char *reduce = _AD.reduceLeft(name); 1.3081 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3082 + else fprintf(_cpp, " 0"); 1.3083 + } 1.3084 + void map(InstructForm &inst) { 1.3085 + const char *reduce = inst.reduce_left(_globals); 1.3086 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3087 + else fprintf(_cpp, " 0"); 1.3088 + } 1.3089 +}; 1.3090 + 1.3091 + 1.3092 +// Information needed to generate the RightOp mapping for the DFA 1.3093 +class OutputRightOp : public OutputMap { 1.3094 +public: 1.3095 + OutputRightOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) 1.3096 + : OutputMap(hpp, cpp, globals, AD) {}; 1.3097 + 1.3098 + void declaration() { fprintf(_hpp, "extern const int rightOp[];\n"); } 1.3099 + void definition() { fprintf(_cpp, "const int rightOp[] = {\n"); } 1.3100 + void closing() { fprintf(_cpp, " 0 // no trailing comma\n"); 1.3101 + OutputMap::closing(); 1.3102 + } 1.3103 + void map(OpClassForm &opc) { fprintf(_cpp, " 0"); } 1.3104 + void map(OperandForm &oper) { 1.3105 + const char *reduce = oper.reduce_right(_globals); 1.3106 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3107 + else fprintf(_cpp, " 0"); 1.3108 + } 1.3109 + void map(char *name) { 1.3110 + const char *reduce = _AD.reduceRight(name); 1.3111 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3112 + else fprintf(_cpp, " 0"); 1.3113 + } 1.3114 + void map(InstructForm &inst) { 1.3115 + const char *reduce = inst.reduce_right(_globals); 1.3116 + if( reduce ) fprintf(_cpp, " %s_rule", reduce); 1.3117 + else fprintf(_cpp, " 0"); 1.3118 + } 1.3119 +}; 1.3120 + 1.3121 + 1.3122 +// Information needed to generate the Rule names for the DFA 1.3123 +class OutputRuleName : public OutputMap { 1.3124 +public: 1.3125 + OutputRuleName(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) 1.3126 + : OutputMap(hpp, cpp, globals, AD) {}; 1.3127 + 1.3128 + void declaration() { fprintf(_hpp, "extern const char *ruleName[];\n"); } 1.3129 + void definition() { fprintf(_cpp, "const char *ruleName[] = {\n"); } 1.3130 + void closing() { fprintf(_cpp, " \"no trailing comma\"\n"); 1.3131 + OutputMap::closing(); 1.3132 + } 1.3133 + void map(OpClassForm &opc) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(opc._ident) ); } 1.3134 + void map(OperandForm &oper) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(oper._ident) ); } 1.3135 + void map(char *name) { fprintf(_cpp, " \"%s\"", name ? name : "0"); } 1.3136 + void map(InstructForm &inst){ fprintf(_cpp, " \"%s\"", inst._ident ? inst._ident : "0"); } 1.3137 +}; 1.3138 + 1.3139 + 1.3140 +// Information needed to generate the swallowed mapping for the DFA 1.3141 +class OutputSwallowed : public OutputMap { 1.3142 +public: 1.3143 + OutputSwallowed(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) 1.3144 + : OutputMap(hpp, cpp, globals, AD) {}; 1.3145 + 1.3146 + void declaration() { fprintf(_hpp, "extern const bool swallowed[];\n"); } 1.3147 + void definition() { fprintf(_cpp, "const bool swallowed[] = {\n"); } 1.3148 + void closing() { fprintf(_cpp, " false // no trailing comma\n"); 1.3149 + OutputMap::closing(); 1.3150 + } 1.3151 + void map(OperandForm &oper) { // Generate the entry for this opcode 1.3152 + const char *swallowed = oper.swallowed(_globals) ? "true" : "false"; 1.3153 + fprintf(_cpp, " %s", swallowed); 1.3154 + } 1.3155 + void map(OpClassForm &opc) { fprintf(_cpp, " false"); } 1.3156 + void map(char *name) { fprintf(_cpp, " false"); } 1.3157 + void map(InstructForm &inst){ fprintf(_cpp, " false"); } 1.3158 +}; 1.3159 + 1.3160 + 1.3161 +// Information needed to generate the decision array for instruction chain rule 1.3162 +class OutputInstChainRule : public OutputMap { 1.3163 +public: 1.3164 + OutputInstChainRule(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) 1.3165 + : OutputMap(hpp, cpp, globals, AD) {}; 1.3166 + 1.3167 + void declaration() { fprintf(_hpp, "extern const bool instruction_chain_rule[];\n"); } 1.3168 + void definition() { fprintf(_cpp, "const bool instruction_chain_rule[] = {\n"); } 1.3169 + void closing() { fprintf(_cpp, " false // no trailing comma\n"); 1.3170 + OutputMap::closing(); 1.3171 + } 1.3172 + void map(OpClassForm &opc) { fprintf(_cpp, " false"); } 1.3173 + void map(OperandForm &oper) { fprintf(_cpp, " false"); } 1.3174 + void map(char *name) { fprintf(_cpp, " false"); } 1.3175 + void map(InstructForm &inst) { // Check for simple chain rule 1.3176 + const char *chain = inst.is_simple_chain_rule(_globals) ? "true" : "false"; 1.3177 + fprintf(_cpp, " %s", chain); 1.3178 + } 1.3179 +}; 1.3180 + 1.3181 + 1.3182 +//---------------------------build_map------------------------------------ 1.3183 +// Build mapping from enumeration for densely packed operands 1.3184 +// TO result and child types. 1.3185 +void ArchDesc::build_map(OutputMap &map) { 1.3186 + FILE *fp_hpp = map.decl_file(); 1.3187 + FILE *fp_cpp = map.def_file(); 1.3188 + int idx = 0; 1.3189 + OperandForm *op; 1.3190 + OpClassForm *opc; 1.3191 + InstructForm *inst; 1.3192 + 1.3193 + // Construct this mapping 1.3194 + map.declaration(); 1.3195 + fprintf(fp_cpp,"\n"); 1.3196 + map.definition(); 1.3197 + 1.3198 + // Output the mapping for operands 1.3199 + map.record_position(OutputMap::BEGIN_OPERANDS, idx ); 1.3200 + _operands.reset(); 1.3201 + for(; (op = (OperandForm*)_operands.iter()) != NULL; ) { 1.3202 + // Ensure this is a machine-world instruction 1.3203 + if ( op->ideal_only() ) continue; 1.3204 + 1.3205 + // Generate the entry for this opcode 1.3206 + map.map(*op); fprintf(fp_cpp, ", // %d\n", idx); 1.3207 + ++idx; 1.3208 + }; 1.3209 + fprintf(fp_cpp, " // last operand\n"); 1.3210 + 1.3211 + // Place all user-defined operand classes into the mapping 1.3212 + map.record_position(OutputMap::BEGIN_OPCLASSES, idx ); 1.3213 + _opclass.reset(); 1.3214 + for(; (opc = (OpClassForm*)_opclass.iter()) != NULL; ) { 1.3215 + map.map(*opc); fprintf(fp_cpp, ", // %d\n", idx); 1.3216 + ++idx; 1.3217 + }; 1.3218 + fprintf(fp_cpp, " // last operand class\n"); 1.3219 + 1.3220 + // Place all internally defined operands into the mapping 1.3221 + map.record_position(OutputMap::BEGIN_INTERNALS, idx ); 1.3222 + _internalOpNames.reset(); 1.3223 + char *name = NULL; 1.3224 + for(; (name = (char *)_internalOpNames.iter()) != NULL; ) { 1.3225 + map.map(name); fprintf(fp_cpp, ", // %d\n", idx); 1.3226 + ++idx; 1.3227 + }; 1.3228 + fprintf(fp_cpp, " // last internally defined operand\n"); 1.3229 + 1.3230 + // Place all user-defined instructions into the mapping 1.3231 + if( map.do_instructions() ) { 1.3232 + map.record_position(OutputMap::BEGIN_INSTRUCTIONS, idx ); 1.3233 + // Output all simple instruction chain rules first 1.3234 + map.record_position(OutputMap::BEGIN_INST_CHAIN_RULES, idx ); 1.3235 + { 1.3236 + _instructions.reset(); 1.3237 + for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3238 + // Ensure this is a machine-world instruction 1.3239 + if ( inst->ideal_only() ) continue; 1.3240 + if ( ! inst->is_simple_chain_rule(_globalNames) ) continue; 1.3241 + if ( inst->rematerialize(_globalNames, get_registers()) ) continue; 1.3242 + 1.3243 + map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); 1.3244 + ++idx; 1.3245 + }; 1.3246 + map.record_position(OutputMap::BEGIN_REMATERIALIZE, idx ); 1.3247 + _instructions.reset(); 1.3248 + for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3249 + // Ensure this is a machine-world instruction 1.3250 + if ( inst->ideal_only() ) continue; 1.3251 + if ( ! inst->is_simple_chain_rule(_globalNames) ) continue; 1.3252 + if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue; 1.3253 + 1.3254 + map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); 1.3255 + ++idx; 1.3256 + }; 1.3257 + map.record_position(OutputMap::END_INST_CHAIN_RULES, idx ); 1.3258 + } 1.3259 + // Output all instructions that are NOT simple chain rules 1.3260 + { 1.3261 + _instructions.reset(); 1.3262 + for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3263 + // Ensure this is a machine-world instruction 1.3264 + if ( inst->ideal_only() ) continue; 1.3265 + if ( inst->is_simple_chain_rule(_globalNames) ) continue; 1.3266 + if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue; 1.3267 + 1.3268 + map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); 1.3269 + ++idx; 1.3270 + }; 1.3271 + map.record_position(OutputMap::END_REMATERIALIZE, idx ); 1.3272 + _instructions.reset(); 1.3273 + for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3274 + // Ensure this is a machine-world instruction 1.3275 + if ( inst->ideal_only() ) continue; 1.3276 + if ( inst->is_simple_chain_rule(_globalNames) ) continue; 1.3277 + if ( inst->rematerialize(_globalNames, get_registers()) ) continue; 1.3278 + 1.3279 + map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); 1.3280 + ++idx; 1.3281 + }; 1.3282 + } 1.3283 + fprintf(fp_cpp, " // last instruction\n"); 1.3284 + map.record_position(OutputMap::END_INSTRUCTIONS, idx ); 1.3285 + } 1.3286 + // Finish defining table 1.3287 + map.closing(); 1.3288 +}; 1.3289 + 1.3290 + 1.3291 +// Helper function for buildReduceMaps 1.3292 +char reg_save_policy(const char *calling_convention) { 1.3293 + char callconv; 1.3294 + 1.3295 + if (!strcmp(calling_convention, "NS")) callconv = 'N'; 1.3296 + else if (!strcmp(calling_convention, "SOE")) callconv = 'E'; 1.3297 + else if (!strcmp(calling_convention, "SOC")) callconv = 'C'; 1.3298 + else if (!strcmp(calling_convention, "AS")) callconv = 'A'; 1.3299 + else callconv = 'Z'; 1.3300 + 1.3301 + return callconv; 1.3302 +} 1.3303 + 1.3304 +//---------------------------generate_assertion_checks------------------- 1.3305 +void ArchDesc::generate_adlc_verification(FILE *fp_cpp) { 1.3306 + fprintf(fp_cpp, "\n"); 1.3307 + 1.3308 + fprintf(fp_cpp, "#ifndef PRODUCT\n"); 1.3309 + fprintf(fp_cpp, "void Compile::adlc_verification() {\n"); 1.3310 + globalDefs().print_asserts(fp_cpp); 1.3311 + fprintf(fp_cpp, "}\n"); 1.3312 + fprintf(fp_cpp, "#endif\n"); 1.3313 + fprintf(fp_cpp, "\n"); 1.3314 +} 1.3315 + 1.3316 +//---------------------------addSourceBlocks----------------------------- 1.3317 +void ArchDesc::addSourceBlocks(FILE *fp_cpp) { 1.3318 + if (_source.count() > 0) 1.3319 + _source.output(fp_cpp); 1.3320 + 1.3321 + generate_adlc_verification(fp_cpp); 1.3322 +} 1.3323 +//---------------------------addHeaderBlocks----------------------------- 1.3324 +void ArchDesc::addHeaderBlocks(FILE *fp_hpp) { 1.3325 + if (_header.count() > 0) 1.3326 + _header.output(fp_hpp); 1.3327 +} 1.3328 +//-------------------------addPreHeaderBlocks---------------------------- 1.3329 +void ArchDesc::addPreHeaderBlocks(FILE *fp_hpp) { 1.3330 + // Output #defines from definition block 1.3331 + globalDefs().print_defines(fp_hpp); 1.3332 + 1.3333 + if (_pre_header.count() > 0) 1.3334 + _pre_header.output(fp_hpp); 1.3335 +} 1.3336 + 1.3337 +//---------------------------buildReduceMaps----------------------------- 1.3338 +// Build mapping from enumeration for densely packed operands 1.3339 +// TO result and child types. 1.3340 +void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) { 1.3341 + RegDef *rdef; 1.3342 + RegDef *next; 1.3343 + 1.3344 + // The emit bodies currently require functions defined in the source block. 1.3345 + 1.3346 + // Build external declarations for mappings 1.3347 + fprintf(fp_hpp, "\n"); 1.3348 + fprintf(fp_hpp, "extern const char register_save_policy[];\n"); 1.3349 + fprintf(fp_hpp, "extern const char c_reg_save_policy[];\n"); 1.3350 + fprintf(fp_hpp, "extern const int register_save_type[];\n"); 1.3351 + fprintf(fp_hpp, "\n"); 1.3352 + 1.3353 + // Construct Save-Policy array 1.3354 + fprintf(fp_cpp, "// Map from machine-independent register number to register_save_policy\n"); 1.3355 + fprintf(fp_cpp, "const char register_save_policy[] = {\n"); 1.3356 + _register->reset_RegDefs(); 1.3357 + for( rdef = _register->iter_RegDefs(); rdef != NULL; rdef = next ) { 1.3358 + next = _register->iter_RegDefs(); 1.3359 + char policy = reg_save_policy(rdef->_callconv); 1.3360 + const char *comma = (next != NULL) ? "," : " // no trailing comma"; 1.3361 + fprintf(fp_cpp, " '%c'%s\n", policy, comma); 1.3362 + } 1.3363 + fprintf(fp_cpp, "};\n\n"); 1.3364 + 1.3365 + // Construct Native Save-Policy array 1.3366 + fprintf(fp_cpp, "// Map from machine-independent register number to c_reg_save_policy\n"); 1.3367 + fprintf(fp_cpp, "const char c_reg_save_policy[] = {\n"); 1.3368 + _register->reset_RegDefs(); 1.3369 + for( rdef = _register->iter_RegDefs(); rdef != NULL; rdef = next ) { 1.3370 + next = _register->iter_RegDefs(); 1.3371 + char policy = reg_save_policy(rdef->_c_conv); 1.3372 + const char *comma = (next != NULL) ? "," : " // no trailing comma"; 1.3373 + fprintf(fp_cpp, " '%c'%s\n", policy, comma); 1.3374 + } 1.3375 + fprintf(fp_cpp, "};\n\n"); 1.3376 + 1.3377 + // Construct Register Save Type array 1.3378 + fprintf(fp_cpp, "// Map from machine-independent register number to register_save_type\n"); 1.3379 + fprintf(fp_cpp, "const int register_save_type[] = {\n"); 1.3380 + _register->reset_RegDefs(); 1.3381 + for( rdef = _register->iter_RegDefs(); rdef != NULL; rdef = next ) { 1.3382 + next = _register->iter_RegDefs(); 1.3383 + const char *comma = (next != NULL) ? "," : " // no trailing comma"; 1.3384 + fprintf(fp_cpp, " %s%s\n", rdef->_idealtype, comma); 1.3385 + } 1.3386 + fprintf(fp_cpp, "};\n\n"); 1.3387 + 1.3388 + // Construct the table for reduceOp 1.3389 + OutputReduceOp output_reduce_op(fp_hpp, fp_cpp, _globalNames, *this); 1.3390 + build_map(output_reduce_op); 1.3391 + // Construct the table for leftOp 1.3392 + OutputLeftOp output_left_op(fp_hpp, fp_cpp, _globalNames, *this); 1.3393 + build_map(output_left_op); 1.3394 + // Construct the table for rightOp 1.3395 + OutputRightOp output_right_op(fp_hpp, fp_cpp, _globalNames, *this); 1.3396 + build_map(output_right_op); 1.3397 + // Construct the table of rule names 1.3398 + OutputRuleName output_rule_name(fp_hpp, fp_cpp, _globalNames, *this); 1.3399 + build_map(output_rule_name); 1.3400 + // Construct the boolean table for subsumed operands 1.3401 + OutputSwallowed output_swallowed(fp_hpp, fp_cpp, _globalNames, *this); 1.3402 + build_map(output_swallowed); 1.3403 + // // // Preserve in case we decide to use this table instead of another 1.3404 + //// Construct the boolean table for instruction chain rules 1.3405 + //OutputInstChainRule output_inst_chain(fp_hpp, fp_cpp, _globalNames, *this); 1.3406 + //build_map(output_inst_chain); 1.3407 + 1.3408 +} 1.3409 + 1.3410 + 1.3411 +//---------------------------buildMachOperGenerator--------------------------- 1.3412 + 1.3413 +// Recurse through match tree, building path through corresponding state tree, 1.3414 +// Until we reach the constant we are looking for. 1.3415 +static void path_to_constant(FILE *fp, FormDict &globals, 1.3416 + MatchNode *mnode, uint idx) { 1.3417 + if ( ! mnode) return; 1.3418 + 1.3419 + unsigned position = 0; 1.3420 + const char *result = NULL; 1.3421 + const char *name = NULL; 1.3422 + const char *optype = NULL; 1.3423 + 1.3424 + // Base Case: access constant in ideal node linked to current state node 1.3425 + // Each type of constant has its own access function 1.3426 + if ( (mnode->_lChild == NULL) && (mnode->_rChild == NULL) 1.3427 + && mnode->base_operand(position, globals, result, name, optype) ) { 1.3428 + if ( strcmp(optype,"ConI") == 0 ) { 1.3429 + fprintf(fp, "_leaf->get_int()"); 1.3430 + } else if ( (strcmp(optype,"ConP") == 0) ) { 1.3431 + fprintf(fp, "_leaf->bottom_type()->is_ptr()"); 1.3432 + } else if ( (strcmp(optype,"ConF") == 0) ) { 1.3433 + fprintf(fp, "_leaf->getf()"); 1.3434 + } else if ( (strcmp(optype,"ConD") == 0) ) { 1.3435 + fprintf(fp, "_leaf->getd()"); 1.3436 + } else if ( (strcmp(optype,"ConL") == 0) ) { 1.3437 + fprintf(fp, "_leaf->get_long()"); 1.3438 + } else if ( (strcmp(optype,"Con")==0) ) { 1.3439 + // !!!!! - Update if adding a machine-independent constant type 1.3440 + fprintf(fp, "_leaf->get_int()"); 1.3441 + assert( false, "Unsupported constant type, pointer or indefinite"); 1.3442 + } else if ( (strcmp(optype,"Bool") == 0) ) { 1.3443 + fprintf(fp, "_leaf->as_Bool()->_test._test"); 1.3444 + } else { 1.3445 + assert( false, "Unsupported constant type"); 1.3446 + } 1.3447 + return; 1.3448 + } 1.3449 + 1.3450 + // If constant is in left child, build path and recurse 1.3451 + uint lConsts = (mnode->_lChild) ? (mnode->_lChild->num_consts(globals) ) : 0; 1.3452 + uint rConsts = (mnode->_rChild) ? (mnode->_rChild->num_consts(globals) ) : 0; 1.3453 + if ( (mnode->_lChild) && (lConsts > idx) ) { 1.3454 + fprintf(fp, "_kids[0]->"); 1.3455 + path_to_constant(fp, globals, mnode->_lChild, idx); 1.3456 + return; 1.3457 + } 1.3458 + // If constant is in right child, build path and recurse 1.3459 + if ( (mnode->_rChild) && (rConsts > (idx - lConsts) ) ) { 1.3460 + idx = idx - lConsts; 1.3461 + fprintf(fp, "_kids[1]->"); 1.3462 + path_to_constant(fp, globals, mnode->_rChild, idx); 1.3463 + return; 1.3464 + } 1.3465 + assert( false, "ShouldNotReachHere()"); 1.3466 +} 1.3467 + 1.3468 +// Generate code that is executed when generating a specific Machine Operand 1.3469 +static void genMachOperCase(FILE *fp, FormDict &globalNames, ArchDesc &AD, 1.3470 + OperandForm &op) { 1.3471 + const char *opName = op._ident; 1.3472 + const char *opEnumName = AD.machOperEnum(opName); 1.3473 + uint num_consts = op.num_consts(globalNames); 1.3474 + 1.3475 + // Generate the case statement for this opcode 1.3476 + fprintf(fp, " case %s:", opEnumName); 1.3477 + fprintf(fp, "\n return new (C) %sOper(", opName); 1.3478 + // Access parameters for constructor from the stat object 1.3479 + // 1.3480 + // Build access to condition code value 1.3481 + if ( (num_consts > 0) ) { 1.3482 + uint i = 0; 1.3483 + path_to_constant(fp, globalNames, op._matrule, i); 1.3484 + for ( i = 1; i < num_consts; ++i ) { 1.3485 + fprintf(fp, ", "); 1.3486 + path_to_constant(fp, globalNames, op._matrule, i); 1.3487 + } 1.3488 + } 1.3489 + fprintf(fp, " );\n"); 1.3490 +} 1.3491 + 1.3492 + 1.3493 +// Build switch to invoke "new" MachNode or MachOper 1.3494 +void ArchDesc::buildMachOperGenerator(FILE *fp_cpp) { 1.3495 + int idx = 0; 1.3496 + 1.3497 + // Build switch to invoke 'new' for a specific MachOper 1.3498 + fprintf(fp_cpp, "\n"); 1.3499 + fprintf(fp_cpp, "\n"); 1.3500 + fprintf(fp_cpp, 1.3501 + "//------------------------- MachOper Generator ---------------\n"); 1.3502 + fprintf(fp_cpp, 1.3503 + "// A switch statement on the dense-packed user-defined type system\n" 1.3504 + "// that invokes 'new' on the corresponding class constructor.\n"); 1.3505 + fprintf(fp_cpp, "\n"); 1.3506 + fprintf(fp_cpp, "MachOper *State::MachOperGenerator"); 1.3507 + fprintf(fp_cpp, "(int opcode, Compile* C)"); 1.3508 + fprintf(fp_cpp, "{\n"); 1.3509 + fprintf(fp_cpp, "\n"); 1.3510 + fprintf(fp_cpp, " switch(opcode) {\n"); 1.3511 + 1.3512 + // Place all user-defined operands into the mapping 1.3513 + _operands.reset(); 1.3514 + int opIndex = 0; 1.3515 + OperandForm *op; 1.3516 + for( ; (op = (OperandForm*)_operands.iter()) != NULL; ) { 1.3517 + // Ensure this is a machine-world instruction 1.3518 + if ( op->ideal_only() ) continue; 1.3519 + 1.3520 + genMachOperCase(fp_cpp, _globalNames, *this, *op); 1.3521 + }; 1.3522 + 1.3523 + // Do not iterate over operand classes for the operand generator!!! 1.3524 + 1.3525 + // Place all internal operands into the mapping 1.3526 + _internalOpNames.reset(); 1.3527 + const char *iopn; 1.3528 + for( ; (iopn = _internalOpNames.iter()) != NULL; ) { 1.3529 + const char *opEnumName = machOperEnum(iopn); 1.3530 + // Generate the case statement for this opcode 1.3531 + fprintf(fp_cpp, " case %s:", opEnumName); 1.3532 + fprintf(fp_cpp, " return NULL;\n"); 1.3533 + }; 1.3534 + 1.3535 + // Generate the default case for switch(opcode) 1.3536 + fprintf(fp_cpp, " \n"); 1.3537 + fprintf(fp_cpp, " default:\n"); 1.3538 + fprintf(fp_cpp, " fprintf(stderr, \"Default MachOper Generator invoked for: \\n\");\n"); 1.3539 + fprintf(fp_cpp, " fprintf(stderr, \" opcode = %cd\\n\", opcode);\n", '%'); 1.3540 + fprintf(fp_cpp, " break;\n"); 1.3541 + fprintf(fp_cpp, " }\n"); 1.3542 + 1.3543 + // Generate the closing for method Matcher::MachOperGenerator 1.3544 + fprintf(fp_cpp, " return NULL;\n"); 1.3545 + fprintf(fp_cpp, "};\n"); 1.3546 +} 1.3547 + 1.3548 + 1.3549 +//---------------------------buildMachNode------------------------------------- 1.3550 +// Build a new MachNode, for MachNodeGenerator or cisc-spilling 1.3551 +void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *indent) { 1.3552 + const char *opType = NULL; 1.3553 + const char *opClass = inst->_ident; 1.3554 + 1.3555 + // Create the MachNode object 1.3556 + fprintf(fp_cpp, "%s %sNode *node = new (C) %sNode();\n",indent, opClass,opClass); 1.3557 + 1.3558 + if ( (inst->num_post_match_opnds() != 0) ) { 1.3559 + // Instruction that contains operands which are not in match rule. 1.3560 + // 1.3561 + // Check if the first post-match component may be an interesting def 1.3562 + bool dont_care = false; 1.3563 + ComponentList &comp_list = inst->_components; 1.3564 + Component *comp = NULL; 1.3565 + comp_list.reset(); 1.3566 + if ( comp_list.match_iter() != NULL ) dont_care = true; 1.3567 + 1.3568 + // Insert operands that are not in match-rule. 1.3569 + // Only insert a DEF if the do_care flag is set 1.3570 + comp_list.reset(); 1.3571 + while ( comp = comp_list.post_match_iter() ) { 1.3572 + // Check if we don't care about DEFs or KILLs that are not USEs 1.3573 + if ( dont_care && (! comp->isa(Component::USE)) ) { 1.3574 + continue; 1.3575 + } 1.3576 + dont_care = true; 1.3577 + // For each operand not in the match rule, call MachOperGenerator 1.3578 + // with the enum for the opcode that needs to be built 1.3579 + // and the node just built, the parent of the operand. 1.3580 + ComponentList clist = inst->_components; 1.3581 + int index = clist.operand_position(comp->_name, comp->_usedef); 1.3582 + const char *opcode = machOperEnum(comp->_type); 1.3583 + const char *parent = "node"; 1.3584 + fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index); 1.3585 + fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode); 1.3586 + } 1.3587 + } 1.3588 + else if ( inst->is_chain_of_constant(_globalNames, opType) ) { 1.3589 + // An instruction that chains from a constant! 1.3590 + // In this case, we need to subsume the constant into the node 1.3591 + // at operand position, oper_input_base(). 1.3592 + // 1.3593 + // Fill in the constant 1.3594 + fprintf(fp_cpp, "%s node->_opnd_array[%d] = ", indent, 1.3595 + inst->oper_input_base(_globalNames)); 1.3596 + // ##### 1.3597 + // Check for multiple constants and then fill them in. 1.3598 + // Just like MachOperGenerator 1.3599 + const char *opName = inst->_matrule->_rChild->_opType; 1.3600 + fprintf(fp_cpp, "new (C) %sOper(", opName); 1.3601 + // Grab operand form 1.3602 + OperandForm *op = (_globalNames[opName])->is_operand(); 1.3603 + // Look up the number of constants 1.3604 + uint num_consts = op->num_consts(_globalNames); 1.3605 + if ( (num_consts > 0) ) { 1.3606 + uint i = 0; 1.3607 + path_to_constant(fp_cpp, _globalNames, op->_matrule, i); 1.3608 + for ( i = 1; i < num_consts; ++i ) { 1.3609 + fprintf(fp_cpp, ", "); 1.3610 + path_to_constant(fp_cpp, _globalNames, op->_matrule, i); 1.3611 + } 1.3612 + } 1.3613 + fprintf(fp_cpp, " );\n"); 1.3614 + // ##### 1.3615 + } 1.3616 + 1.3617 + // Fill in the bottom_type where requested 1.3618 + if ( inst->captures_bottom_type() ) { 1.3619 + fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent); 1.3620 + } 1.3621 + if( inst->is_ideal_if() ) { 1.3622 + fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent); 1.3623 + fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent); 1.3624 + } 1.3625 + if( inst->is_ideal_fastlock() ) { 1.3626 + fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent); 1.3627 + } 1.3628 + 1.3629 +} 1.3630 + 1.3631 +//---------------------------declare_cisc_version------------------------------ 1.3632 +// Build CISC version of this instruction 1.3633 +void InstructForm::declare_cisc_version(ArchDesc &AD, FILE *fp_hpp) { 1.3634 + if( AD.can_cisc_spill() ) { 1.3635 + InstructForm *inst_cisc = cisc_spill_alternate(); 1.3636 + if (inst_cisc != NULL) { 1.3637 + fprintf(fp_hpp, " virtual int cisc_operand() const { return %d; }\n", cisc_spill_operand()); 1.3638 + fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset, Compile* C);\n"); 1.3639 + fprintf(fp_hpp, " virtual void use_cisc_RegMask();\n"); 1.3640 + fprintf(fp_hpp, " virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n"); 1.3641 + } 1.3642 + } 1.3643 +} 1.3644 + 1.3645 +//---------------------------define_cisc_version------------------------------- 1.3646 +// Build CISC version of this instruction 1.3647 +bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) { 1.3648 + InstructForm *inst_cisc = this->cisc_spill_alternate(); 1.3649 + if( AD.can_cisc_spill() && (inst_cisc != NULL) ) { 1.3650 + const char *name = inst_cisc->_ident; 1.3651 + assert( inst_cisc->num_opnds() == this->num_opnds(), "Must have same number of operands"); 1.3652 + OperandForm *cisc_oper = AD.cisc_spill_operand(); 1.3653 + assert( cisc_oper != NULL, "insanity check"); 1.3654 + const char *cisc_oper_name = cisc_oper->_ident; 1.3655 + assert( cisc_oper_name != NULL, "insanity check"); 1.3656 + // 1.3657 + // Set the correct reg_mask_or_stack for the cisc operand 1.3658 + fprintf(fp_cpp, "\n"); 1.3659 + fprintf(fp_cpp, "void %sNode::use_cisc_RegMask() {\n", this->_ident); 1.3660 + // Lookup the correct reg_mask_or_stack 1.3661 + const char *reg_mask_name = cisc_reg_mask_name(); 1.3662 + fprintf(fp_cpp, " _cisc_RegMask = &STACK_OR_%s;\n", reg_mask_name); 1.3663 + fprintf(fp_cpp, "}\n"); 1.3664 + // 1.3665 + // Construct CISC version of this instruction 1.3666 + fprintf(fp_cpp, "\n"); 1.3667 + fprintf(fp_cpp, "// Build CISC version of this instruction\n"); 1.3668 + fprintf(fp_cpp, "MachNode *%sNode::cisc_version( int offset, Compile* C ) {\n", this->_ident); 1.3669 + // Create the MachNode object 1.3670 + fprintf(fp_cpp, " %sNode *node = new (C) %sNode();\n", name, name); 1.3671 + // Fill in the bottom_type where requested 1.3672 + if ( this->captures_bottom_type() ) { 1.3673 + fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); 1.3674 + } 1.3675 + fprintf(fp_cpp, "\n"); 1.3676 + fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); 1.3677 + fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); 1.3678 + // Construct operand to access [stack_pointer + offset] 1.3679 + fprintf(fp_cpp, " // Construct operand to access [stack_pointer + offset]\n"); 1.3680 + fprintf(fp_cpp, " node->set_opnd_array(cisc_operand(), new (C) %sOper(offset));\n", cisc_oper_name); 1.3681 + fprintf(fp_cpp, "\n"); 1.3682 + 1.3683 + // Return result and exit scope 1.3684 + fprintf(fp_cpp, " return node;\n"); 1.3685 + fprintf(fp_cpp, "}\n"); 1.3686 + fprintf(fp_cpp, "\n"); 1.3687 + return true; 1.3688 + } 1.3689 + return false; 1.3690 +} 1.3691 + 1.3692 +//---------------------------declare_short_branch_methods---------------------- 1.3693 +// Build prototypes for short branch methods 1.3694 +void InstructForm::declare_short_branch_methods(FILE *fp_hpp) { 1.3695 + if (has_short_branch_form()) { 1.3696 + fprintf(fp_hpp, " virtual MachNode *short_branch_version(Compile* C);\n"); 1.3697 + } 1.3698 +} 1.3699 + 1.3700 +//---------------------------define_short_branch_methods----------------------- 1.3701 +// Build definitions for short branch methods 1.3702 +bool InstructForm::define_short_branch_methods(FILE *fp_cpp) { 1.3703 + if (has_short_branch_form()) { 1.3704 + InstructForm *short_branch = short_branch_form(); 1.3705 + const char *name = short_branch->_ident; 1.3706 + 1.3707 + // Construct short_branch_version() method. 1.3708 + fprintf(fp_cpp, "// Build short branch version of this instruction\n"); 1.3709 + fprintf(fp_cpp, "MachNode *%sNode::short_branch_version(Compile* C) {\n", this->_ident); 1.3710 + // Create the MachNode object 1.3711 + fprintf(fp_cpp, " %sNode *node = new (C) %sNode();\n", name, name); 1.3712 + if( is_ideal_if() ) { 1.3713 + fprintf(fp_cpp, " node->_prob = _prob;\n"); 1.3714 + fprintf(fp_cpp, " node->_fcnt = _fcnt;\n"); 1.3715 + } 1.3716 + // Fill in the bottom_type where requested 1.3717 + if ( this->captures_bottom_type() ) { 1.3718 + fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); 1.3719 + } 1.3720 + 1.3721 + fprintf(fp_cpp, "\n"); 1.3722 + // Short branch version must use same node index for access 1.3723 + // through allocator's tables 1.3724 + fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); 1.3725 + fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); 1.3726 + 1.3727 + // Return result and exit scope 1.3728 + fprintf(fp_cpp, " return node;\n"); 1.3729 + fprintf(fp_cpp, "}\n"); 1.3730 + fprintf(fp_cpp,"\n"); 1.3731 + return true; 1.3732 + } 1.3733 + return false; 1.3734 +} 1.3735 + 1.3736 + 1.3737 +//---------------------------buildMachNodeGenerator---------------------------- 1.3738 +// Build switch to invoke appropriate "new" MachNode for an opcode 1.3739 +void ArchDesc::buildMachNodeGenerator(FILE *fp_cpp) { 1.3740 + 1.3741 + // Build switch to invoke 'new' for a specific MachNode 1.3742 + fprintf(fp_cpp, "\n"); 1.3743 + fprintf(fp_cpp, "\n"); 1.3744 + fprintf(fp_cpp, 1.3745 + "//------------------------- MachNode Generator ---------------\n"); 1.3746 + fprintf(fp_cpp, 1.3747 + "// A switch statement on the dense-packed user-defined type system\n" 1.3748 + "// that invokes 'new' on the corresponding class constructor.\n"); 1.3749 + fprintf(fp_cpp, "\n"); 1.3750 + fprintf(fp_cpp, "MachNode *State::MachNodeGenerator"); 1.3751 + fprintf(fp_cpp, "(int opcode, Compile* C)"); 1.3752 + fprintf(fp_cpp, "{\n"); 1.3753 + fprintf(fp_cpp, " switch(opcode) {\n"); 1.3754 + 1.3755 + // Provide constructor for all user-defined instructions 1.3756 + _instructions.reset(); 1.3757 + int opIndex = operandFormCount(); 1.3758 + InstructForm *inst; 1.3759 + for( ; (inst = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3760 + // Ensure that matrule is defined. 1.3761 + if ( inst->_matrule == NULL ) continue; 1.3762 + 1.3763 + int opcode = opIndex++; 1.3764 + const char *opClass = inst->_ident; 1.3765 + char *opType = NULL; 1.3766 + 1.3767 + // Generate the case statement for this instruction 1.3768 + fprintf(fp_cpp, " case %s_rule:", opClass); 1.3769 + 1.3770 + // Start local scope 1.3771 + fprintf(fp_cpp, " {\n"); 1.3772 + // Generate code to construct the new MachNode 1.3773 + buildMachNode(fp_cpp, inst, " "); 1.3774 + // Return result and exit scope 1.3775 + fprintf(fp_cpp, " return node;\n"); 1.3776 + fprintf(fp_cpp, " }\n"); 1.3777 + } 1.3778 + 1.3779 + // Generate the default case for switch(opcode) 1.3780 + fprintf(fp_cpp, " \n"); 1.3781 + fprintf(fp_cpp, " default:\n"); 1.3782 + fprintf(fp_cpp, " fprintf(stderr, \"Default MachNode Generator invoked for: \\n\");\n"); 1.3783 + fprintf(fp_cpp, " fprintf(stderr, \" opcode = %cd\\n\", opcode);\n", '%'); 1.3784 + fprintf(fp_cpp, " break;\n"); 1.3785 + fprintf(fp_cpp, " };\n"); 1.3786 + 1.3787 + // Generate the closing for method Matcher::MachNodeGenerator 1.3788 + fprintf(fp_cpp, " return NULL;\n"); 1.3789 + fprintf(fp_cpp, "}\n"); 1.3790 +} 1.3791 + 1.3792 + 1.3793 +//---------------------------buildInstructMatchCheck-------------------------- 1.3794 +// Output the method to Matcher which checks whether or not a specific 1.3795 +// instruction has a matching rule for the host architecture. 1.3796 +void ArchDesc::buildInstructMatchCheck(FILE *fp_cpp) const { 1.3797 + fprintf(fp_cpp, "\n\n"); 1.3798 + fprintf(fp_cpp, "const bool Matcher::has_match_rule(int opcode) {\n"); 1.3799 + fprintf(fp_cpp, " assert(_last_machine_leaf < opcode && opcode < _last_opcode, \"opcode in range\");\n"); 1.3800 + fprintf(fp_cpp, " return _hasMatchRule[opcode];\n"); 1.3801 + fprintf(fp_cpp, "}\n\n"); 1.3802 + 1.3803 + fprintf(fp_cpp, "const bool Matcher::_hasMatchRule[_last_opcode] = {\n"); 1.3804 + int i; 1.3805 + for (i = 0; i < _last_opcode - 1; i++) { 1.3806 + fprintf(fp_cpp, " %-5s, // %s\n", 1.3807 + _has_match_rule[i] ? "true" : "false", 1.3808 + NodeClassNames[i]); 1.3809 + } 1.3810 + fprintf(fp_cpp, " %-5s // %s\n", 1.3811 + _has_match_rule[i] ? "true" : "false", 1.3812 + NodeClassNames[i]); 1.3813 + fprintf(fp_cpp, "};\n"); 1.3814 +} 1.3815 + 1.3816 +//---------------------------buildFrameMethods--------------------------------- 1.3817 +// Output the methods to Matcher which specify frame behavior 1.3818 +void ArchDesc::buildFrameMethods(FILE *fp_cpp) { 1.3819 + fprintf(fp_cpp,"\n\n"); 1.3820 + // Stack Direction 1.3821 + fprintf(fp_cpp,"bool Matcher::stack_direction() const { return %s; }\n\n", 1.3822 + _frame->_direction ? "true" : "false"); 1.3823 + // Sync Stack Slots 1.3824 + fprintf(fp_cpp,"int Compile::sync_stack_slots() const { return %s; }\n\n", 1.3825 + _frame->_sync_stack_slots); 1.3826 + // Java Stack Alignment 1.3827 + fprintf(fp_cpp,"uint Matcher::stack_alignment_in_bytes() { return %s; }\n\n", 1.3828 + _frame->_alignment); 1.3829 + // Java Return Address Location 1.3830 + fprintf(fp_cpp,"OptoReg::Name Matcher::return_addr() const {"); 1.3831 + if (_frame->_return_addr_loc) { 1.3832 + fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 1.3833 + _frame->_return_addr); 1.3834 + } 1.3835 + else { 1.3836 + fprintf(fp_cpp," return OptoReg::stack2reg(%s); }\n\n", 1.3837 + _frame->_return_addr); 1.3838 + } 1.3839 + // Java Stack Slot Preservation 1.3840 + fprintf(fp_cpp,"uint Compile::in_preserve_stack_slots() "); 1.3841 + fprintf(fp_cpp,"{ return %s; }\n\n", _frame->_in_preserve_slots); 1.3842 + // Top Of Stack Slot Preservation, for both Java and C 1.3843 + fprintf(fp_cpp,"uint Compile::out_preserve_stack_slots() "); 1.3844 + fprintf(fp_cpp,"{ return SharedRuntime::out_preserve_stack_slots(); }\n\n"); 1.3845 + // varargs C out slots killed 1.3846 + fprintf(fp_cpp,"uint Compile::varargs_C_out_slots_killed() const "); 1.3847 + fprintf(fp_cpp,"{ return %s; }\n\n", _frame->_varargs_C_out_slots_killed); 1.3848 + // Java Argument Position 1.3849 + fprintf(fp_cpp,"void Matcher::calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length, bool is_outgoing) {\n"); 1.3850 + fprintf(fp_cpp,"%s\n", _frame->_calling_convention); 1.3851 + fprintf(fp_cpp,"}\n\n"); 1.3852 + // Native Argument Position 1.3853 + fprintf(fp_cpp,"void Matcher::c_calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length) {\n"); 1.3854 + fprintf(fp_cpp,"%s\n", _frame->_c_calling_convention); 1.3855 + fprintf(fp_cpp,"}\n\n"); 1.3856 + // Java Return Value Location 1.3857 + fprintf(fp_cpp,"OptoRegPair Matcher::return_value(int ideal_reg, bool is_outgoing) {\n"); 1.3858 + fprintf(fp_cpp,"%s\n", _frame->_return_value); 1.3859 + fprintf(fp_cpp,"}\n\n"); 1.3860 + // Native Return Value Location 1.3861 + fprintf(fp_cpp,"OptoRegPair Matcher::c_return_value(int ideal_reg, bool is_outgoing) {\n"); 1.3862 + fprintf(fp_cpp,"%s\n", _frame->_c_return_value); 1.3863 + fprintf(fp_cpp,"}\n\n"); 1.3864 + 1.3865 + // Inline Cache Register, mask definition, and encoding 1.3866 + fprintf(fp_cpp,"OptoReg::Name Matcher::inline_cache_reg() {"); 1.3867 + fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 1.3868 + _frame->_inline_cache_reg); 1.3869 + fprintf(fp_cpp,"const RegMask &Matcher::inline_cache_reg_mask() {"); 1.3870 + fprintf(fp_cpp," return INLINE_CACHE_REG_mask; }\n\n"); 1.3871 + fprintf(fp_cpp,"int Matcher::inline_cache_reg_encode() {"); 1.3872 + fprintf(fp_cpp," return _regEncode[inline_cache_reg()]; }\n\n"); 1.3873 + 1.3874 + // Interpreter's Method Oop Register, mask definition, and encoding 1.3875 + fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_method_oop_reg() {"); 1.3876 + fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 1.3877 + _frame->_interpreter_method_oop_reg); 1.3878 + fprintf(fp_cpp,"const RegMask &Matcher::interpreter_method_oop_reg_mask() {"); 1.3879 + fprintf(fp_cpp," return INTERPRETER_METHOD_OOP_REG_mask; }\n\n"); 1.3880 + fprintf(fp_cpp,"int Matcher::interpreter_method_oop_reg_encode() {"); 1.3881 + fprintf(fp_cpp," return _regEncode[interpreter_method_oop_reg()]; }\n\n"); 1.3882 + 1.3883 + // Interpreter's Frame Pointer Register, mask definition, and encoding 1.3884 + fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_frame_pointer_reg() {"); 1.3885 + if (_frame->_interpreter_frame_pointer_reg == NULL) 1.3886 + fprintf(fp_cpp," return OptoReg::Bad; }\n\n"); 1.3887 + else 1.3888 + fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 1.3889 + _frame->_interpreter_frame_pointer_reg); 1.3890 + fprintf(fp_cpp,"const RegMask &Matcher::interpreter_frame_pointer_reg_mask() {"); 1.3891 + if (_frame->_interpreter_frame_pointer_reg == NULL) 1.3892 + fprintf(fp_cpp," static RegMask dummy; return dummy; }\n\n"); 1.3893 + else 1.3894 + fprintf(fp_cpp," return INTERPRETER_FRAME_POINTER_REG_mask; }\n\n"); 1.3895 + 1.3896 + // Frame Pointer definition 1.3897 + /* CNC - I can not contemplate having a different frame pointer between 1.3898 + Java and native code; makes my head hurt to think about it. 1.3899 + fprintf(fp_cpp,"OptoReg::Name Matcher::frame_pointer() const {"); 1.3900 + fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 1.3901 + _frame->_frame_pointer); 1.3902 + */ 1.3903 + // (Native) Frame Pointer definition 1.3904 + fprintf(fp_cpp,"OptoReg::Name Matcher::c_frame_pointer() const {"); 1.3905 + fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 1.3906 + _frame->_frame_pointer); 1.3907 + 1.3908 + // Number of callee-save + always-save registers for calling convention 1.3909 + fprintf(fp_cpp, "// Number of callee-save + always-save registers\n"); 1.3910 + fprintf(fp_cpp, "int Matcher::number_of_saved_registers() {\n"); 1.3911 + RegDef *rdef; 1.3912 + int nof_saved_registers = 0; 1.3913 + _register->reset_RegDefs(); 1.3914 + while( (rdef = _register->iter_RegDefs()) != NULL ) { 1.3915 + if( !strcmp(rdef->_callconv, "SOE") || !strcmp(rdef->_callconv, "AS") ) 1.3916 + ++nof_saved_registers; 1.3917 + } 1.3918 + fprintf(fp_cpp, " return %d;\n", nof_saved_registers); 1.3919 + fprintf(fp_cpp, "};\n\n"); 1.3920 +} 1.3921 + 1.3922 + 1.3923 + 1.3924 + 1.3925 +static int PrintAdlcCisc = 0; 1.3926 +//---------------------------identify_cisc_spilling---------------------------- 1.3927 +// Get info for the CISC_oracle and MachNode::cisc_version() 1.3928 +void ArchDesc::identify_cisc_spill_instructions() { 1.3929 + 1.3930 + // Find the user-defined operand for cisc-spilling 1.3931 + if( _frame->_cisc_spilling_operand_name != NULL ) { 1.3932 + const Form *form = _globalNames[_frame->_cisc_spilling_operand_name]; 1.3933 + OperandForm *oper = form ? form->is_operand() : NULL; 1.3934 + // Verify the user's suggestion 1.3935 + if( oper != NULL ) { 1.3936 + // Ensure that match field is defined. 1.3937 + if ( oper->_matrule != NULL ) { 1.3938 + MatchRule &mrule = *oper->_matrule; 1.3939 + if( strcmp(mrule._opType,"AddP") == 0 ) { 1.3940 + MatchNode *left = mrule._lChild; 1.3941 + MatchNode *right= mrule._rChild; 1.3942 + if( left != NULL && right != NULL ) { 1.3943 + const Form *left_op = _globalNames[left->_opType]->is_operand(); 1.3944 + const Form *right_op = _globalNames[right->_opType]->is_operand(); 1.3945 + if( (left_op != NULL && right_op != NULL) 1.3946 + && (left_op->interface_type(_globalNames) == Form::register_interface) 1.3947 + && (right_op->interface_type(_globalNames) == Form::constant_interface) ) { 1.3948 + // Successfully verified operand 1.3949 + set_cisc_spill_operand( oper ); 1.3950 + if( _cisc_spill_debug ) { 1.3951 + fprintf(stderr, "\n\nVerified CISC-spill operand %s\n\n", oper->_ident); 1.3952 + } 1.3953 + } 1.3954 + } 1.3955 + } 1.3956 + } 1.3957 + } 1.3958 + } 1.3959 + 1.3960 + if( cisc_spill_operand() != NULL ) { 1.3961 + // N^2 comparison of instructions looking for a cisc-spilling version 1.3962 + _instructions.reset(); 1.3963 + InstructForm *instr; 1.3964 + for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { 1.3965 + // Ensure that match field is defined. 1.3966 + if ( instr->_matrule == NULL ) continue; 1.3967 + 1.3968 + MatchRule &mrule = *instr->_matrule; 1.3969 + Predicate *pred = instr->build_predicate(); 1.3970 + 1.3971 + // Grab the machine type of the operand 1.3972 + const char *rootOp = instr->_ident; 1.3973 + mrule._machType = rootOp; 1.3974 + 1.3975 + // Find result type for match 1.3976 + const char *result = instr->reduce_result(); 1.3977 + 1.3978 + if( PrintAdlcCisc ) fprintf(stderr, " new instruction %s \n", instr->_ident ? instr->_ident : " "); 1.3979 + bool found_cisc_alternate = false; 1.3980 + _instructions.reset2(); 1.3981 + InstructForm *instr2; 1.3982 + for( ; !found_cisc_alternate && (instr2 = (InstructForm*)_instructions.iter2()) != NULL; ) { 1.3983 + // Ensure that match field is defined. 1.3984 + if( PrintAdlcCisc ) fprintf(stderr, " instr2 == %s \n", instr2->_ident ? instr2->_ident : " "); 1.3985 + if ( instr2->_matrule != NULL 1.3986 + && (instr != instr2 ) // Skip self 1.3987 + && (instr2->reduce_result() != NULL) // want same result 1.3988 + && (strcmp(result, instr2->reduce_result()) == 0)) { 1.3989 + MatchRule &mrule2 = *instr2->_matrule; 1.3990 + Predicate *pred2 = instr2->build_predicate(); 1.3991 + found_cisc_alternate = instr->cisc_spills_to(*this, instr2); 1.3992 + } 1.3993 + } 1.3994 + } 1.3995 + } 1.3996 +} 1.3997 + 1.3998 +//---------------------------build_cisc_spilling------------------------------- 1.3999 +// Get info for the CISC_oracle and MachNode::cisc_version() 1.4000 +void ArchDesc::build_cisc_spill_instructions(FILE *fp_hpp, FILE *fp_cpp) { 1.4001 + // Output the table for cisc spilling 1.4002 + fprintf(fp_cpp, "// The following instructions can cisc-spill\n"); 1.4003 + _instructions.reset(); 1.4004 + InstructForm *inst = NULL; 1.4005 + for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) { 1.4006 + // Ensure this is a machine-world instruction 1.4007 + if ( inst->ideal_only() ) continue; 1.4008 + const char *inst_name = inst->_ident; 1.4009 + int operand = inst->cisc_spill_operand(); 1.4010 + if( operand != AdlcVMDeps::Not_cisc_spillable ) { 1.4011 + InstructForm *inst2 = inst->cisc_spill_alternate(); 1.4012 + fprintf(fp_cpp, "// %s can cisc-spill operand %d to %s\n", inst->_ident, operand, inst2->_ident); 1.4013 + } 1.4014 + } 1.4015 + fprintf(fp_cpp, "\n\n"); 1.4016 +} 1.4017 + 1.4018 +//---------------------------identify_short_branches---------------------------- 1.4019 +// Get info for our short branch replacement oracle. 1.4020 +void ArchDesc::identify_short_branches() { 1.4021 + // Walk over all instructions, checking to see if they match a short 1.4022 + // branching alternate. 1.4023 + _instructions.reset(); 1.4024 + InstructForm *instr; 1.4025 + while( (instr = (InstructForm*)_instructions.iter()) != NULL ) { 1.4026 + // The instruction must have a match rule. 1.4027 + if (instr->_matrule != NULL && 1.4028 + instr->is_short_branch()) { 1.4029 + 1.4030 + _instructions.reset2(); 1.4031 + InstructForm *instr2; 1.4032 + while( (instr2 = (InstructForm*)_instructions.iter2()) != NULL ) { 1.4033 + instr2->check_branch_variant(*this, instr); 1.4034 + } 1.4035 + } 1.4036 + } 1.4037 +} 1.4038 + 1.4039 + 1.4040 +//---------------------------identify_unique_operands--------------------------- 1.4041 +// Identify unique operands. 1.4042 +void ArchDesc::identify_unique_operands() { 1.4043 + // Walk over all instructions. 1.4044 + _instructions.reset(); 1.4045 + InstructForm *instr; 1.4046 + while( (instr = (InstructForm*)_instructions.iter()) != NULL ) { 1.4047 + // Ensure this is a machine-world instruction 1.4048 + if (!instr->ideal_only()) { 1.4049 + instr->set_unique_opnds(); 1.4050 + } 1.4051 + } 1.4052 +}