Example #1
0
        public void TestAssemblyLine()
        {
            Assert.IsTrue(
                Float.GenerateAssemblyLine(0.200000002980232f)
                .Last().Equals(
                    (".single", "0.2")
                    )
                );

            var x = Float.GenerateAssemblyLine(0x402E000007800000UL).ToArray();

            Assert.IsTrue(
                x.Last().Equals(
                    (".quad", "0x402E000007800000")
                    )
                );

            var y = Float.GenerateAssemblyLine(0.199999988079071f).ToArray();

            Assert.IsTrue(
                y.Last().Equals(
                    (".word", "0x3E4CCCCC")
                    )
                );

            var z = Float.GenerateAssemblyLine(15.0).ToArray();

            Assert.IsTrue(
                z.Last().Equals(
                    (".double", "15")
                    )
                );
        }
Example #2
0
        public IEnumerable <string> Disassemble(bool debugAddress = false)
        {
            var disassembler = new Disassembler(new DefaultDisassemblyFormatter(Symbols));

            Func <string, string, string> formatPair = (left, right) =>
                                                       right == null
                ? $"\t{left}"
                : $"\t{left.PadRight(16)}{right}";

            Func <UInt32, Instruction, DisassemblerOutput, string> formatDisasm = (pc, insn, output) =>
                                                                                  !debugAddress
                ? formatPair(output.Opcode, output.Operands)
                : formatPair(output.Opcode, (output.Operands ?? "").PadRight(32) + string.Format("# 0x{0:X8}  0x{2:X8}  {1}", pc, Disassembler.DefaultWithoutPc.Disassemble(0, insn), insn.Word));

            yield return("#include \"mips.h\"");

            yield return("#define s8 $fp");

            yield return("");

            var x = 0;

            yield return(formatPair("#", null));

            foreach (var s in Sections)
            {
                yield return(formatPair($"# {s.Name}", string.Format("0x{0:X8} - 0x{1:X8} ({2,6:0.00} kb)", s.StartAddress, s.EndAddress, s.Size / 1024.0)));

                if (x++ == 2)
                {
                    yield return(formatPair("# [relocs]", string.Format("0x{0:X8} - 0x{1:X8} ({2,6:0.00} kb)", Sections[2].EndAddress, Sections[2].EndAddress + HeaderOffset, HeaderOffset / 1024.0)));
                }
            }

            if (_oddities.Count > 0)
            {
                yield return(formatPair("#", null));

                yield return(formatPair("# Oddities:", null));

                foreach (var o in _oddities)
                {
                    yield return(formatPair($"#   - {o}", null));
                }
            }

            yield return(formatPair("#", null));

            yield return("");

            yield return(formatPair(".set", "noreorder"));

            yield return(formatPair(".set", "noat"));

            yield return("");

            for (var j = 0; j < Sections.Count; j++)
            {
                var section = Sections[j];

                if (section.Size == 0)
                {
                    continue;
                }

                UInt32 pc = section.StartAddress;

                if (section.Id >= 1)
                {
                    yield return("");

                    yield return("");
                }

                if (section.Id > 1)
                {
                    yield return(formatPair(".section", $"{section.Name}"));
                }
                else
                {
                    yield return(formatPair(section.Id == 1 ? ".data" : ".text", null));
                }
                yield return("");

                switch (section.Id)
                {
                case 0:
                    foreach (var insn in section.Data.ToInstructions())
                    {
                        var symbol = Symbols.Lookup(pc);

                        if (symbol != null)
                        {
                            if (symbol.TypeHint.HasFlags(TypeHint.Function))
                            {
                                yield return("");

                                yield return(formatPair(".global", symbol.Name));

                                yield return(formatPair(".type", $"{symbol.Name}, @function"));

                                yield return("");

                                yield return(symbol.Name + ":");
                            }
                            else
                            {
                                var pattern = @" \+ \d+$";
                                var name    = symbol.Name;

                                if (Regex.IsMatch(name, pattern))
                                {
                                    name = Regex.Replace(name, pattern, "");
                                }

                                yield return(name + ":");
                            }
                        }

                        yield return(formatDisasm(pc, insn, disassembler.Disassemble(pc, insn)));

                        pc += 4;
                    }
                    break;

                case 1:
                case 2:
                    for (var i = 0; i < section.Data.Count; i++)
                    {
                        var symbol = Symbols.Lookup(pc + (UInt32)i);


                        if (symbol != null)
                        {
                            var stuffs = new List <string>
                            {
                                "",
                                formatPair(".type", $"{symbol.Name}, @object"),
                                symbol.Name + ":"
                            };


                            var reloc  = Relocations.Lookup(pc + (UInt32)i);
                            var doByte = false;

                            Action <int> size = (s) =>
                                                stuffs.Insert(2, formatPair(".size", $"{symbol.Name}, {s}"));

                            bool checkNoSymbolsForNextNbytes(int length) =>
                            Enumerable.Range(1, length - 1)
                            .Select(y => Symbols.Lookup(pc + (UInt32)(i + y)))
                            .All(y => y == null);

                            if (reloc != null && checkNoSymbolsForNextNbytes(4))
                            {
                                size(4);
                                stuffs.Add(formatPair(".word", Symbols.Lookup(reloc.Address).Name));
                                i += 3;
                            }
                            else if (symbol.TypeHint.HasFlags(TypeHint.HalfWord | TypeHint.HalfWordUnsigned) && checkNoSymbolsForNextNbytes(2))
                            {
                                size(2);
                                stuffs.Add(formatPair(".short", string.Format("0x{0:X4}", section.Data[i] << 8 | section.Data[i + 1])));
                                i++;
                            }
                            else if (symbol.TypeHint.HasFlags(TypeHint.Word | TypeHint.WordUnsigned) && checkNoSymbolsForNextNbytes(4))
                            {
                                size(4);
                                stuffs.Add(formatPair(".word", string.Format("0x{0:X8}", Utilities.ReadU32(section.Data, i))));
                                i += 3;
                            }
                            else if (symbol.TypeHint.HasFlags(TypeHint.DoubleWord) && checkNoSymbolsForNextNbytes(8))
                            {
                                size(8);
                                stuffs.Add(formatPair(".quad", string.Format("0x{0:X16}", Utilities.ReadU32(section.Data, i))));
                                i += 7;
                            }
                            else if (symbol.TypeHint.HasFlags(TypeHint.Single) && checkNoSymbolsForNextNbytes(4))
                            {
                                size(4);

                                var flt = BitConverter.ToSingle(BitConverter.GetBytes(Utilities.ReadU32(section.Data, i)), 0);

                                stuffs.AddRange(Float.GenerateAssemblyLine(flt).Select(y => formatPair(y.left, y.right)));

                                i += 3;
                            }
                            else if (symbol.TypeHint.HasFlags(TypeHint.Double) && checkNoSymbolsForNextNbytes(8))
                            {
                                size(8);

                                var flt = BitConverter.ToDouble(BitConverter.GetBytes(Utilities.ReadU64(section.Data, i)), 0);

                                stuffs.AddRange(Float.GenerateAssemblyLine(flt).Select(y => formatPair(y.left, y.right)));

                                i += 7;
                            }
                            else
                            {
                                doByte = true;
                            }

                            foreach (var q in stuffs)
                            {
                                yield return(q);
                            }

                            if (!doByte)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            var reloc = Relocations.Lookup(pc + (UInt32)i);

                            if (reloc != null)
                            {
                                yield return(formatPair(".word", Symbols.Lookup(reloc.Address).Name));

                                i += 3;

                                continue;
                            }
                        }

                        yield return(formatPair(".byte", string.Format("0x{0:X2}", section.Data[i])));
                    }
                    break;

                case 3:
                    var bssSyms = Symbols
                                  .Where(s => s.Address >= section.StartAddress && s.Address < section.EndAddress)
                                  .OrderBy(s => s.Address)
                                  .ToArray();

                    var symIdx = 0;

                    if (bssSyms.Length == 0)
                    {
                        yield return(formatPair(".space", $"{Sections[3].Size}"));

                        break;
                    }

                    for (var ptr = 0; ptr < section.Size;)
                    {
                        long curAddr;
                        var  sym = bssSyms[symIdx];

                        if ((curAddr = section.StartAddress + ptr) < sym.Address)
                        {
                            var spaceSize = bssSyms[symIdx].Address - curAddr;

                            yield return(formatPair(".space", $"{spaceSize}"));

                            ptr += (int)spaceSize;
                        }
                        else
                        {
                            var size = (symIdx + 1 == bssSyms.Length
                                    ? section.EndAddress
                                    : bssSyms[symIdx + 1].Address) - sym.Address;

                            var right = $"{sym.Name},{size},1";

                            if (debugAddress)
                            {
                                right = right.PadRight(24) + string.Format("# 0x{0:X8}", ptr + section.StartAddress);
                            }

                            yield return(formatPair(".local", sym.Name));

                            yield return(formatPair(".comm", right));

                            ptr += (int)size;
                            symIdx++;
                        }
                    }
                    break;
                }
            }
        }