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