📄 gen_insn_test.pl
字号:
#!/usr/bin/perluse 5.006;use strict;use warnings;our %ArgTypes = ( r8 => "reg8_t", r16 => "reg16_t", r32 => "reg32_t", mm => "reg64_t", xmm => "reg128_t", m8 => "reg8_t", m16 => "reg16_t", m32 => "reg32_t", m64 => "reg64_t", m128 => "reg128_t", eflags => "reg32_t", st => "reg64_t", fpucw => "reg16_t", fpusw => "reg16_t" );our %SubTypeFormats = ( sb => "%d", ub => "%u", sw => "%d", uw => "%u", sd => "%ld", ud => "%lu", sq => "%lld", uq => "%llu", ps => "%.16g", pd => "%.16g" );our %SubTypeSuffixes = ( sb => "", ub => "U", sw => "", uw => "", sd => "L", ud => "UL", sq => "LL", uq => "ULL", ps => "F", pd => "" );our %RegNums = ( al => 0, ax => 0, eax => 0, bl => 1, bx => 1, ebx => 1, cl => 2, cx => 2, ecx => 2, dl => 3, dx => 3, edx => 3, ah => 4, bh => 5, ch => 6, dh => 7, st0 => 0, st1 => 1, st2 => 2, st3 => 3, st4 => 4, st5 => 5, st6 => 6, st7 => 7 );our %RegTypes = ( al => "r8", ah => "r8", ax => "r16", eax => "r32", bl => "r8", bh => "r8", bx => "r16", ebx => "r32", cl => "r8", ch => "r8", cx => "r16", ecx => "r32", dl => "r8", dh => "r8", dx => "r16", edx => "r32" );our @IntRegs = ( { r8 => "al", r16 => "ax", r32 => "eax" }, { r8 => "bl", r16 => "bx", r32 => "ebx" }, { r8 => "cl", r16 => "cx", r32 => "ecx" }, { r8 => "dl", r16 => "dx", r32 => "edx" }, { r8 => "ah" }, { r8 => "bh" }, { r8 => "ch" }, { r8 => "dh" } );print <<EOF;#include <math.h>#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>typedef union { char sb[1]; unsigned char ub[1];} reg8_t;typedef union { char sb[2]; unsigned char ub[2]; short sw[1]; unsigned short uw[1];} reg16_t;typedef union { char sb[4]; unsigned char ub[4]; short sw[2]; unsigned short uw[2]; long int sd[1]; unsigned long int ud[1]; float ps[1];} reg32_t;typedef union { char sb[8]; unsigned char ub[8]; short sw[4]; unsigned short uw[4]; long int sd[2]; unsigned long int ud[2]; long long int sq[1]; unsigned long long int uq[1]; float ps[2]; double pd[1];} reg64_t __attribute__ ((aligned (8)));typedef union { char sb[16]; unsigned char ub[16]; short sw[8]; unsigned short uw[8]; long int sd[4]; unsigned long int ud[4]; long long int sq[2]; unsigned long long int uq[2]; float ps[4]; double pd[2];} reg128_t __attribute__ ((aligned (16)));static sigjmp_buf catchpoint;static void handle_sigill(int signum){ siglongjmp(catchpoint, 1);}__attribute__((unused))static int eq_float(float f1, float f2){ return f1 == f2 || fabsf(f1 - f2) < fabsf(f1) * 1.5 * pow(2,-12);}__attribute__((unused))static int eq_double(double d1, double d2){ return d1 == d2 || fabs(d1 - d2) < fabs(d1) * 1.5 * pow(2,-12);}EOFmy %tests;my @tests;while (<>){ next if /^#/; my $insn; my $presets; my $args; my $results; if (/^(\S+)\s+(?:(\S+(?:\s+\S+)*)\s+:\s+)?((?:\S+\s+)*?)(?:=>\s+(\S+(?:\s+\S+)*))?$/) { $insn = $1; $presets = $2 || ""; $args = $3 || ""; $results = $4 || "";# print STDERR "insn: $insn\n";# print STDERR "presets: $presets\n";# print STDERR "args: $args\n";# print STDERR "results: $results\n"; } else { die "Can't parse test $_"; } $tests{$insn}++; my $test = "${insn}_$tests{$insn}"; push @tests, $test; print qq|static void $test(void)\n|; print qq|\{\n|; my @intregs = @IntRegs; my @mmregs = map { "mm$_" } (6,7,0,1,2,3,4,5); my @xmmregs = map { "xmm$_" } (4,5,0,1,2,3,6,7); my @fpregs = map { "st$_" } (0 .. 7); my @presets; my $presetc = 0; my $eflagsmask; my $eflagsset; my $fpucwmask; my $fpucwset; my $fpuswmask; my $fpuswset; foreach my $preset (split(/\s+/, $presets)) { if ($preset =~ /^([abcd][lh]|[abcd]x|e[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/) { my $name = "preset$presetc"; my $type = $RegTypes{$1}; my $regnum = $RegNums{$1}; my $register = $intregs[$regnum]; my $subtype = $2; my @values = split(/,/, $3); die "Register $1 already used" unless defined($register); my $preset = { name => $name, type => $type, subtype => $subtype, register => $register }; delete($intregs[$regnum]); push @presets, $preset; print qq| $ArgTypes{$type} $name = \{ .$subtype = \{|; my $valuec = 0; foreach my $value (@values) { print qq|,| if $valuec > 0; print qq| $value$SubTypeSuffixes{$subtype}|; $valuec++; } print qq| \} \};\n|; $presetc++; } elsif ($preset =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/) { my $name = "preset$presetc"; my $type = "st"; my $regnum = $1; my $register = $fpregs[$regnum]; my $subtype = $2; my @values = split(/,/, $3); die "Register st$1 already used" unless defined($register); my $preset = { name => $name, type => $type, subtype => $subtype, register => $register }; delete($fpregs[$regnum]); push @presets, $preset; print qq| $ArgTypes{$type} $name = \{ .$subtype = \{|; my $valuec = 0; foreach my $value (@values) { print qq|,| if $valuec > 0; print qq| $value$SubTypeSuffixes{$subtype}|; $valuec++; } print qq| \} \};\n|; $presetc++; } elsif ($preset =~ /^(eflags)\[([^\]]+)\]$/) { my $type = $1; my @values = split(/,/, $2); $values[0] = oct($values[0]) if $values[0] =~ /^0/; $values[1] = oct($values[1]) if $values[1] =~ /^0/; $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff; $eflagsset = sprintf "0x%08x", $values[1]; } elsif ($preset =~ /^(fpucw)\[([^\]]+)\]$/) { my $type = $1; my @values = split(/,/, $2); $values[0] = oct($values[0]) if $values[0] =~ /^0/; $values[1] = oct($values[1]) if $values[1] =~ /^0/; $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff; $fpucwset = sprintf "0x%04x", $values[1]; } elsif ($preset =~ /^(fpusw)\[([^\]]+)\]$/) { my $type = $1; my @values = split(/,/, $2); $values[0] = oct($values[0]) if $values[0] =~ /^0/; $values[1] = oct($values[1]) if $values[1] =~ /^0/; $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff; $fpuswset = sprintf "0x%04x", $values[1]; } else { die "Can't parse preset $preset"; } } my @args; my $argc = 0; foreach my $arg (split(/\s+/, $args)) { my $name = "arg$argc"; if ($arg =~ /^([abcd]l|[abcd]x|e[abcd]x|r8|r16|r32|mm|xmm|m8|m16|m32|m64|m128)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/) { my $type = $RegTypes{$1} || $1; my $regnum = $RegNums{$1}; my $register = $intregs[$regnum] if defined($regnum); my $subtype = $2; my @values = split(/,/, $3); die "Register $1 already used" if defined($regnum) && !defined($register); my $arg = { name => $name, type => $type, subtype => $subtype }; if (defined($register)) { $arg->{register} = $register; delete($intregs[$regnum]); } push @args, $arg; print qq| $ArgTypes{$type} $name = \{ .$subtype = \{|; my $valuec = 0; foreach my $value (@values) { print qq|,| if $valuec > 0; print qq| $value$SubTypeSuffixes{$subtype}|; $valuec++; } print qq| \} \};\n|; } elsif ($arg =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/) { my $type = "st"; my $regnum = $1; my $register = $fpregs[$regnum] if defined($regnum); my $subtype = $2; my @values = split(/,/, $3); die "Register st$1 already used" if defined($regnum) && !defined($register); my $arg = { name => $name, type => $type, subtype => $subtype }; if (defined($register)) { $arg->{register} = $register; delete($fpregs[$regnum]); } push @args, $arg; print qq| $ArgTypes{$type} $name = \{ .$subtype = \{|; my $valuec = 0; foreach my $value (@values) { print qq|,| if $valuec > 0; print qq| $value$SubTypeSuffixes{$subtype}|; $valuec++; } print qq| \} \};\n|; } elsif ($arg =~ /^(imm8|imm16|imm32)\[([^\]]+)\]$/) { my $type = $1; my $value = $2; my $arg = { type => $type, value => $value }; push @args, $arg; } else { die "Can't parse argument $arg"; } $argc++; } foreach my $arg (@presets, @args) { if ($arg->{type} =~ /^(r8|r16|r32|m8|m16|m32)$/) { while (!exists($arg->{register}) || !defined($arg->{register})) { $arg->{register} = shift @intregs; } $arg->{register} = $arg->{register}->{$arg->{type}}; } elsif ($arg->{type} =~ /^(mm|m64)$/) { $arg->{register} = shift @mmregs; } elsif ($arg->{type} =~ /^(xmm|m128)$/) { $arg->{register} = shift @xmmregs; } elsif ($arg->{type} =~ /^st$/) { while (!exists($arg->{register}) || !defined($arg->{register})) { $arg->{register} = shift @fpregs; } } } my @results; my $resultc = 0; foreach my $result (split(/\s+/, $results)) { my $name = "result$resultc"; if ($result =~ /^(\d+)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/) { my $index = $1; my $type = $args[$index]->{type}; my $subtype = $2; my @values = split(/,/, $3); die "Argument $index not specified" unless exists($args[$index]); my $result = { name => $name, type => $type, subtype => $subtype, arg => $args[$index], register => $args[$index]->{register}, values => [ @values ] }; push @results, $result; print qq| $ArgTypes{$type} $name|; print qq| = arg$index| if $type =~ /^m(8|16|32|64|128)$/; print qq|;\n|; $args[$index]->{result} = $result; } elsif ($result =~ /^([abcd][lh]|[abcd]x|e[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/) { my $register = $1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -