Annotation of tme/ic/m68k/m68k-opmap-make.pl, revision 1.1.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.