|
|
|
#!/usr/bin/env perl
|
|
|
|
|
|
|
|
open FILE, "input.bin" or die $!;
|
|
|
|
|
|
|
|
binmode FILE;
|
|
|
|
|
|
|
|
$bytecount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
# Addressing modes
|
|
|
|
#
|
|
|
|
# 0) (nothing)
|
|
|
|
# 1) immediate value (#imm) [4,8,16,32]
|
|
|
|
# 2) compressed direct address (dir)
|
|
|
|
# 3) direct address (addr16)
|
|
|
|
# 4) register direct (Ri, RWi, RLi,
|
|
|
|
# A, AL, SP, PCB, DTB, USB, SSB, ADB, DPR,
|
|
|
|
# PS, CCR, RP, ILM)
|
|
|
|
# 5) register indirect (@RWj 0<=j<=3)
|
|
|
|
# 6) register indirect with post-incrementing (@RWj + 0<=j<=3)
|
|
|
|
# 7) register indirect with displacement (@RWi + disp8 0<=i<=7)
|
|
|
|
# (@RWj + disp16 0<=j<=3)
|
|
|
|
# 8) register indirect with base index (@RW0 + RW7, @RW1 + RW7)
|
|
|
|
# 9) program counter indirect with displacement (@PC + disp16)
|
|
|
|
#10) accumulator indirect (@A)
|
|
|
|
#11) direct I/O (io)
|
|
|
|
#12) long register indirect with displacement (@RLi + disp8 0<=i<=3)
|
|
|
|
#13) compressed direct bit address (dir:bp)
|
|
|
|
#14) I/O direct bit address (io:bp)
|
|
|
|
#15) direct bit address (addr16:bp)
|
|
|
|
#16) register list (rlst)
|
|
|
|
#17) program counter relative branching address (rel)
|
|
|
|
#18) direct branching address (addr16)
|
|
|
|
#19) physical direct branching address (addr24)
|
|
|
|
#20) accumulator indirect branching address (@A)
|
|
|
|
#21) vector address (#vct)
|
|
|
|
#22) indirect specification branching address (@ear)
|
|
|
|
#23) indirect specification branching address (@eam)
|
|
|
|
|
|
|
|
|
|
|
|
# Instructions which should terminate disassembly:
|
|
|
|
# RET
|
|
|
|
# RETP
|
|
|
|
# RETI
|
|
|
|
# BRA
|
|
|
|
# JMP
|
|
|
|
# JMPP
|
|
|
|
# Undefined instruction
|
|
|
|
|
|
|
|
@memory = ();
|
|
|
|
@targets = (0xff19f6);
|
|
|
|
$stopat = 0xffc645;
|
|
|
|
|
|
|
|
$baseaddr = 0xff0000;
|
|
|
|
|
|
|
|
%labels = {};
|
|
|
|
$labelnum = 0;
|
|
|
|
|
|
|
|
if (open LABELS, "<input.labels") {
|
|
|
|
while (<LABELS>) {
|
|
|
|
chomp;
|
|
|
|
if (($name, $addr) = /(.*): (.*)/) {
|
|
|
|
$addr = hex $addr;
|
|
|
|
$labels{$addr} = $name;
|
|
|
|
if ($name =~ /^L(\d+)$/) {
|
|
|
|
$labelnum = $1 + 1 if ($1 >= $labelnum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close LABELS;
|
|
|
|
|
|
|
|
$output = 0;
|
|
|
|
|
|
|
|
%io = (
|
|
|
|
0x01 => "PDR1",
|
|
|
|
0x02 => "PDR2",
|
|
|
|
0x03 => "PDR3",
|
|
|
|
0x04 => "PDR4",
|
|
|
|
0x05 => "PDR5",
|
|
|
|
0x06 => "PDR6",
|
|
|
|
0x07 => "PDR7",
|
|
|
|
0x08 => "PDR8",
|
|
|
|
0x09 => "PDR9",
|
|
|
|
0x0A => "PDRA",
|
|
|
|
0x11 => "DDR1",
|
|
|
|
0x12 => "DDR2",
|
|
|
|
0x13 => "DDR3",
|
|
|
|
0x14 => "DDR4",
|
|
|
|
0x15 => "DDR5",
|
|
|
|
0x16 => "ADER",
|
|
|
|
0x17 => "DDR7",
|
|
|
|
0x18 => "DDR8",
|
|
|
|
0x19 => "DDR9",
|
|
|
|
0x1A => "DDRA",
|
|
|
|
0x20 => "SMR0",
|
|
|
|
0x21 => "SCR0",
|
|
|
|
0x22 => "S[IO]DR0",
|
|
|
|
0x23 => "SSR0",
|
|
|
|
0x24 => "SMR1",
|
|
|
|
0x25 => "SCR1",
|
|
|
|
0x26 => "S[IO]DR1",
|
|
|
|
0x27 => "SSR1",
|
|
|
|
0x28 => "ENIR",
|
|
|
|
0x29 => "EIRR",
|
|
|
|
0x2A => "ELVRl",
|
|
|
|
0x2B => "ELVRh",
|
|
|
|
0x2C => "ADCSl",
|
|
|
|
0x2D => "ADCSh",
|
|
|
|
0x2E => "ADCRl",
|
|
|
|
0x2F => "ADCRh",
|
|
|
|
0x30 => "PPGC0",
|
|
|
|
0x31 => "PPGC1",
|
|
|
|
0x34 => "PRL0l",
|
|
|
|
0x35 => "PRL0h",
|
|
|
|
0x36 => "PRL1l",
|
|
|
|
0x37 => "PRL1h",
|
|
|
|
0x38 => "TMCSR0l",
|
|
|
|
0x39 => "TMCSR0h",
|
|
|
|
0x3A => "TMR(LR)0l",
|
|
|
|
0x3B => "TMR(LR)0h",
|
|
|
|
0x3C => "TMCSR1l",
|
|
|
|
0x3D => "TMCSR1h",
|
|
|
|
0x3E => "TMR(LR)1l",
|
|
|
|
0x3F => "TMR(LR)1h",
|
|
|
|
0x44 => "SMR2",
|
|
|
|
0x45 => "SCR2",
|
|
|
|
0x46 => "S[IO]DR2",
|
|
|
|
0x47 => "SSR2",
|
|
|
|
0x48 => "CSCR0",
|
|
|
|
0x49 => "CSCR1",
|
|
|
|
0x4A => "CSCR2",
|
|
|
|
0x4B => "CSCR3",
|
|
|
|
0x4C => "CSCR4",
|
|
|
|
0x4D => "CSCR5",
|
|
|
|
0x4E => "CSCR6",
|
|
|
|
0x4F => "CSCR7",
|
|
|
|
0x51 => "CDCR0",
|
|
|
|
0x53 => "CDCR1",
|
|
|
|
0x9F => "DIRR",
|
|
|
|
0xA0 => "LPMCR",
|
|
|
|
0xA1 => "CKSCR",
|
|
|
|
0xA5 => "ARSR",
|
|
|
|
0xA6 => "HACR",
|
|
|
|
0xA7 => "ECSR",
|
|
|
|
0xA8 => "WDTC",
|
|
|
|
0xA9 => "TBTC",
|
|
|
|
0xB0 => "ICR00",
|
|
|
|
0xB1 => "ICR01",
|
|
|
|
0xB2 => "ICR02",
|
|
|
|
0xB3 => "ICR03",
|
|
|
|
0xB4 => "ICR04",
|
|
|
|
0xB5 => "ICR05",
|
|
|
|
0xB6 => "ICR06",
|
|
|
|
0xB7 => "ICR07",
|
|
|
|
0xB8 => "ICR08",
|
|
|
|
0xB9 => "ICR09",
|
|
|
|
0xBA => "ICR10",
|
|
|
|
0xBB => "ICR11",
|
|
|
|
0xBC => "ICR12",
|
|
|
|
0xBD => "ICR13",
|
|
|
|
0xBE => "ICR14",
|
|
|
|
0xBF => "ICR15",
|
|
|
|
# Specific to LC2412
|
|
|
|
0xC0 => "KEY0",
|
|
|
|
0xC1 => "KEY1",
|
|
|
|
0xC2 => "KEY2",
|
|
|
|
0xC3 => "KEY3",
|
|
|
|
0xC4 => "KEY4",
|
|
|
|
0xC5 => "LEDC",
|
|
|
|
0xC6 => "LCD",
|
|
|
|
0xC8 => "PC_ADL",
|
|
|
|
0xC9 => "PC_ADM",
|
|
|
|
0xCA => "PC_ADH",
|
|
|
|
0xCB => "PC_DW",
|
|
|
|
0xCC => "PC_DR",
|
|
|
|
0xCD => "PC_CR",
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
my $byte = getc FILE;
|
|
|
|
last unless defined($byte);
|
|
|
|
$byte = ord($byte);
|
|
|
|
push(@memory, $byte);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(FILE);
|
|
|
|
|
|
|
|
@initialtargets = @targets;
|
|
|
|
|
|
|
|
for my $pass (0..1) {
|
|
|
|
@targets = @initialtargets;
|
|
|
|
%targets_all = {};
|
|
|
|
foreach $target (@targets) {
|
|
|
|
$targets_all{$target} = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output = $pass;
|
|
|
|
while (@targets) {
|
|
|
|
$target = shift @targets;
|
|
|
|
printf "Disassembling from %x:\n", $target if $output;
|
|
|
|
disassemble($target);
|
|
|
|
@targets = (); # XXX stop here.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
open LABELS, ">input.labels" or die $!;
|
|
|
|
|
|
|
|
foreach my $addr (sort keys %labels) {
|
|
|
|
printf LABELS "%s: %06x\n", $labels{$addr}, $addr
|
|
|
|
if defined($labels{$addr});
|
|
|
|
}
|
|
|
|
|
|
|
|
close LABELS;
|
|
|
|
|
|
|
|
sub disassemble
|
|
|
|
{
|
|
|
|
my ($start) = @_;
|
|
|
|
setaddress($start);
|
|
|
|
$finish_disassembly = 0;
|
|
|
|
$newline = 0;
|
|
|
|
while (!$finish_disassembly)
|
|
|
|
{
|
|
|
|
local @instr = ();
|
|
|
|
my $byte = getbyte();
|
|
|
|
last unless defined($byte);
|
|
|
|
local $address = $bytecount-1;
|
|
|
|
decode_instruction($byte);
|
|
|
|
$finish_disassembly = 1 if ($address >= $stopat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub setaddress
|
|
|
|
{
|
|
|
|
my ($address) = @_;
|
|
|
|
$bytecount = $address;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub getbyte
|
|
|
|
{
|
|
|
|
return undef if ($bytecount - $baseaddr > @memory);
|
|
|
|
return undef if ($bytecount - $baseaddr < 0);
|
|
|
|
my $ret = $memory[$bytecount++ - $baseaddr];
|
|
|
|
push(@instr, $ret);
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_instruction
|
|
|
|
{
|
|
|
|
my ($byte) = @_;
|
|
|
|
local $amode = undef;
|
|
|
|
local @operands = ();
|
|
|
|
local $comment = "";
|
|
|
|
local $branch = 0;
|
|
|
|
|
|
|
|
if ($byte == 0x00) {
|
|
|
|
output_instruction("NOP");
|
|
|
|
} elsif ($byte == 0x01) {
|
|
|
|
branch();
|
|
|
|
output_instruction("INT9");
|
|
|
|
} elsif ($byte == 0x02) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ADDDC");
|
|
|
|
} elsif ($byte == 0x03) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("NEG");
|
|
|
|
} elsif ($byte == 0x04) {
|
|
|
|
output_instruction("PCB");
|
|
|
|
} elsif ($byte == 0x05) {
|
|
|
|
output_instruction("DTB");
|
|
|
|
} elsif ($byte == 0x06) {
|
|
|
|
output_instruction("ADB");
|
|
|
|
} elsif ($byte == 0x07) {
|
|
|
|
output_instruction("SDB");
|
|
|
|
} elsif ($byte == 0x08) {
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("LINK");
|
|
|
|
} elsif ($byte == 0x09) {
|
|
|
|
output_instruction("UNLINK");
|
|
|
|
} elsif ($byte == 0x0A) {
|
|
|
|
set_operand("RP");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x0B) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("NEGW");
|
|
|
|
} elsif ($byte == 0x0C) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("LSLW");
|
|
|
|
} elsif ($byte == 0x0E) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ASRW");
|
|
|
|
} elsif ($byte == 0x0F) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("LSRW");
|
|
|
|
} elsif ($byte == 0x10) {
|
|
|
|
output_instruction("CMR");
|
|
|
|
} elsif ($byte == 0x11) {
|
|
|
|
output_instruction("NCC");
|
|
|
|
} elsif ($byte == 0x12) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("SUBDC");
|
|
|
|
} elsif ($byte == 0x13) {
|
|
|
|
branch();
|
|
|
|
set_operand('@A');
|
|
|
|
output_instruction("JCTX");
|
|
|
|
} elsif ($byte == 0x14) {
|
|
|
|
output_instruction("EXT");
|
|
|
|
} elsif ($byte == 0x15) {
|
|
|
|
output_instruction("ZEXT");
|
|
|
|
} elsif ($byte == 0x16) {
|
|
|
|
output_instruction("SWAP");
|
|
|
|
} elsif ($byte == 0x17) {
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("ADDSP");
|
|
|
|
} elsif ($byte == 0x18) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm32();
|
|
|
|
output_instruction("ADDL");
|
|
|
|
} elsif ($byte == 0x19) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm32();
|
|
|
|
output_instruction("SUBL");
|
|
|
|
} elsif ($byte == 0x1A) {
|
|
|
|
set_operand("ILM");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x1B) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm32();
|
|
|
|
output_instruction("CMPL");
|
|
|
|
} elsif ($byte == 0x1C) {
|
|
|
|
output_instruction("EXTW");
|
|
|
|
} elsif ($byte == 0x1D) {
|
|
|
|
output_instruction("ZEXTW");
|
|
|
|
} elsif ($byte == 0x1E) {
|
|
|
|
output_instruction("SWAPW");
|
|
|
|
} elsif ($byte == 0x1F) {
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("ADDSP");
|
|
|
|
} elsif ($byte == 0x20) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_dir();
|
|
|
|
output_instruction("ADD");
|
|
|
|
} elsif ($byte == 0x21) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_dir();
|
|
|
|
output_instruction("SUB");
|
|
|
|
} elsif ($byte == 0x22) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ADDC");
|
|
|
|
} elsif ($byte == 0x23) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("CMP");
|
|
|
|
} elsif ($byte == 0x24) {
|
|
|
|
set_operand("CCR");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("AND");
|
|
|
|
} elsif ($byte == 0x25) {
|
|
|
|
set_operand("CCR");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("OR");
|
|
|
|
} elsif ($byte == 0x26) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("DIVU");
|
|
|
|
} elsif ($byte == 0x27) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MULU");
|
|
|
|
} elsif ($byte == 0x28) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ADDW");
|
|
|
|
} elsif ($byte == 0x29) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("SUBW");
|
|
|
|
} elsif ($byte == 0x2A) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("CBNE");
|
|
|
|
} elsif ($byte == 0x2B) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("CMPW");
|
|
|
|
} elsif ($byte == 0x2C) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ANDW");
|
|
|
|
} elsif ($byte == 0x2D) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ORW");
|
|
|
|
} elsif ($byte == 0x2E) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("XORW");
|
|
|
|
} elsif ($byte == 0x2F) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MULUW");
|
|
|
|
} elsif ($byte == 0x30) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("ADD");
|
|
|
|
} elsif ($byte == 0x31) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("SUB");
|
|
|
|
} elsif ($byte == 0x32) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("SUBC");
|
|
|
|
} elsif ($byte == 0x33) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("CMP");
|
|
|
|
} elsif ($byte == 0x34) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("AND");
|
|
|
|
} elsif ($byte == 0x35) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("OR");
|
|
|
|
} elsif ($byte == 0x36) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("XOR");
|
|
|
|
} elsif ($byte == 0x37) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("NOT");
|
|
|
|
} elsif ($byte == 0x38) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("ADDW");
|
|
|
|
} elsif ($byte == 0x39) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("SUBW");
|
|
|
|
} elsif ($byte == 0x3A) {
|
|
|
|
branch();
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("CWBNE");
|
|
|
|
} elsif ($byte == 0x3B) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("CMPW");
|
|
|
|
} elsif ($byte == 0x3C) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("ANDW");
|
|
|
|
} elsif ($byte == 0x3D) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("ORW");
|
|
|
|
} elsif ($byte == 0x3E) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("XORW");
|
|
|
|
} elsif ($byte == 0x3F) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("NOTW");
|
|
|
|
} elsif ($byte == 0x40) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_dir();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x41) {
|
|
|
|
read_operand_dir();
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x42) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x43) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif ($byte == 0x44) {
|
|
|
|
read_operand_dir();
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x45) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_dir();
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif ($byte == 0x46) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("SP");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x47) {
|
|
|
|
set_operand("SP");
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x48) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_dir();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x49) {
|
|
|
|
read_operand_dir();
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x4A) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x4B) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_imm32();
|
|
|
|
output_instruction("MOVL");
|
|
|
|
} elsif ($byte == 0x4C) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("PUSHW");
|
|
|
|
} elsif ($byte == 0x4D) {
|
|
|
|
set_operand("AH");
|
|
|
|
output_instruction("PUSHW");
|
|
|
|
} elsif ($byte == 0x4E) {
|
|
|
|
set_operand("PS");
|
|
|
|
output_instruction("PUSHW");
|
|
|
|
} elsif ($byte == 0x4F) {
|
|
|
|
read_operand_rlst();
|
|
|
|
output_instruction("PUSHW");
|
|
|
|
} elsif ($byte == 0x50) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_io();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x51) {
|
|
|
|
read_operand_io();
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x52) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_addr16();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x53) {
|
|
|
|
read_operand_addr16();
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x54) {
|
|
|
|
read_operand_io();
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x55) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_io();
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif ($byte == 0x56) {
|
|
|
|
read_operand_io();
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x57) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_addr16();
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif ($byte == 0x58) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_io();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x59) {
|
|
|
|
read_operand_io();
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x5A) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_addr16();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x5B) {
|
|
|
|
read_operand_addr16();
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x5C) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("POPW");
|
|
|
|
} elsif ($byte == 0x5D) {
|
|
|
|
set_operand("AH");
|
|
|
|
output_instruction("POPW");
|
|
|
|
} elsif ($byte == 0x5E) {
|
|
|
|
set_operand("PS");
|
|
|
|
output_instruction("POPW");
|
|
|
|
} elsif ($byte == 0x5F) {
|
|
|
|
read_operand_rlst();
|
|
|
|
output_instruction("POPW");
|
|
|
|
} elsif ($byte == 0x60) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("BRA");
|
|
|
|
} elsif ($byte == 0x61) {
|
|
|
|
branch();
|
|
|
|
set_operand('@A');
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("JMP");
|
|
|
|
} elsif ($byte == 0x62) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr16();
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("JMP");
|
|
|
|
} elsif ($byte == 0x63) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr24();
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("JMPP");
|
|
|
|
} elsif ($byte == 0x64) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr16();
|
|
|
|
output_instruction("CALL");
|
|
|
|
} elsif ($byte == 0x65) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr24();
|
|
|
|
output_instruction("CALL");
|
|
|
|
} elsif ($byte == 0x66) {
|
|
|
|
branch();
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("RETP");
|
|
|
|
} elsif ($byte == 0x67) {
|
|
|
|
branch();
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("RET");
|
|
|
|
} elsif ($byte == 0x68) {
|
|
|
|
branch();
|
|
|
|
read_operand_vct8();
|
|
|
|
output_instruction("INT");
|
|
|
|
} elsif ($byte == 0x68) {
|
|
|
|
branch();
|
|
|
|
read_operand_vct8();
|
|
|
|
output_instruction("INT");
|
|
|
|
} elsif ($byte == 0x69) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr16();
|
|
|
|
output_instruction("INT");
|
|
|
|
} elsif ($byte == 0x6A) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr24();
|
|
|
|
output_instruction("INTP");
|
|
|
|
} elsif ($byte == 0x6B) {
|
|
|
|
branch();
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("RETI");
|
|
|
|
} elsif ($byte == 0x6C) {
|
|
|
|
decode_bit_manipulation();
|
|
|
|
} elsif ($byte == 0x6E) {
|
|
|
|
decode_string_manipulation();
|
|
|
|
} elsif ($byte == 0x6F) {
|
|
|
|
decode_two_byte();
|
|
|
|
} elsif ($byte == 0x70) {
|
|
|
|
decode_ea_70();
|
|
|
|
} elsif ($byte == 0x71) {
|
|
|
|
decode_ea_71();
|
|
|
|
} elsif ($byte == 0x72) {
|
|
|
|
decode_ea_72();
|
|
|
|
} elsif ($byte == 0x73) {
|
|
|
|
decode_ea_73();
|
|
|
|
} elsif ($byte == 0x74) {
|
|
|
|
decode_ea_74();
|
|
|
|
} elsif ($byte == 0x75) {
|
|
|
|
decode_ea_75();
|
|
|
|
} elsif ($byte == 0x76) {
|
|
|
|
decode_ea_76();
|
|
|
|
} elsif ($byte == 0x77) {
|
|
|
|
decode_ea_77();
|
|
|
|
} elsif ($byte == 0x78) {
|
|
|
|
decode_ea_78();
|
|
|
|
} elsif ($byte == 0x79) {
|
|
|
|
decode_ea_79();
|
|
|
|
} elsif ($byte == 0x7A) {
|
|
|
|
decode_ea_7a();
|
|
|
|
} elsif ($byte == 0x7B) {
|
|
|
|
decode_ea_7b();
|
|
|
|
} elsif ($byte == 0x7C) {
|
|
|
|
decode_ea_7c();
|
|
|
|
} elsif ($byte == 0x7D) {
|
|
|
|
decode_ea_7d();
|
|
|
|
} elsif ($byte == 0x7E) {
|
|
|
|
decode_ea_7e();
|
|
|
|
} elsif ($byte == 0x7F) {
|
|
|
|
decode_ea_7f();
|
|
|
|
} elsif (($byte & 0xf8) == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", $byte & 0x7);
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif (($byte & 0xf8) == 0x88) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("RW", $byte & 0x7);
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif (($byte & 0xf8) == 0x90) {
|
|
|
|
set_operand_register("R", $byte & 0x7);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif (($byte & 0xf8) == 0x98) {
|
|
|
|
set_operand_register("RW", $byte & 0x7);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif (($byte & 0xf8) == 0xA0) {
|
|
|
|
set_operand_register("R", $byte & 0x7);
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif (($byte & 0xf8) == 0xA8) {
|
|
|
|
set_operand_register("RW", $byte & 0x7);
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif (($byte & 0xf8) == 0xB0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", $byte & 0x7);
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif (($byte & 0xf8) == 0xB8) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register_disp8("RW", $byte & 0x7);
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif (($byte & 0xf8) == 0xC0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register_disp8("RW", $byte & 0x7);
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif (($byte & 0xf8) == 0xC8) {
|
|
|
|
set_operand_register_disp8("RW", $byte & 0x7);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif (($byte & 0xf0) == 0xD0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_imm4($byte & 0xf);
|
|
|
|
output_instruction("MOVN");
|
|
|
|
} elsif (($byte & 0xf0) == 0xE0) {
|
|
|
|
branch();
|
|
|
|
set_operand_imm4($byte & 0xf);
|
|
|
|
output_instruction("CALLV");
|
|
|
|
} elsif ($byte == 0xF0) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BZ");
|
|
|
|
} elsif ($byte == 0xF1) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BNZ");
|
|
|
|
} elsif ($byte == 0xF2) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BC");
|
|
|
|
} elsif ($byte == 0xF3) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BNC");
|
|
|
|
} elsif ($byte == 0xF4) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BN");
|
|
|
|
} elsif ($byte == 0xF5) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BP");
|
|
|
|
} elsif ($byte == 0xF6) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BV");
|
|
|
|
} elsif ($byte == 0xF7) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BNV");
|
|
|
|
} elsif ($byte == 0xF8) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BT");
|
|
|
|
} elsif ($byte == 0xF9) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BNT");
|
|
|
|
} elsif ($byte == 0xFA) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BLT");
|
|
|
|
} elsif ($byte == 0xFB) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BGE");
|
|
|
|
} elsif ($byte == 0xFC) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BLE");
|
|
|
|
} elsif ($byte == 0xFD) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BGT");
|
|
|
|
} elsif ($byte == 0xFE) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BLS");
|
|
|
|
} elsif ($byte == 0xFF) {
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BHI");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("first byte");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_bit_manipulation
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
if (($byte & 0xf8) == 0x00) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
output_instruction("MOVB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x08) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_dir_bp($byte & 0x7);
|
|
|
|
output_instruction("MOVB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x18) {
|
|
|
|
set_operand("A");
|
|
|
|
read_operand_addr16_bp($byte & 0x7);
|
|
|
|
output_instruction("MOVB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x20) {
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x28) {
|
|
|
|
read_operand_dir_bp($byte & 0x7);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x38) {
|
|
|
|
read_operand_addr16_bp($byte & 0x7);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x40) {
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
output_instruction("CLRB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x48) {
|
|
|
|
read_operand_dir_bp($byte & 0x7);
|
|
|
|
output_instruction("CLRB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x58) {
|
|
|
|
read_operand_addr16_bp($byte & 0x7);
|
|
|
|
output_instruction("CLRB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x60) {
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
output_instruction("SETB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x68) {
|
|
|
|
read_operand_dir_bp($byte & 0x7);
|
|
|
|
output_instruction("SETB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x78) {
|
|
|
|
read_operand_addr16_bp($byte & 0x7);
|
|
|
|
output_instruction("SETB");
|
|
|
|
} elsif (($byte & 0xf8) == 0x80) {
|
|
|
|
branch();
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BBC");
|
|
|
|
} elsif (($byte & 0xf8) == 0x88) {
|
|
|
|
branch();
|
|
|
|
read_operand_dir_bp($byte & 0x7);
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BBC");
|
|
|
|
} elsif (($byte & 0xf8) == 0x98) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr16_bp($byte & 0x7);
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BBC");
|
|
|
|
} elsif (($byte & 0xf8) == 0xA0) {
|
|
|
|
branch();
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BBS");
|
|
|
|
} elsif (($byte & 0xf8) == 0xA8) {
|
|
|
|
branch();
|
|
|
|
read_operand_dir_bp($byte & 0x7);
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BBS");
|
|
|
|
} elsif (($byte & 0xf8) == 0xB8) {
|
|
|
|
branch();
|
|
|
|
read_operand_addr16_bp($byte & 0x7);
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("BBS");
|
|
|
|
} elsif (($byte & 0xf8) == 0xC0) {
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
output_instruction("WBTS");
|
|
|
|
} elsif (($byte & 0xf8) == 0xE0) {
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
output_instruction("WBTC");
|
|
|
|
} elsif (($byte & 0xf8) == 0xF8) {
|
|
|
|
read_operand_io_bp($byte & 0x7);
|
|
|
|
output_instruction("SBBS");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("bit manipulation");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_string_manipulation
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $arg1 = ($byte & 0xc) >> 2;
|
|
|
|
my $arg2 = ($byte & 0x3);
|
|
|
|
my $op = ($byte) >> 4;
|
|
|
|
my @r = ("PCB", "DTB", "ADB", "SPB");
|
|
|
|
my @i = ("MOVSI", "MOVSD", "MOVSWI", "MOVSWD", "", "", "", "",
|
|
|
|
"SCEQI", "SCEQD", "SCWEQI", "SCWEQD", "FILSI", "", "FILSWI", "");
|
|
|
|
if ($op < 4) {
|
|
|
|
set_operand($r[$arg1]);
|
|
|
|
set_operand($r[$arg2]);
|
|
|
|
output_instruction($i[$op]);
|
|
|
|
} elsif (((($op >= 8) && ($op <= 0xc)) || ($op == 0xe)) &&
|
|
|
|
($arg1 == 0)) {
|
|
|
|
set_operand($r[$arg2]);
|
|
|
|
output_instruction($i[$op]);
|
|
|
|
} else {
|
|
|
|
undefined_instruction("string manipulation");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_two_byte
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
if ($byte == 0x00) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("DTB");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x01) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("ADB");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x02) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("SSB");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x03) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("USB");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x04) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("DPR");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x05) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand('@A');
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x06) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand("PCB");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x07) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ROLC");
|
|
|
|
} elsif ($byte == 0x0C) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("LSLW");
|
|
|
|
} elsif ($byte == 0x0D) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand('@A');
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x0E) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("ASRW");
|
|
|
|
} elsif ($byte == 0x0F) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("LSRW");
|
|
|
|
} elsif ($byte == 0x10) {
|
|
|
|
set_operand("DTB");
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x11) {
|
|
|
|
set_operand("ADB");
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x12) {
|
|
|
|
set_operand("SSB");
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x13) {
|
|
|
|
set_operand("USB");
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x14) {
|
|
|
|
set_operand("DPR");
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x15) {
|
|
|
|
set_operand('@AL');
|
|
|
|
set_operand("AH");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x16) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand('@A');
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($byte == 0x17) {
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("RORC");
|
|
|
|
} elsif ($byte == 0x1C) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("LSLL");
|
|
|
|
} elsif ($byte == 0x1D) {
|
|
|
|
set_operand('@AL');
|
|
|
|
set_operand("AH");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($byte == 0x1E) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("ASRL");
|
|
|
|
} elsif ($byte == 0x1F) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("LSRL");
|
|
|
|
} elsif ($byte == 0x2C) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("LSL");
|
|
|
|
} elsif ($byte == 0x2D) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("NRML");
|
|
|
|
} elsif ($byte == 0x2E) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("ASR");
|
|
|
|
} elsif ($byte == 0x2F) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register("R", 0);
|
|
|
|
output_instruction("LSR");
|
|
|
|
} elsif (($byte & 0xf9) == 0x20) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register_disp8("RL", ($byte & 7) >>1);
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif (($byte & 0xf9) == 0x30) {
|
|
|
|
set_operand_register_disp8("RL", ($byte & 7) >>1);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif (($byte & 0xf9) == 0x38) {
|
|
|
|
set_operand_register_disp8("RL", ($byte & 7) >>1);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif (($byte & 0xf9) == 0x40) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register_disp8("RL", ($byte & 7) >>1);
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif (($byte & 0xf9) == 0x48) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_register_disp8("RL", ($byte & 7) >>1);
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("two byte");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_70
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("ADDL");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("SUBL");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
branch();
|
|
|
|
read_operand_imm16();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("CWBNE");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("CMPL");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("ANDL");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("ORL");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("XORL");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
branch();
|
|
|
|
read_operand_imm8();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("CBNE");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (70)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_71
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
branch();
|
|
|
|
set_operand_ea('@RL', $byte);
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("JMPP");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
branch();
|
|
|
|
set_operand_ea('@RL', $byte);
|
|
|
|
output_instruction("CALLP");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("INCL");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("DECL");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
output_instruction("MOVL");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand_ea("RL", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVL");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
read_operand_imm8();
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("MOVEA");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (71)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_72
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("ROLC");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("RORC");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("INC");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("DEC");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOV");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("MOVX");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("XCH");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (72)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_73
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
branch();
|
|
|
|
set_operand_ea('@RW', $byte);
|
|
|
|
unconditional_branch();
|
|
|
|
output_instruction("JMP");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
branch();
|
|
|
|
set_operand_ea('@RW', $byte);
|
|
|
|
output_instruction("CALL");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("INCW");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("DECW");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
read_operand_imm16();
|
|
|
|
output_instruction("MOVW");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("XCHW");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (73)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_74
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("ADD");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("SUB");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("ADDC");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("CMP");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("AND");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("OR");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("XOR");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("DBNZ");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (74)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_75
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ADD");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("SUB");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("SUBC");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("NEG");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("AND");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("OR");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("XOR");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("NOT");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (75)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_76
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("ADDW");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("SUBW");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("ADDCW");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("CMPW");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("ANDW");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("ORW");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("XORW");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
branch();
|
|
|
|
read_operand_rel();
|
|
|
|
output_instruction("DWBNZ");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (76)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_77
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ADDW");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("SUBW");
|
|
|
|
} elsif ($op == 0x40) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("SUBCW");
|
|
|
|
} elsif ($op == 0x60) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("NEGW");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ANDW");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("ORW");
|
|
|
|
} elsif ($op == 0xC0) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand("A");
|
|
|
|
output_instruction("XORW");
|
|
|
|
} elsif ($op == 0xE0) {
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("NOTW");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (77)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_78
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $op = $byte & 0xe0;
|
|
|
|
if ($op == 0x00) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("MULU");
|
|
|
|
} elsif ($op == 0x20) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("MULUW");
|
|
|
|
} elsif ($op == 0x80) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("DIVU");
|
|
|
|
} elsif ($op == 0xA0) {
|
|
|
|
set_operand("A");
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("DIVUW");
|
|
|
|
} else {
|
|
|
|
undefined_instruction("ea (78)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_79
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_register("RW", $reg);
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("MOVEA");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_7a
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_register("R", $reg);
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("MOV");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_7b
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_register("RW", $reg);
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("MOVW");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_7c
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
set_operand_register("R", $reg);
|
|
|
|
output_instruction("MOV");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_7d
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
set_operand_register("RW", $reg);
|
|
|
|
output_instruction("MOVW");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_7e
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_register("R", $reg);
|
|
|
|
set_operand_ea("R", $byte);
|
|
|
|
output_instruction("XCH");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub decode_ea_7f
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $reg = ($byte & 0xe0) >> 5;
|
|
|
|
set_operand_register("RW", $reg);
|
|
|
|
set_operand_ea("RW", $byte);
|
|
|
|
output_instruction("XCHW");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub signextend8
|
|
|
|
{
|
|
|
|
my ($byte) = @_;
|
|
|
|
if ($byte & 0x80) {
|
|
|
|
$byte -= 0x100;
|
|
|
|
}
|
|
|
|
return $byte;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub signextend16
|
|
|
|
{
|
|
|
|
my ($word) = @_;
|
|
|
|
if ($word & 0x8000) {
|
|
|
|
$word -= 0x10000;
|
|
|
|
}
|
|
|
|
return $word;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand
|
|
|
|
{
|
|
|
|
my ($operand) = @_;
|
|
|
|
push (@operands, $operand);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_dir
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
set_operand(sprintf("dir:0x%.2x", $byte));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_dir_bp
|
|
|
|
{
|
|
|
|
my ($bp) = @_;
|
|
|
|
my $byte = getbyte();
|
|
|
|
set_operand(sprintf("dir:0x%.2x:%d", $byte, $bp));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_io
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
if ($io{$byte}) {
|
|
|
|
set_operand(sprintf("I:%s", $io{$byte}));
|
|
|
|
add_comment(sprintf("0x%.2x", $byte));
|
|
|
|
} else {
|
|
|
|
set_operand(sprintf("I:0x%.2x", $byte));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_io_bp
|
|
|
|
{
|
|
|
|
my ($bp) = @_;
|
|
|
|
my $byte = getbyte();
|
|
|
|
if ($io{$byte}) {
|
|
|
|
set_operand(sprintf("I:%s:%d", $io{$byte}, $bp));
|
|
|
|
add_comment(sprintf("0x%.2x", $byte));
|
|
|
|
} else {
|
|
|
|
set_operand(sprintf("I:0x%.2x:%d", $byte, $bp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_vct8
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
set_operand(sprintf("#vct:0x%.2x", $byte));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_addr16
|
|
|
|
{
|
|
|
|
my ($at) = @_;
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $addr = $byte1;
|
|
|
|
$addr += $byte2 << 8;
|
|
|
|
if ($branch) {
|
|
|
|
$addr = ($addr & 0xffff) | ($address & ~0xffff);
|
|
|
|
set_operand(sprintf("%s%s", $at, get_label($addr)));
|
|
|
|
add_comment(sprintf("0x%.6x", $addr));
|
|
|
|
} else {
|
|
|
|
set_operand(sprintf("%sD:0x%.4x", $at, $addr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_addr16_bp
|
|
|
|
{
|
|
|
|
my ($bp) = @_;
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $addr = $byte1;
|
|
|
|
$addr += $byte2 << 8;
|
|
|
|
set_operand(sprintf("D:0x%.4x:%d", $addr, $bp));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_addr24
|
|
|
|
{
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $byte3 = getbyte();
|
|
|
|
my $addr = $byte1;
|
|
|
|
$addr += $byte2 << 8;
|
|
|
|
$addr += $byte3 << 16;
|
|
|
|
if ($branch) {
|
|
|
|
set_operand(sprintf("%s", get_label($addr)));
|
|
|
|
add_comment(sprintf("0x%.6x", $addr));
|
|
|
|
} else {
|
|
|
|
set_operand(sprintf("0x%.6x", $addr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## ASSUMPTION: This is always the last operand!!!
|
|
|
|
sub read_operand_rel
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $addr = $bytecount + signextend8($byte);
|
|
|
|
$addr = $addr & 0xffff;
|
|
|
|
$addr = $addr | ($address &~0xffff);
|
|
|
|
# add_target($addr);
|
|
|
|
set_operand(get_label($addr));
|
|
|
|
add_comment(sprintf("0x%x", $addr));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_label
|
|
|
|
{
|
|
|
|
($addr) = @_;
|
|
|
|
return $labels{$addr} if defined($labels{$addr});
|
|
|
|
$labels{$addr}="L" . $labelnum++;
|
|
|
|
return $labels{$addr};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub add_target
|
|
|
|
{
|
|
|
|
($addr) = @_;
|
|
|
|
return if defined($targets_all{$addr});
|
|
|
|
push(@targets, $addr);
|
|
|
|
$targets_all{$addr}=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub add_comment
|
|
|
|
{
|
|
|
|
($text) = @_;
|
|
|
|
$comment = $comment . " " unless ($comment eq "");
|
|
|
|
$comment = $comment . $text;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_rlst
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $string = "[";
|
|
|
|
my $comma = "";
|
|
|
|
my $inrange = 0;
|
|
|
|
my $reg = 0;
|
|
|
|
while ($byte != 0) {
|
|
|
|
if ($byte & 1) {
|
|
|
|
if ($inrange) {
|
|
|
|
if (($byte & 2) == 0) {
|
|
|
|
$string .= "-RW" . $reg;
|
|
|
|
$inrange = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$string .= $comma . "RW" . $reg;
|
|
|
|
$comma = ", ";
|
|
|
|
if ($byte & 2) {
|
|
|
|
$inrange = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$byte = $byte >> 1;
|
|
|
|
$reg++;
|
|
|
|
}
|
|
|
|
$string .= "]";
|
|
|
|
set_operand($string);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand_imm4
|
|
|
|
{
|
|
|
|
my ($byte) = @_;
|
|
|
|
set_operand(sprintf("#%d", $byte));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_imm8
|
|
|
|
{
|
|
|
|
my $byte = getbyte();
|
|
|
|
set_operand(sprintf("#%d", $byte));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_imm16
|
|
|
|
{
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $word = $byte1;
|
|
|
|
$word += ($byte2 << 8);
|
|
|
|
set_operand(sprintf("#%d", $word));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_operand_imm32
|
|
|
|
{
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $byte3 = getbyte();
|
|
|
|
my $byte4 = getbyte();
|
|
|
|
my $word = $byte1;
|
|
|
|
$word += ($byte2 << 8);
|
|
|
|
$word += ($byte3 << 16);
|
|
|
|
$word += ($byte4 << 24);
|
|
|
|
set_operand(sprintf("#0x%x", $word));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand_register
|
|
|
|
{
|
|
|
|
my ($type, $reg) = @_;
|
|
|
|
set_operand(sprintf("%s%d", $type, $reg));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand_register_disp8
|
|
|
|
{
|
|
|
|
my ($type, $reg) = @_;
|
|
|
|
my $byte = getbyte();
|
|
|
|
my $disp = signextend8($byte);
|
|
|
|
set_operand(sprintf("\@%s%d%+d", $type, $reg, $disp));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand_register_disp16
|
|
|
|
{
|
|
|
|
my ($type, $reg) = @_;
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $word = $byte1 + ($byte2 << 8);
|
|
|
|
my $disp = signextend16($word);
|
|
|
|
set_operand(sprintf("\@%s%d%+d", $type, $reg, $disp));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand_pc_disp16
|
|
|
|
{
|
|
|
|
my ($at) = @_;
|
|
|
|
my $byte1 = getbyte();
|
|
|
|
my $byte2 = getbyte();
|
|
|
|
my $word = $byte1 + ($byte2 << 8);
|
|
|
|
my $disp = signextend16($word);
|
|
|
|
set_operand(sprintf("%s\@PC%+d", $at, $disp));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub set_operand_ea
|
|
|
|
{
|
|
|
|
my ($type, $byte) = @_;
|
|
|
|
my $at = "";
|
|
|
|
$at = '@' if ($type =~ /@/);
|
|
|
|
$byte = $byte & 0x1f;
|
|
|
|
if ($byte < 0x08) {
|
|
|
|
my $rn = $byte;
|
|
|
|
$rn = $rn >> 1 if ($type =~ /RL/);
|
|
|
|
set_operand(sprintf("%s%d", $type, $rn));
|
|
|
|
} elsif ($byte < 0x0c) {
|
|
|
|
set_operand(sprintf('%s@RW%d', $at, $byte & 3));
|
|
|
|
} elsif ($byte < 0x10) {
|
|
|
|
set_operand(sprintf('%s@RW%d+', $at, $byte & 3));
|
|
|
|
} elsif ($byte < 0x18) {
|
|
|
|
set_operand_register_disp8($at."RW", $byte & 7);
|
|
|
|
} elsif ($byte < 0x1c) {
|
|
|
|
set_operand_register_disp16($at."RW", $byte & 3);
|
|
|
|
} elsif ($byte == 0x1c) {
|
|
|
|
set_operand($at . '@RW0+RW7');
|
|
|
|
} elsif ($byte == 0x1d) {
|
|
|
|
set_operand($at . '@RW1+RW7');
|
|
|
|
} elsif ($byte == 0x1e) {
|
|
|
|
set_operand_pc_disp16($at);
|
|
|
|
} elsif ($byte == 0x1f) {
|
|
|
|
read_operand_addr16($at);
|
|
|
|
} else {
|
|
|
|
printf "Unknown ea operand: %x\n", $byte if $output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub branch
|
|
|
|
{
|
|
|
|
$branch = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub unconditional_branch
|
|
|
|
{
|
|
|
|
# $finish_disassembly = 1;
|
|
|
|
$newline = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub undefined_instruction
|
|
|
|
{
|
|
|
|
my ($type) = @_;
|
|
|
|
|
|
|
|
@operands = ();
|
|
|
|
output_instruction("Undefined instruction: $type");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub output_instruction
|
|
|
|
{
|
|
|
|
my ($decode) = @_;
|
|
|
|
my $spaces = 16;
|
|
|
|
my $comma = "";
|
|
|
|
|
|
|
|
return unless $output;
|
|
|
|
|
|
|
|
printf "\n%s:\n", $labels{$address} if ($labels{$address});
|
|
|
|
|
|
|
|
printf "%.8x: ", $address;
|
|
|
|
for $byte (@instr) {
|
|
|
|
printf "%.2x ", $byte;
|
|
|
|
$spaces = $spaces - 3;
|
|
|
|
}
|
|
|
|
for (0..$spaces) {
|
|
|
|
print " ";
|
|
|
|
}
|
|
|
|
printf "%s", $decode;
|
|
|
|
for $operand (@operands) {
|
|
|
|
printf "%s %s", $comma, $operand;
|
|
|
|
$comma = ",";
|
|
|
|
}
|
|
|
|
if ($comment ne "") {
|
|
|
|
printf " ; %s", $comment;
|
|
|
|
}
|
|
|
|
print "\n";
|
|
|
|
|
|
|
|
print "\n" if $newline;
|
|
|
|
$newline = 0;
|
|
|
|
}
|