mirror of
https://github.com/ctm/executor.git
synced 2024-09-26 14:55:54 +00:00
260 lines
7.2 KiB
Perl
260 lines
7.2 KiB
Perl
|
#!/usr/bin/perl
|
||
|
|
||
|
# $Id: makerawblt.pl,v 1.4 1995/10/29 23:49:06 mat Exp $
|
||
|
|
||
|
# This is how many times to unwrap the blitting loop
|
||
|
$max_unwrap_factor = 8;
|
||
|
|
||
|
print "/* This file is machine-generated; DO NOT EDIT! */\n\n";
|
||
|
|
||
|
print ("\#define JUMP_TO_NEXT \\\n" .
|
||
|
"do \{ \\\n" .
|
||
|
" const void *next = s\[1\].label; \\\n" .
|
||
|
" NEXT_ROW; \\\n" .
|
||
|
" arg = s\[1\].arg; \\\n" .
|
||
|
" s = (const blt_section_t *) ((const uint8 *) s + sec_size); \\\n" .
|
||
|
" goto *next; \\\n" .
|
||
|
"} while (0)\n" .
|
||
|
"\n" .
|
||
|
"/* Maximum number of times we'll unwrap any blitter loops. */\n" .
|
||
|
"\#define MAX_LOOP_UNWRAP $max_unwrap_factor" . "U\n" .
|
||
|
"\#define REPEAT_MOD_0_STUB 0U\n" .
|
||
|
"\#define MASK_STUB (REPEAT_MOD_0_STUB + MAX_LOOP_UNWRAP)\n" .
|
||
|
"\#define DONE_STUB (MASK_STUB + 1)\n" .
|
||
|
"\#define FUNC_PTR (DONE_STUB + 1)\n");
|
||
|
|
||
|
$func_number = 0;
|
||
|
$func_empty = 1;
|
||
|
|
||
|
while (length ($line = &next_line)) {
|
||
|
@cmd = split (/\s+/, $line);
|
||
|
if ($cmd[0] eq 'begin_pat_func' || $cmd[0] eq 'begin_src_func') {
|
||
|
&output_func;
|
||
|
&reset_func;
|
||
|
|
||
|
$patblt = ($cmd[0] eq 'begin_pat_func');
|
||
|
$prefix = $patblt ? "xdblt" : "srcblt";
|
||
|
|
||
|
$init = "";
|
||
|
$inloop = "";
|
||
|
while (length ($line = &next_line) && $line ne 'end_func') {
|
||
|
@cmd = split (/\s+/, $line);
|
||
|
($rest) = ($line =~ /^\s*\w+\s+(.*)/);
|
||
|
$rest .= "\n";
|
||
|
if ($cmd[0] eq 'init') {
|
||
|
$init .= $rest;
|
||
|
} elsif ($cmd[0] eq 'inloop') {
|
||
|
$inloop .= $rest;
|
||
|
} else {
|
||
|
die "Unknown func command $cmd[0] on line $lineno.\n";
|
||
|
}
|
||
|
}
|
||
|
} elsif ($cmd[0] eq 'begin_mode') {
|
||
|
$mode_name = $cmd[1];
|
||
|
|
||
|
$unwrap_factor = $cmd[2];
|
||
|
if ($unwrap_factor eq 'max_unwrap') {
|
||
|
$unwrap_factor = $max_unwrap_factor;
|
||
|
} elsif ($unwrap_factor < 1
|
||
|
|| $unwrap_factor > $max_unwrap_factor
|
||
|
|| $max_unwrap_factor % $unwrap_factor) {
|
||
|
die "Illegal unwrap factor on line $lineno.\n";
|
||
|
}
|
||
|
|
||
|
if ($unwrap_factor != $max_unwrap_factor) {
|
||
|
die ("unwrap factor must equal max_unwrap for now...the problem " .
|
||
|
"is with how much to offset dst by for the initial cruft..." .
|
||
|
"it would vary with the unwrap factor.\n");
|
||
|
}
|
||
|
|
||
|
$repeat = "";
|
||
|
$mask = "";
|
||
|
|
||
|
while (length ($line = &next_line) && $line ne 'end_mode') {
|
||
|
@cmd = split (/\s+/, $line);
|
||
|
($rest) = ($line =~ /^\s*\w+\s+(.*)/);
|
||
|
$rest .= "\n";
|
||
|
if ($cmd[0] eq 'repeat') {
|
||
|
$repeat .= $rest;
|
||
|
} elsif ($cmd[0] eq 'mask') {
|
||
|
$mask .= $rest;
|
||
|
} else {
|
||
|
die "Unknown mode command $cmd[0] on line $lineno.\n";
|
||
|
}
|
||
|
}
|
||
|
&process_mode ($mode_name, $repeat, $mask);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Handle any leftovers
|
||
|
&output_func;
|
||
|
|
||
|
|
||
|
sub output_func {
|
||
|
return if ($func_empty);
|
||
|
|
||
|
print ("\n" .
|
||
|
"\n" .
|
||
|
"extern const void \*$label_array_name\[$label_array_index\] " .
|
||
|
"asm (\"_$label_array_name\");\n" .
|
||
|
"\n" .
|
||
|
"const void * const *\n" .
|
||
|
"$prefix" . "_func_$func_number (const blt_section_t *section,\n");
|
||
|
|
||
|
if ($patblt) {
|
||
|
print "uint8 *row_base, long num_rows, long y)\n";
|
||
|
} else {
|
||
|
print ("const uint8 *src_row_base, uint8 *dst_row_base, " .
|
||
|
"long num_rows)\n");
|
||
|
}
|
||
|
|
||
|
print ("\{\n" .
|
||
|
$label_arrays .
|
||
|
"\};\n" .
|
||
|
"\#if defined (mc68000)\n" .
|
||
|
"/* Convince gcc to use one register addl, not two addqw's */\n" .
|
||
|
"register uint32 sec_size = sizeof (section[0]);\n" .
|
||
|
"\#elif !defined (sec_size)\n" .
|
||
|
"#define sec_size (sizeof (section[0]))\n" .
|
||
|
"\#endif\n" .
|
||
|
$init .
|
||
|
" do \{\n" .
|
||
|
$inloop .
|
||
|
" const blt_section_t *s = section;\n" .
|
||
|
" int32 arg = s->arg;\n");
|
||
|
|
||
|
if ($patblt) {
|
||
|
print "uint32 *dst = (uint32 *) \&row_base\[s->offset\];\n";
|
||
|
} else {
|
||
|
print ("const uint32 *src = (const uint32 *) " .
|
||
|
"\&src_row_base\[s->offset\];\n" .
|
||
|
"uint32 *dst = (uint32 *) " .
|
||
|
"\&dst_row_base\[s->offset\];\n");
|
||
|
}
|
||
|
|
||
|
print (" goto *(s->label);\n" .
|
||
|
"\n" .
|
||
|
"$code" .
|
||
|
" done:\n");
|
||
|
|
||
|
if ($patblt) {
|
||
|
print " row_base += $prefix" . "_dst_row_bytes;\n";
|
||
|
} else {
|
||
|
print " src_row_base += $prefix" . "_src_row_stride;\n";
|
||
|
print " dst_row_base += $prefix" . "_dst_row_stride;\n";
|
||
|
}
|
||
|
|
||
|
print (" \} while (--num_rows > 0);\n" .
|
||
|
" return labels; /* Let gcc know labels are used. */\n" .
|
||
|
"\}\n");
|
||
|
|
||
|
++$func_number;
|
||
|
}
|
||
|
|
||
|
sub reset_func {
|
||
|
$code = "";
|
||
|
$label_array_name = "$prefix" . "_func_$func_number" . "_labels";
|
||
|
$label_arrays = ("static const void *labels\[\] " .
|
||
|
"asm (\"_$label_array_name\") = \{\n");
|
||
|
$label_array_index = 0;
|
||
|
$func_empty = 1;
|
||
|
|
||
|
undef %mask_labels_seen;
|
||
|
undef %repeat_labels_seen;
|
||
|
}
|
||
|
|
||
|
|
||
|
sub process_mode {
|
||
|
local ($tag, $repeat, $mask) = @_;
|
||
|
local ($l);
|
||
|
|
||
|
if (defined ($mask_labels_seen{$mask})) {
|
||
|
$mask_label = $mask_labels_seen{$mask};
|
||
|
} else {
|
||
|
$mask_label = "$tag" . "_mask";
|
||
|
$mask_labels_seen{$mask} = $mask_label;
|
||
|
($new = $mask) =~ s/\@dst\@/\*dst/g;
|
||
|
$new =~ s/\@src\@/\*src/g;
|
||
|
$new =~ s/\@src_plus_1\@/src\[1\]/g;
|
||
|
$code .= ("$mask_label:\n" .
|
||
|
"$new" .
|
||
|
"JUMP_TO_NEXT;\n");
|
||
|
}
|
||
|
|
||
|
if (defined ($repeat_labels_seen{$repeat})) {
|
||
|
$repeat_label = $repeat_labels_seen{$repeat};
|
||
|
} else {
|
||
|
$repeat_label = $tag . "_many";
|
||
|
$repeat_labels_seen{$repeat} = $repeat_label;
|
||
|
|
||
|
$loop = (" $repeat_label" . "_loop:\n" .
|
||
|
"\#if !defined (i386)\n");
|
||
|
if (!$patblt) {
|
||
|
$loop .= "src += $unwrap_factor;\n";
|
||
|
}
|
||
|
$loop .= (" dst += $unwrap_factor;\n" .
|
||
|
"\#endif\n");
|
||
|
|
||
|
for ($i = 0; $i < $unwrap_factor; $i++) {
|
||
|
$loop .= "$repeat_label" . "_" . ($max_unwrap_factor - $i) . ":\n";
|
||
|
($new = $repeat) =~ s/\@dst\@/dst\[$i\]/g;
|
||
|
$new =~ s/\@src\@/src\[$i\]/g;
|
||
|
$p1 = $i + 1;
|
||
|
$new =~ s/\@src_plus_1\@/src\[$p1\]/g;
|
||
|
|
||
|
$loop .= " $new";
|
||
|
}
|
||
|
|
||
|
$loop .= "\#if defined (i386)\n";
|
||
|
if (!$patblt) {
|
||
|
$loop .= "src += $unwrap_factor; /* Avoids AGI stall here. */\n";
|
||
|
}
|
||
|
$loop .= (" dst += $unwrap_factor; /* Avoids AGI stall here. */\n" .
|
||
|
"\#endif\n" .
|
||
|
" if ((arg -= $unwrap_factor) > 0)\n" .
|
||
|
" goto $repeat_label" . "_loop;\n" .
|
||
|
" JUMP_TO_NEXT;\n");
|
||
|
|
||
|
$code .= $loop;
|
||
|
}
|
||
|
|
||
|
$this_label_array = "";
|
||
|
for ($i = 0; $i < $max_unwrap_factor; $i++) {
|
||
|
$this_label_array .= ("\&\&$repeat_label" . "_" .
|
||
|
((($i - 1) & ($unwrap_factor - 1)) + 1) . ",\n");
|
||
|
}
|
||
|
|
||
|
$this_label_array .= " \&\&$mask_label,\n";
|
||
|
$this_label_array .= " \&\&done,\n";
|
||
|
$this_label_array .= " $prefix" . "_func_$func_number,\n";
|
||
|
|
||
|
if (defined ($label_arrays_seen{$this_label_array})) {
|
||
|
$index = $label_arrays_seen{$this_label_array};
|
||
|
} else {
|
||
|
$index = $label_array_index;
|
||
|
$label_arrays_seen{$this_label_array} = $index;
|
||
|
$label_array_index += $max_unwrap_factor + 3;
|
||
|
$label_arrays .= $this_label_array;
|
||
|
}
|
||
|
|
||
|
$label_arrays .= ("\#define $prefix" . "_$tag" . "_labels " .
|
||
|
"(\&$label_array_name\[$index\])\n");
|
||
|
$func_empty = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
# Returns the next non-empty line after stripping out comments, or the
|
||
|
# empty string if there are no more lines.
|
||
|
sub next_line {
|
||
|
local ($line);
|
||
|
while (<>) {
|
||
|
++$lineno;
|
||
|
($line) = /(^[^\#]*)/; # We begin comments with '#' characters
|
||
|
$line =~ s/\s+$//; # Strip trailing whitespace
|
||
|
$line =~ s/^\s+//; # Strip leading whitespace
|
||
|
return $line if (length ($line));
|
||
|
}
|
||
|
|
||
|
"";
|
||
|
}
|