nkeynes@561: /** nkeynes@561: * $Id$ nkeynes@561: * nkeynes@561: * gendec instruction definitions parser nkeynes@561: * nkeynes@561: * Copyright (c) 2005 Nathan Keynes. nkeynes@561: * nkeynes@561: * This program is free software; you can redistribute it and/or modify nkeynes@561: * it under the terms of the GNU General Public License as published by nkeynes@561: * the Free Software Foundation; either version 2 of the License, or nkeynes@561: * (at your option) any later version. nkeynes@561: * nkeynes@561: * This program is distributed in the hope that it will be useful, nkeynes@561: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@561: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@561: * GNU General Public License for more details. nkeynes@561: */ nkeynes@561: nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include "tools/gendec.h" nkeynes@359: nkeynes@359: #define CONSUME_CHAR(x) if( **str != x ) { fprintf( stderr, "Unexpected input character '%c', expected '%c' at line %d\n", **str, x, yyline ); return -1; } else { (*str)++; } nkeynes@359: static int yyline; nkeynes@359: nkeynes@359: struct rule *new_rule() { nkeynes@359: struct rule *rule = malloc( sizeof( struct rule ) ); nkeynes@359: memset( rule, 0, sizeof( struct rule ) ); nkeynes@359: return rule; nkeynes@359: } nkeynes@359: nkeynes@420: int parse_registers_block( char *buf, int buflen, FILE *f ); nkeynes@420: int parse_rule( char **str, struct rule *rule ); nkeynes@420: int parse_bitstring( char **str, struct rule *rule ); nkeynes@420: int parse_bitoperand( char **str, struct rule *rule ); nkeynes@420: int parse_integer( char **str ); nkeynes@420: int parse_rule_format( char **str, struct rule *rule ); nkeynes@420: int parse_operand_uses( char **str, struct rule *rule ); nkeynes@420: nkeynes@420: nkeynes@420: nkeynes@359: struct ruleset *parse_ruleset_file( FILE *f ) nkeynes@359: { nkeynes@359: struct ruleset *rules = malloc( sizeof(struct ruleset ) ); nkeynes@359: char buf[512]; nkeynes@359: nkeynes@359: rules->rule_count = 0; nkeynes@359: yyline = 0; nkeynes@359: while( fgets( buf, sizeof(buf), f ) != NULL ) { nkeynes@736: yyline++; nkeynes@736: if( strncasecmp(buf, "registers", 9) == 0 ) { nkeynes@736: parse_registers_block(buf, sizeof(buf), f); nkeynes@736: } else if( buf[0] != '\0' && buf[0] != '#' && buf[0] != '\n' ) { nkeynes@736: struct rule *rule; nkeynes@736: char *p = buf; nkeynes@736: rule = new_rule(); nkeynes@736: if( parse_rule( &p, rule ) != 0 ) { nkeynes@736: free( rule ); nkeynes@736: } else { nkeynes@736: rules->rules[rules->rule_count++] = rule; nkeynes@736: } nkeynes@736: } nkeynes@359: } nkeynes@359: return rules; nkeynes@359: } nkeynes@359: nkeynes@359: int parse_registers_block( char *buf, int buflen, FILE *f ) { nkeynes@359: do { nkeynes@736: if( strchr(buf, '}') != NULL ) { nkeynes@736: break; nkeynes@736: } nkeynes@359: } while( fgets( buf, buflen, f ) != NULL ); nkeynes@420: return 0; nkeynes@359: } nkeynes@359: nkeynes@359: /** nkeynes@359: * Parse a single complete rule nkeynes@359: * @return 0 on success, non-zero on failure nkeynes@359: */ nkeynes@359: int parse_rule( char **str, struct rule *rule ) nkeynes@359: { nkeynes@359: if( parse_bitstring( str, rule ) != 0 ) { nkeynes@736: return -1; nkeynes@359: } nkeynes@359: nkeynes@359: /* consume whitespace in between */ nkeynes@359: while( isspace(**str) ) (*str)++; nkeynes@359: if( **str == '\0' ) { nkeynes@736: fprintf( stderr, "Unexpected end of file in rule on line %d\n", yyline ); nkeynes@736: return -1; nkeynes@359: } nkeynes@736: nkeynes@359: int result = parse_rule_format( str, rule ); nkeynes@359: if( result == 0 ) { nkeynes@736: /* Reverse operand bit shifts */ nkeynes@736: int j; nkeynes@736: for( j=0; joperand_count; j++ ) { nkeynes@736: rule->operands[j].bit_shift = nkeynes@736: rule->bit_count - rule->operands[j].bit_shift - rule->operands[j].bit_count; nkeynes@736: } nkeynes@736: if( **str == '!' ) { nkeynes@736: (*str)++; nkeynes@736: result = parse_operand_uses( str, rule ); nkeynes@736: } nkeynes@359: } nkeynes@359: nkeynes@359: return 0; nkeynes@359: } nkeynes@359: nkeynes@359: int parse_bitstring( char **str, struct rule *rule ) nkeynes@359: { nkeynes@359: while( !isspace(**str) ) { nkeynes@736: int ch = **str; nkeynes@736: (*str)++; nkeynes@736: switch( ch ) { nkeynes@736: case '0': nkeynes@736: rule->bits = rule->bits << 1; nkeynes@736: rule->mask = (rule->mask << 1) | 1; nkeynes@736: rule->bit_count++; nkeynes@736: break; nkeynes@736: case '1': nkeynes@736: rule->bits = (rule->bits << 1) | 1; nkeynes@736: rule->mask = (rule->mask << 1) | 1; nkeynes@736: rule->bit_count++; nkeynes@736: break; nkeynes@736: case '(': nkeynes@736: if( parse_bitoperand( str, rule ) != 0 ) { nkeynes@736: return -1 ; nkeynes@736: } nkeynes@736: break; nkeynes@736: default: nkeynes@736: (*str)--; nkeynes@736: fprintf( stderr, "Unexpected character '%c' in bitstring at line %d\n", ch, yyline ); nkeynes@736: return -1; nkeynes@736: } nkeynes@359: } nkeynes@359: return 0; nkeynes@359: } nkeynes@359: nkeynes@359: int parse_bitoperand( char **str, struct rule *rule ) nkeynes@359: { nkeynes@359: char *p = rule->operands[rule->operand_count].name; nkeynes@359: nkeynes@359: if( rule->operand_count == MAX_OPERANDS ) { nkeynes@736: fprintf( stderr, "Maximum operands/rule exceeded (%d) at line %d\n", MAX_OPERANDS, yyline ); nkeynes@736: return -1; nkeynes@359: } nkeynes@359: nkeynes@359: while( isalnum(**str) || **str == '_' ) { nkeynes@736: *p++ = *(*str)++; nkeynes@359: } nkeynes@359: *p = '\0'; nkeynes@359: CONSUME_CHAR(':'); nkeynes@736: nkeynes@359: int size = parse_integer( str ); nkeynes@359: if( size == -1 ) { nkeynes@736: return -1; nkeynes@359: } nkeynes@359: rule->operands[rule->operand_count].bit_count = size; nkeynes@359: if( **str == 's' || **str == 'S' ) { nkeynes@736: (*str)++; nkeynes@736: rule->operands[rule->operand_count].is_signed = 1; nkeynes@359: } else if( **str == 'u' || **str == 'U' ) { nkeynes@736: (*str)++; nkeynes@736: rule->operands[rule->operand_count].is_signed = 0; nkeynes@359: } nkeynes@359: if( **str == '<' ) { nkeynes@736: (*str)++; nkeynes@736: CONSUME_CHAR('<'); nkeynes@736: int lsl = parse_integer(str); nkeynes@736: if( lsl == -1 ) { nkeynes@736: return -1; nkeynes@736: } nkeynes@736: rule->operands[rule->operand_count].left_shift = lsl; nkeynes@359: } nkeynes@359: CONSUME_CHAR(')'); nkeynes@359: nkeynes@359: rule->operands[rule->operand_count].bit_shift = rule->bit_count; nkeynes@359: rule->bit_count += size; nkeynes@359: rule->bits = rule->bits << size; nkeynes@359: rule->mask = rule->mask << size; nkeynes@359: rule->operand_count++; nkeynes@359: return 0; nkeynes@359: } nkeynes@359: nkeynes@359: int parse_integer( char **str ) nkeynes@359: { nkeynes@359: uint32_t val = 0; nkeynes@359: if( !isdigit(**str) ) { nkeynes@736: fprintf(stderr, "Expected digit (0-9) but was '%c' at line %d\n", **str, yyline ); nkeynes@736: return -1; nkeynes@359: } nkeynes@359: do { nkeynes@736: val = val * 10 + (**str - '0'); nkeynes@736: (*str)++; nkeynes@359: } while( isdigit(**str) ); nkeynes@359: return val; nkeynes@359: } nkeynes@359: nkeynes@359: int parse_rule_format( char **str, struct rule *rule ) nkeynes@359: { nkeynes@359: nkeynes@359: char tmp[64]; nkeynes@359: char *p = tmp; nkeynes@359: while( **str != '\n' && **str != '\0' && **str != '!' ) { nkeynes@736: *p++ = *(*str)++; nkeynes@359: } nkeynes@359: *p = '\0'; nkeynes@359: strcpy( rule->format, tmp ); nkeynes@359: nkeynes@359: return 0; nkeynes@359: } nkeynes@359: nkeynes@359: int parse_operand_uses( char **str, struct rule *rule ) nkeynes@359: { nkeynes@420: return 0; nkeynes@359: } nkeynes@359: nkeynes@359: void dump_ruleset( struct ruleset *rules, FILE *f ) nkeynes@359: { nkeynes@359: int i, j; nkeynes@359: fprintf( f, "Rulset: %d rules\n", rules->rule_count ); nkeynes@359: for( i=0; irule_count; i++ ) { nkeynes@736: struct rule *rule = rules->rules[i]; nkeynes@736: fprintf( f, "Match: %08X/%08X %s: ", rule->bits, rule->mask, rule->format ); nkeynes@736: for( j=0; joperand_count; j++ ) { nkeynes@736: fprintf( f, "%s = (%s)(ir>>%d)&0x%X ", rule->operands[j].name, nkeynes@736: rule->operands[j].is_signed ? "signed" : "unsigned", nkeynes@736: rule->operands[j].bit_shift, nkeynes@736: (1<operands[j].bit_count)-1 ); nkeynes@736: } nkeynes@736: fprintf( f, "\n" ); nkeynes@359: } nkeynes@359: } nkeynes@359: nkeynes@359: void dump_rulesubset( struct ruleset *rules, int ruleidx[], int rule_count, FILE *f ) nkeynes@359: { nkeynes@359: int i,j; nkeynes@359: for( i=0; irules[ruleidx[i]]; nkeynes@736: fprintf( f, "Match: %08X/%08X %s: ", rule->bits, rule->mask, rule->format ); nkeynes@736: for( j=0; joperand_count; j++ ) { nkeynes@736: fprintf( f, "%s = (%s)(ir>>%d)&0x%X ", rule->operands[j].name, nkeynes@736: rule->operands[j].is_signed ? "signed" : "unsigned", nkeynes@736: rule->operands[j].bit_shift, nkeynes@736: (1<operands[j].bit_count)-1 ); nkeynes@736: } nkeynes@736: fprintf( f, "\n" ); nkeynes@359: } nkeynes@359: }