📄 tos-ramsize
字号:
($match, $reg1, my $sublo) = match_2args ($addr+$inc, "subi");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, my $subhi) = match_2args ($addr+$inc, "sbci");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "movw");
if ($match) {
$inc += 2;
}
($match, $reg1, $reg2) = match_2args ($addr+$inc, "add");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "adc");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "lpm");
return (0, \@targets, 0) if (!$match || $reg1 ne "r0" || $reg2 ne "Z+");
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "lpm");
return (0, \@targets, 0) if (!$match || $reg1 ne "r31" || $reg2 ne "Z");
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "mov");
return (0, \@targets, 0) if (!$match || $reg1 ne "r30" || $reg2 ne "r0");
$inc += 2;
if (match_0args ($addr+$inc, "ijmp")) {
$inc += 2;
push @targets, $oob_target;
if ($verbosity > 3) {
printf "found a jump table of size %d\n", hex($table_size);
}
for (my $i=0; $i<hex($table_size); $i++) {
my $index = 2*($i+65536-make16($sublo,$subhi));
my $l = $raw_text{$index};
my $h = $raw_text{$index+1};
my $targ = 2*make16($l,$h);
if ($verbosity > 3) {
printf " entry at %x pointing to %x (%s,%s)\n", $index, $targ, $l, $h;
}
# this is a strong sanity check-- if we've got something
# wrong it's highly unlikely that all jump table entries
# will point to actual instructions
die "tos-ramsize FAIL" if (!defined($insns{$targ}));
push @targets, $targ;
}
return (1, \@targets, $inc);
} else {
return (0, \@targets, 0);
}
}
# cpi r30, 0x1D ; 29
# cpc r31, r1
# brcs .+4 ; 0x39d2 <SchedulerBasicP__TaskBasic__runTask+0x38>
# jmp 0x547c ; 0x547c <SchedulerBasicP__TaskBasic__runTask+0x1ae2>
# subi r30, 0xBA ; 186
# sbci r31, 0xFF ; 255
# add r30, r30
# adc r31, r31
# lpm r0, Z+
# lpm r31, Z
# mov r30, r0
# ijmp
sub match_jump_table_2 ($) {
(my $addr) = @_;
my $match;
my $reg1;
my $reg2;
my $immed;
my $oob_target;
my @targets;
my $inc = 0;
($match, $reg1, my $table_size) = match_2args ($addr+$inc, "cpi");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "cpc");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $immed) = match_branch ($addr+$inc, "brcs");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $oob_target) = match_branch ($addr+$inc, "jmp");
return (0, \@targets, 0) if (!$match);
$inc += 4;
($match, $reg1, my $sublo) = match_2args ($addr+$inc, "subi");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, my $subhi) = match_2args ($addr+$inc, "sbci");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "movw");
if ($match) {
$inc += 2;
}
($match, $reg1, $reg2) = match_2args ($addr+$inc, "add");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "adc");
return (0, \@targets, 0) if (!$match);
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "lpm");
return (0, \@targets, 0) if (!$match || $reg1 ne "r0" || $reg2 ne "Z+");
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "lpm");
return (0, \@targets, 0) if (!$match || $reg1 ne "r31" || $reg2 ne "Z");
$inc += 2;
($match, $reg1, $reg2) = match_2args ($addr+$inc, "mov");
return (0, \@targets, 0) if (!$match || $reg1 ne "r30" || $reg2 ne "r0");
$inc += 2;
if (match_0args ($addr+$inc, "ijmp")) {
$inc += 2;
push @targets, $oob_target;
if ($verbosity > 3) {
printf "found a jump table of size %d\n", hex($table_size);
}
for (my $i=0; $i<hex($table_size); $i++) {
my $index = 2*($i+65536-make16($sublo,$subhi));
my $l = $raw_text{$index};
my $h = $raw_text{$index+1};
my $targ = 2*make16($l,$h);
if ($verbosity > 3) {
printf " entry at %x pointing to %x (%s,%s)\n", $index, $targ, $l, $h;
}
# this is a strong sanity check-- if we've got something
# wrong it's highly unlikely that all jump table entries
# will point to actual instructions
die "tos-ramsize FAIL" if (!defined($insns{$targ}));
push @targets, $targ;
}
return (1, \@targets, $inc);
} else {
return (0, \@targets, 0);
}
}
# in r28, 0x3d ; 61
# in r29, 0x3e ; 62
# subi r28, 0x9D ; 157
# sbci r29, 0x00 ; 0
# in r0, 0x3f ; 63
# cli
# out 0x3e, r29 ; 62
# out 0x3f, r0 ; 63
# out 0x3d, r28 ; 61
# in r28, 0x3d ; 61
# in r29, 0x3e ; 62
# sbiw r28, 0x14 ; 20
# in r0, 0x3f ; 63
# cli
# out 0x3e, r29 ; 62
# out 0x3f, r0 ; 63
# out 0x3d, r28 ; 61
sub match_constant_push_1 ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $dec;
my $inc = 0;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc +=2;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc +=2;
($match, $reg, $dec) = match_2args ($addr+$inc, "sbiw");
if ($match && $reg eq "r28") {
$dec = hex($dec);
$inc +=2;
} else {
($match, $reg, my $dec1) = match_2args ($addr+$inc, "subi");
return (0, 0) if (!$match || $reg ne "r28");
$inc +=2;
($match, $reg, my $dec2) = match_2args ($addr+$inc, "sbci");
return (0, 0) if (!$match || $reg ne "r29");
$inc +=2;
$dec = make16($dec1,$dec2);
}
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc +=2;
return (0, 0) if (!match_0args($addr+$inc, "cli"));
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc +=2;
return (1, $dec, $inc);
}
# in r28, 0x3d ; 61
# in r29, 0x3e ; 62
# sbiw r28, 0x05 ; 5
# out 0x3e, r29 ; 62
# out 0x3d, r28 ; 61
sub match_constant_push_2 ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $dec;
my $inc = 0;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc +=2;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc +=2;
($match, $reg, $dec) = match_2args ($addr+$inc, "sbiw");
return (0, 0) if (!$match || $reg ne "r28");
$inc +=2;
$dec = hex($dec);
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc +=2;
return (1, $dec, $inc);
}
# rcall .+0 ; 0x2792 <IPP__icmpv6_input+0x1e>
sub match_constant_push_3 ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $dec;
my $inc = 0;
($match, $reg, $immed) = match_0args ($addr+$inc, "rcall");
return (0, 0) if (!$match);
return (0, 0) if (get_target($addr) != $addr+$PC_SIZE{$platform});
$inc +=2;
return (1, $PC_SIZE{$platform}, $inc);
}
# adiw r28, 0x14 ; 20
# in r0, 0x3f ; 63
# cli
# out 0x3e, r29 ; 62
# out 0x3f, r0 ; 63
# out 0x3d, r28 ; 61
sub match_constant_pop_1 ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $dec;
my $inc = 0;
($match, $reg, $immed) = match_2args ($addr+$inc, "adiw");
return (0, 0, 0) if (!$match || $reg ne "r28");
$dec = -hex($immed);
$inc += 2;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc += 2;
return (0, 0, 0) if (!match_0args($addr+$inc, "cli"));
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc += 2;
return (1, $dec, $inc);
}
# adiw r28, 0x05 ; 5
# out 0x3e, r29 ; 62
# out 0x3d, r28 ; 61
sub match_constant_pop_2 ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $dec;
my $inc = 0;
($match, $reg, $immed) = match_2args ($addr+$inc, "adiw");
return (0, 0, 0) if (!$match || $reg ne "r28");
$dec = -hex($immed);
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc += 2;
return (1, $dec, $inc);
}
# in r28, 0x3d ; 61
# in r29, 0x3e ; 62
# subi r28, 0x9E ; 158
# sbci r29, 0xFF ; 255
# in r0, 0x3f ; 63
# cli
# out 0x3e, r29 ; 62
# out 0x3f, r0 ; 63
# out 0x3d, r28 ; 61
sub match_constant_stack_op ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $inc = 0;
($match, $reg, my $dec_lo) = match_2args ($addr+$inc, "subi");
return (0, 0, 0) if (!$match || $reg ne "r28");
$inc += 2;
($match, $reg, my $dec_hi) = match_2args ($addr+$inc, "sbci");
return (0, 0, 0) if (!$match || $reg ne "r29");
$inc += 2;
my $dec = make16($dec_lo,$dec_hi);
if ($dec > 32768) {
$dec = - (65536 - $dec);
}
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc += 2;
return (0, 0, 0) if (!match_0args($addr+$inc, "cli"));
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r29" || $immed ne "0x3e");
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc += 2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0, 0) if (!$match || $reg ne "r28" || $immed ne "0x3d");
$inc += 2;
return (1, $dec, $inc);
}
# in r24, 0x3d ; 61
# in r25, 0x3e ; 62
# adiw r24, 0x06 ; 6
# in r0, 0x3f ; 63
# cli
# out 0x3e, r25 ; 62
# out 0x3f, r0 ; 63
# out 0x3d, r24 ; 61
sub match_constant_pop_4 ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
my $stack_inc;
my $inc = 0;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r24" || $immed ne "0x3d");
$inc +=2;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r25" || $immed ne "0x3e");
$inc +=2;
($match, $reg, $stack_inc) = match_2args ($addr+$inc, "adiw");
return (0, 0) if (!$match || $reg ne "r24");
$stack_inc = -hex($stack_inc);
$inc +=2;
($match, $reg, $immed) = match_2args ($addr+$inc, "in");
return (0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc +=2;
return (0, 0) if (!match_0args($addr+$inc, "cli"));
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r25" || $immed ne "0x3e");
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r0" || $immed ne "0x3f");
$inc +=2;
($match, $immed, $reg) = match_2args ($addr+$inc, "out");
return (0, 0) if (!$match || $reg ne "r24" || $immed ne "0x3d");
$inc +=2;
return (1, $stack_inc, $inc);
}
# ldi r26, 0x00 ; 0
# ldi r27, 0x00 ; 0
# ldi r30, 0x97 ; 151
# ldi r31, 0x06 ; 6
# jmp 0x19dc ; 0x19dc <__prologue_saves__+0x4>
sub match_prologue_saves ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $immed;
($match, $reg, my $im_lo) = match_2args ($addr, "ldi");
return (0, 0, 0) if (!$match || $reg ne "r26");
($match, $reg, my $im_hi) = match_2args ($addr+2, "ldi");
return (0, 0, 0) if (!$match || $reg ne "r27");
($match, $reg, $immed) = match_2args ($addr+4, "ldi");
return (0, 0, 0) if (!$match || $reg ne "r30");
($match, $reg, $immed) = match_2args ($addr+6, "ldi");
return (0, 0, 0) if (!$match || $reg ne "r31");
($match, my $target) = match_branch ($addr+8, "jmp");
return (0, 0, 0) if (!$match);
my $ps = $label_to_addr{"__prologue_saves__"};
if (defined($ps) &&
$target >= $ps &&
$target <= ($ps+38)) {
# this is a little conservative since we may jump into the middle
my $st = 18+make16($im_lo, $im_hi);
return (1, $st, 12);
}
return (0, 0, 0);
}
# jmp 0x2598 ; 0x2598 <__epilogue_restores__+0x14>
sub match_epilogue_restores ($) {
(my $addr) = @_;
my $hex_addr = sprintf "%x", $addr;
my $match;
my $reg;
my $inc = 0;
($match, my $target) = match_branch ($addr+$inc, "jmp");
return (0,0) if (!$match);
my $er = $label_to_addr{"__epilogue_restores__"};
if (defined($er) &&
$target >= $er &&
$target <= ($er+38)) {
$addr += 4;
return (1, $ZERO_STACK, $inc);
} else {
return (0,0);
}
}
sub replace_insn ($$$$) {
(my $addr, my $size, my $se, my $name) = @_;
$insns{$addr} = $name;
$insn_size{$addr} = $size;
$stack_effect{$addr} = $se;
for (my $i=1; $i<$size; $i++) {
delete ($insns{$addr+$i});
}
}
sub make_macro_insns () {
foreach my $addr (keys %insns) {
my $res;
my $stack;
my $listref;
my $size;
# todo-- factor this into list of function
($res, $size, my $initial_depth) = match_init_sp($addr);
if ($res) {
if (defined($initial_stack_depth)) {
# FIXME: avr-gcc-412 initializes SP both in
# crt0 and in main(), we can believe the second one
#die "tos-ramsize FAIL: multiple initialization of SP?";
}
die "tos-ramsize FAIL" if ($initial_depth < 0 || $initial_depth >= $RAM_SIZE{$platform});
$initial_stack_depth = $initial_depth;
replace_insn ($addr, $size, 0, "init_sp");
}
($res, $listref, $size) = match_jump_table_1($addr);
if ($res) {
replace_insn ($addr, $size, 0, "jump_table");
$jump_lists{$addr} = $listref;
}
($res, $listref, $size) = match_jump_table_2($addr);
if ($res) {
replace_insn ($addr, $size, 0, "jump_table");
$jump_lists{$addr} = $listref;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -