On Mon, 2001-09-10 at 19:54, Dan Sugalski wrote:
> At 07:45 PM 9/10/2001 -0500, Brian Wheeler wrote:
> >If eq_i_ic is really treated as /eq(_i)+_ic/ then this code still
> >doesn't work:
> >
> >eq_i_ic I1,I2,NEXT,DONE
> >
> >because that'd be like eq_i_i_ic_ic, right?
>
> Right. But don't forget, I screwed up the eq op--it ought to have a single
> destination. :)
>
DOH! That's the trick :)
> >I assume that opcodes aren't going to have variable arguments at this level,
> >so there should be a one-to-one mapping between function and opcode, right?
>
> Each opcode number has a single function, yes. The same "high-level"
> opcode, for example eq or add, might map to two or more different 'real'
> opcodes based on the types of the args. There won't be any runtime
> morphing--it's more "The assembler sees the first arg of foo as a numberic
> register and the second as a constant, so it must be foo_n_nc".
>
> >A thought (though gross): if we restrict mneumonics to not use the
> >underscore,
> >then anything after _ can be the op signature.
>
> Too gross. We don't need to go there. :)
>
Just checking.
> >Also, doing it this way takes out the special cases for the comparison and
> >jump ops: the fixups are known to be done with things that have type 'a'
>
> The jump ops will be easy to figure--either they'll take a register, a
> constant number, or a label. We don't allow labels that could be confused
> with registers. (No I0: anywhere...)
>
>
I've had more thoughts about my first patch. The case issue isn't an
issue since it only touches the generation tools, not the C code that's
generated (at least, not directly).
It also provides the additional information needed to let the assembler
choose the correct opcode, and the disassembler to dump things nicely :)
I've also fixed up the supporting tools. As a test case, I rebuilt
test_prog, assembled test.parm, ran it and dissassembled it. Looks for
for that one, at least :)
Please consider this new patch.
Brian
Index: assemble.pl
===================================================================
RCS file: /home/perlcvs/parrot/assemble.pl,v
retrieving revision 1.6
diff -u -r1.6 assemble.pl
--- assemble.pl 2001/09/10 21:26:08 1.6
+++ assemble.pl 2001/09/11 02:02:15
@@ -9,7 +9,16 @@
my %pack_type;
%pack_type = (i => 'l',
n => 'd',
- );
+ );
+
+my %real_type=('i'=>'i',
+ 'n'=>'n',
+ 'N'=>'i',
+ 'I'=>'i',
+ 'S'=>'i',
+ 's'=>'i',
+ 'D'=>'i');
+
my $sizeof_packi = length(pack($pack_type{i},1024));
open GUTS, "interp_guts.h";
@@ -26,8 +35,11 @@
s/^\s+//;
next unless $_;
my ($name, $args, @types) = split /\s+/, $_;
+ my @rtypes=@types;
+ @types=map { $_ = $real_type{$_}} @types;
$opcodes{$name}{ARGS} = $args;
$opcodes{$name}{TYPES} = [@types];
+ $opcodes{$name}{RTYPES}=[@rtypes];
}
my $pc = 0;
@@ -65,23 +77,17 @@
die "wrong arg count--got ". scalar @args. " needed " .
$opcodes{$opcode}{ARGS};
}
- $args[0] = fixup($args[0])
- if $opcode eq "branch_ic" and $args[0] =~ /[a-zA-Z]/;
-
-# if ($opcode eq "eq_i_ic" or $opcode eq "lt_i_ic") {
- if ($opcode =~ /^(eq|ne|lt|le|gt|ge)_i_ic$/) {
- $args[2] = fixup($args[2]) if $args[2] =~ /[a-zA-Z]/;
- $args[3] = fixup($args[3]) if $args[3] =~ /[a-zA-Z]/;
- }
- if ($opcode eq "if_i_ic") {
- $args[1] = fixup($args[1]) if $args[1] =~ /[a-zA-Z]/;
- $args[2] = fixup($args[2]) if $args[2] =~ /[a-zA-Z]/;
- }
-
print pack "l", $opcodes{$opcode}{CODE};
foreach (0..$#args) {
- $args[$_] =~ s/^[INPS]?(\d+)$/$1/i;
- my $type = $pack_type{$opcodes{$opcode}{TYPES}[$_]};
+ my($rtype)=$opcodes{$opcode}{RTYPES}[$_];
+ my($type)=$opcodes{$opcode}{TYPES}[$_];
+ if($rtype eq "I" || $rtype eq "N" || $rtype eq "P" || $rtype eq "S") {
+ # its a register argument
+ $args[$_]=~s/^[INPS](\d+)$/$1/i;
+ } elsif($rtype eq "D") {
+ # a destination
+ $args[$_]=fixup($args[$_]);
+ }
print pack $type, $args[$_];
}
$pc += 1+@args;
Index: disassemble.pl
===================================================================
RCS file: /home/perlcvs/parrot/disassemble.pl,v
retrieving revision 1.3
diff -u -r1.3 disassemble.pl
--- disassemble.pl 2001/09/10 21:45:33 1.3
+++ disassemble.pl 2001/09/11 02:02:16
@@ -8,14 +8,25 @@
my(%opcodes, @opcodes);
-my %unpack_type;
-%unpack_type = (i => 'l',
- n => 'd',
- );
+
+my %unpack_type = (i => 'l',
+ I => 'l',
+ n => 'd',
+ N => 'l',
+ D => 'l',
+ S => 'l',
+ s => 'l',
+ );
my %unpack_size = (i => 4,
n => 8,
+ I => 4,
+ N => 4,
+ D => 4,
+ S => 4,
+ s => 4,
);
+
open GUTS, "interp_guts.h";
my $opcode;
while (<GUTS>) {
@@ -51,15 +62,29 @@
my $constants = unpack('l', <>);
# Skip for now
+my $offset=0;
while (<>) {
my $code = unpack 'l', $_;
my $args = $opcodes[$code]{ARGS};
- print $opcodes[$code]{NAME};
+ my $op_offset=$offset;
+ print sprintf("%08x ",$offset),$opcodes[$code]{NAME};
+ $offset+=4;
if ($args) {
foreach (1..$args) {
- local $/ = \$unpack_size{$opcodes[$code]{TYPES}[$_-1]};
+ my $type=$opcodes[$code]{TYPES}[$_-1];
+ local $/ = \$unpack_size{$type};
+ $offset+=$unpack_size{$type};
my $data = <> || die("EOF when expecting argument!\n");
- print " ", unpack $unpack_type{$opcodes[$code]{TYPES}[$_-1]},
$data;+ if($type eq "I" || $type eq "N" || $type eq "P" || $type eq
"S") {
+ # register
+ print " ",$type,unpack($unpack_type{$type},$data);
+ } elsif($type eq "D") {
+ # destination address
+ print "
",sprintf("%08x",$op_offset+unpack($unpack_type{$type},$data)*4);
+ } else {
+ # constant
+ print " ", unpack $unpack_type{$type}, $data;
+ }
}
}
print "\n";
Index: opcode_table
===================================================================
RCS file: /home/perlcvs/parrot/opcode_table,v
retrieving revision 1.6
diff -u -r1.6 opcode_table
--- opcode_table 2001/09/10 21:26:09 1.6
+++ opcode_table 2001/09/11 02:02:16
@@ -11,70 +11,80 @@
# not the type of the register or anything. So N3 is still an i, since
that
# 3 specifying the register should be packed as an integer.
+# Revised arg types:
+# i Integer constant
+# I Integer register
+# n Numeric constant
+# N Numeric register
+# s String constant?
+# S String register
+# D Destination
+
+
# This must be opcode zero
end 0
# Integer ops
-set_i_ic 2 i i
-set_i 2 i i
-add_i 3 i i i
-sub_i 3 i i i
-mul_i 3 i i i
-div_i 3 i i i
-inc_i 1 i
-inc_i_ic 2 i i
-dec_i 1 i
-dec_i_ic 2 i i
+set_i_ic 2 I i
+set_i 2 I I
+add_i 3 I I I
+sub_i 3 I I I
+mul_i 3 I I I
+div_i 3 I I I
+inc_i 1 I
+inc_i_ic 2 I i
+dec_i 1 I
+dec_i_ic 2 I i
# NUM ops
-set_n_nc 2 i n
-add_n 3 i i i
-sub_n 3 i i i
-mul_n 3 i i i
-div_n 3 i i i
-inc_n 1 i
-inc_n_nc 2 i n
-dec_n 1 i
-dec_n_nc 2 i n
+set_n_nc 2 N n
+add_n 3 N N N
+sub_n 3 N N N
+mul_n 3 N N N
+div_n 3 N N N
+inc_n 1 N
+inc_n_nc 2 N n
+dec_n 1 N
+dec_n_nc 2 N n
# String ops
-set_s_sc 2 i i
-print_s 1 i
-length_s_i 2 i i
-chopn_s_ic 2 i i
+set_s_sc 2 S s
+print_s 1 S
+length_s_i 2 S I
+chopn_s_ic 2 S i
# Comparators
-eq_i_ic 4 i i i i
-eq_n_ic 4 i i i i
-ne_i_ic 4 i i i i
-lt_i_ic 4 i i i i
-le_i_ic 4 i i i i
-gt_i_ic 4 i i i i
-ge_i_ic 4 i i i i
+eq_i_ic 4 I I D D
+eq_n_ic 4 N N D D
+ne_i_ic 4 I I D D
+lt_i_ic 4 I I D D
+le_i_ic 4 I I D D
+gt_i_ic 4 I I D D
+ge_i_ic 4 I I D D
# Flow control
-jump_i 1 i
-branch_ic 1 i
-if_i_ic 3 i i i
-if_n_ic 3 i i i
+jump_i 1 D
+branch_ic 1 D
+if_i_ic 3 I D D
+if_n_ic 3 N D D
# Convertors
-iton_n_i 2 i i
-ntoi_i_n 2 i i
+iton_n_i 2 N I
+ntoi_i_n 2 I N
# Miscellaneous and debugging ops
-time_i 1 i
-print_i 1 i
-time_n 1 i
-print_n 1 i
+time_i 1 I
+print_i 1 I
+time_n 1 N
+print_n 1 N
noop 0
# Register ops
Index: process_opfunc.pl
===================================================================
RCS file: /home/perlcvs/parrot/process_opfunc.pl,v
retrieving revision 1.3
diff -u -r1.3 process_opfunc.pl
--- process_opfunc.pl 2001/09/10 21:26:09 1.3
+++ process_opfunc.pl 2001/09/11 02:02:16
@@ -40,6 +40,17 @@
$opcode{$2}{OPNUM} = $1;
}
+
+my %psize = (i => 1,
+ n => 2,
+ I => 1,
+ N => 1,
+ D => 1,
+ S => 1,
+ s => 1,
+ );
+
+
open OPCODE, "opcode_table" or die "Can't open opcode_table, $!/$^E";
while (<OPCODE>) {
s/#.*//;
@@ -49,10 +60,13 @@
my ($name, $params, @params) = split /\s+/;
$opcode{$name}{PARAM_COUNT} = $params;
$opcode{$name}{PARAM_ARRAY} = \@params;
+
+ my $psize=0;
+ foreach (@params) {
+ $psize+=$psize{$_};
+ }
- my $num_i = () = grep {/i/} @params;
- my $num_n = () = grep {/n/} @params;
- $opcode{$name}{RETURN_OFFSET} = 1 + $num_i + $num_n * 2;
+ $opcode{$name}{RETURN_OFFSET} = 1 + $psize;
my $count = 1;
$opcode{$name}{PARAMETER_SUB} = ["",
map {if ($_ eq "n") {