Annotation of tme/ic/m68k/m68k-opmap-make.pl, revision 1.1

1.1     ! root        1: #! /usr/local/bin/perl -w
        !             2: 
        !             3: # m68k-opmap-make.pl - compiles the complete decoding of all legal
        !             4: # first-instruction-word values into the opcode map used by the C
        !             5: # decoder:
        !             6: 
        !             7: # $Id: m68k-opmap-make.pl,v 1.3 2003/04/23 19:20:30 fredette Exp $
        !             8: 
        !             9: # globals:
        !            10: $0 =~ /^(.*\/)?([^\/]+)$/; $PROG = $2;
        !            11: $debug = 0;
        !            12: 
        !            13: # to silence -w:
        !            14: undef($value);
        !            15: 
        !            16: # emit our header:
        !            17: print <<"EOF;";
        !            18: /* generated automatically by $PROG, do not edit! */
        !            19: 
        !            20: /* includes: */
        !            21: #include "m68k-impl.h"
        !            22: EOF;
        !            23: 
        !            24: # we begin with no submaps and no opcode maps:
        !            25: $submap_next = 0;
        !            26: $opcode_map_next = 0;
        !            27: %opcode_maps = ();
        !            28: 
        !            29: # assuming an ILP32 machine, various sizeofs:
        !            30: $sizeof_opcode = 12;
        !            31: $sizeof_submap = 64 * 24;
        !            32: 
        !            33: # loop over standard input:
        !            34: for ($line = 1; defined($_ = <STDIN>); $line++) {
        !            35:     chomp;
        !            36: 
        !            37:     # break the line into tokens:
        !            38:     @tokens = split(' ', $_);
        !            39: 
        !            40:     # if this is the beginning of a new CPU:
        !            41:     if ($tokens[0] eq "cpu-begin") {
        !            42:        $cpu_name = $tokens[1];
        !            43: 
        !            44:        # initialize for this CPU:
        !            45:        print STDERR "$PROG: initializing for $cpu_name...";
        !            46: 
        !            47:        # initialize the full map:
        !            48:        undef(@map_line);
        !            49:        for ($pattern = 65536; $pattern-- > 0;) {
        !            50:            $map_op0[$pattern] = "U";
        !            51:            $map_op1[$pattern] = "U";
        !            52:            $map_eax_size[$pattern] = "U";
        !            53:            $map_eax_cycles[$pattern] = "U";
        !            54:            $map_imm_operand[$pattern] = "U";
        !            55:            $map_imm_size[$pattern] = "U";
        !            56:            $map_eay_size[$pattern] = "U";
        !            57:            $map_eay_cycles[$pattern] = "U";
        !            58:        }
        !            59: 
        !            60:        # initialize the special operations:
        !            61:        undef(%specop);
        !            62: 
        !            63:        # we're done initializing and we're now reading patterns:
        !            64:        $patterns = 0;
        !            65:        print STDERR " done\n$PROG: reading $cpu_name patterns...";
        !            66:     }
        !            67: 
        !            68:     # if this is a special-operation line:
        !            69:     elsif ($tokens[0] eq "specop") {
        !            70:        shift(@tokens);
        !            71:        $specop = shift(@tokens);
        !            72:        foreach (@tokens) {
        !            73:            $specop{$_} = $specop;
        !            74:        }
        !            75:     }
        !            76: 
        !            77:     # if this is a pattern:
        !            78:     elsif ($tokens[0] =~ /^[01]/) {
        !            79:     
        !            80:        # the first token is the pattern.  die if this pattern has already
        !            81:        # appeared:
        !            82:        $pattern = oct("0b".shift(@tokens));
        !            83:        die "stdin:$line: duplicate pattern of line $map_line[$pattern]\n"
        !            84:            if (defined($map_line[$pattern]));
        !            85:        $map_line[$pattern] = $line;
        !            86: 
        !            87:        # fill this map entry:
        !            88:        foreach $token (@tokens) {
        !            89:            ($what, $value) = split(/=/, $token, 2);
        !            90:            eval("\$map_".$what."[$pattern] = \$value;");
        !            91:        }
        !            92:        die "stdin:$line: no function given\n"
        !            93:            if (!defined($map_func[$pattern]));
        !            94:        $patterns++;
        !            95:     }
        !            96: 
        !            97:     # if this is the end of a CPU:
        !            98:     elsif ($tokens[0] eq "cpu-end") {
        !            99:        $cpu_name = $tokens[1];
        !           100: 
        !           101:        # note how many patterns we read:
        !           102:        print STDERR " read $patterns $cpu_name patterns\n";
        !           103:     
        !           104:        # sanity-check the information read in, and force all unused
        !           105:        # full map entries to illegal:
        !           106:        print STDERR "$PROG: finding unused $cpu_name patterns...";
        !           107:        $unused = 0;
        !           108:        for ($pattern = 65536; $pattern-- > 0;) {
        !           109: 
        !           110:            # if this is an unused map entry:
        !           111:            if (!defined($map_line[$pattern])) {
        !           112:                $map_func[$pattern] = "illegal";
        !           113:                $unused++;
        !           114:                next;
        !           115:            }
        !           116: 
        !           117:            # since the overwhelming majority of instructions use at
        !           118:            # most one effective address path (the eax path), only the
        !           119:            # size of the eax path operand is stored in the opcode
        !           120:            # maps.  any instruction that uses the eay path must do so
        !           121:            # with the same size as the eax path:
        !           122:            if ($map_eay_size[$pattern] ne "U") {
        !           123: 
        !           124:                # if this instruction isn't using the eax path, switch
        !           125:                # to using the eax path instead.  the only instruction
        !           126:                # allowed to do this is move.S.  temporarily rewrite
        !           127:                # this function to a special function "movenonmemtomem":
        !           128:                if ($map_eax_size[$pattern] eq "U") {
        !           129:                    die "$PROG: pattern ".sprintf("%b", $pattern)." ($map_func[$pattern]) uses the eay path\n"
        !           130:                        if ($map_func[$pattern] !~ /^(move)(\d+)$/);
        !           131:                    $map_func[$pattern] = $1."nonmemtomem".$2;
        !           132:                    $map_eax_size[$pattern] = $map_eay_size[$pattern];
        !           133:                    $map_eax_cycles[$pattern] = $map_eay_cycles[$pattern];
        !           134:                    $map_op0[$pattern] =~ s/^memy/memx/;
        !           135:                    $map_op1[$pattern] =~ s/^memy/memx/;
        !           136:                }
        !           137: 
        !           138:                # otherwise, this instruction is using both ea paths.
        !           139:                # the only instruction allowed to do this is move.S.
        !           140:                # temporarily rewrite this function to a special
        !           141:                # function "movememtomem":
        !           142:                else {
        !           143:                    die "$PROG: pattern ".sprintf("%b", $pattern)." ($map_func[$pattern]) uses both ea paths\n"
        !           144:                        if ($map_func[$pattern] !~ /^(move)(\d+)$/);
        !           145:                    $map_func[$pattern] = $1."memtomem".$2;
        !           146:                    die "$PROG: pattern ".sprintf("%b", $pattern)." ($map_func[$pattern]) uses both ea paths at different sizes\n"
        !           147:                        if ($map_eay_size[$pattern] ne $map_eax_size[$pattern]);
        !           148:                    die "$PROG: pattern ".sprintf("%b", $pattern)." ($map_func[$pattern]) doesn't use eay write-only\n"
        !           149:                        if ($map_eay_cycles[$pattern] ne "wo");
        !           150:                }
        !           151:            }
        !           152:        }
        !           153:        print STDERR " found $unused unused $cpu_name patterns\n";
        !           154: 
        !           155:        # loop over the root patterns to come up with the root map
        !           156:        # entry, the submap key and the functions list for each:
        !           157:        print STDERR "$PROG: making $cpu_name root map entries and submap keys...";
        !           158:        for ($root = 0; $root < 1024; $root++) {
        !           159: 
        !           160:            # get counts of the different map entry attribute values.
        !           161:            # the most popular attribute values will get stored in the
        !           162:            # root map entry, while the others will get set in submap
        !           163:            # entries:
        !           164:            #
        !           165:            undef(%count_func);
        !           166:            undef(%count_op0);
        !           167:            undef(%count_op1);
        !           168:            undef(%count_eax_size);
        !           169:            undef(%count_imm);
        !           170:            for ($sub = 0, $pattern = $root << 6; $sub < 64 ; $sub++, $pattern++) {
        !           171: 
        !           172:                # the decoder specially cancels all attributes other
        !           173:                # than "function" when the function is "illegal", so
        !           174:                # don't count any of its attribute values.
        !           175:                #
        !           176:                # otherwise, function, specop, and EA cycles go
        !           177:                # together, and immediate operand and immediate size
        !           178:                # go together:
        !           179:                #
        !           180:                $func = $map_func[$pattern];
        !           181:                if ($func ne "illegal") {
        !           182:                    $specop = "un" if (!defined($specop = $specop{$func}));
        !           183:                    $func .= ".$specop";
        !           184:                    if ($map_eax_size[$pattern] eq "U") {
        !           185:                        # a pattern that doesn't use the EA path can have
        !           186:                        # any value for its opcode map entry cycles:
        !           187:                        die "$PROG: pattern ".sprintf("%b", $pattern)." ($func) doesn't use the EA path but needs $map_eax_cycles[$pattern] cycles?\n"
        !           188:                            if ($map_eax_cycles[$pattern] ne "U");
        !           189:                        $func .= ".any";
        !           190:                    }
        !           191:                    elsif ($map_eax_size[$pattern] eq "UNSIZED") {
        !           192:                        # a pattern that uses the raw effective address
        !           193:                        # must have UNDEF for its opcode map entry cycles:
        !           194:                        die "$PROG: pattern ".sprintf("%b", $pattern)." ($func) takes the raw EA path but needs $map_eax_cycles[$pattern] cycles?\n"
        !           195:                            if ($map_eax_cycles[$pattern] ne "U");
        !           196:                        $func .= ".un";
        !           197:                    }
        !           198:                    else {
        !           199:                        # otherwise, this pattern must have its specified
        !           200:                        # value for its opcode map entry cycles:
        !           201:                        die "$PROG: pattern ".sprintf("%b", $pattern)." ($func) uses the EA path at size $map_eax_size[$pattern] but needs $map_eax_cycles[$pattern] cycles?\n"
        !           202:                            if ($map_eax_cycles[$pattern] eq "U"
        !           203:                                || $map_eax_cycles[$pattern] eq "un");
        !           204:                        $func .= ".".$map_eax_cycles[$pattern];
        !           205:                    }
        !           206:                    $map_func[$pattern] = $func;
        !           207:                    $count_op0{$map_op0[$pattern]}++;
        !           208:                    $count_op1{$map_op1[$pattern]}++;
        !           209:                    $count_eax_size{$map_eax_size[$pattern]}++;
        !           210:                    $count_imm{$map_imm_operand[$pattern].".".$map_imm_size[$pattern]}++;
        !           211:                }
        !           212:                $count_func{$func}++;
        !           213:            }
        !           214: 
        !           215:            # a pattern that doesn't use the EA path can use the same
        !           216:            # opcode map entry as a pattern that has the same function
        !           217:            # but does use the EA path, because the former pattern
        !           218:            # will have UNDEF for its eax size, which makes the cycles
        !           219:            # member of the opcode map entry a don't care:
        !           220:            #
        !           221:            @funcs = (keys(%count_func));
        !           222:            %funcs_rewrite = ();
        !           223:            foreach $func (@funcs) {
        !           224:                @parts = split(/\./, $func);
        !           225:                if (@parts == 3
        !           226:                    && $parts[2] ne "any") {
        !           227:                    $func_rewrite = $parts[0].".".$parts[1].".any";
        !           228:                    if (defined($count_func{$func_rewrite})) {
        !           229:                        $count_func{$func} += delete($count_func{$func_rewrite});
        !           230:                        $funcs_rewrite{$func_rewrite} = $func;
        !           231:                    }
        !           232:                }
        !           233:            }
        !           234:            for ($sub = 0, $pattern = $root << 6; $sub < 64 ; $sub++, $pattern++) {
        !           235:                $map_func[$pattern] = $func
        !           236:                    if (defined($func = $funcs_rewrite{$map_func[$pattern]}));
        !           237:            }
        !           238: 
        !           239:            # sort the attributes:
        !           240:            @funcs = (sort { ($count_func{$b} == $count_func{$a}
        !           241:                              ? $a cmp $b
        !           242:                              : $count_func{$b} <=> $count_func{$a}) } keys(%count_func));
        !           243:            @op0s = (sort { ($count_op0{$b} == $count_op0{$a}
        !           244:                             ? $a cmp $b
        !           245:                             : $count_op0{$b} <=> $count_op0{$a}) } keys(%count_op0));
        !           246:            @op1s = (sort { ($count_op1{$b} == $count_op1{$a}
        !           247:                             ? $a cmp $b
        !           248:                             : $count_op1{$b} <=> $count_op1{$a}) } keys(%count_op1));
        !           249:            @eax_sizes = (sort { ($count_eax_size{$b} == $count_eax_size{$a}
        !           250:                                  ? $a cmp $b
        !           251:                                  : $count_eax_size{$b} <=> $count_eax_size{$a}) } keys(%count_eax_size));
        !           252:            @imms = (sort { ($count_imm{$b} == $count_imm{$a}
        !           253:                             ? $a cmp $b
        !           254:                             : $count_imm{$b} <=> $count_imm{$a}) } keys(%count_imm));
        !           255:            
        !           256:            # make sure the attributes have at least undef in them.  for
        !           257:            # all-illegal roots they would otherwise be empty:
        !           258:            push(@op0s, "U"); $count_op0{"U"}++;
        !           259:            push(@op1s, "U"); $count_op1{"U"}++;
        !           260:            push(@eax_sizes, "U"); $count_eax_size{"U"}++;
        !           261:            push(@imms, "U.U"); $count_imm{"U.U"}++;
        !           262:            
        !           263:            # display the attributes:
        !           264:            if (1 && $debug) {
        !           265:                print STDERR "root $root:";
        !           266:                print STDERR "\n  funcs"; foreach (@funcs) { print STDERR " $_ ($count_func{$_})"}
        !           267:                print STDERR "\n  op0s"; foreach (@op0s) { print STDERR " $_ ($count_op0{$_})"}
        !           268:                print STDERR "\n  op1s"; foreach (@op1s) { print STDERR " $_ ($count_op1{$_})"}
        !           269:                print STDERR "\n  eax_sizes"; foreach (@eax_sizes) { print STDERR " $_ ($count_eax_size{$_})"}
        !           270:                print STDERR "\n  imms"; foreach (@imms) { print STDERR " $_ ($count_imm{$_})"}
        !           271:                print STDERR "\n";
        !           272:            }
        !           273: 
        !           274:            # form the submap key.  this is a very long string
        !           275:            # describing what a submap must do with attributes in
        !           276:            # order to be associated with this root.  this string is
        !           277:            # very long because it lists all attributes for the 64
        !           278:            # subs under this root:
        !           279:            #
        !           280:            # this string really ends up being a regular expression,
        !           281:            # and since the decoder specially cancels all attributes
        !           282:            # when the function is "illegal", illegal can really take
        !           283:            # any attributes, so wildcards are used:
        !           284:            #
        !           285:            @key = ();
        !           286:            for ($sub = 0, $pattern = $root << 6; $sub < 64 ; $sub++, $pattern++) {
        !           287:                if ($map_func[$pattern] eq "illegal") {
        !           288:                    push(@key, '\S+');
        !           289:                    push(@key, '\S+');
        !           290:                    push(@key, '\S+');
        !           291:                    push(@key, '\S+');
        !           292:                }
        !           293:                else {
        !           294: 
        !           295:                    # the op0 and op1 attributes can be anything for
        !           296:                    # patterns that don't use them ("U" for
        !           297:                    # undefined), because even if they are defined in
        !           298:                    # the submap or root, the instruction decoder does
        !           299:                    # nothing except pass them to the instruction
        !           300:                    # functions, which don't care.  so they can be
        !           301:                    # anything in the submap key:
        !           302:                    $_ = $map_op0[$pattern]; push(@key, ($_ eq "U" ? '\S+' : $_ eq $op0s[0] ? "U" : $_));
        !           303:                    $_ = $map_op1[$pattern]; push(@key, ($_ eq "U" ? '\S+' : $_ eq $op1s[0] ? "U" : $_));
        !           304: 
        !           305:                    # however, the same is not true for the EA size
        !           306:                    # and immediate operand attributes.  if a pattern
        !           307:                    # doesn't use these attributes, they *must* be
        !           308:                    # undefined in the submap, so that any defined
        !           309:                    # attribute in the root is ignored - otherwise the
        !           310:                    # instruction decoder will do EA work and fetch
        !           311:                    # immediates when it isn't supposed to.  this
        !           312:                    # means that we have to introduce a
        !           313:                    # use-the-root-attribute value for those patterns
        !           314:                    # that *must* use the root attribute value.  we
        !           315:                    # use "X" to stand for this value:
        !           316:                    $_ = $map_eax_size[$pattern]; push(@key, ($_ eq $eax_sizes[0] ? "X" : $_));
        !           317:                    $_ = $map_imm_operand[$pattern].".".$map_imm_size[$pattern]; push(@key, ($_ eq $imms[0] ? "X" : $_));
        !           318:                }
        !           319:            }
        !           320:            $key = join(" ", @key);
        !           321:            $root_key[$root] = $key;
        !           322:            $root_funcs[$root] = join(",", @funcs);
        !           323:            $root_op0[$root] = $op0s[0];
        !           324:            $root_op1[$root] = $op1s[0];
        !           325:            $root_eax_size[$root] = $eax_sizes[0];
        !           326:            $imms[0] =~ /^(.*)\.(.*)$/;
        !           327:            $root_imm_operand[$root] = $1;
        !           328:            $root_imm_size[$root] = $2;
        !           329:            undef($root_submap[$root]);
        !           330:            print STDERR "  key $key\n" if (0 && $debug);
        !           331:        }
        !           332:        print STDERR " done\n";
        !           333: 
        !           334:        # create submaps and opcode maps for the roots:
        !           335:        $submaps_new = $submap_next;
        !           336:        print STDERR "$PROG: creating $cpu_name submaps...";
        !           337:        for ($root = 0; $root < 1024; $root++) {
        !           338:     
        !           339:            # get the function array and key for this root:
        !           340:            @funcs = split(/,/, $root_funcs[$root]);
        !           341:            $key = $root_key[$root];
        !           342:            print STDERR "  root $root key $key\n" if (0 && $debug);
        !           343:     
        !           344:            # calculate the additional memory cost of creating a new
        !           345:            # submap for this root:
        !           346:            $submap_best_cost = ($sizeof_submap
        !           347:                                 # our opcode map:
        !           348:                                 + (@funcs * $sizeof_opcode));
        !           349:     
        !           350:            # check all of the existing submaps for a key match:
        !           351:            undef($submap_best);
        !           352:            $key =~ s/\./\\\./g;
        !           353:            for ($submap = 0; $submap < $submap_next; $submap++) {
        !           354:                next unless ($submap_key[$submap] =~ /^$key$/);
        !           355:        
        !           356:                # get the opcode map indices array, and the size of
        !           357:                # the opcode map currently required by this submap:
        !           358:                @opcode_map_indices = split(/,/, $submap_opcode_map_indices[$submap]);
        !           359:                $opcode_map_size = $submap_opcode_map_size[$submap];
        !           360:        
        !           361:                # loop over the submap entries, seeing how the submap's opcode
        !           362:                # map indices would have to change to accomodate this root:
        !           363:                undef(@index_to_func);
        !           364:                undef(%func_to_new_index);
        !           365:                for ($sub = 0, $pattern = $root << 6; $sub < 64 ; $sub++, $pattern++) {
        !           366:                    $opcode_map_index = $opcode_map_indices[$sub];
        !           367:                    $func = $index_to_func[$opcode_map_index];
        !           368:                    if (!defined($func)) {
        !           369:                        $index_to_func[$opcode_map_index] = $map_func[$pattern];
        !           370:                    }
        !           371:                    elsif ($func ne $map_func[$pattern]) {
        !           372:                        if (!defined($_ = $func_to_new_index{$map_func[$pattern]})) {
        !           373:                            $_ = $func_to_new_index{$func} = $opcode_map_size++;
        !           374:                            $index_to_func[$_] = $func;
        !           375:                        }
        !           376:                        $opcode_map_indices[$sub] = $_;
        !           377:                    }
        !           378:                }
        !           379: 
        !           380:                # a submap for an earlier CPU is off-limits unless we
        !           381:                # can use it without growing the opcode map it
        !           382:                # requires, since both the submap and the earlier
        !           383:                # CPU's opcode maps have already been generated:
        !           384:                next if ($submap < $submaps_new
        !           385:                         && $opcode_map_size > $submap_opcode_map_size[$submap]);
        !           386:        
        !           387:                # calculate the additional memory cost of reusing this
        !           388:                # submap for this root:
        !           389:                $submap_cost = 0;
        !           390: 
        !           391:                # if the exact opcode map we would need doesn't
        !           392:                # already exist, we would have to create it:
        !           393:                $opcode_map_key = join(" ", @index_to_func);
        !           394:                $submap_cost += ($sizeof_opcode
        !           395:                                 * $opcode_map_size)
        !           396:                    if (!defined($opcode_map{$opcode_map_key}));
        !           397: 
        !           398:                # if we would grow the size of the opcode map required
        !           399:                # by this submap by N entries, that's N more opcodes
        !           400:                # for *each* root already using this submap:
        !           401:                $submap_cost += ($sizeof_opcode
        !           402:                                 * ($submap_refcnt[$submap]
        !           403:                                    * ($opcode_map_size
        !           404:                                       - $submap_opcode_map_size[$submap])));
        !           405: 
        !           406:                # if using this submap for this root is still better
        !           407:                # than any alternative, remember it and how we may
        !           408:                # want to change it:
        !           409:                if ($submap_cost < $submap_best_cost) {
        !           410:                    $submap_best = $submap;
        !           411:                    $submap_best_cost = $submap_cost;
        !           412:                    @submap_best_opcode_map_indices = @opcode_map_indices;
        !           413:                    $submap_best_opcode_map_size = $opcode_map_size;
        !           414:                }
        !           415:            }
        !           416:     
        !           417:            # if there is a best existing submap, make changes to it:
        !           418:            if (defined($submap_best)) {
        !           419:                if ($submap_opcode_map_size[$submap_best] != $submap_best_opcode_map_size) {
        !           420:                    $submap_opcode_map_indices[$submap_best] = join(",", @submap_best_opcode_map_indices);
        !           421:                    $submap_opcode_map_size[$submap_best] = $submap_best_opcode_map_size;
        !           422:                    print STDERR "  submap $submap_best now funcs ".join(",", @funcs).", ($opcode_map_size) indices ".join(",", @opcode_map_indices)."\n"
        !           423:                        if ($debug);
        !           424:                }
        !           425:            }
        !           426:     
        !           427:            # otherwise, create a new submap:
        !           428:            else {
        !           429:        
        !           430:                # allocate a new submap number:
        !           431:                $submap_best = $submap_next++;
        !           432:        
        !           433:                # create the hash of function name to opcode map index:
        !           434:                undef(%func_to_index);
        !           435:                $opcode_map_size = 0;
        !           436:                foreach $func (@funcs) {
        !           437:                    $func_to_index{$func} = $opcode_map_size++;
        !           438:                }
        !           439:        
        !           440:                # now make the list of opcode map indices:
        !           441:                @opcode_map_indices = ();
        !           442:                for ($sub = 0, $pattern = $root << 6; $sub < 64 ; $sub++, $pattern++) {
        !           443:                    die "internal error - func $map_func[$pattern] missing from ".join(" ", @funcs)."\n"
        !           444:                        if (!defined($func_to_index{$map_func[$pattern]}));
        !           445:                    push(@opcode_map_indices, $func_to_index{$map_func[$pattern]});
        !           446:                }
        !           447:        
        !           448:                # officially add this new submap:
        !           449:                $submap_opcode_map_indices[$submap_best] = join(",", @opcode_map_indices);
        !           450:                $submap_opcode_map_size[$submap_best] = $opcode_map_size;
        !           451:                $submap_key[$submap_best] = $root_key[$root];
        !           452:                print STDERR "  new submap $submap_best, funcs ".join(",", @funcs).", ($opcode_map_size) indices ".join(",", @opcode_map_indices)."\n"
        !           453:                    if ($debug);
        !           454:            }
        !           455:     
        !           456:            # note how reference counts have changed:
        !           457:            $root_submap[$root] = $submap_best;
        !           458:            $submap_refcnt[$submap_best]++;
        !           459:            print STDERR "  refcnt on submap $submap_best now $submap_refcnt[$submap_best]\n" if ($debug);          
        !           460:        }
        !           461: 
        !           462:        # write out any newly created submaps:
        !           463:        $submaps = 0;
        !           464:        for ($submap = $submaps_new; $submap < $submap_next; $submap++) {
        !           465:            next if ($submap_refcnt[$submap] == 0);
        !           466:            $submaps++;
        !           467: 
        !           468:            print <<"EOF;";
        !           469: 
        !           470: /* create submap $submap: */
        !           471: static struct _tme_m68k_decoder_submap *
        !           472: _tme_m68k_create_submap$submap(struct tme_m68k *ic)
        !           473: {
        !           474:   struct _tme_m68k_decoder_submap *submap, *submap_entry;
        !           475:   int entry_i;
        !           476: 
        !           477:   /* allocate and initialize the submap: */
        !           478:   submap = tme_new(struct _tme_m68k_decoder_submap, 64);
        !           479:   submap_entry = submap;
        !           480:   for (entry_i = 0; entry_i < 64; entry_i++) {
        !           481:       submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand0 = NULL;
        !           482:       submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand1 = NULL;
        !           483:       submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_eax_size = TME_M68K_SIZE_UNDEF;
        !           484:       submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_operand = TME_M68K_OPNUM_UNDEF;
        !           485:       submap_entry++;
        !           486:   }
        !           487: 
        !           488:   /* fill the submap: */
        !           489:   submap_entry = submap;
        !           490: EOF;
        !           491: 
        !           492:            # get the submap key and opcode map indices and split them up:
        !           493:            @key = split(' ', $submap_key[$submap]);
        !           494:            @opcode_map_indices = split(/,/, $submap_opcode_map_indices[$submap]);
        !           495: 
        !           496:            # emit the code to initialize each submap entry:
        !           497:            for ($sub = 0; $sub < 64 ; $sub++) {
        !           498:                print "\n  /* submap $submap sub $sub */\n";
        !           499: 
        !           500:                # emit op0:
        !           501:                $op0 = &operand_final(shift(@key));
        !           502:                print "  submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand0 = $op0;\n"
        !           503:                    if (defined($op0));
        !           504: 
        !           505:                # emit op1:
        !           506:                $op1 = &operand_final(shift(@key));
        !           507:                print "  submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand1 = $op1;\n"
        !           508:                    if (defined($op1));
        !           509: 
        !           510:                # emit eax_size:
        !           511:                $eax_size = shift(@key);
        !           512:                $eax_size = "SUBMAP_X" if ($eax_size eq "X");
        !           513:                print "  submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_eax_size = TME_M68K_SIZE_$eax_size;\n"
        !           514:                    if ($eax_size ne "U" && $eax_size ne '\S+');
        !           515: 
        !           516:                # emit imm_size and imm_operand:
        !           517:                $_ = shift(@key);
        !           518:                if ($_ eq "X") {
        !           519:                    print "  submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_operand = TME_M68K_OPNUM_SUBMAP_X;\n";
        !           520:                }
        !           521:                elsif ($_ !~ /^U/ && $_ ne '\S+') {
        !           522:                    ($imm_operand, $imm_size) = (/^(\S+)\.(\S+)/);
        !           523:                    $imm_size = "16U8" if ($imm_size eq "8");
        !           524:                    print "  submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_operand = $imm_operand;\n";
        !           525:                    print "  submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_size = TME_M68K_SIZE_$imm_size;\n";
        !           526:                }
        !           527:                
        !           528:                # emit the opcode map index:
        !           529:                print "  (submap_entry++)->_tme_m68k_decoder_submap_opcode_map_index = $opcode_map_indices[$sub];\n";
        !           530:            }
        !           531: 
        !           532:            # finish the function:
        !           533:            print <<"EOF;";
        !           534: 
        !           535:   /* done: */
        !           536:   return(submap);
        !           537: }
        !           538: EOF;
        !           539:        }
        !           540: 
        !           541:        # for each root, according to the submap used, either use an
        !           542:        # existing opcode map or create a new opcode map:
        !           543:        $opcode_maps = 0;
        !           544:        for ($root = 0; $root < 1024; $root++) {
        !           545: 
        !           546:            # create the opcode map key:
        !           547:            $submap = $root_submap[$root];
        !           548:            @opcode_map_indices = split(/,/, $submap_opcode_map_indices[$submap]);
        !           549:            $opcode_map_size = $submap_opcode_map_size[$submap];
        !           550:            undef(@index_to_func);
        !           551:            for ($sub = 0, $pattern = $root << 6; $sub < 64 ; $sub++, $pattern++) {
        !           552:                $opcode_map_index = $opcode_map_indices[$sub];
        !           553:                $func = $index_to_func[$opcode_map_index];
        !           554:                if (!defined($func)) {
        !           555:                    $index_to_func[$opcode_map_index] = $map_func[$pattern];
        !           556:                }
        !           557:                elsif ($func ne $map_func[$pattern]) {
        !           558:                    die "$PROG internal error: opcode map indices broken (root $root, submap $submap, sub $sub index $opcode_map_index needs to be $map_func[$pattern], but it's already $func)\n";
        !           559:                }
        !           560:            }
        !           561:            $opcode_map_key = join(" ", @index_to_func);
        !           562: 
        !           563:            # if the exact opcode map we need doesn't already exist,
        !           564:            # create it:
        !           565:            if (!defined($opcode_map = $opcode_maps{$opcode_map_key})) {
        !           566:                $opcode_map = $opcode_map_next++;
        !           567:                $opcode_maps{$opcode_map_key} = $opcode_map;
        !           568:                $opcode_maps++;
        !           569:     
        !           570:                print "\n";
        !           571:                print "/* opcode map for $cpu_name root $root (submap $submap): */\n";
        !           572:                print "static const struct _tme_m68k_opcode _tme_m68k_opcode_map${opcode_map}[$opcode_map_size] = {\n";
        !           573:                for ($map_i = 0; $map_i < $opcode_map_size; $map_i++) {
        !           574:                    @parts = split(/\./, $index_to_func[$map_i]);
        !           575:                    ($func, $specop, $cycles) = @parts;
        !           576:                    if ($func =~ /^(\S+)(nonmemtomem)(\d+)/
        !           577:                        || $func =~ /^(\S+)(memtomem)(\d+)/) {
        !           578:                        $func = $1.$3;
        !           579:                        $specop = $1.$2;
        !           580:                    }
        !           581:                    $specop = "undef" 
        !           582:                        if (!defined($specop)
        !           583:                            || $specop eq "un");
        !           584:                    $specop =~ tr/a-z/A-Z/;
        !           585:                    $specop = "TME_M68K_SPECOP_$specop";
        !           586:                    if (!defined($cycles)
        !           587:                        || $cycles eq "un"
        !           588:                        || $cycles eq "any") {
        !           589:                        $cycles = "TME_BUS_CYCLE_UNDEF";
        !           590:                    }
        !           591:                    elsif ($cycles eq "ro") {
        !           592:                        $cycles = "TME_BUS_CYCLE_READ";
        !           593:                    }
        !           594:                    elsif ($cycles eq "wo") {
        !           595:                        $cycles = "TME_BUS_CYCLE_WRITE";
        !           596:                    }
        !           597:                    elsif ($cycles eq "rw") {
        !           598:                        $cycles = "TME_BUS_CYCLE_READ|TME_BUS_CYCLE_WRITE";
        !           599:                    }
        !           600:                    else {
        !           601:                        die "$PROG error: bad cycles $cycles\n";
        !           602:                    }
        !           603:                    print "  { tme_m68k_$func, $specop, $cycles },\n";
        !           604:                }
        !           605:                print "};\n";
        !           606:            }
        !           607:            $root_opcode_map[$root] = $opcode_map;
        !           608:        }
        !           609:        print STDERR " created $submaps new submaps, $opcode_maps new opcode maps\n";
        !           610: 
        !           611:        # write out the function that creates the root map:
        !           612:        print <<"EOF;";
        !           613: 
        !           614: /* initializes the ${cpu_name} decoder map: */
        !           615: void
        !           616: _tme_${cpu_name}_decoder_map_init(struct tme_m68k *ic)
        !           617: {
        !           618:   struct _tme_m68k_decoder_root *root, *root_entry;
        !           619:   int entry_i;
        !           620: EOF;
        !           621: 
        !           622:        print "\n";
        !           623:        print "  /* the submaps used by this CPU: */\n";
        !           624:        undef(@submap_done);
        !           625:        for ($root = 0; $root < 1024; $root++) {
        !           626:            $submap = $root_submap[$root];
        !           627:            if (!$submap_done[$submap]) {
        !           628:                print "  struct _tme_m68k_decoder_submap *submap$submap = _tme_m68k_create_submap$submap(ic);\n";
        !           629:                $submap_done[$submap] = 1;
        !           630:            }
        !           631:        }
        !           632: 
        !           633:        print <<'EOF;';
        !           634: 
        !           635:   /* allocate and initialize the root map: */
        !           636:   root = tme_new(struct _tme_m68k_decoder_root, 1024);
        !           637:   ic->_tme_m68k_decoder_root = root;
        !           638:   root_entry = root;
        !           639:   for (entry_i = 0; entry_i < 1024; entry_i++) {
        !           640:       root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand0 = NULL;
        !           641:       root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand1 = NULL;
        !           642:       root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_eax_size = TME_M68K_SIZE_UNDEF;
        !           643:       root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_operand = TME_M68K_OPNUM_UNDEF;
        !           644:       root_entry++;
        !           645:   }
        !           646:   root_entry = root;
        !           647: EOF;
        !           648: 
        !           649:        print "\n";
        !           650:        print "  /* fill the root map: */\n";
        !           651:        for ($root = 0; $root < 1024; $root++) {
        !           652:            print "\n  /* root $root (base opcode ".sprintf("0x%04x", ($root << 6))."): */\n";
        !           653:     
        !           654:            # emit op0:
        !           655:            $op0 = &operand_final($root_op0[$root]);
        !           656:            print "  root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand0 = $op0;\n"
        !           657:                if (defined($op0));
        !           658:            
        !           659:            # emit op1:
        !           660:            $op1 = &operand_final($root_op1[$root]);
        !           661:            print "  root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand1 = $op1;\n"
        !           662:                if (defined($op1));
        !           663:            
        !           664:            # emit eax_size:
        !           665:            $eax_size = $root_eax_size[$root];
        !           666:            print "  root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_eax_size = TME_M68K_SIZE_$eax_size;\n"
        !           667:                if ($eax_size ne "U");
        !           668:            
        !           669:            # emit imm_size and imm_operand:
        !           670:            $imm_operand = $root_imm_operand[$root];
        !           671:            if ($imm_operand ne "U" && $imm_operand ne '\S+') {
        !           672:                $imm_size = $root_imm_size[$root];
        !           673:                $imm_size = "16U8" if ($imm_size eq "8");
        !           674:                print "  root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_operand = $imm_operand;\n";
        !           675:                print "  root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_size = TME_M68K_SIZE_$imm_size;\n";
        !           676:            }
        !           677:            
        !           678:            # emit the submap and opcode map:
        !           679:            print "  root_entry->_tme_m68k_decoder_root_submap = submap$root_submap[$root];\n";
        !           680:            print "  (root_entry++)->_tme_m68k_decoder_root_opcode_map = _tme_m68k_opcode_map$root_opcode_map[$root];\n";
        !           681:        }
        !           682: 
        !           683:        # close the function:
        !           684:        print "\n}\n";
        !           685:     }
        !           686: 
        !           687:     # anything else is an error:
        !           688:     else {
        !           689:        print STDERR "stdin:$line $PROG error: don't know how to handle: ".join(" ", @tokens)."\n";
        !           690:        exit(1);
        !           691:     }
        !           692: }
        !           693: 
        !           694: # done:
        !           695: exit(0);
        !           696: 
        !           697: # this subroutine returns the final C version of an operand:
        !           698: sub operand_final {
        !           699:     local ($op) = @_;
        !           700: 
        !           701:     if ($op eq "U" || $op eq '\S+') {
        !           702:        undef($op);
        !           703:     }
        !           704:     elsif ($op =~ /^\%([ad][0-7])\.(\d+)/) {
        !           705:        ($op, $op_size) = ($1, $2);
        !           706:        $op =~ tr/a-z/A-Z/;
        !           707:        if ($op_size == 16) {
        !           708:            $op .= " << 1";
        !           709:        }
        !           710:        elsif ($op_size == 8) {
        !           711:            $op .= " << 2";
        !           712:        }
        !           713:        $op = "&ic->tme_m68k_ireg_uint${op_size}(TME_M68K_IREG_${op})";
        !           714:     }
        !           715:     elsif ($op eq "eax.32") {
        !           716:        $op = "&ic->_tme_m68k_ea_address";
        !           717:     }
        !           718:     elsif ($op =~ /^imm(\d+)\.(\d+)/) {
        !           719:        $op = "(tme_uint${2}_t *) &_tme_m68k_imm${2}[${1}]";
        !           720:     }
        !           721:     elsif ($op =~ /^mem[xy]\.(\d+)/) {
        !           722:        $op = "&ic->tme_m68k_ireg_memx${1}";
        !           723:     }
        !           724:     else {
        !           725:        die "$PROG fatal: unknown operand $op\n";
        !           726:     }
        !           727:     $op;
        !           728: }      

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.