|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.