1 /*
2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
199 // Add the new match rule to the list
200 rule->_next = match_parse(instr->_localNames);
201 if (rule->_next) {
202 rule = rule->_next;
203 if( instr->is_ideal_control() ) {
204 parse_err(SYNERR, "unique match rule expected for %s\n", rule->_name);
205 return;
206 }
207 assert(match_rules_cnt < 100," too many match rule clones");
208 char* buf = (char*) malloc(strlen(instr->_ident) + 4);
209 sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++);
210 rule->_result = buf;
211 // Check for commutative operations with tree operands.
212 matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
213 }
214 }
215 }
216 else if (!strcmp(ident, "encode")) {
217 parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
218 }
219 else if (!strcmp(ident, "ins_encode"))
220 instr->_insencode = ins_encode_parse(*instr);
221 else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
222 else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
223 else if (!strcmp(ident, "effect")) effect_parse(instr);
224 else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
225 else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
226 else if (!strcmp(ident, "constraint")) {
227 parse_err(SYNERR, "Instructions do not specify a constraint\n");
228 }
229 else if (!strcmp(ident, "construct")) {
230 parse_err(SYNERR, "Instructions do not specify a construct\n");
231 }
232 else if (!strcmp(ident, "format")) instr->_format = format_parse();
233 else if (!strcmp(ident, "interface")) {
234 parse_err(SYNERR, "Instructions do not specify an interface\n");
235 }
236 else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
237 else { // Done with staticly defined parts of instruction definition
238 // Check identifier to see if it is the name of an attribute
239 const Form *form = _globalNames[ident];
240 AttributeForm *attr = form ? form->is_attribute() : NULL;
918 // Check if there is a string to pass through to output
919 char *start = _ptr; // Record start of the next string
920 while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
921 // If at the start of a comment, skip past it
922 if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
923 skipws_no_preproc();
924 } else {
925 // ELSE advance to the next character, or start of the next line
926 next_char_or_line();
927 }
928 }
929 // If a string was found, terminate it and record in EncClass
930 if ( start != _ptr ) {
931 *_ptr = '\0'; // Terminate the string
932 encoding->add_code(start);
933 }
934
935 // (2)
936 // If we are at a replacement variable,
937 // copy it and record in EncClass
938 if ( _curchar == '$' ) {
939 // Found replacement Variable
940 char *rep_var = get_rep_var_ident_dup();
941 // Add flag to _strings list indicating we should check _rep_vars
942 encoding->add_rep_var(rep_var);
943 }
944 } // end while part of format description
945 next_char(); // Skip '%'
946 next_char(); // Skip '}'
947
948 skipws();
949
950 if (_AD._adlocation_debug) {
951 encoding->add_code(end_line_marker());
952 }
953
954 // Debug Stuff
955 if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
956 }
957
958 //------------------------------frame_parse-----------------------------------
959 void ADLParser::frame_parse(void) {
960 FrameForm *frame; // Information about stack-frame layout
2757 if ( (rule = get_paren_expr("pred expression", true)) == NULL ) {
2758 parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
2759 return NULL;
2760 }
2761 // Debug Stuff
2762 if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule);
2763 if (_curchar != ';') {
2764 parse_err(SYNERR, "missing ';' in predicate definition\n");
2765 return NULL;
2766 }
2767 next_char(); // Point after the terminator
2768
2769 predicate = new Predicate(rule); // Build new predicate object
2770 skipws();
2771 return predicate;
2772 }
2773
2774
2775 //------------------------------ins_encode_parse_block-------------------------
2776 // Parse the block form of ins_encode. See ins_encode_parse for more details
2777 InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
2778 // Create a new encoding name based on the name of the instruction
2779 // definition, which should be unique.
2780 const char * prefix = "__enc_";
2781 char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1);
2782 sprintf(ec_name, "%s%s", prefix, inst._ident);
2783
2784 assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
2785 EncClass *encoding = _AD._encode->add_EncClass(ec_name);
2786 encoding->_linenum = linenum();
2787
2788 // synthesize the arguments list for the enc_class from the
2789 // arguments to the instruct definition.
2790 const char * param = NULL;
2791 inst._parameters.reset();
2792 while ((param = inst._parameters.iter()) != NULL) {
2793 OperandForm *opForm = (OperandForm*)inst._localNames[param];
2794 encoding->add_parameter(opForm->_ident, param);
2795 }
2796
2797 // Add the prologue to create the MacroAssembler
2798 encoding->add_code("\n"
2799 " // Define a MacroAssembler instance for use by the encoding. The\n"
2800 " // name is chosen to match the __ idiom used for assembly in other\n"
2801 " // parts of hotspot and assumes the existence of the standard\n"
2802 " // #define __ _masm.\n"
2803 " MacroAssembler _masm(&cbuf);\n");
2804
2805 // Parse the following %{ }% block
2806 enc_class_parse_block(encoding, ec_name);
2807
2808 // Build an encoding rule which invokes the encoding rule we just
2809 // created, passing all arguments that we received.
2810 InsEncode *encrule = new InsEncode(); // Encode class for instruction
2811 NameAndList *params = encrule->add_encode(ec_name);
2812 inst._parameters.reset();
2813 while ((param = inst._parameters.iter()) != NULL) {
2814 params->add_entry(param);
2815 }
2816
2817 return encrule;
2818 }
2819
2820
2821 //------------------------------ins_encode_parse-------------------------------
2822 // Encode rules have the form
2823 // ins_encode( encode_class_name(parameter_list), ... );
2824 //
2825 // The "encode_class_name" must be defined in the encode section
2826 // The parameter list contains $names that are locals.
2827 //
2828 // Alternatively it can be written like this:
2829 //
2830 // ins_encode %{
2831 // ... // body
2832 // %}
2833 //
2834 // which synthesizes a new encoding class taking the same arguments as
2835 // the InstructForm, and automatically prefixes the definition with:
2836 //
2837 // MacroAssembler masm(&cbuf);\n");
2838 //
2839 // making it more compact to take advantage of the MacroAssembler and
2840 // placing the assembly closer to it's use by instructions.
2841 InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
2842
2843 // Parse encode class name
2844 skipws(); // Skip whitespace
2845 if (_curchar != '(') {
2846 // Check for ins_encode %{ form
2847 if ((_curchar == '%') && (*(_ptr+1) == '{')) {
2848 next_char(); // Skip '%'
2849 next_char(); // Skip '{'
2850
2851 // Parse the block form of ins_encode
2852 return ins_encode_parse_block(inst);
2853 }
2854
2855 parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
2856 return NULL;
2857 }
2858 next_char(); // move past '('
2859 skipws();
2860
2861 InsEncode *encrule = new InsEncode(); // Encode class for instruction
2862 encrule->_linenum = linenum();
2863 char *ec_name = NULL; // String representation of encode rule
2864 // identifier is optional.
2865 while (_curchar != ')') {
2866 ec_name = get_ident();
2867 if (ec_name == NULL) {
2868 parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
2869 return NULL;
2870 }
2871 // Check that encoding is defined in the encode section
2872 EncClass *encode_class = _AD._encode->encClass(ec_name);
2873 if (encode_class == NULL) {
2874 // Like to defer checking these till later...
2875 // parse_err(WARN, "Using an undefined encode class '%s' in 'ins_encode'.\n", ec_name);
2876 }
2877
2878 // Get list for encode method's parameters
2879 NameAndList *params = encrule->add_encode(ec_name);
2880
2881 // Parse the parameters to this encode method.
2882 skipws();
2883 if ( _curchar == '(' ) {
2884 next_char(); // move past '(' for parameters
2885
2886 // Parse the encode method's parameters
2887 while (_curchar != ')') {
2888 char *param = get_ident_or_literal_constant("encoding operand");
2889 if ( param != NULL ) {
2890 // Found a parameter:
2891 // Check it is a local name, add it to the list, then check for more
2892 // New: allow hex constants as parameters to an encode method.
2893 // New: allow parenthesized expressions as parameters.
2894 // New: allow "primary", "secondary", "tertiary" as parameters.
2895 // New: allow user-defined register name as parameter
2896 if ( (inst._localNames[param] == NULL) &&
2897 !ADLParser::is_literal_constant(param) &&
2898 (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
2899 ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
2900 parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
2901 return NULL;
2902 }
2903 params->add_entry(param);
2904
2905 skipws();
2906 if (_curchar == ',' ) {
2907 // More parameters to come
2908 next_char(); // move past ',' between parameters
2909 skipws(); // Skip to next parameter
2910 }
2911 else if (_curchar == ')') {
2912 // Done with parameter list
2913 }
2914 else {
2915 // Only ',' or ')' are valid after a parameter name
2916 parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
2917 ec_name);
2918 return NULL;
2919 }
2920
2921 } else {
2922 skipws();
2923 // Did not find a parameter
2924 if (_curchar == ',') {
2925 parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
2926 return NULL;
2927 }
2928 if (_curchar != ')') {
2929 parse_err(SYNERR, "Expected ')' after encode parameters.\n");
2930 return NULL;
2931 }
2932 }
2933 } // WHILE loop collecting parameters
2934 next_char(); // move past ')' at end of parameters
2935 } // done with parameter list for encoding
2936
2937 // Check for ',' or ')' after encoding
2938 skipws(); // move to character after parameters
2939 if ( _curchar == ',' ) {
2940 // Found a ','
2941 next_char(); // move past ',' between encode methods
2942 skipws();
2943 }
2944 else if ( _curchar != ')' ) {
2945 // If not a ',' then only a ')' is allowed
2946 parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
2947 return NULL;
2948 }
2949
2950 // Check for ',' separating parameters
2951 // if ( _curchar != ',' && _curchar != ')' ) {
2952 // parse_err(SYNERR, "expected ',' or ')' after encode method inside ins_encode.\n");
2953 // return NULL;
2954 // }
2955
2956 } // done parsing ins_encode methods and their parameters
2957 if (_curchar != ')') {
2958 parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
2959 return NULL;
2960 }
2961 next_char(); // move past ')'
2962 skipws(); // Skip leading whitespace
2963
2964 if ( _curchar != ';' ) {
2965 parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
2966 return NULL;
2967 }
2968 next_char(); // move past ';'
2969 skipws(); // be friendly to oper_parse()
2970
2971 // Debug Stuff
2972 if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
2973
2974 return encrule;
2975 }
2976
2977
2978 //------------------------------size_parse-----------------------------------
2979 char* ADLParser::size_parse(InstructForm *instr) {
2980 char* sizeOfInstr = NULL;
2981
2982 // Get value of the instruction's size
2983 skipws();
2984
2985 // Parse size
2986 sizeOfInstr = get_paren_expr("size expression");
2987 if (sizeOfInstr == NULL) {
2988 parse_err(SYNERR, "size of opcode expected at %c\n", _curchar);
2989 return NULL;
2990 }
2991
2992 skipws();
2993
2994 // Check for terminator
|
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
199 // Add the new match rule to the list
200 rule->_next = match_parse(instr->_localNames);
201 if (rule->_next) {
202 rule = rule->_next;
203 if( instr->is_ideal_control() ) {
204 parse_err(SYNERR, "unique match rule expected for %s\n", rule->_name);
205 return;
206 }
207 assert(match_rules_cnt < 100," too many match rule clones");
208 char* buf = (char*) malloc(strlen(instr->_ident) + 4);
209 sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++);
210 rule->_result = buf;
211 // Check for commutative operations with tree operands.
212 matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
213 }
214 }
215 }
216 else if (!strcmp(ident, "encode")) {
217 parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
218 }
219 else if (!strcmp(ident, "ins_encode")) ins_encode_parse(*instr);
220 else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
221 else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
222 else if (!strcmp(ident, "effect")) effect_parse(instr);
223 else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
224 else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
225 else if (!strcmp(ident, "constraint")) {
226 parse_err(SYNERR, "Instructions do not specify a constraint\n");
227 }
228 else if (!strcmp(ident, "construct")) {
229 parse_err(SYNERR, "Instructions do not specify a construct\n");
230 }
231 else if (!strcmp(ident, "format")) instr->_format = format_parse();
232 else if (!strcmp(ident, "interface")) {
233 parse_err(SYNERR, "Instructions do not specify an interface\n");
234 }
235 else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
236 else { // Done with staticly defined parts of instruction definition
237 // Check identifier to see if it is the name of an attribute
238 const Form *form = _globalNames[ident];
239 AttributeForm *attr = form ? form->is_attribute() : NULL;
917 // Check if there is a string to pass through to output
918 char *start = _ptr; // Record start of the next string
919 while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
920 // If at the start of a comment, skip past it
921 if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
922 skipws_no_preproc();
923 } else {
924 // ELSE advance to the next character, or start of the next line
925 next_char_or_line();
926 }
927 }
928 // If a string was found, terminate it and record in EncClass
929 if ( start != _ptr ) {
930 *_ptr = '\0'; // Terminate the string
931 encoding->add_code(start);
932 }
933
934 // (2)
935 // If we are at a replacement variable,
936 // copy it and record in EncClass
937 if (_curchar == '$') {
938 // Found replacement Variable
939 char* rep_var = get_rep_var_ident_dup();
940 // Add flag to _strings list indicating we should check _rep_vars
941 encoding->add_rep_var(rep_var);
942 }
943 } // end while part of format description
944 next_char(); // Skip '%'
945 next_char(); // Skip '}'
946
947 skipws();
948
949 if (_AD._adlocation_debug) {
950 encoding->add_code(end_line_marker());
951 }
952
953 // Debug Stuff
954 if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
955 }
956
957 //------------------------------frame_parse-----------------------------------
958 void ADLParser::frame_parse(void) {
959 FrameForm *frame; // Information about stack-frame layout
2756 if ( (rule = get_paren_expr("pred expression", true)) == NULL ) {
2757 parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
2758 return NULL;
2759 }
2760 // Debug Stuff
2761 if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule);
2762 if (_curchar != ';') {
2763 parse_err(SYNERR, "missing ';' in predicate definition\n");
2764 return NULL;
2765 }
2766 next_char(); // Point after the terminator
2767
2768 predicate = new Predicate(rule); // Build new predicate object
2769 skipws();
2770 return predicate;
2771 }
2772
2773
2774 //------------------------------ins_encode_parse_block-------------------------
2775 // Parse the block form of ins_encode. See ins_encode_parse for more details
2776 void ADLParser::ins_encode_parse_block(InstructForm& inst) {
2777 // Create a new encoding name based on the name of the instruction
2778 // definition, which should be unique.
2779 const char* prefix = "__ins_encode_";
2780 char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
2781 sprintf(ec_name, "%s%s", prefix, inst._ident);
2782
2783 assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
2784 EncClass* encoding = _AD._encode->add_EncClass(ec_name);
2785 encoding->_linenum = linenum();
2786
2787 // synthesize the arguments list for the enc_class from the
2788 // arguments to the instruct definition.
2789 const char* param = NULL;
2790 inst._parameters.reset();
2791 while ((param = inst._parameters.iter()) != NULL) {
2792 OperandForm* opForm = (OperandForm*) inst._localNames[param];
2793 encoding->add_parameter(opForm->_ident, param);
2794 }
2795
2796 // Define a MacroAssembler instance for use by the encoding. The
2797 // name is chosen to match the __ idiom used for assembly in other
2798 // parts of hotspot and assumes the existence of the standard
2799 // #define __ _masm.
2800 encoding->add_code(" MacroAssembler _masm(&cbuf);\n");
2801
2802 // Parse the following %{ }% block
2803 ins_encode_parse_block_impl(inst, encoding, ec_name);
2804
2805 // Build an encoding rule which invokes the encoding rule we just
2806 // created, passing all arguments that we received.
2807 InsEncode* encrule = new InsEncode(); // Encode class for instruction
2808 NameAndList* params = encrule->add_encode(ec_name);
2809 inst._parameters.reset();
2810 while ((param = inst._parameters.iter()) != NULL) {
2811 params->add_entry(param);
2812 }
2813
2814 // Set encode class of this instruction.
2815 inst._insencode = encrule;
2816 }
2817
2818
2819 void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) {
2820 skipws_no_preproc(); // Skip leading whitespace
2821 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
2822 if (_AD._adlocation_debug) {
2823 encoding->add_code(get_line_string());
2824 }
2825
2826 // Collect the parts of the encode description
2827 // (1) strings that are passed through to output
2828 // (2) replacement/substitution variable, preceeded by a '$'
2829 while ((_curchar != '%') && (*(_ptr+1) != '}')) {
2830
2831 // (1)
2832 // Check if there is a string to pass through to output
2833 char *start = _ptr; // Record start of the next string
2834 while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
2835 // If at the start of a comment, skip past it
2836 if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
2837 skipws_no_preproc();
2838 } else {
2839 // ELSE advance to the next character, or start of the next line
2840 next_char_or_line();
2841 }
2842 }
2843 // If a string was found, terminate it and record in EncClass
2844 if (start != _ptr) {
2845 *_ptr = '\0'; // Terminate the string
2846 encoding->add_code(start);
2847 }
2848
2849 // (2)
2850 // If we are at a replacement variable,
2851 // copy it and record in EncClass
2852 if (_curchar == '$') {
2853 // Found replacement Variable
2854 char* rep_var = get_rep_var_ident_dup();
2855
2856 // Add flag to _strings list indicating we should check _rep_vars
2857 encoding->add_rep_var(rep_var);
2858
2859 skipws();
2860
2861 // Check if this instruct is a MachConstantNode.
2862 if (strcmp(rep_var, "constanttablebase") == 0) {
2863 // This instruct is a MachConstantNode.
2864 inst.set_is_mach_constant(true);
2865
2866 if (_curchar == '(') {
2867 parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name);
2868 return;
2869 }
2870 }
2871 else if ((strcmp(rep_var, "constantaddress") == 0) ||
2872 (strcmp(rep_var, "constantoffset") == 0)) {
2873 // This instruct is a MachConstantNode.
2874 inst.set_is_mach_constant(true);
2875
2876 // If the constant keyword has an argument, parse it.
2877 if (_curchar == '(') constant_parse(inst);
2878 }
2879 }
2880 } // end while part of format description
2881 next_char(); // Skip '%'
2882 next_char(); // Skip '}'
2883
2884 skipws();
2885
2886 if (_AD._adlocation_debug) {
2887 encoding->add_code(end_line_marker());
2888 }
2889
2890 // Debug Stuff
2891 if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
2892 }
2893
2894
2895 //------------------------------ins_encode_parse-------------------------------
2896 // Encode rules have the form
2897 // ins_encode( encode_class_name(parameter_list), ... );
2898 //
2899 // The "encode_class_name" must be defined in the encode section
2900 // The parameter list contains $names that are locals.
2901 //
2902 // Alternatively it can be written like this:
2903 //
2904 // ins_encode %{
2905 // ... // body
2906 // %}
2907 //
2908 // which synthesizes a new encoding class taking the same arguments as
2909 // the InstructForm, and automatically prefixes the definition with:
2910 //
2911 // MacroAssembler masm(&cbuf);\n");
2912 //
2913 // making it more compact to take advantage of the MacroAssembler and
2914 // placing the assembly closer to it's use by instructions.
2915 void ADLParser::ins_encode_parse(InstructForm& inst) {
2916
2917 // Parse encode class name
2918 skipws(); // Skip whitespace
2919 if (_curchar != '(') {
2920 // Check for ins_encode %{ form
2921 if ((_curchar == '%') && (*(_ptr+1) == '{')) {
2922 next_char(); // Skip '%'
2923 next_char(); // Skip '{'
2924
2925 // Parse the block form of ins_encode
2926 ins_encode_parse_block(inst);
2927 return;
2928 }
2929
2930 parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
2931 return;
2932 }
2933 next_char(); // move past '('
2934 skipws();
2935
2936 InsEncode *encrule = new InsEncode(); // Encode class for instruction
2937 encrule->_linenum = linenum();
2938 char *ec_name = NULL; // String representation of encode rule
2939 // identifier is optional.
2940 while (_curchar != ')') {
2941 ec_name = get_ident();
2942 if (ec_name == NULL) {
2943 parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
2944 return;
2945 }
2946 // Check that encoding is defined in the encode section
2947 EncClass *encode_class = _AD._encode->encClass(ec_name);
2948 if (encode_class == NULL) {
2949 // Like to defer checking these till later...
2950 // parse_err(WARN, "Using an undefined encode class '%s' in 'ins_encode'.\n", ec_name);
2951 }
2952
2953 // Get list for encode method's parameters
2954 NameAndList *params = encrule->add_encode(ec_name);
2955
2956 // Parse the parameters to this encode method.
2957 skipws();
2958 if ( _curchar == '(' ) {
2959 next_char(); // move past '(' for parameters
2960
2961 // Parse the encode method's parameters
2962 while (_curchar != ')') {
2963 char *param = get_ident_or_literal_constant("encoding operand");
2964 if ( param != NULL ) {
2965 // Found a parameter:
2966 // Check it is a local name, add it to the list, then check for more
2967 // New: allow hex constants as parameters to an encode method.
2968 // New: allow parenthesized expressions as parameters.
2969 // New: allow "primary", "secondary", "tertiary" as parameters.
2970 // New: allow user-defined register name as parameter
2971 if ( (inst._localNames[param] == NULL) &&
2972 !ADLParser::is_literal_constant(param) &&
2973 (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
2974 ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
2975 parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
2976 return;
2977 }
2978 params->add_entry(param);
2979
2980 skipws();
2981 if (_curchar == ',' ) {
2982 // More parameters to come
2983 next_char(); // move past ',' between parameters
2984 skipws(); // Skip to next parameter
2985 }
2986 else if (_curchar == ')') {
2987 // Done with parameter list
2988 }
2989 else {
2990 // Only ',' or ')' are valid after a parameter name
2991 parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
2992 ec_name);
2993 return;
2994 }
2995
2996 } else {
2997 skipws();
2998 // Did not find a parameter
2999 if (_curchar == ',') {
3000 parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
3001 return;
3002 }
3003 if (_curchar != ')') {
3004 parse_err(SYNERR, "Expected ')' after encode parameters.\n");
3005 return;
3006 }
3007 }
3008 } // WHILE loop collecting parameters
3009 next_char(); // move past ')' at end of parameters
3010 } // done with parameter list for encoding
3011
3012 // Check for ',' or ')' after encoding
3013 skipws(); // move to character after parameters
3014 if ( _curchar == ',' ) {
3015 // Found a ','
3016 next_char(); // move past ',' between encode methods
3017 skipws();
3018 }
3019 else if ( _curchar != ')' ) {
3020 // If not a ',' then only a ')' is allowed
3021 parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
3022 return;
3023 }
3024
3025 // Check for ',' separating parameters
3026 // if ( _curchar != ',' && _curchar != ')' ) {
3027 // parse_err(SYNERR, "expected ',' or ')' after encode method inside ins_encode.\n");
3028 // return NULL;
3029 // }
3030
3031 } // done parsing ins_encode methods and their parameters
3032 if (_curchar != ')') {
3033 parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
3034 return;
3035 }
3036 next_char(); // move past ')'
3037 skipws(); // Skip leading whitespace
3038
3039 if ( _curchar != ';' ) {
3040 parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
3041 return;
3042 }
3043 next_char(); // move past ';'
3044 skipws(); // be friendly to oper_parse()
3045
3046 // Debug Stuff
3047 if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
3048
3049 // Set encode class of this instruction.
3050 inst._insencode = encrule;
3051 }
3052
3053
3054 //------------------------------constant_parse---------------------------------
3055 // Parse a constant expression.
3056 void ADLParser::constant_parse(InstructForm& inst) {
3057 // Create a new encoding name based on the name of the instruction
3058 // definition, which should be unique.
3059 const char* prefix = "__constant_";
3060 char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
3061 sprintf(ec_name, "%s%s", prefix, inst._ident);
3062
3063 assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
3064 EncClass* encoding = _AD._encode->add_EncClass(ec_name);
3065 encoding->_linenum = linenum();
3066
3067 // synthesize the arguments list for the enc_class from the
3068 // arguments to the instruct definition.
3069 const char* param = NULL;
3070 inst._parameters.reset();
3071 while ((param = inst._parameters.iter()) != NULL) {
3072 OperandForm* opForm = (OperandForm*) inst._localNames[param];
3073 encoding->add_parameter(opForm->_ident, param);
3074 }
3075
3076 // Parse the following ( ) expression.
3077 constant_parse_expression(encoding, ec_name);
3078
3079 // Build an encoding rule which invokes the encoding rule we just
3080 // created, passing all arguments that we received.
3081 InsEncode* encrule = new InsEncode(); // Encode class for instruction
3082 NameAndList* params = encrule->add_encode(ec_name);
3083 inst._parameters.reset();
3084 while ((param = inst._parameters.iter()) != NULL) {
3085 params->add_entry(param);
3086 }
3087
3088 // Set encode class of this instruction.
3089 inst._constant = encrule;
3090 }
3091
3092
3093 //------------------------------constant_parse_expression----------------------
3094 void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
3095 skipws();
3096
3097 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
3098 if (_AD._adlocation_debug) {
3099 encoding->add_code(get_line_string());
3100 }
3101
3102 // Start code line.
3103 encoding->add_code(" add_to_constant_table");
3104
3105 // Parse everything in ( ) expression.
3106 encoding->add_code("(");
3107 next_char(); // Skip '('
3108 int parens_depth = 1;
3109
3110 // Collect the parts of the constant expression.
3111 // (1) strings that are passed through to output
3112 // (2) replacement/substitution variable, preceeded by a '$'
3113 while (parens_depth > 0) {
3114 if (_curchar == '(') {
3115 parens_depth++;
3116 encoding->add_code("(");
3117 next_char();
3118 }
3119 else if (_curchar == ')') {
3120 parens_depth--;
3121 encoding->add_code(")");
3122 next_char();
3123 }
3124 else {
3125 // (1)
3126 // Check if there is a string to pass through to output
3127 char *start = _ptr; // Record start of the next string
3128 while ((_curchar != '$') && (_curchar != '(') && (_curchar != ')')) {
3129 next_char();
3130 }
3131 // If a string was found, terminate it and record in EncClass
3132 if (start != _ptr) {
3133 *_ptr = '\0'; // Terminate the string
3134 encoding->add_code(start);
3135 }
3136
3137 // (2)
3138 // If we are at a replacement variable, copy it and record in EncClass.
3139 if (_curchar == '$') {
3140 // Found replacement Variable
3141 char* rep_var = get_rep_var_ident_dup();
3142 encoding->add_rep_var(rep_var);
3143 }
3144 }
3145 }
3146
3147 // Finish code line.
3148 encoding->add_code(";");
3149
3150 if (_AD._adlocation_debug) {
3151 encoding->add_code(end_line_marker());
3152 }
3153
3154 // Debug Stuff
3155 if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
3156 }
3157
3158
3159 //------------------------------size_parse-----------------------------------
3160 char* ADLParser::size_parse(InstructForm *instr) {
3161 char* sizeOfInstr = NULL;
3162
3163 // Get value of the instruction's size
3164 skipws();
3165
3166 // Parse size
3167 sizeOfInstr = get_paren_expr("size expression");
3168 if (sizeOfInstr == NULL) {
3169 parse_err(SYNERR, "size of opcode expected at %c\n", _curchar);
3170 return NULL;
3171 }
3172
3173 skipws();
3174
3175 // Check for terminator
|