diff options
| author | Anghelo Carvajal <angheloalf95@gmail.com> | 2023-03-28 23:42:56 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-29 03:42:56 +0100 |
| commit | d66a21685f45d130f980e8a5ec7b08cfe189e40b (patch) | |
| tree | f11b3b09dc5772e419fe08d3d0ead4e778def57f /tools/asm-processor | |
| parent | 6a5e64cc4c26398cc607bb02cdc12a056ddf42d1 (diff) | |
Initial repo setup (#1)
* git subrepo clone git@github.com:ethteck/splat.git tools/splat
subrepo:
subdir: "tools/splat"
merged: "4fec014"
upstream:
origin: "git@github.com:ethteck/splat.git"
branch: "master"
commit: "4fec014"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* gitignore
* decompress_baserom.py
* Initial yaml
* run flib
* more yaml stuff
* Builds an uncompressed ROM
* setup ido download
* git subrepo clone git@github.com:simonlindholm/asm-differ.git tools/asm-differ
subrepo:
subdir: "tools/asm-differ"
merged: "ae40866"
upstream:
origin: "git@github.com:simonlindholm/asm-differ.git"
branch: "main"
commit: "ae40866"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* git subrepo clone git@github.com:simonlindholm/asm-processor.git tools/asm-processor
subrepo:
subdir: "tools/asm-processor"
merged: "bbd86ea"
upstream:
origin: "git@github.com:simonlindholm/asm-processor.git"
branch: "main"
commit: "bbd86ea"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* git subrepo clone (merge) git@github.com:EllipticEllipsis/fado.git tools/fado
subrepo:
subdir: "tools/fado"
merged: "8d896ee"
upstream:
origin: "git@github.com:EllipticEllipsis/fado.git"
branch: "master"
commit: "8d896ee"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* setup ido in makefile
* data and rodata
* add automatic file splits
* bootstrap most symbol_addrs
* git subrepo clone --branch=irix git@github.com:hensldm/ultralib.git lib/ultralib
subrepo:
subdir: "lib/ultralib"
merged: "0d1e095"
upstream:
origin: "git@github.com:hensldm/ultralib.git"
branch: "irix"
commit: "0d1e095"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* setup ido building
* various tooling
* git subrepo pull tools/asm-differ
subrepo:
subdir: "tools/asm-differ"
merged: "857b398"
upstream:
origin: "git@github.com:simonlindholm/asm-differ.git"
branch: "main"
commit: "857b398"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* Change defines to match IDO
* review
* newlin
* update gitignore
* Windows error
* D_01000000
* yeet settings.json
* yeet
* git subrepo clone git@github.com:decompals/ultralib.git lib/ultralib
subrepo:
subdir: "lib/ultralib"
merged: "d03b2a3"
upstream:
origin: "git@github.com:decompals/ultralib.git"
branch: "main"
commit: "d03b2a3"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* clangformat and clangtidy
* Setup a bunch of headers
* bootstrap boot and code functions and variables headers
* global.h
* update format.py includes
* -D_MIPS_SZLONG=32
* format.py: --verbose
* Update tools/decompress_baserom.py
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
* Add libc to global.h
* review
* yeet saved_regs
* yeet headers
* yeet _MSC_VER
* more header cleanup
* add readme licensing note
---------
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
Diffstat (limited to 'tools/asm-processor')
56 files changed, 4568 insertions, 0 deletions
diff --git a/tools/asm-processor/.gitignore b/tools/asm-processor/.gitignore new file mode 100644 index 0000000..cc5bba4 --- /dev/null +++ b/tools/asm-processor/.gitignore @@ -0,0 +1,2 @@ +*.o +*.py[cod] diff --git a/tools/asm-processor/.gitrepo b/tools/asm-processor/.gitrepo new file mode 100644 index 0000000..ef2baa1 --- /dev/null +++ b/tools/asm-processor/.gitrepo @@ -0,0 +1,12 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme +; +[subrepo] + remote = git@github.com:simonlindholm/asm-processor.git + branch = main + commit = bbd86ea1faf84e6a7a0e101ab8068a00a3dfb2fc + parent = 75437386de04179489f4fd5fb345d122ff8a2dc0 + method = merge + cmdver = 0.4.3 diff --git a/tools/asm-processor/LICENSE b/tools/asm-processor/LICENSE new file mode 100644 index 0000000..cf1ab25 --- /dev/null +++ b/tools/asm-processor/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org> diff --git a/tools/asm-processor/README.md b/tools/asm-processor/README.md new file mode 100644 index 0000000..009147c --- /dev/null +++ b/tools/asm-processor/README.md @@ -0,0 +1,112 @@ +# asm-processor + +Pre-process .c files and post-process .o files to enable embedding MIPS assembly into IDO-compiled C. + +## Usage + +Let's say you have a file compiled with `-g` on the IDO compiler, that looks like this: +```c +float func4(void) { + "func4"; + return 0.2f; +} +``` + +This script enables replacing it by: +```asm +GLOBAL_ASM( +.rdata +.word 0x66756e63 # func +.word 0x34000000 # 4\0\0\0 + +.late_rodata +glabel rv +.word 0x3e4ccccd # 0.2f + +.text +glabel func4 +lui $at, %hi(rv) +jr $ra +lwc1 $f0, %lo(rv)($at) +jr $ra +nop +jr $ra +nop +) +``` + +To compile the file, run `python3 build.py $CC -- $AS $ASFLAGS -- $CFLAGS -o out.o in.c`, where $CC points to an IDO binary (5.3/7.1 and recomp/qemu all supported), $AS is e.g. `mips-linux-gnu-as`, $ASFLAGS e.g. `-march=vr4300 -mabi=32` and $CFLAGS e.g. `-Wab,-r4300_mul -non_shared -G 0 -Xcpluscomm -g`. build.py may be customized as needed. + +In addition to an .o file, build.py also generates a .d file with Makefile dependencies for .s files referenced by the input .c file. +This functionality may be removed if not needed. + +Reading assembly from file is also supported, by either `GLOBAL_ASM("file.s")` or `#pragma GLOBAL_ASM("file.s")`. + +### What is supported? + +`.text`, `.data`, `.bss` and `.rodata` sections, `.word`/`.incbin`, `.ascii`/`.asciz`, and `-g`, `-g3`, `-O1`, `-O2`, `-framepointer` and `-mips1`/`-mips2` flags to the IDO compiler. + +### What is not supported? + +* complicated assembly (.ifdef, macro declarations/calls other than `glabel`, pseudo-instructions that expand to several real instructions) +* non-IDO compilers +* `-O3` (due to function reordering) + +C `#ifdef`s only work outside of `GLOBAL_ASM` calls, but is otherwise able to replace `.ifdef`. + +### What's up with "late rodata"? + +The IDO compiler emits rodata in two passes: first array/string contents, then large literals/switch jump tables. + +Data declared within `.rdata`/`.section .rodata` will end up in the first half, and `.late_rodata`/`.section .late_rodata` in the second half. + +### How does it work? + +It's a bit of a hack! +The basic idea is replace `GLOBAL_ASM` blocks with dummy C functions/global vars of the same sections sizes as the assembly. +Then the C file gets compiled, and the dummy contents overwritten with the injected assembly. + +To accomplish this, asm-processor has logic for guessing the size of assembly contents +(which assumes the assembly isn't too complicated, e.g. no macros), +and for emitting C code of exact sizes for a bunch of different IDO compiler flags. + +The assembler code is padded with nops to line it up with its correct position in the C; +this allows C and asm ELF files to be merged easily without having to fix up e.g. symbol addresses. + +The most difficult part is `late_rodata`, which is hard to create programmatically. +asm-processor does that by emitting code that uses dummy float literals/double literals/jump tables, +assembles the late_rodata at another location of the .rodata section, then overwrites the dummy rodata. +This does require some movement of symbols and relocations, and quite a bit of care in what code to +emit and how to preserve .double alignment. + +It's worth noting some alternative ways in which asm-processor would have been implemented: +- One idea to get rid of the C/asm size estimations is to emit arbitrary code, and then move code, +symbols and relocations to the correct place after the sizes are known. +Given the machinery for `late_rodata` this wouldn't have been too difficult, and it would have the upside of improved portability. +There is a big downside, however: using dummy code of incorrect size throws off alignment and can introduce unintended padding. +Fixing this would require running multiple passes of asm-processor, with one compile per `ASM_GLOBAL`. +- Another idea is to run the compiler with -S to emit assembly, modify the emitted assembly, then run the assembler +(which in IDO's case may perform additional instruction reordering etc.). +This option has not been investigated in much detail, and would perhaps be superior to the current implementation. +It does have a few unknowns to it, e.g. instruction encoding differences between GNU `as` and IDO's assembler, +how to avoid reordering the injected assembly, and how .rodata/.late_rodata are implemented. + +### Testing + +There are a few tests to ensure you don't break anything when hacking on asm-processor: `./run-tests.sh` should exit without output if they pass, or else output a diff from previous to new version. + +Tests need the environment variable `MIPS_CC` set to point to the IDO 7.1 compiler, with Pascal support enabled. + +For example if asm-processor is cloned in the same directory as [ido static recomp](https://github.com/decompals/ido-static-recomp) and the working directory is asm-processor, tests can be run using: + +```sh +MIPS_CC=../ido-static-recomp/build/7.1/out/cc ./run-tests.sh +``` + +Or using [qemu-irix](https://github.com/zeldaret/oot/releases/tag/0.1q) (don't forget `chmod u+x qemu-irix`) to emulate IDO: + +```sh +MIPS_CC='./qemu-irix -silent -L ../ido-static-recomp/ido/7.1/ ../ido-static-recomp/ido/7.1/usr/bin/cc' ./run-tests.sh +``` + +To skip running Pascal tests, remove the `tests/*.p` glob from `run-tests.sh`. diff --git a/tools/asm-processor/add-test.sh b/tools/asm-processor/add-test.sh new file mode 100755 index 0000000..708548e --- /dev/null +++ b/tools/asm-processor/add-test.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +for A in "$@"; do + OBJDUMPFLAGS="-srt" + ./compile-test.sh "$A" && mips-linux-gnu-objdump $OBJDUMPFLAGS "${A%.*}.o" > "${A%.*}.objdump" +done diff --git a/tools/asm-processor/asm_processor.py b/tools/asm-processor/asm_processor.py new file mode 100644 index 0000000..0d62bc3 --- /dev/null +++ b/tools/asm-processor/asm_processor.py @@ -0,0 +1,1472 @@ +#!/usr/bin/env python3 +import argparse +import tempfile +import struct +import copy +import sys +import re +import os +from collections import namedtuple +from io import StringIO + +MAX_FN_SIZE = 100 +SLOW_CHECKS = False + +EI_NIDENT = 16 +EI_CLASS = 4 +EI_DATA = 5 +EI_VERSION = 6 +EI_OSABI = 7 +EI_ABIVERSION = 8 +STN_UNDEF = 0 + +SHN_UNDEF = 0 +SHN_ABS = 0xfff1 +SHN_COMMON = 0xfff2 +SHN_XINDEX = 0xffff +SHN_LORESERVE = 0xff00 + +STT_NOTYPE = 0 +STT_OBJECT = 1 +STT_FUNC = 2 +STT_SECTION = 3 +STT_FILE = 4 +STT_COMMON = 5 +STT_TLS = 6 + +STB_LOCAL = 0 +STB_GLOBAL = 1 +STB_WEAK = 2 + +STV_DEFAULT = 0 +STV_INTERNAL = 1 +STV_HIDDEN = 2 +STV_PROTECTED = 3 + +SHT_NULL = 0 +SHT_PROGBITS = 1 +SHT_SYMTAB = 2 +SHT_STRTAB = 3 +SHT_RELA = 4 +SHT_HASH = 5 +SHT_DYNAMIC = 6 +SHT_NOTE = 7 +SHT_NOBITS = 8 +SHT_REL = 9 +SHT_SHLIB = 10 +SHT_DYNSYM = 11 +SHT_INIT_ARRAY = 14 +SHT_FINI_ARRAY = 15 +SHT_PREINIT_ARRAY = 16 +SHT_GROUP = 17 +SHT_SYMTAB_SHNDX = 18 +SHT_MIPS_GPTAB = 0x70000003 +SHT_MIPS_DEBUG = 0x70000005 +SHT_MIPS_REGINFO = 0x70000006 +SHT_MIPS_OPTIONS = 0x7000000d + +SHF_WRITE = 0x1 +SHF_ALLOC = 0x2 +SHF_EXECINSTR = 0x4 +SHF_MERGE = 0x10 +SHF_STRINGS = 0x20 +SHF_INFO_LINK = 0x40 +SHF_LINK_ORDER = 0x80 +SHF_OS_NONCONFORMING = 0x100 +SHF_GROUP = 0x200 +SHF_TLS = 0x400 + +R_MIPS_32 = 2 +R_MIPS_26 = 4 +R_MIPS_HI16 = 5 +R_MIPS_LO16 = 6 + +MIPS_DEBUG_ST_STATIC = 2 +MIPS_DEBUG_ST_STATIC_PROC = 14 + + +class ElfFormat: + def __init__(self, is_big_endian): + self.is_big_endian = is_big_endian + self.struct_char = ">" if is_big_endian else "<" + + def pack(self, fmt, *args): + return struct.pack(self.struct_char + fmt, *args) + + def unpack(self, fmt, data): + return struct.unpack(self.struct_char + fmt, data) + + +class ElfHeader: + """ + typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; + } Elf32_Ehdr; + """ + + def __init__(self, data): + self.e_ident = data[:EI_NIDENT] + assert self.e_ident[EI_CLASS] == 1 # 32-bit + self.fmt = ElfFormat(is_big_endian=(self.e_ident[EI_DATA] == 2)) + self.e_type, self.e_machine, self.e_version, self.e_entry, self.e_phoff, self.e_shoff, self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum, self.e_shentsize, self.e_shnum, self.e_shstrndx = self.fmt.unpack('HHIIIIIHHHHHH', data[EI_NIDENT:]) + assert self.e_type == 1 # relocatable + assert self.e_machine == 8 # MIPS I Architecture + assert self.e_phoff == 0 # no program header + assert self.e_shoff != 0 # section header + assert self.e_shstrndx != SHN_UNDEF + + def to_bin(self): + return self.e_ident + self.fmt.pack('HHIIIIIHHHHHH', self.e_type, + self.e_machine, self.e_version, self.e_entry, self.e_phoff, + self.e_shoff, self.e_flags, self.e_ehsize, self.e_phentsize, + self.e_phnum, self.e_shentsize, self.e_shnum, self.e_shstrndx) + + +class Symbol: + """ + typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; + } Elf32_Sym; + """ + + def __init__(self, fmt, data, strtab, name=None): + self.fmt = fmt + self.st_name, self.st_value, self.st_size, st_info, self.st_other, self.st_shndx = fmt.unpack('IIIBBH', data) + assert self.st_shndx != SHN_XINDEX, "too many sections (SHN_XINDEX not supported)" + self.bind = st_info >> 4 + self.type = st_info & 15 + self.name = name if name is not None else strtab.lookup_str(self.st_name) + self.visibility = self.st_other & 3 + + @staticmethod + def from_parts(fmt, st_name, st_value, st_size, st_info, st_other, st_shndx, strtab, name): + header = fmt.pack('IIIBBH', st_name, st_value, st_size, st_info, st_other, st_shndx) + return Symbol(fmt, header, strtab, name) + + def to_bin(self): + st_info = (self.bind << 4) | self.type + return self.fmt.pack('IIIBBH', self.st_name, self.st_value, self.st_size, st_info, self.st_other, self.st_shndx) + + +class Relocation: + def __init__(self, fmt, data, sh_type): + self.fmt = fmt + self.sh_type = sh_type + if sh_type == SHT_REL: + self.r_offset, self.r_info = fmt.unpack('II', data) + else: + self.r_offset, self.r_info, self.r_addend = fmt.unpack('III', data) + self.sym_index = self.r_info >> 8 + self.rel_type = self.r_info & 0xff + + def to_bin(self): + self.r_info = (self.sym_index << 8) | self.rel_type + if self.sh_type == SHT_REL: + return self.fmt.pack('II', self.r_offset, self.r_info) + else: + return self.fmt.pack('III', self.r_offset, self.r_info, self.r_addend) + + +class Section: + """ + typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; + } Elf32_Shdr; + """ + + def __init__(self, fmt, header, data, index): + self.fmt = fmt + self.sh_name, self.sh_type, self.sh_flags, self.sh_addr, self.sh_offset, self.sh_size, self.sh_link, self.sh_info, self.sh_addralign, self.sh_entsize = fmt.unpack('IIIIIIIIII', header) + assert not self.sh_flags & SHF_LINK_ORDER + if self.sh_entsize != 0: + assert self.sh_size % self.sh_entsize == 0 + if self.sh_type == SHT_NOBITS: + self.data = b'' + else: + self.data = data[self.sh_offset:self.sh_offset + self.sh_size] + self.index = index + self.relocated_by = [] + + @staticmethod + def from_parts(fmt, sh_name, sh_type, sh_flags, sh_link, sh_info, sh_addralign, sh_entsize, data, index): + header = fmt.pack('IIIIIIIIII', sh_name, sh_type, sh_flags, 0, 0, len(data), sh_link, sh_info, sh_addralign, sh_entsize) + return Section(fmt, header, data, index) + + def lookup_str(self, index): + assert self.sh_type == SHT_STRTAB + to = self.data.find(b'\0', index) + assert to != -1 + return self.data[index:to].decode('latin1') + + def add_str(self, string): + assert self.sh_type == SHT_STRTAB + ret = len(self.data) + self.data += string.encode('latin1') + b'\0' + return ret + + def is_rel(self): + return self.sh_type == SHT_REL or self.sh_type == SHT_RELA + + def header_to_bin(self): + if self.sh_type != SHT_NOBITS: + self.sh_size = len(self.data) + return self.fmt.pack('IIIIIIIIII', self.sh_name, self.sh_type, self.sh_flags, self.sh_addr, self.sh_offset, self.sh_size, self.sh_link, self.sh_info, self.sh_addralign, self.sh_entsize) + + def late_init(self, sections): + if self.sh_type == SHT_SYMTAB: + self.init_symbols(sections) + elif self.is_rel(): + self.rel_target = sections[self.sh_info] + self.rel_target.relocated_by.append(self) + self.init_relocs() + + def find_symbol(self, name): + assert self.sh_type == SHT_SYMTAB + for s in self.symbol_entries: + if s.name == name: + return (s.st_shndx, s.st_value) + return None + + def find_symbol_in_section(self, name, section): + pos = self.find_symbol(name) + assert pos is not None + assert pos[0] == section.index + return pos[1] + + def init_symbols(self, sections): + assert self.sh_type == SHT_SYMTAB + assert self.sh_entsize == 16 + self.strtab = sections[self.sh_link] + entries = [] + for i in range(0, self.sh_size, self.sh_entsize): + entries.append(Symbol(self.fmt, self.data[i:i+self.sh_entsize], self.strtab)) + self.symbol_entries = entries + + def init_relocs(self): + assert self.is_rel() + entries = [] + for i in range(0, self.sh_size, self.sh_entsize): + entries.append(Relocation(self.fmt, self.data[i:i+self.sh_entsize], self.sh_type)) + self.relocations = entries + + def local_symbols(self): + assert self.sh_type == SHT_SYMTAB + return self.symbol_entries[:self.sh_info] + + def global_symbols(self): + assert self.sh_type == SHT_SYMTAB + return self.symbol_entries[self.sh_info:] + + def relocate_mdebug(self, original_offset): + assert self.sh_type == SHT_MIPS_DEBUG + new_data = bytearray(self.data) + shift_by = self.sh_offset - original_offset + + # Update the file-relative offsets in the Symbolic HDRR + hdrr_magic, hdrr_vstamp, hdrr_ilineMax, hdrr_cbLine, \ + hdrr_cbLineOffset, hdrr_idnMax, hdrr_cbDnOffset, hdrr_ipdMax, \ + hdrr_cbPdOffset, hdrr_isymMax, hdrr_cbSymOffset, hdrr_ioptMax, \ + hdrr_cbOptOffset, hdrr_iauxMax, hdrr_cbAuxOffset, hdrr_issMax, \ + hdrr_cbSsOffset, hdrr_issExtMax, hdrr_cbSsExtOffset, hdrr_ifdMax, \ + hdrr_cbFdOffset, hdrr_crfd, hdrr_cbRfdOffset, hdrr_iextMax, \ + hdrr_cbExtOffset = self.fmt.unpack("HHIIIIIIIIIIIIIIIIIIIIIII", self.data[0:0x60]) + + assert hdrr_magic == 0x7009, "Invalid magic value for .mdebug symbolic header" + + hdrr_cbLineOffset += shift_by + hdrr_cbDnOffset += shift_by + hdrr_cbPdOffset += shift_by + hdrr_cbSymOffset += shift_by + hdrr_cbOptOffset += shift_by + hdrr_cbAuxOffset += shift_by + hdrr_cbSsOffset += shift_by + hdrr_cbSsExtOffset += shift_by + hdrr_cbFdOffset += shift_by + hdrr_cbRfdOffset += shift_by + hdrr_cbExtOffset += shift_by + + new_data[0:0x60] = self.fmt.pack("HHIIIIIIIIIIIIIIIIIIIIIII", hdrr_magic, hdrr_vstamp, hdrr_ilineMax, hdrr_cbLine, \ + hdrr_cbLineOffset, hdrr_idnMax, hdrr_cbDnOffset, hdrr_ipdMax, \ + hdrr_cbPdOffset, hdrr_isymMax, hdrr_cbSymOffset, hdrr_ioptMax, \ + hdrr_cbOptOffset, hdrr_iauxMax, hdrr_cbAuxOffset, hdrr_issMax, \ + hdrr_cbSsOffset, hdrr_issExtMax, hdrr_cbSsExtOffset, hdrr_ifdMax, \ + hdrr_cbFdOffset, hdrr_crfd, hdrr_cbRfdOffset, hdrr_iextMax, \ + hdrr_cbExtOffset) + + self.data = bytes(new_data) + +class ElfFile: + def __init__(self, data): + self.data = data + assert data[:4] == b'\x7fELF', "not an ELF file" + + self.elf_header = ElfHeader(data[0:52]) + self.fmt = self.elf_header.fmt + + offset, size = self.elf_header.e_shoff, self.elf_header.e_shentsize + null_section = Section(self.fmt, data[offset:offset + size], data, 0) + num_sections = self.elf_header.e_shnum or null_section.sh_size + + self.sections = [null_section] + for i in range(1, num_sections): + ind = offset + i * size + self.sections.append(Section(self.fmt, data[ind:ind + size], data, i)) + + symtab = None + for s in self.sections: + if s.sh_type == SHT_SYMTAB: + assert not symtab + symtab = s + assert symtab is not None + self.symtab = symtab + + shstr = self.sections[self.elf_header.e_shstrndx] + for s in self.sections: + s.name = shstr.lookup_str(s.sh_name) + s.late_init(self.sections) + + def find_section(self, name): + for s in self.sections: + if s.name == name: + return s + return None + + def add_section(self, name, sh_type, sh_flags, sh_link, sh_info, sh_addralign, sh_entsize, data): + shstr = self.sections[self.elf_header.e_shstrndx] + sh_name = shstr.add_str(name) + s = Section.from_parts(self.fmt, sh_name=sh_name, sh_type=sh_type, + sh_flags=sh_flags, sh_link=sh_link, sh_info=sh_info, + sh_addralign=sh_addralign, sh_entsize=sh_entsize, data=data, + index=len(self.sections)) + self.sections.append(s) + s.name = name + s.late_init(self.sections) + return s + + def drop_mdebug_gptab(self): + # We can only drop sections at the end, since otherwise section + # references might be wrong. Luckily, these sections typically are. + while self.sections[-1].sh_type in [SHT_MIPS_DEBUG, SHT_MIPS_GPTAB]: + self.sections.pop() + + def write(self, filename): + outfile = open(filename, 'wb') + outidx = 0 + def write_out(data): + nonlocal outidx + outfile.write(data) + outidx += len(data) + def pad_out(align): + if align and outidx % align: + write_out(b'\0' * (align - outidx % align)) + + self.elf_header.e_shnum = len(self.sections) + write_out(self.elf_header.to_bin()) + + for s in self.sections: + if s.sh_type != SHT_NOBITS and s.sh_type != SHT_NULL: + pad_out(s.sh_addralign) + old_offset = s.sh_offset + s.sh_offset = outidx + if s.sh_type == SHT_MIPS_DEBUG and s.sh_offset != old_offset: + # The .mdebug section has moved, relocate offsets + s.relocate_mdebug(old_offset) + write_out(s.data) + + pad_out(4) + self.elf_header.e_shoff = outidx + for s in self.sections: + write_out(s.header_to_bin()) + + outfile.seek(0) + outfile.write(self.elf_header.to_bin()) + outfile.close() + + +def is_temp_name(name): + return name.startswith('_asmpp_') + + +# https://stackoverflow.com/a/241506 +def re_comment_replacer(match): + s = match.group(0) + if s[0] in "/#": + return " " + else: + return s + + +re_comment_or_string = re.compile( + r'#.*|/\*.*?\*/|"(?:\\.|[^\\"])*"' +) + + +class Failure(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + + +class GlobalState: + def __init__(self, min_instr_count, skip_instr_count, use_jtbl_for_rodata, prelude_if_late_rodata, mips1, pascal): + # A value that hopefully never appears as a 32-bit rodata constant (or we + # miscompile late rodata). Increases by 1 in each step. + self.late_rodata_hex = 0xE0123456 + self.valuectr = 0 + self.namectr = 0 + self.min_instr_count = min_instr_count + self.skip_instr_count = skip_instr_count + self.use_jtbl_for_rodata = use_jtbl_for_rodata + self.prelude_if_late_rodata = prelude_if_late_rodata + self.mips1 = mips1 + self.pascal = pascal + + def next_late_rodata_hex(self): + dummy_bytes = struct.pack('>I', self.late_rodata_hex) + if (self.late_rodata_hex & 0xffff) == 0: + # Avoid lui + self.late_rodata_hex += 1 + self.late_rodata_hex += 1 + return dummy_bytes + + def make_name(self, cat): + self.namectr += 1 + return '_asmpp_{}{}'.format(cat, self.namectr) + + def func_prologue(self, name): + if self.pascal: + return " ".join([ + "procedure {}();".format(name), + "type", + " pi = ^integer;", + " pf = ^single;", + " pd = ^double;", + "var", + " vi: pi;", + " vf: pf;", + " vd: pd;", + "begin", + " vi := vi;", + " vf := vf;", + " vd := vd;", + ]) + else: + return 'void {}(void) {{'.format(name) + + def func_epilogue(self): + if self.pascal: + return "end;" + else: + return "}" + + def pascal_assignment(self, tp, val): + self.valuectr += 1 + address = (8 * self.valuectr) & 0x7FFF + return 'v{} := p{}({}); v{}^ := {};'.format(tp, tp, address, tp, val) + +Function = namedtuple('Function', ['text_glabels', 'asm_conts', 'late_rodata_dummy_bytes', 'jtbl_rodata_size', 'late_rodata_asm_conts', 'fn_desc', 'data']) + + +class GlobalAsmBlock: + def __init__(self, fn_desc): + self.fn_desc = fn_desc + self.cur_section = '.text' + self.asm_conts = [] + self.late_rodata_asm_conts = [] + self.late_rodata_alignment = 0 + self.late_rodata_alignment_from_content = False + self.text_glabels = [] + self.fn_section_sizes = { + '.text': 0, + '.data': 0, + '.bss': 0, + '.rodata': 0, + '.late_rodata': 0, + } + self.fn_ins_inds = [] + self.glued_line = '' + self.num_lines = 0 + + def fail(self, message, line=None): + context = self.fn_desc + if line: + context += ", at line \"" + line + "\"" + raise Failure(message + "\nwithin " + context) + + def count_quoted_size(self, line, z, real_line, output_enc): + line = line.encode(output_enc).decode('latin1') + in_quote = False + has_comma = True + num_parts = 0 + ret = 0 + i = 0 + digits = "0123456789" # 0-7 would be more sane, but this matches GNU as + while i < len(line): + c = line[i] + i += 1 + if not in_quote: + if c == '"': + in_quote = True + if z and not has_comma: + self.fail(".asciiz with glued strings is not supported due to GNU as version diffs") + num_parts += 1 + elif c == ',': + has_comma = True + else: + if c == '"': + in_quote = False + has_comma = False + continue + ret += 1 + if c != '\\': + continue + if i == len(line): + self.fail("backslash at end of line not supported", real_line) + c = line[i] + i += 1 + # (if c is in "bfnrtv", we have a real escaped literal) + if c == 'x': + # hex literal, consume any number of hex chars, possibly none + while i < len(line) and line[i] in digits + "abcdefABCDEF": + i += 1 + elif c in digits: + # octal literal, consume up to two more digits + it = 0 + while i < len(line) and line[i] in digits and it < 2: + i += 1 + it += 1 + + if in_quote: + self.fail("unterminated string literal", real_line) + if num_parts == 0: + self.fail(".ascii with no string", real_line) + return ret + num_parts if z else ret + + def align2(self): + while self.fn_section_sizes[self.cur_section] % 2 != 0: + self.fn_section_sizes[self.cur_section] += 1 + + def align4(self): + while self.fn_section_sizes[self.cur_section] % 4 != 0: + self.fn_section_sizes[self.cur_section] += 1 + + def add_sized(self, size, line): + if self.cur_section in ['.text', '.late_rodata']: + if size % 4 != 0: + self.fail("size must be a multiple of 4", line) + if size < 0: + self.fail("size cannot be negative", line) + self.fn_section_sizes[self.cur_section] += size + if self.cur_section == '.text': + if not self.text_glabels: + self.fail(".text block without an initial glabel", line) + self.fn_ins_inds.append((self.num_lines - 1, size // 4)) + + def process_line(self, line, output_enc): + self.num_lines += 1 + if line.endswith('\\'): + self.glued_line += line[:-1] + return + line = self.glued_line + line + self.glued_line = '' + + real_line = line + line = re.sub(re_comment_or_string, re_comment_replacer, line) + line = line.strip() + line = re.sub(r'^[a-zA-Z0-9_]+:\s*', '', line) + changed_section = False + emitting_double = False + if line.startswith('glabel ') and self.cur_section == '.text': + self.text_glabels.append(line.split()[1]) + if not line: + pass # empty line + elif line.startswith('glabel ') or line.startswith('dlabel ') or line.startswith('endlabel ') or (' ' not in line and line.endswith(':')): + pass # label + elif line.startswith('.section') or line in ['.text', '.data', '.rdata', '.rodata', '.bss', '.late_rodata']: + # section change + self.cur_section = '.rodata' if line == '.rdata' else line.split(',')[0].split()[-1] + if self.cur_section not in ['.data', '.text', '.rodata', '.late_rodata', '.bss']: + self.fail("unrecognized .section directive", real_line) + changed_section = True + elif line.startswith('.late_rodata_alignment'): + if self.cur_section != '.late_rodata': + self.fail(".late_rodata_alignment must occur within .late_rodata section", real_line) + value = int(line.split()[1]) + if value not in [4, 8]: + self.fail(".late_rodata_alignment argument must be 4 or 8", real_line) + if self.late_rodata_alignment and self.late_rodata_alignment != value: + self.fail(".late_rodata_alignment alignment assumption conflicts with earlier .double directive. Make sure to provide explicit alignment padding.") + self.late_rodata_alignment = value + changed_section = True + elif line.startswith('.incbin'): + self.add_sized(int(line.split(',')[-1].strip(), 0), real_line) + elif line.startswith('.word') or line.startswith('.gpword') or line.startswith('.float'): + self.align4() + self.add_sized(4 * len(line.split(',')), real_line) + elif line.startswith('.double'): + self.align4() + if self.cur_section == '.late_rodata': + align8 = self.fn_section_sizes[self.cur_section] % 8 + # Automatically set late_rodata_alignment, so the generated C code uses doubles. + # This gives us correct alignment for the transferred doubles even when the + # late_rodata_alignment is wrong, e.g. for non-matching compilation. + if not self.late_rodata_alignment: + self.late_rodata_alignment = 8 - align8 + self.late_rodata_alignment_from_content = True + elif self.late_rodata_alignment != 8 - align8: + if self.late_rodata_alignment_from_content: + self.fail("found two .double directives with different start addresses mod 8. Make sure to provide explicit alignment padding.", real_line) + else: + self.fail(".double at address that is not 0 mod 8 (based on .late_rodata_alignment assumption). Make sure to provide explicit alignment padding.", real_line) + self.add_sized(8 * len(line.split(',')), real_line) + emitting_double = True + elif line.startswith('.space'): + self.add_sized(int(line.split()[1], 0), real_line) + elif line.startswith('.balign') or line.startswith('.align'): + align = int(line.split()[1]) + if align != 4: + self.fail("only .balign 4 is supported", real_line) + self.align4() + elif line.startswith('.asci'): + z = (line.startswith('.asciz') or line.startswith('.asciiz')) + self.add_sized(self.count_quoted_size(line, z, real_line, output_enc), real_line) + elif line.startswith('.byte'): + self.add_sized(len(line.split(',')), real_line) + elif line.startswith('.half'): + self.align2() + self.add_sized(2*len(line.split(',')), real_line) + elif line.startswith('.'): + # .macro, ... + self.fail("asm directive not supported", real_line) + else: + # Unfortunately, macros are hard to support for .rodata -- + # we don't know how how space they will expand to before + # running the assembler, but we need that information to + # construct the C code. So if we need that we'll either + # need to run the assembler twice (at least in some rare + # cases), or change how this program is invoked. + # Similarly, we can't currently deal with pseudo-instructions + # that expand to several real instructions. + if self.cur_section != '.text': + self.fail("instruction or macro call in non-.text section? not supported", real_line) + self.add_sized(4, real_line) + if self.cur_section == '.late_rodata': + if not changed_section: + if emitting_double: + self.late_rodata_asm_conts.append(".align 0") + self.late_rodata_asm_conts.append(real_line) + if emitting_double: + self.late_rodata_asm_conts.append(".align 2") + else: + self.asm_conts.append(real_line) + + def finish(self, state): + src = [''] * (self.num_lines + 1) + late_rodata_dummy_bytes = [] + jtbl_rodata_size = 0 + late_rodata_fn_output = [] + + num_instr = self.fn_section_sizes['.text'] // 4 + + if self.fn_section_sizes['.late_rodata'] > 0: + # Generate late rodata by emitting unique float constants. + # This requires 3 instructions for each 4 bytes of rodata. + # If we know alignment, we can use doubles, which give 3 + # instructions for 8 bytes of rodata. + size = self.fn_section_sizes['.late_rodata'] // 4 + skip_next = False + needs_double = (self.late_rodata_alignment != 0) + extra_mips1_nop = False + if state.pascal: + jtbl_size = 9 if state.mips1 else 8 + jtbl_min_rodata_size = 2 + else: + jtbl_size = 11 if state.mips1 else 9 + jtbl_min_rodata_size = 5 + for i in range(size): + if skip_next: + skip_next = False + continue + # Jump tables give 9 instructions (11 with -mips1) for >= 5 words of rodata, + # and should be emitted when: + # - -O2 or -O2 -g3 are used, which give the right codegen + # - we have emitted our first .float/.double (to ensure that we find the + # created rodata in the binary) + # - we have emitted our first .double, if any (to ensure alignment of doubles + # in shifted rodata sections) + # - we have at least 5 words of rodata left to emit (otherwise IDO does not + # generate a jump table) + # - we have at least 10 more instructions to go in this function (otherwise our + # function size computation will be wrong since the delay slot goes unused) + if (not needs_double and state.use_jtbl_for_rodata and i >= 1 and + size - i >= jtbl_min_rodata_size and + num_instr - len(late_rodata_fn_output) >= jtbl_size + 1): + if state.pascal: + cases = " ".join("{}: ;".format(case) for case in range(size - i)) + line = "case 0 of " + cases + " otherwise end;" + else: + cases = " ".join("case {}:".format(case) for case in range(size - i)) + line = "switch (*(volatile int*)0) { " + cases + " ; }" + late_rodata_fn_output.append(line) + late_rodata_fn_output.extend([""] * (jtbl_size - 1)) + jtbl_rodata_size = (size - i) * 4 + extra_mips1_nop = i != 2 + break + dummy_bytes = state.next_late_rodata_hex() + late_rodata_dummy_bytes.append(dummy_bytes) + if self.late_rodata_alignment == 4 * ((i + 1) % 2 + 1) and i + 1 < size: + dummy_bytes2 = state.next_late_rodata_hex() + late_rodata_dummy_bytes.append(dummy_bytes2) + fval, = struct.unpack('>d', dummy_bytes + dummy_bytes2) + if state.pascal: + line = state.pascal_assignment('d', fval) + else: + line = '*(volatile double*)0 = {};'.format(fval) + late_rodata_fn_output.append(line) + skip_next = True + needs_double = False + if state.mips1: + # mips1 does not have ldc1/sdc1 + late_rodata_fn_output.append('') + late_rodata_fn_output.append('') + extra_mips1_nop = False + else: + fval, = struct.unpack('>f', dummy_bytes) + if state.pascal: + line = state.pascal_assignment('f', fval) + else: + line = '*(volatile float*)0 = {}f;'.format(fval) + late_rodata_fn_output.append(line) + extra_mips1_nop = True + late_rodata_fn_output.append('') + late_rodata_fn_output.append('') + if state.mips1 and extra_mips1_nop: + late_rodata_fn_output.append('') + + text_name = None + if self.fn_section_sizes['.text'] > 0 or late_rodata_fn_output: + text_name = state.make_name('func') + src[0] = state.func_prologue(text_name) + src[self.num_lines] = state.func_epilogue() + instr_count = self.fn_section_sizes['.text'] // 4 + if instr_count < state.min_instr_count: + self.fail("too short .text block") + tot_emitted = 0 + tot_skipped = 0 + fn_emitted = 0 + fn_skipped = 0 + skipping = True + rodata_stack = late_rodata_fn_output[::-1] + for (line, count) in self.fn_ins_inds: + for _ in range(count): + if (fn_emitted > MAX_FN_SIZE and instr_count - tot_emitted > state.min_instr_count and + (not rodata_stack or rodata_stack[-1])): + # Don't let functions become too large. When a function reaches 284 + # instructions, and -O2 -framepointer flags are passed, the IRIX + # compiler decides it is a great idea to start optimizing more. + # Also, Pascal cannot handle too large functions before it runs out + # of unique statements to write. + fn_emitted = 0 + fn_skipped = 0 + skipping = True + src[line] += (' ' + state.func_epilogue() + ' ' + + state.func_prologue(state.make_name('large_func')) + ' ') + if ( + skipping and + fn_skipped < state.skip_instr_count + + (state.prelude_if_late_rodata if rodata_stack else 0) + ): + fn_skipped += 1 + tot_skipped += 1 + else: + skipping = False + if rodata_stack: + src[line] += rodata_stack.pop() + elif state.pascal: + src[line] += state.pascal_assignment('i', '0') + else: + src[line] += '*(volatile int*)0 = 0;' + tot_emitted += 1 + fn_emitted += 1 + if rodata_stack: + size = len(late_rodata_fn_output) // 3 + available = instr_count - tot_skipped + self.fail( + "late rodata to text ratio is too high: {} / {} must be <= 1/3\n" + "add .late_rodata_alignment (4|8) to the .late_rodata " + "block to double the allowed ratio." + .format(size, available)) + + rodata_name = None + if self.fn_section_sizes['.rodata'] > 0: + if state.pascal: + self.fail(".rodata isn't supported with Pascal for now") + rodata_name = state.make_name('rodata') + src[self.num_lines] += ' const char {}[{}] = {{1}};'.format(rodata_name, self.fn_section_sizes['.rodata']) + + data_name = None + if self.fn_section_sizes['.data'] > 0: + data_name = state.make_name('data') + if state.pascal: + line = ' var {}: packed array[1..{}] of char := [otherwise: 0];'.format(data_name, self.fn_section_sizes['.data']) + else: + line = ' char {}[{}] = {{1}};'.format(data_name, self.fn_section_sizes['.data']) + src[self.num_lines] += line + + bss_name = None + if self.fn_section_sizes['.bss'] > 0: + if state.pascal: + self.fail(".bss isn't supported with Pascal") + bss_name = state.make_name('bss') + src[self.num_lines] += ' char {}[{}];'.format(bss_name, self.fn_section_sizes['.bss']) + + fn = Function( + text_glabels=self.text_glabels, + asm_conts=self.asm_conts, + late_rodata_dummy_bytes=late_rodata_dummy_bytes, + jtbl_rodata_size=jtbl_rodata_size, + late_rodata_asm_conts=self.late_rodata_asm_conts, + fn_desc=self.fn_desc, + data={ + '.text': (text_name, self.fn_section_sizes['.text']), + '.data': (data_name, self.fn_section_sizes['.data']), + '.rodata': (rodata_name, self.fn_section_sizes['.rodata']), + '.bss': (bss_name, self.fn_section_sizes['.bss']), + }) + return src, fn + +cutscene_data_regexpr = re.compile(r"CutsceneData (.|\n)*\[\] = {") +float_regexpr = re.compile(r"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f") + +def repl_float_hex(m): + return str(struct.unpack(">I", struct.pack(">f", float(m.group(0).strip().rstrip("f"))))[0]) + +Opts = namedtuple('Opts', ['opt', 'framepointer', 'mips1', 'kpic', 'pascal', 'input_enc', 'output_enc']) + +def parse_source(f, opts, out_dependencies, print_source=None): + if opts.opt in ['O1', 'O2']: + if opts.framepointer: + min_instr_count = 6 + skip_instr_count = 5 + else: + min_instr_count = 2 + skip_instr_count = 1 + elif opts.opt == 'O0': + if opts.framepointer: + min_instr_count = 8 + skip_instr_count = 8 + else: + min_instr_count = 4 + skip_instr_count = 4 + elif opts.opt == 'g': + if opts.framepointer: + min_instr_count = 7 + skip_instr_count = 7 + else: + min_instr_count = 4 + skip_instr_count = 4 + elif opts.opt == 'g3': + if opts.framepointer: + min_instr_count = 4 + skip_instr_count = 4 + else: + min_instr_count = 2 + skip_instr_count = 2 + else: + raise Failure("must pass one of -g, -O0, -O1, -O2, -O2 -g3") + prelude_if_late_rodata = 0 + if opts.kpic: + # Without optimizations, the PIC prelude always takes up 3 instructions. + # With optimizations, the prelude is optimized out if there's no late rodata. + if opts.opt in ('g3', 'O2'): + prelude_if_late_rodata = 3 + else: + min_instr_count += 3 + skip_instr_count += 3 + + use_jtbl_for_rodata = False + if opts.opt in ['O2', 'g3'] and not opts.framepointer and not opts.kpic: + use_jtbl_for_rodata = True + + state = GlobalState(min_instr_count, skip_instr_count, use_jtbl_for_rodata, prelude_if_late_rodata, opts.mips1, opts.pascal) + output_enc = opts.output_enc + + global_asm = None + asm_functions = [] + output_lines = [ + '#line 1 "' + f.name + '"' + ] + + is_cutscene_data = False + is_early_include = False + + for line_no, raw_line in enumerate(f, 1): + raw_line = raw_line.rstrip() + line = raw_line.lstrip() + + # Print exactly one output line per source line, to make compiler + # errors have correct line numbers. These will be overridden with + # reasonable content further down. + output_lines.append('') + + if global_asm is not None: + if line.startswith(')'): + src, fn = global_asm.finish(state) + for i, line2 in enumerate(src): + output_lines[start_index + i] = line2 + asm_functions.append(fn) + global_asm = None + else: + global_asm.process_line(raw_line, output_enc) + elif line in ['GLOBAL_ASM(', '#pragma GLOBAL_ASM(']: + global_asm = GlobalAsmBlock("GLOBAL_ASM block at line " + str(line_no)) + start_index = len(output_lines) + elif ((line.startswith('GLOBAL_ASM("') or line.startswith('#pragma GLOBAL_ASM("')) + and line.endswith('")')): + fname = line[line.index('(') + 2 : -2] + out_dependencies.append(fname) + global_asm = GlobalAsmBlock(fname) + with open(fname, encoding=opts.input_enc) as f: + for line2 in f: + global_asm.process_line(line2.rstrip(), output_enc) + src, fn = global_asm.finish(state) + output_lines[-1] = ''.join(src) + asm_functions.append(fn) + global_asm = None + elif line == '#pragma asmproc recurse': + # C includes qualified as + # #pragma asmproc recurse + # #include "file.c" + # will be processed recursively when encountered + is_early_include = True + elif is_early_include: + # Previous line was a #pragma asmproc recurse + is_early_include = False + if not line.startswith("#include "): + raise Failure("#pragma asmproc recurse must be followed by an #include ") + fpath = os.path.dirname(f.name) + fname = os.path.join(fpath, line[line.index(' ') + 2 : -1]) + out_dependencies.append(fname) + include_src = StringIO() + with open(fname, encoding=opts.input_enc) as include_file: + parse_source(include_file, opts, out_dependencies, include_src) + include_src.write('#line ' + str(line_no + 1) + ' "' + f.name + '"') + output_lines[-1] = include_src.getvalue() + include_src.close() + else: + # This is a hack to replace all floating-point numbers in an array of a particular type + # (in this case CutsceneData) with their corresponding IEEE-754 hexadecimal representation + if cutscene_data_regexpr.search(line) is not None: + is_cutscene_data = True + elif line.endswith("};"): + is_cutscene_data = False + if is_cutscene_data: + raw_line = re.sub(float_regexpr, repl_float_hex, raw_line) + output_lines[-1] = raw_line + + if print_source: + if isinstance(print_source, StringIO): + for line in output_lines: + print_source.write(line + '\n') + else: + newline_encoded = "\n".encode(output_enc) + for line in output_lines: + try: + line_encoded = line.encode(output_enc) + except UnicodeEncodeError: + print("Failed to encode a line to", output_enc) + print("The line:", line) + print("The line, utf-8-encoded:", line.encode("utf-8")) + raise + print_source.write(line_encoded) + print_source.write(newline_encoded) + print_source.flush() + + return asm_functions + +def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc, drop_mdebug_gptab, convert_statics): + SECTIONS = ['.data', '.text', '.rodata', '.bss'] + + with open(objfile_name, 'rb') as f: + objfile = ElfFile(f.read()) + fmt = objfile.fmt + + prev_locs = { + '.text': 0, + '.data': 0, + '.rodata': 0, + '.bss': 0, + } + to_copy = { + '.text': [], + '.data': [], + '.rodata': [], + '.bss': [], + } + asm = [] + all_late_rodata_dummy_bytes = [] + all_jtbl_rodata_size = [] + late_rodata_asm = [] + late_rodata_source_name_start = None + late_rodata_source_name_end = None + + # Generate an assembly file with all the assembly we need to fill in. For + # simplicity we pad with nops/.space so that addresses match exactly, so we + # don't have to fix up relocations/symbol references. + all_text_glabels = set() + func_sizes = {} + for function in functions: + ifdefed = False + for sectype, (temp_name, size) in function.data.items(): + if temp_name is None: + continue + assert size > 0 + loc = objfile.symtab.find_symbol(temp_name) + if loc is None: + ifdefed = True + break + loc = loc[1] + prev_loc = prev_locs[sectype] + if loc < prev_loc: + # If the dummy C generates too little asm, and we have two + # consecutive GLOBAL_ASM blocks, we detect that error here. + # On the other hand, if it generates too much, we don't have + # a good way of discovering that error: it's indistinguishable + # from a static symbol occurring after the GLOBAL_ASM block. + raise Failure("Wrongly computed size for section {} (diff {}). This is an asm-processor bug!".format(sectype, prev_loc- loc)) + if loc != prev_loc: + asm.append('.section ' + sectype) + if sectype == '.text': + for i in range((loc - prev_loc) // 4): + asm.append('nop') + else: + asm.append('.space {}'.format(loc - prev_loc)) + to_copy[sectype].append((loc, size, temp_name, function.fn_desc)) + if function.text_glabels and sectype == '.text': + func_sizes[function.text_glabels[0]] = size + prev_locs[sectype] = loc + size + if not ifdefed: + all_text_glabels.update(function.text_glabels) + all_late_rodata_dummy_bytes.append(function.late_rodata_dummy_bytes) + all_jtbl_rodata_size.append(function.jtbl_rodata_size) + late_rodata_asm.append(function.late_rodata_asm_conts) + for sectype, (temp_name, size) in function.data.items(): + if temp_name is not None: + asm.append('.section ' + sectype) + asm.append('glabel ' + temp_name + '_asm_start') + asm.append('.text') + for line in function.asm_conts: + asm.append(line) + for sectype, (temp_name, size) in function.data.items(): + if temp_name is not None: + asm.append('.section ' + sectype) + asm.append('glabel ' + temp_name + '_asm_end') + if any(late_rodata_asm): + late_rodata_source_name_start = '_asmpp_late_rodata_start' + late_rodata_source_name_end = '_asmpp_late_rodata_end' + asm.append('.section .late_rodata') + # Put some padding at the start to avoid conflating symbols with + # references to the whole section. + asm.append('.word 0, 0') + asm.append('glabel {}'.format(late_rodata_source_name_start)) + for conts in late_rodata_asm: + asm.extend(conts) + asm.append('glabel {}'.format(late_rodata_source_name_end)) + + o_file = tempfile.NamedTemporaryFile(prefix='asm-processor', suffix='.o', delete=False) + o_name = o_file.name + o_file.close() + s_file = tempfile.NamedTemporaryFile(prefix='asm-processor', suffix='.s', delete=False) + s_name = s_file.name + try: + s_file.write(asm_prelude + b'\n') + for line in asm: + s_file.write(line.encode(output_enc) + b'\n') + s_file.close() + ret = os.system(assembler + " " + s_name + " -o " + o_name) + if ret != 0: + raise Failure("failed to assemble") + with open(o_name, 'rb') as f: + asm_objfile = ElfFile(f.read()) + + # Remove clutter from objdump output for tests, and make the tests + # portable by avoiding absolute paths. Outside of tests .mdebug is + # useful for showing source together with asm, though. + mdebug_section = objfile.find_section('.mdebug') + if drop_mdebug_gptab: + objfile.drop_mdebug_gptab() + + # Unify reginfo sections + target_reginfo = objfile.find_section('.reginfo') + if target_reginfo is not None: + source_reginfo_data = list(asm_objfile.find_section('.reginfo').data) + data = list(target_reginfo.data) + for i in range(20): + data[i] |= source_reginfo_data[i] + target_reginfo.data = bytes(data) + + # Move over section contents + modified_text_positions = set() + jtbl_rodata_positions = set() + last_rodata_pos = 0 + for sectype in SECTIONS: + if not to_copy[sectype]: + continue + source = asm_objfile.find_section(sectype) + assert source is not None, "didn't find source section: " + sectype + for (pos, count, temp_name, fn_desc) in to_copy[sectype]: + loc1 = asm_objfile.symtab.find_symbol_in_section(temp_name + '_asm_start', source) + loc2 = asm_objfile.symtab.find_symbol_in_section(temp_name + '_asm_end', source) + assert loc1 == pos, "assembly and C files don't line up for section " + sectype + ", " + fn_desc + if loc2 - loc1 != count: + raise Failure("incorrectly computed size for section " + sectype + ", " + fn_desc + ". If using .double, make sure to provide explicit alignment padding.") + if sectype == '.bss': + continue + target = objfile.find_section(sectype) + assert target is not None, "missing target section of type " + sectype + data = list(target.data) + for (pos, count, _, _) in to_copy[sectype]: + data[pos:pos + count] = source.data[pos:pos + count] + if sectype == '.text': + assert count % 4 == 0 + assert pos % 4 == 0 + for i in range(count // 4): + modified_text_positions.add(pos + 4 * i) + elif sectype == '.rodata': + last_rodata_pos = pos + count + target.data = bytes(data) + + # Move over late rodata. This is heuristic, sadly, since I can't think + # of another way of doing it. + moved_late_rodata = {} + if any(all_late_rodata_dummy_bytes) or any(all_jtbl_rodata_size): + source = asm_objfile.find_section('.late_rodata') + target = objfile.find_section('.rodata') + source_pos = asm_objfile.symtab.find_symbol_in_section(late_rodata_source_name_start, source) + source_end = asm_objfile.symtab.find_symbol_in_section(late_rodata_source_name_end, source) + if source_end - source_pos != sum(map(len, all_late_rodata_dummy_bytes)) * 4 + sum(all_jtbl_rodata_size): + raise Failure("computed wrong size of .late_rodata") + new_data = list(target.data) + for dummy_bytes_list, jtbl_rodata_size in zip(all_late_rodata_dummy_bytes, all_jtbl_rodata_size): + for index, dummy_bytes in enumerate(dummy_bytes_list): + if not fmt.is_big_endian: + dummy_bytes = dummy_bytes[::-1] + pos = target.data.index(dummy_bytes, last_rodata_pos) + # This check is nice, but makes time complexity worse for large files: + if SLOW_CHECKS and target.data.find(dummy_bytes, pos + 4) != -1: + raise Failure("multiple occurrences of late_rodata hex magic. Change asm-processor to use something better than 0xE0123456!") + if index == 0 and len(dummy_bytes_list) > 1 and target.data[pos+4:pos+8] == b'\0\0\0\0': + # Ugly hack to handle double alignment for non-matching builds. + # We were told by .late_rodata_alignment (or deduced from a .double) + # that a function's late_rodata started out 4 (mod 8), and emitted + # a float and then a double. But it was actually 0 (mod 8), so our + # double was moved by 4 bytes. To make them adjacent to keep jump + # tables correct, move the float by 4 bytes as well. + new_data[pos:pos+4] = b'\0\0\0\0' + pos += 4 + new_data[pos:pos+4] = source.data[source_pos:source_pos+4] + moved_late_rodata[source_pos] = pos + last_rodata_pos = pos + 4 + source_pos += 4 + if jtbl_rodata_size > 0: + assert dummy_bytes_list, "should always have dummy bytes before jtbl data" + pos = last_rodata_pos + new_data[pos : pos + jtbl_rodata_size] = \ + source.data[source_pos : source_pos + jtbl_rodata_size] + for i in range(0, jtbl_rodata_size, 4): + moved_late_rodata[source_pos + i] = pos + i + jtbl_rodata_positions.add(pos + i) + last_rodata_pos += jtbl_rodata_size + source_pos += jtbl_rodata_size + target.data = bytes(new_data) + + # Merge strtab data. + strtab_adj = len(objfile.symtab.strtab.data) + objfile.symtab.strtab.data += asm_objfile.symtab.strtab.data + + # Find relocated symbols + relocated_symbols = set() + for sectype in SECTIONS + ['.late_rodata']: + for obj in [asm_objfile, objfile]: + sec = obj.find_section(sectype) + if sec is None: + continue + for reltab in sec.relocated_by: + for rel in reltab.relocations: + relocated_symbols.add(obj.symtab.symbol_entries[rel.sym_index]) + + # Move over symbols, deleting the temporary function labels. + # Skip over new local symbols that aren't relocated against, to + # avoid conflicts. + empty_symbol = objfile.symtab.symbol_entries[0] + new_syms = [s for s in objfile.symtab.symbol_entries[1:] if not is_temp_name(s.name)] + + for i, s in enumerate(asm_objfile.symtab.symbol_entries): + is_local = (i < asm_objfile.symtab.sh_info) + if is_local and s not in relocated_symbols: + continue + if is_temp_name(s.name): + assert s not in relocated_symbols + continue + if s.st_shndx not in [SHN_UNDEF, SHN_ABS]: + section_name = asm_objfile.sections[s.st_shndx].name + target_section_name = section_name + if section_name == ".late_rodata": + target_section_name = ".rodata" + elif section_name not in SECTIONS: + raise Failure("generated assembly .o must only have symbols for .text, .data, .rodata, .late_rodata, ABS and UNDEF, but found " + section_name) + objfile_section = objfile.find_section(target_section_name) + if objfile_section is None: + raise Failure("generated assembly .o has section that real objfile lacks: " + target_section_name) + s.st_shndx = objfile_section.index + # glabel's aren't marked as functions, making objdump output confusing. Fix that. + if s.name in all_text_glabels: + s.type = STT_FUNC + if s.name in func_sizes: + s.st_size = func_sizes[s.name] + if section_name == '.late_rodata': + if s.st_value == 0: + # This must be a symbol corresponding to the whole .late_rodata + # section, being referred to from a relocation. + # Moving local symbols is tricky, because it requires fixing up + # lo16/hi16 relocation references to .late_rodata+<offset>. + # Just disallow it for now. + raise Failure("local symbols in .late_rodata are not allowed") + s.st_value = moved_late_rodata[s.st_value] + s.st_name += strtab_adj + new_syms.append(s) + make_statics_global = convert_statics in ("global", "global-with-filename") + + # Add static symbols from .mdebug, so they can be referred to from GLOBAL_ASM + if mdebug_section and convert_statics != "no": + strtab_index = len(objfile.symtab.strtab.data) + new_strtab_data = [] + ifd_max, cb_fd_offset = fmt.unpack('II', mdebug_section.data[18*4 : 20*4]) + cb_sym_offset, = fmt.unpack('I', mdebug_section.data[9*4 : 10*4]) + cb_ss_offset, = fmt.unpack('I', mdebug_section.data[15*4 : 16*4]) + for i in range(ifd_max): + offset = cb_fd_offset + 18*4*i + iss_base, _, isym_base, csym = fmt.unpack('IIII', objfile.data[offset + 2*4 : offset + 6*4]) + for j in range(csym): + offset2 = cb_sym_offset + 12 * (isym_base + j) + iss, value, st_sc_index = fmt.unpack('III', objfile.data[offset2 : offset2 + 12]) + st = (st_sc_index >> 26) + sc = (st_sc_index >> 21) & 0x1f + if st in [MIPS_DEBUG_ST_STATIC, MIPS_DEBUG_ST_STATIC_PROC]: + symbol_name_offset = cb_ss_offset + iss_base + iss + symbol_name_offset_end = objfile.data.find(b'\0', symbol_name_offset) + assert symbol_name_offset_end != -1 + symbol_name = objfile.data[symbol_name_offset : symbol_name_offset_end + 1] + emitted_symbol_name = symbol_name + if convert_statics == "global-with-filename": + # Change the emitted symbol name to include the filename, + # but don't let that affect deduplication logic. + emitted_symbol_name = objfile_name.encode("utf-8") + b":" + symbol_name + section_name = {1: '.text', 2: '.data', 3: '.bss', 15: '.rodata'}[sc] + section = objfile.find_section(section_name) + symtype = STT_FUNC if sc == 1 else STT_OBJECT + binding = STB_GLOBAL if make_statics_global else STB_LOCAL + sym = Symbol.from_parts( + fmt, + st_name=strtab_index, + st_value=value, + st_size=0, + st_info=(binding << 4 | symtype), + st_other=STV_DEFAULT, + st_shndx=section.index, + strtab=objfile.symtab.strtab, + name=symbol_name[:-1].decode('latin1')) + strtab_index += len(emitted_symbol_name) + new_strtab_data.append(emitted_symbol_name) + new_syms.append(sym) + objfile.symtab.strtab.data += b''.join(new_strtab_data) + + # Get rid of duplicate symbols, favoring ones that are not UNDEF. + # Skip this for unnamed local symbols though. + new_syms.sort(key=lambda s: 0 if s.st_shndx != SHN_UNDEF else 1) + old_syms = [] + newer_syms = [] + name_to_sym = {} + for s in new_syms: + if s.name == "_gp_disp": + s.type = STT_OBJECT + if s.bind == STB_LOCAL and s.st_shndx == SHN_UNDEF: + raise Failure("local symbol \"" + s.name + "\" is undefined") + if not s.name: + if s.bind != STB_LOCAL: + raise Failure("global symbol with no name") + newer_syms.append(s) + else: + existing = name_to_sym.get(s.name) + if not existing: + name_to_sym[s.name] = s + newer_syms.append(s) + elif s.st_shndx != SHN_UNDEF: + raise Failure("symbol \"" + s.name + "\" defined twice") + else: + s.replace_by = existing + old_syms.append(s) + new_syms = newer_syms + + # Put local symbols in front, with the initial dummy entry first, and + # _gp_disp at the end if it exists. + new_syms.insert(0, empty_symbol) + new_syms.sort(key=lambda s: (s.bind != STB_LOCAL, s.name == "_gp_disp")) + num_local_syms = sum(1 for s in new_syms if s.bind == STB_LOCAL) + + for i, s in enumerate(new_syms): + s.new_index = i + for s in old_syms: + s.new_index = s.replace_by.new_index + objfile.symtab.data = b''.join(s.to_bin() for s in new_syms) + objfile.symtab.sh_info = num_local_syms + + # Fix up relocation symbol references + for sectype in SECTIONS: + target = objfile.find_section(sectype) + + if target is not None: + # fixup relocation symbol indices, since we butchered them above + for reltab in target.relocated_by: + nrels = [] + for rel in reltab.relocations: + if (sectype == '.text' and rel.r_offset in modified_text_positions or + sectype == '.rodata' and rel.r_offset in jtbl_rodata_positions): + # don't include relocations for late_rodata dummy code + continue + rel.sym_index = objfile.symtab.symbol_entries[rel.sym_index].new_index + nrels.append(rel) + reltab.relocations = nrels + reltab.data = b''.join(rel.to_bin() for rel in nrels) + + # Move over relocations + for sectype in SECTIONS + ['.late_rodata']: + source = asm_objfile.find_section(sectype) + if source is None or not source.data: + continue + + target_sectype = '.rodata' if sectype == '.late_rodata' else sectype + target = objfile.find_section(target_sectype) + assert target is not None, target_sectype + target_reltab = objfile.find_section('.rel' + target_sectype) + target_reltaba = objfile.find_section('.rela' + target_sectype) + for reltab in source.relocated_by: + for rel in reltab.relocations: + rel.sym_index = asm_objfile.symtab.symbol_entries[rel.sym_index].new_index + if sectype == '.late_rodata': + rel.r_offset = moved_late_rodata[rel.r_offset] + new_data = b''.join(rel.to_bin() for rel in reltab.relocations) + if reltab.sh_type == SHT_REL: + if not target_reltab: + target_reltab = objfile.add_section('.rel' + target_sectype, + sh_type=SHT_REL, sh_flags=0, + sh_link=objfile.symtab.index, sh_info=target.index, + sh_addralign=4, sh_entsize=8, data=b'') + target_reltab.data += new_data + else: + if not target_reltaba: + target_reltaba = objfile.add_section('.rela' + target_sectype, + sh_type=SHT_RELA, sh_flags=0, + sh_link=objfile.symtab.index, sh_info=target.index, + sh_addralign=4, sh_entsize=12, data=b'') + target_reltaba.data += new_data + + objfile.write(objfile_name) + finally: + s_file.close() + os.remove(s_name) + try: + os.remove(o_name) + except: + pass + +def run_wrapped(argv, outfile, functions): + parser = argparse.ArgumentParser(description="Pre-process .c files and post-process .o files to enable embedding assembly into C.") + parser.add_argument('filename', help="path to .c code") + parser.add_argument('--post-process', dest='objfile', help="path to .o file to post-process") + parser.add_argument('--assembler', dest='assembler', help="assembler command (e.g. \"mips-linux-gnu-as -march=vr4300 -mabi=32\")") + parser.add_argument('--asm-prelude', dest='asm_prelude', help="path to a file containing a prelude to the assembly file (with .set and .macro directives, e.g.)") + parser.add_argument('--input-enc', default='latin1', help="input encoding (default: %(default)s)") + parser.add_argument('--output-enc', default='latin1', help="output encoding (default: %(default)s)") + parser.add_argument('--drop-mdebug-gptab', dest='drop_mdebug_gptab', action='store_true', help="drop mdebug and gptab sections") + parser.add_argument('--convert-statics', dest='convert_statics', choices=["no", "local", "global", "global-with-filename"], default="local", help="change static symbol visibility (default: %(default)s)") + parser.add_argument('--force', dest='force', action='store_true', help="force processing of files without GLOBAL_ASM blocks") + parser.add_argument('-framepointer', dest='framepointer', action='store_true') + parser.add_argument('-mips1', dest='mips1', action='store_true') + parser.add_argument('-g3', dest='g3', action='store_true') + parser.add_argument('-KPIC', dest='kpic', action='store_true') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-O0', dest='opt', action='store_const', const='O0') + group.add_argument('-O1', dest='opt', action='store_const', const='O1') + group.add_argument('-O2', dest='opt', action='store_const', const='O2') + group.add_argument('-g', dest='opt', action='store_const', const='g') + args = parser.parse_args(argv) + opt = args.opt + pascal = any(args.filename.endswith(ext) for ext in (".p", ".pas", ".pp")) + if args.g3: + if opt != 'O2': + raise Failure("-g3 is only supported together with -O2") + opt = 'g3' + if args.mips1 and (opt not in ('O1', 'O2') or args.framepointer): + raise Failure("-mips1 is only supported together with -O1 or -O2") + if pascal and opt not in ('O1', 'O2', 'g3'): + raise Failure("Pascal is only supported together with -O1, -O2 or -O2 -g3") + opts = Opts(opt, args.framepointer, args.mips1, args.kpic, pascal, args.input_enc, args.output_enc) + + if args.objfile is None: + with open(args.filename, encoding=args.input_enc) as f: + deps = [] + functions = parse_source(f, opts, out_dependencies=deps, print_source=outfile) + return functions, deps + else: + if args.assembler is None: + raise Failure("must pass assembler command") + if functions is None: + with open(args.filename, encoding=args.input_enc) as f: + functions = parse_source(f, opts, out_dependencies=[]) + if not functions and not args.force: + return + asm_prelude = b'' + if args.asm_prelude: + with open(args.asm_prelude, 'rb') as f: + asm_prelude = f.read() + fixup_objfile(args.objfile, functions, asm_prelude, args.assembler, args.output_enc, args.drop_mdebug_gptab, args.convert_statics) + +def run(argv, outfile=sys.stdout.buffer, functions=None): + try: + return run_wrapped(argv, outfile, functions) + except Failure as e: + print("Error:", e, file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + run(sys.argv[1:]) diff --git a/tools/asm-processor/build.py b/tools/asm-processor/build.py new file mode 100644 index 0000000..efbaade --- /dev/null +++ b/tools/asm-processor/build.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +import sys +from pathlib import Path +import shlex +import subprocess +import tempfile +import uuid +import asm_processor + +# Boolean for debugging purposes +# Preprocessed files are temporary, set to True to keep a copy +keep_preprocessed_files = False + +dir_path = Path(__file__).resolve().parent +asm_prelude_path = dir_path / "prelude.inc" + +all_args = sys.argv[1:] +sep0 = next(index for index, arg in enumerate(all_args) if not arg.startswith("-")) +sep1 = all_args.index("--") +sep2 = all_args.index("--", sep1 + 1) + +asmproc_flags = all_args[:sep0] +compiler = all_args[sep0:sep1] + +assembler_args = all_args[sep1 + 1 : sep2] +assembler_sh = " ".join(shlex.quote(x) for x in assembler_args) + + +compile_args = all_args[sep2 + 1 :] + +in_file = Path(compile_args[-1]) +del compile_args[-1] + +out_ind = compile_args.index("-o") +out_file = Path(compile_args[out_ind + 1]) +del compile_args[out_ind + 1] +del compile_args[out_ind] + + +in_dir = in_file.resolve().parent +opt_flags = [ + x for x in compile_args if x in {"-g3", "-g", "-O0", "-O1", "-O2", "-framepointer", "-KPIC"} +] +if "-mips2" not in compile_args: + opt_flags.append("-mips1") + +asmproc_flags += opt_flags + [str(in_file)] + +# Drop .mdebug and .gptab sections from resulting binaries. This makes +# resulting .o files much smaller and speeds up builds, but loses line +# number debug data. +# asmproc_flags += ["--drop-mdebug-gptab"] + +# Convert encoding before compiling. +# asmproc_flags += ["--input-enc", "utf-8", "--output-enc", "euc-jp"] + +with tempfile.TemporaryDirectory(prefix="asm_processor") as tmpdirname: + tmpdir_path = Path(tmpdirname) + preprocessed_filename = "preprocessed_" + uuid.uuid4().hex + in_file.suffix + preprocessed_path = tmpdir_path / preprocessed_filename + + with preprocessed_path.open("wb") as f: + functions, deps = asm_processor.run(asmproc_flags, outfile=f) + + if keep_preprocessed_files: + import shutil + + keep_output_dir = Path("./asm_processor_preprocessed") + keep_output_dir.mkdir(parents=True, exist_ok=True) + + shutil.copy( + preprocessed_path, + keep_output_dir / (in_file.stem + "_" + preprocessed_filename), + ) + + compile_cmdline = ( + compiler + + compile_args + + ["-I", str(in_dir), "-o", str(out_file), str(preprocessed_path)] + ) + + try: + subprocess.check_call(compile_cmdline) + except subprocess.CalledProcessError as e: + print("Failed to compile file " + str(in_file) + ". Command line:") + print() + print(" ".join(shlex.quote(x) for x in compile_cmdline)) + print() + sys.exit(55) + + asm_processor.run( + asmproc_flags + + [ + "--post-process", + str(out_file), + "--assembler", + assembler_sh, + "--asm-prelude", + str(asm_prelude_path), + ], + functions=functions, + ) + + deps_file = out_file.with_suffix(".asmproc.d") + if deps: + with deps_file.open("w") as f: + f.write(str(out_file) + ": " + " \\\n ".join(deps) + "\n") + for dep in deps: + f.write("\n" + dep + ":\n") + else: + try: + deps_file.unlink() + except OSError: + pass diff --git a/tools/asm-processor/compile-test.sh b/tools/asm-processor/compile-test.sh new file mode 100755 index 0000000..6551662 --- /dev/null +++ b/tools/asm-processor/compile-test.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -o pipefail +INPUT="$1" +OUTPUT="${INPUT%.*}.o" + +rm -f "$OUTPUT" + +CC="$MIPS_CC" # ido 7.1 via recomp or qemu-irix +AS="mips-linux-gnu-as" +ASFLAGS="-march=vr4300 -mabi=32" +OPTFLAGS=$(grep 'COMPILE-FLAGS: ' $INPUT | sed 's#^.*COMPILE-FLAGS: ##' | sed 's#}$##') +ASMPFLAGS=$(grep 'ASMP-FLAGS: ' $INPUT | sed 's#^.*ASMP-FLAGS: ##' | sed 's#}$##') +ISET=$(grep 'COMPILE-ISET: ' $INPUT | sed 's#^.*COMPILE-ISET: ##' | sed 's#}$##') +if [[ -z "$OPTFLAGS" ]]; then + OPTFLAGS="-g" +fi +CFLAGS="-Wab,-r4300_mul -G 0 -Xcpluscomm -fullwarn -wlint -woff 819,820,852,821 -signed -c" +if [[ -z "$ISET" ]]; then + CFLAGS="$CFLAGS -mips2" +fi +if [[ "$OPTFLAGS" != *-KPIC* ]]; then + CFLAGS="$CFLAGS -non_shared" +fi + +set -e +python3 build.py --drop-mdebug-gptab $ASMPFLAGS $CC -- $AS $ASFLAGS -- $CFLAGS $OPTFLAGS $ISET -o "$OUTPUT" "$INPUT" diff --git a/tools/asm-processor/prelude.inc b/tools/asm-processor/prelude.inc new file mode 100644 index 0000000..3e58ff1 --- /dev/null +++ b/tools/asm-processor/prelude.inc @@ -0,0 +1,43 @@ +.set noat +.set noreorder +.set gp=64 +.macro glabel label + .global \label + \label: +.endm + + +# Float register aliases (o32 ABI, odd ones are rarely used) + +.set $fv0, $f0 +.set $fv0f, $f1 +.set $fv1, $f2 +.set $fv1f, $f3 +.set $ft0, $f4 +.set $ft0f, $f5 +.set $ft1, $f6 +.set $ft1f, $f7 +.set $ft2, $f8 +.set $ft2f, $f9 +.set $ft3, $f10 +.set $ft3f, $f11 +.set $fa0, $f12 +.set $fa0f, $f13 +.set $fa1, $f14 +.set $fa1f, $f15 +.set $ft4, $f16 +.set $ft4f, $f17 +.set $ft5, $f18 +.set $ft5f, $f19 +.set $fs0, $f20 +.set $fs0f, $f21 +.set $fs1, $f22 +.set $fs1f, $f23 +.set $fs2, $f24 +.set $fs2f, $f25 +.set $fs3, $f26 +.set $fs3f, $f27 +.set $fs4, $f28 +.set $fs4f, $f29 +.set $fs5, $f30 +.set $fs5f, $f31 diff --git a/tools/asm-processor/run-tests.sh b/tools/asm-processor/run-tests.sh new file mode 100755 index 0000000..5cae0a7 --- /dev/null +++ b/tools/asm-processor/run-tests.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +for A in tests/*.c tests/*.p; do + OBJDUMPFLAGS=-srt + echo $A + ./compile-test.sh "$A" && mips-linux-gnu-objdump $OBJDUMPFLAGS "${A%.*}.o" | diff - "${A%.*}.objdump" || echo FAIL "$A" +done diff --git a/tools/asm-processor/tests/ascii.c b/tools/asm-processor/tests/ascii.c new file mode 100644 index 0000000..bb27d25 --- /dev/null +++ b/tools/asm-processor/tests/ascii.c @@ -0,0 +1,19 @@ +void foo(void) { "abcdef"; } + +GLOBAL_ASM( +.rdata + .ascii "AB" + .ascii "CD", "EF" + .ascii "GH\n\n\n\0\11\222\3333\44444\x1234567\n\nIJK" +) + +void bar(void) { "hello"; } + +GLOBAL_ASM( +.rdata + .asciiz "12" + .asciiz "34", "56" + .asciiz "78\n\n\n\0\11\222\3333\44444\x1234567\n\n9A" +) + +void baz(void) { "ghijkl"; } diff --git a/tools/asm-processor/tests/ascii.objdump b/tools/asm-processor/tests/ascii.objdump new file mode 100644 index 0000000..bf42638 --- /dev/null +++ b/tools/asm-processor/tests/ascii.objdump @@ -0,0 +1,29 @@ + +tests/ascii.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000030 .text +00000000 l d .rodata 00000050 .rodata +00000000 g F .text 00000010 foo +00000010 g F .text 00000010 bar +00000020 g F .text 00000010 baz + + +Contents of section .text: + 0000 03e00008 00000000 03e00008 00000000 ................ + 0010 03e00008 00000000 03e00008 00000000 ................ + 0020 03e00008 00000000 03e00008 00000000 ................ +Contents of section .rodata: + 0000 61626364 65660000 41424344 45464748 abcdef..ABCDEFGH + 0010 0a0a0a00 0992db33 24343467 0a0a494a .......3$44g..IJ + 0020 4b000000 68656c6c 6f000000 31320033 K...hello...12.3 + 0030 34003536 0037380a 0a0a0009 92db3324 4.56.78.......3$ + 0040 3434670a 0a394100 6768696a 6b6c0000 44g..9A.ghijkl.. +Contents of section .options: + 0000 01200000 00000000 80000000 00000000 . .............. + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000000 00000000 00000000 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/comments.c b/tools/asm-processor/tests/comments.c new file mode 100644 index 0000000..4c93669 --- /dev/null +++ b/tools/asm-processor/tests/comments.c @@ -0,0 +1,6 @@ +const char before[] = "^"; +GLOBAL_ASM( +.rdata +.asciz "aaaa /* bbbb */ # cccc", /**//**//**//**/ /*/ "xxxx" /*/ /* dddd " eeee */ "# ffff" # gggg "hhhh" /* iiii */ +) +const char after[] = "$"; diff --git a/tools/asm-processor/tests/comments.objdump b/tools/asm-processor/tests/comments.objdump new file mode 100644 index 0000000..246df20 --- /dev/null +++ b/tools/asm-processor/tests/comments.objdump @@ -0,0 +1,21 @@ + +tests/comments.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .rodata 00000030 .rodata +00000000 g O .rodata 00000002 before +00000024 g O .rodata 00000002 after + + +Contents of section .rodata: + 0000 5e000000 61616161 202f2a20 62626262 ^...aaaa /* bbbb + 0010 202a2f20 23206363 63630023 20666666 */ # cccc.# fff + 0020 66000000 24000000 00000000 00000000 f...$........... +Contents of section .options: + 0000 01200000 00000000 00000000 00000000 . .............. + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/force.c b/tools/asm-processor/tests/force.c new file mode 100644 index 0000000..03b630c --- /dev/null +++ b/tools/asm-processor/tests/force.c @@ -0,0 +1,17 @@ +// COMPILE-FLAGS: -O2 +// ASMP-FLAGS: --convert-statics=global-with-filename --force +static int xtext(int a, int b, int c); +const int rodata1[] = {1}; +static const int rodata2[] = {2}; +int data1[] = {3}; +static int data2[] = {4}; +int bss1; +static int bss2; + +static int xtext(int a, int b, int c) { + return 1; +} + +void baz(void) { + xtext(bss2, rodata2[0], data2[0]); +} diff --git a/tools/asm-processor/tests/force.objdump b/tools/asm-processor/tests/force.objdump new file mode 100644 index 0000000..7ef7024 --- /dev/null +++ b/tools/asm-processor/tests/force.objdump @@ -0,0 +1,47 @@ + +tests/force.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000050 .text +00000000 l d .rodata 00000010 .rodata +00000000 l d .data 00000010 .data +00000000 l d .bss 00000010 .bss +00000000 g O .rodata 00000004 rodata1 +00000000 g O .data 00000004 data1 +00000000 g O .bss 00000004 bss1 +00000014 g F .text 00000034 baz +00000004 g O .rodata 00000000 tests/force.o:rodata2 +00000004 g O .data 00000000 tests/force.o:data2 +00000004 g O .bss 00000000 tests/force.o:bss2 +00000000 g F .text 00000000 tests/force.o:xtext + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +0000001c R_MIPS_HI16 .bss +00000034 R_MIPS_LO16 .bss +00000020 R_MIPS_HI16 .rodata +0000002c R_MIPS_LO16 .rodata +00000024 R_MIPS_HI16 .data +00000028 R_MIPS_LO16 .data +00000030 R_MIPS_26 .text + + +Contents of section .text: + 0000 afa40000 afa50004 afa60008 03e00008 ................ + 0010 24020001 27bdffe8 afbf0014 3c040000 $...'.......<... + 0020 3c050000 3c060000 8cc60004 8ca50004 <...<........... + 0030 0c000000 8c840004 8fbf0014 27bd0018 ............'... + 0040 03e00008 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 00000001 00000002 00000000 00000000 ................ +Contents of section .data: + 0000 00000003 00000004 00000000 00000000 ................ +Contents of section .options: + 0000 01200000 00000000 a0000074 00000000 . .........t.... + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a0000074 00000000 00000000 00000000 ...t............ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/kpic-o1.c b/tools/asm-processor/tests/kpic-o1.c new file mode 100644 index 0000000..4d3346d --- /dev/null +++ b/tools/asm-processor/tests/kpic-o1.c @@ -0,0 +1,93 @@ +// COMPILE-FLAGS: -O1 -KPIC +GLOBAL_ASM( +glabel foo +addiu $a0, $a0, 1 +addiu $a0, $a0, 2 +addiu $a0, $a0, 3 +addiu $a0, $a0, 4 +addiu $a0, $a0, 5 +addiu $a0, $a0, 6 +addiu $a0, $a0, 7 +addiu $a0, $a0, 8 +addiu $a0, $a0, 9 +addiu $a0, $a0, 10 +addiu $a0, $a0, 11 +addiu $a0, $a0, 12 +) +GLOBAL_ASM( +.late_rodata +.float 1 +.text +glabel float_fn +addiu $a0, $a0, 13 +addiu $a0, $a0, 14 +addiu $a0, $a0, 15 +addiu $a0, $a0, 16 +addiu $a0, $a0, 17 +addiu $a0, $a0, 18 +addiu $a0, $a0, 19 +addiu $a0, $a0, 20 +addiu $a0, $a0, 21 +addiu $a0, $a0, 22 +addiu $a0, $a0, 23 +addiu $a0, $a0, 24 +addiu $a0, $a0, 25 +addiu $a0, $a0, 26 +addiu $a0, $a0, 27 +addiu $a0, $a0, 28 +addiu $a0, $a0, 29 +addiu $a0, $a0, 30 +) +GLOBAL_ASM( +.late_rodata +.late_rodata_alignment 4 +.float 2 +.double 1 +.double 2 +.double 3 +.double 4 +.double 5 +.double 6 +.double 7 +.double 8 +.text +glabel doubles +addiu $a0, $a0, 31 +addiu $a0, $a0, 32 +addiu $a0, $a0, 33 +addiu $a0, $a0, 34 +addiu $a0, $a0, 35 +addiu $a0, $a0, 36 +addiu $a0, $a0, 37 +addiu $a0, $a0, 38 +addiu $a0, $a0, 39 +addiu $a0, $a0, 40 +addiu $a0, $a0, 41 +addiu $a0, $a0, 42 +addiu $a0, $a0, 43 +addiu $a0, $a0, 44 +addiu $a0, $a0, 45 +addiu $a0, $a0, 46 +addiu $a0, $a0, 47 +addiu $a0, $a0, 48 +addiu $a0, $a0, 49 +addiu $a0, $a0, 50 +addiu $a0, $a0, 51 +addiu $a0, $a0, 52 +addiu $a0, $a0, 53 +addiu $a0, $a0, 54 +addiu $a0, $a0, 55 +addiu $a0, $a0, 56 +addiu $a0, $a0, 57 +addiu $a0, $a0, 58 +addiu $a0, $a0, 59 +addiu $a0, $a0, 60 +addiu $a0, $a0, 61 +addiu $a0, $a0, 62 +addiu $a0, $a0, 63 +addiu $a0, $a0, 64 +addiu $a0, $a0, 65 +addiu $a0, $a0, 66 +addiu $a0, $a0, 67 +addiu $a0, $a0, 68 +) diff --git a/tools/asm-processor/tests/kpic-o1.objdump b/tools/asm-processor/tests/kpic-o1.objdump new file mode 100644 index 0000000..6e33675 --- /dev/null +++ b/tools/asm-processor/tests/kpic-o1.objdump @@ -0,0 +1,46 @@ + +tests/kpic-o1.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000110 .text +00000000 l d .rodata 00000050 .rodata +00000000 g F .text 00000030 foo +00000030 g F .text 00000048 float_fn +00000078 g F .text 00000098 doubles +00000000 O *UND* 00000000 _gp_disp + + +RELOCATION RECORDS FOR [.text]: (none) + +Contents of section .text: + 0000 24840001 24840002 24840003 24840004 $...$...$...$... + 0010 24840005 24840006 24840007 24840008 $...$...$...$... + 0020 24840009 2484000a 2484000b 2484000c $...$...$...$... + 0030 2484000d 2484000e 2484000f 24840010 $...$...$...$... + 0040 24840011 24840012 24840013 24840014 $...$...$...$... + 0050 24840015 24840016 24840017 24840018 $...$...$...$... + 0060 24840019 2484001a 2484001b 2484001c $...$...$...$... + 0070 2484001d 2484001e 2484001f 24840020 $...$...$...$.. + 0080 24840021 24840022 24840023 24840024 $..!$.."$..#$..$ + 0090 24840025 24840026 24840027 24840028 $..%$..&$..'$..( + 00a0 24840029 2484002a 2484002b 2484002c $..)$..*$..+$.., + 00b0 2484002d 2484002e 2484002f 24840030 $..-$...$../$..0 + 00c0 24840031 24840032 24840033 24840034 $..1$..2$..3$..4 + 00d0 24840035 24840036 24840037 24840038 $..5$..6$..7$..8 + 00e0 24840039 2484003a 2484003b 2484003c $..9$..:$..;$..< + 00f0 2484003d 2484003e 2484003f 24840040 $..=$..>$..?$..@ + 0100 24840041 24840042 24840043 24840044 $..A$..B$..C$..D +Contents of section .rodata: + 0000 3f800000 40000000 3ff00000 00000000 ?...@...?....... + 0010 40000000 00000000 40080000 00000000 @.......@....... + 0020 40100000 00000000 40140000 00000000 @.......@....... + 0030 40180000 00000000 401c0000 00000000 @.......@....... + 0040 40200000 00000000 00000000 00000000 @ .............. +Contents of section .options: + 0000 01200000 00000000 92000002 00000000 . .............. + 0010 000f0ff0 00000000 00000000 00000000 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 92000012 00000000 000f0ff0 00000000 ................ + 0010 00000000 00000000 ........ diff --git a/tools/asm-processor/tests/kpic-o2.c b/tools/asm-processor/tests/kpic-o2.c new file mode 100644 index 0000000..f037341 --- /dev/null +++ b/tools/asm-processor/tests/kpic-o2.c @@ -0,0 +1,92 @@ +// COMPILE-FLAGS: -O2 -KPIC +GLOBAL_ASM( +glabel foo +addiu $a0, $a0, 1 +addiu $a0, $a0, 2 +addiu $a0, $a0, 3 +addiu $a0, $a0, 4 +addiu $a0, $a0, 5 +addiu $a0, $a0, 6 +addiu $a0, $a0, 7 +addiu $a0, $a0, 8 +addiu $a0, $a0, 9 +addiu $a0, $a0, 10 +addiu $a0, $a0, 11 +addiu $a0, $a0, 12 +) +GLOBAL_ASM( +.late_rodata +.float 1 +.text +glabel float_fn +addiu $a0, $a0, 13 +addiu $a0, $a0, 14 +addiu $a0, $a0, 15 +addiu $a0, $a0, 16 +addiu $a0, $a0, 17 +addiu $a0, $a0, 18 +addiu $a0, $a0, 19 +addiu $a0, $a0, 20 +addiu $a0, $a0, 21 +addiu $a0, $a0, 22 +addiu $a0, $a0, 23 +addiu $a0, $a0, 24 +addiu $a0, $a0, 25 +addiu $a0, $a0, 26 +addiu $a0, $a0, 27 +addiu $a0, $a0, 28 +addiu $a0, $a0, 29 +addiu $a0, $a0, 30 +) +GLOBAL_ASM( +.late_rodata +.float 2 +.double 1 +.double 2 +.double 3 +.double 4 +.double 5 +.double 6 +.double 7 +.double 8 +.text +glabel doubles +addiu $a0, $a0, 31 +addiu $a0, $a0, 32 +addiu $a0, $a0, 33 +addiu $a0, $a0, 34 +addiu $a0, $a0, 35 +addiu $a0, $a0, 36 +addiu $a0, $a0, 37 +addiu $a0, $a0, 38 +addiu $a0, $a0, 39 +addiu $a0, $a0, 40 +addiu $a0, $a0, 41 +addiu $a0, $a0, 42 +addiu $a0, $a0, 43 +addiu $a0, $a0, 44 +addiu $a0, $a0, 45 +addiu $a0, $a0, 46 +addiu $a0, $a0, 47 +addiu $a0, $a0, 48 +addiu $a0, $a0, 49 +addiu $a0, $a0, 50 +addiu $a0, $a0, 51 +addiu $a0, $a0, 52 +addiu $a0, $a0, 53 +addiu $a0, $a0, 54 +addiu $a0, $a0, 55 +addiu $a0, $a0, 56 +addiu $a0, $a0, 57 +addiu $a0, $a0, 58 +addiu $a0, $a0, 59 +addiu $a0, $a0, 60 +addiu $a0, $a0, 61 +addiu $a0, $a0, 62 +addiu $a0, $a0, 63 +addiu $a0, $a0, 64 +addiu $a0, $a0, 65 +addiu $a0, $a0, 66 +addiu $a0, $a0, 67 +addiu $a0, $a0, 68 +) diff --git a/tools/asm-processor/tests/kpic-o2.objdump b/tools/asm-processor/tests/kpic-o2.objdump new file mode 100644 index 0000000..abf87ae --- /dev/null +++ b/tools/asm-processor/tests/kpic-o2.objdump @@ -0,0 +1,46 @@ + +tests/kpic-o2.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000110 .text +00000000 l d .rodata 00000050 .rodata +00000000 g F .text 00000030 foo +00000030 g F .text 00000048 float_fn +00000078 g F .text 00000098 doubles +00000000 O *UND* 00000000 _gp_disp + + +RELOCATION RECORDS FOR [.text]: (none) + +Contents of section .text: + 0000 24840001 24840002 24840003 24840004 $...$...$...$... + 0010 24840005 24840006 24840007 24840008 $...$...$...$... + 0020 24840009 2484000a 2484000b 2484000c $...$...$...$... + 0030 2484000d 2484000e 2484000f 24840010 $...$...$...$... + 0040 24840011 24840012 24840013 24840014 $...$...$...$... + 0050 24840015 24840016 24840017 24840018 $...$...$...$... + 0060 24840019 2484001a 2484001b 2484001c $...$...$...$... + 0070 2484001d 2484001e 2484001f 24840020 $...$...$...$.. + 0080 24840021 24840022 24840023 24840024 $..!$.."$..#$..$ + 0090 24840025 24840026 24840027 24840028 $..%$..&$..'$..( + 00a0 24840029 2484002a 2484002b 2484002c $..)$..*$..+$.., + 00b0 2484002d 2484002e 2484002f 24840030 $..-$...$../$..0 + 00c0 24840031 24840032 24840033 24840034 $..1$..2$..3$..4 + 00d0 24840035 24840036 24840037 24840038 $..5$..6$..7$..8 + 00e0 24840039 2484003a 2484003b 2484003c $..9$..:$..;$..< + 00f0 2484003d 2484003e 2484003f 24840040 $..=$..>$..?$..@ + 0100 24840041 24840042 24840043 24840044 $..A$..B$..C$..D +Contents of section .rodata: + 0000 3f800000 40000000 3ff00000 00000000 ?...@...?....... + 0010 40000000 00000000 40080000 00000000 @.......@....... + 0020 40100000 00000000 40140000 00000000 @.......@....... + 0030 40180000 00000000 401c0000 00000000 @.......@....... + 0040 40200000 00000000 00000000 00000000 @ .............. +Contents of section .options: + 0000 01200000 00000000 92000002 00000000 . .............. + 0010 000f0ff0 00000000 00000000 00000000 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 92000012 00000000 000f0ff0 00000000 ................ + 0010 00000000 00000000 ........ diff --git a/tools/asm-processor/tests/label-sameline.c b/tools/asm-processor/tests/label-sameline.c new file mode 100644 index 0000000..a35b43d --- /dev/null +++ b/tools/asm-processor/tests/label-sameline.c @@ -0,0 +1,7 @@ +GLOBAL_ASM( +.rdata +.word 0x12345678 +glabel blah +.word blah2 + /*a*/ blah2: /*b*/ .word blah /*c*/ +) diff --git a/tools/asm-processor/tests/label-sameline.objdump b/tools/asm-processor/tests/label-sameline.objdump new file mode 100644 index 0000000..1f1aacf --- /dev/null +++ b/tools/asm-processor/tests/label-sameline.objdump @@ -0,0 +1,25 @@ + +tests/label-sameline.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .rodata 00000010 .rodata +00000000 l d .rodata 00000000 +00000004 g .rodata 00000000 blah + + +RELOCATION RECORDS FOR [.rodata]: +OFFSET TYPE VALUE +00000004 R_MIPS_32 +00000008 R_MIPS_32 blah + + +Contents of section .rodata: + 0000 12345678 00000008 00000000 00000000 .4Vx............ +Contents of section .options: + 0000 01200000 00000000 00000000 00000000 . .............. + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/large.c b/tools/asm-processor/tests/large.c new file mode 100644 index 0000000..4ffb4ac --- /dev/null +++ b/tools/asm-processor/tests/large.c @@ -0,0 +1,164 @@ + +GLOBAL_ASM( +glabel test + +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 +addiu $sp, $sp, -24 + sw $zero, 4($sp) +lw $t6, 4($sp) +addu $t7, $a0, $t6 +sb $zero, ($t7) +lw $t8, 4($sp) +addiu $t9, $t8, 1 +slt $at, $t9, $a1 + sw $t9, 4($sp) + nop +jr $ra + addiu $sp, $sp, 24 + +) + +void foo(void) {} diff --git a/tools/asm-processor/tests/large.objdump b/tools/asm-processor/tests/large.objdump new file mode 100644 index 0000000..17409a7 --- /dev/null +++ b/tools/asm-processor/tests/large.objdump @@ -0,0 +1,58 @@ + +tests/large.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000280 .text +00000270 g F .text 00000010 foo +00000000 g F .text 00000270 test + + +Contents of section .text: + 0000 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0010 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0020 afb90004 00000000 03e00008 27bd0018 ............'... + 0030 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0040 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0050 afb90004 00000000 03e00008 27bd0018 ............'... + 0060 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0070 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0080 afb90004 00000000 03e00008 27bd0018 ............'... + 0090 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 00a0 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 00b0 afb90004 00000000 03e00008 27bd0018 ............'... + 00c0 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 00d0 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 00e0 afb90004 00000000 03e00008 27bd0018 ............'... + 00f0 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0100 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0110 afb90004 00000000 03e00008 27bd0018 ............'... + 0120 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0130 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0140 afb90004 00000000 03e00008 27bd0018 ............'... + 0150 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0160 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0170 afb90004 00000000 03e00008 27bd0018 ............'... + 0180 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0190 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 01a0 afb90004 00000000 03e00008 27bd0018 ............'... + 01b0 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 01c0 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 01d0 afb90004 00000000 03e00008 27bd0018 ............'... + 01e0 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 01f0 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0200 afb90004 00000000 03e00008 27bd0018 ............'... + 0210 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0220 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0230 afb90004 00000000 03e00008 27bd0018 ............'... + 0240 27bdffe8 afa00004 8fae0004 008e7821 '.............x! + 0250 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0260 afb90004 00000000 03e00008 27bd0018 ............'... + 0270 03e00008 00000000 03e00008 00000000 ................ +Contents of section .options: + 0000 01200000 00000000 80000000 00000000 . .............. + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a300c032 00000000 00000000 00000000 ...2............ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/late_rodata_align.c b/tools/asm-processor/tests/late_rodata_align.c new file mode 100644 index 0000000..7367c79 --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_align.c @@ -0,0 +1,80 @@ +GLOBAL_ASM( +.late_rodata + .float 4.1 + .float 4.2 + .float 4.3 + .float 4.4 +.text +glabel a + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float foo(void) { "foo"; return 1.1f; } + +GLOBAL_ASM( +.late_rodata +.late_rodata_alignment 4 + .float 5.1 + .float 5.2 + .float 5.3 + .float 5.4 +.text +glabel b + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float bar(void) { "bar"; return 1.2f; } + +GLOBAL_ASM( +.late_rodata +.late_rodata_alignment 8 + .float 6.1 + .float 6.2 + .float 6.3 + .float 6.4 + .float 6.5 +.text +glabel c + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + diff --git a/tools/asm-processor/tests/late_rodata_align.objdump b/tools/asm-processor/tests/late_rodata_align.objdump new file mode 100644 index 0000000..87c05e8 --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_align.objdump @@ -0,0 +1,51 @@ + +tests/late_rodata_align.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000000f0 .text +00000000 l d .rodata 00000050 .rodata +00000040 g F .text 0000001c foo +00000090 g F .text 0000001c bar +00000000 g F .text 00000040 a +0000005c g F .text 00000034 b +000000ac g F .text 00000038 c + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000040 R_MIPS_HI16 .rodata +00000048 R_MIPS_LO16 .rodata +00000090 R_MIPS_HI16 .rodata +00000098 R_MIPS_LO16 .rodata + + +Contents of section .text: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ + 0020 00000000 00000000 00000000 00000000 ................ + 0030 00000000 00000000 00000000 00000000 ................ + 0040 3c010000 03e00008 c4200018 03e00008 <........ ...... + 0050 00000000 03e00008 00000000 00000000 ................ + 0060 00000000 00000000 00000000 00000000 ................ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 3c010000 03e00008 c420002c 03e00008 <........ .,.... + 00a0 00000000 03e00008 00000000 00000000 ................ + 00b0 00000000 00000000 00000000 00000000 ................ + 00c0 00000000 00000000 00000000 00000000 ................ + 00d0 00000000 00000000 00000000 00000000 ................ + 00e0 00000000 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 666f6f00 62617200 40833333 40866666 foo.bar.@.33@.ff + 0010 4089999a 408ccccd 3f8ccccd 40a33333 @...@...?...@.33 + 0020 40a66666 40a9999a 40accccd 3f99999a @.ff@...@...?... + 0030 40c33333 40c66666 40c9999a 40cccccd @.33@.ff@...@... + 0040 40d00000 00000000 00000000 00000000 @............... +Contents of section .options: + 0000 01200000 00000000 80000002 00000000 . .............. + 0010 000005f1 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000002 00000000 000005f1 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/late_rodata_doubles.c b/tools/asm-processor/tests/late_rodata_doubles.c new file mode 100644 index 0000000..0a27b41 --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_doubles.c @@ -0,0 +1,83 @@ +GLOBAL_ASM( +.late_rodata + .float 4.1 +.text +glabel a + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float foo(void) { + return 4.15f; +} + +GLOBAL_ASM( +.late_rodata + .float 4.2 + .word 0 + .double 4.3 +.text +glabel b + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float bar(void) { + return 4.4f; +} + +GLOBAL_ASM( +.late_rodata + .float 4.55 + .double 4.6 +.text +glabel c + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float baz(void) { + return 4.6f; +} diff --git a/tools/asm-processor/tests/late_rodata_doubles.objdump b/tools/asm-processor/tests/late_rodata_doubles.objdump new file mode 100644 index 0000000..84d7e67 --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_doubles.objdump @@ -0,0 +1,55 @@ + +tests/late_rodata_doubles.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000120 .text +00000000 l d .rodata 00000030 .rodata +00000040 g F .text 0000001c foo +0000009c g F .text 0000001c bar +000000f8 g F .text 0000001c baz +00000000 g F .text 00000040 a +0000005c g F .text 00000040 b +000000b8 g F .text 00000040 c + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000040 R_MIPS_HI16 .rodata +00000048 R_MIPS_LO16 .rodata +0000009c R_MIPS_HI16 .rodata +000000a4 R_MIPS_LO16 .rodata +000000f8 R_MIPS_HI16 .rodata +00000100 R_MIPS_LO16 .rodata + + +Contents of section .text: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ + 0020 00000000 00000000 00000000 00000000 ................ + 0030 00000000 00000000 00000000 00000000 ................ + 0040 3c010000 03e00008 c4200004 03e00008 <........ ...... + 0050 00000000 03e00008 00000000 00000000 ................ + 0060 00000000 00000000 00000000 00000000 ................ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 00000000 00000000 00000000 3c010000 ............<... + 00a0 03e00008 c4200018 03e00008 00000000 ..... .......... + 00b0 03e00008 00000000 00000000 00000000 ................ + 00c0 00000000 00000000 00000000 00000000 ................ + 00d0 00000000 00000000 00000000 00000000 ................ + 00e0 00000000 00000000 00000000 00000000 ................ + 00f0 00000000 00000000 3c010000 03e00008 ........<....... + 0100 c4200028 03e00008 00000000 03e00008 . .(............ + 0110 00000000 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 40833333 4084cccd 40866666 00000000 @.33@...@.ff.... + 0010 40113333 33333333 408ccccd 4091999a @.333333@...@... + 0020 40126666 66666666 40933333 00000000 @.ffffff@.33.... +Contents of section .options: + 0000 01200000 00000000 80000002 00000000 . .............. + 0010 000000f1 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000002 00000000 000000f1 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/late_rodata_doubles_mips1.c b/tools/asm-processor/tests/late_rodata_doubles_mips1.c new file mode 100644 index 0000000..b97261f --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_doubles_mips1.c @@ -0,0 +1,86 @@ +// COMPILE-FLAGS: -O2 +// COMPILE-ISET: -mips1 +// exact copy of late_rodata_doubles.c except for the -mips1 -O2 additions +GLOBAL_ASM( +.late_rodata + .float 4.1 +.text +glabel a + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float foo(void) { + return 4.15f; +} + +GLOBAL_ASM( +.late_rodata + .float 4.2 + .word 0 + .double 4.3 +.text +glabel b + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float bar(void) { + return 4.4f; +} + +GLOBAL_ASM( +.late_rodata + .float 4.55 + .double 4.6 +.text +glabel c + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +float baz(void) { + return 4.6f; +} diff --git a/tools/asm-processor/tests/late_rodata_doubles_mips1.objdump b/tools/asm-processor/tests/late_rodata_doubles_mips1.objdump new file mode 100644 index 0000000..8fac85f --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_doubles_mips1.objdump @@ -0,0 +1,52 @@ + +tests/late_rodata_doubles_mips1.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000000f0 .text +00000000 l d .rodata 00000030 .rodata +00000040 g F .text 00000010 foo +00000090 g F .text 00000010 bar +000000e0 g F .text 00000010 baz +00000000 g F .text 00000040 a +00000050 g F .text 00000040 b +000000a0 g F .text 00000040 c + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000040 R_MIPS_HI16 .rodata +00000044 R_MIPS_LO16 .rodata +00000090 R_MIPS_HI16 .rodata +00000094 R_MIPS_LO16 .rodata +000000e0 R_MIPS_HI16 .rodata +000000e4 R_MIPS_LO16 .rodata + + +Contents of section .text: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ + 0020 00000000 00000000 00000000 00000000 ................ + 0030 00000000 00000000 00000000 00000000 ................ + 0040 3c010000 c4200004 03e00008 00000000 <.... .......... + 0050 00000000 00000000 00000000 00000000 ................ + 0060 00000000 00000000 00000000 00000000 ................ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 3c010000 c4200018 03e00008 00000000 <.... .......... + 00a0 00000000 00000000 00000000 00000000 ................ + 00b0 00000000 00000000 00000000 00000000 ................ + 00c0 00000000 00000000 00000000 00000000 ................ + 00d0 00000000 00000000 00000000 00000000 ................ + 00e0 3c010000 c4200028 03e00008 00000000 <.... .(........ +Contents of section .rodata: + 0000 40833333 4084cccd 40866666 00000000 @.33@...@.ff.... + 0010 40113333 33333333 408ccccd 4091999a @.333333@...@... + 0020 40126666 66666666 40933333 00000000 @.ffffff@.33.... +Contents of section .options: + 0000 01200000 00000000 80000002 00000000 . .............. + 0010 000c0011 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000002 00000000 000c0011 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/late_rodata_jtbl.c b/tools/asm-processor/tests/late_rodata_jtbl.c new file mode 100644 index 0000000..3c2a5bb --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_jtbl.c @@ -0,0 +1,153 @@ +// COMPILE-FLAGS: -O2 +GLOBAL_ASM( +.late_rodata +.double 1 +.double 2 +.double 3 +.double 4 +.double 5 +.double 6 +.double 7 +.double 8 +.text +glabel doubles1 +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +) + +float a(void) { return 1.1f; } + +GLOBAL_ASM( +.late_rodata +.float 1 +.double 2 +.double 3 +.double 4 +.double 5 +.double 6 +.double 7 +.double 8 +.double 9 +.float 10 +.text +glabel doubles2 +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +) + +GLOBAL_ASM( +glabel a2 +move $a0, $a0 +nop +nop +nop +jr $ra +move $a0, $a0 +) + +GLOBAL_ASM( +.late_rodata + +glabel jtbl +.word case0, case1, case2, case3, case4, case5, case6, case7, case8, case9, case10 +.word case11, case12, case13, case14, case15, case16, case17, case18, case19, case20 +.word case21, case22, case23, case24, case25, case26 + +.text +glabel foo +sltiu $at, $a0, 0xa +beqz $at, .L756E659B + sll $t7, $a0, 2 +lui $at, %hi(jtbl) +addu $at, $at, $t7 +lw $t7, %lo(jtbl)($at) +jr $t7 + nop +case0: addiu $a0, $a0, 1 +case1: addiu $a0, $a0, 1 +case2: addiu $a0, $a0, 1 +case3: addiu $a0, $a0, 1 +case4: addiu $a0, $a0, 1 +case5: addiu $a0, $a0, 1 +case6: addiu $a0, $a0, 1 +case7: addiu $a0, $a0, 1 +case8: addiu $a0, $a0, 1 +case9: addiu $a0, $a0, 1 +case10: addiu $a0, $a0, 1 +case11: addiu $a0, $a0, 1 +case12: addiu $a0, $a0, 1 +case13: addiu $a0, $a0, 1 +case14: addiu $a0, $a0, 1 +case15: addiu $a0, $a0, 1 +case16: addiu $a0, $a0, 1 +case17: addiu $a0, $a0, 1 +case18: addiu $a0, $a0, 1 +case19: addiu $a0, $a0, 1 +case20: addiu $a0, $a0, 1 +case21: addiu $a0, $a0, 1 +case22: addiu $a0, $a0, 1 +case23: addiu $a0, $a0, 1 +case24: addiu $a0, $a0, 1 +case25: addiu $a0, $a0, 1 +case26: +jr $ra + addiu $v0, $a0, 1 + +.L756E659B: +addiu $v0, $zero, 2 +jr $ra + nop +) + +GLOBAL_ASM( +glabel b2 +move $a0, $a0 +nop +nop +jr $ra +move $a0, $a0 +) + +float b(void) { return 1.2f; } diff --git a/tools/asm-processor/tests/late_rodata_jtbl.objdump b/tools/asm-processor/tests/late_rodata_jtbl.objdump new file mode 100644 index 0000000..44bb6e8 --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_jtbl.objdump @@ -0,0 +1,110 @@ + +tests/late_rodata_jtbl.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000001a0 .text +00000000 l d .rodata 00000100 .rodata +00000000 l d .text 00000000 +0000005c g F .text 0000000c a +0000018c g F .text 0000000c b +00000000 g F .text 0000005c doubles1 +00000068 g F .text 0000005c doubles2 +000000c4 g F .text 00000018 a2 +000000dc g F .text 0000009c foo +0000008c g .rodata 00000000 jtbl +00000178 g F .text 00000014 b2 + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +0000005c R_MIPS_HI16 .rodata +00000064 R_MIPS_LO16 .rodata +0000018c R_MIPS_HI16 .rodata +00000194 R_MIPS_LO16 .rodata +000000e8 R_MIPS_HI16 jtbl +000000f0 R_MIPS_LO16 jtbl + + +RELOCATION RECORDS FOR [.rodata]: +OFFSET TYPE VALUE +0000008c R_MIPS_32 +00000090 R_MIPS_32 +00000094 R_MIPS_32 +00000098 R_MIPS_32 +0000009c R_MIPS_32 +000000a0 R_MIPS_32 +000000a4 R_MIPS_32 +000000a8 R_MIPS_32 +000000ac R_MIPS_32 +000000b0 R_MIPS_32 +000000b4 R_MIPS_32 +000000b8 R_MIPS_32 +000000bc R_MIPS_32 +000000c0 R_MIPS_32 +000000c4 R_MIPS_32 +000000c8 R_MIPS_32 +000000cc R_MIPS_32 +000000d0 R_MIPS_32 +000000d4 R_MIPS_32 +000000d8 R_MIPS_32 +000000dc R_MIPS_32 +000000e0 R_MIPS_32 +000000e4 R_MIPS_32 +000000e8 R_MIPS_32 +000000ec R_MIPS_32 +000000f0 R_MIPS_32 +000000f4 R_MIPS_32 + + +Contents of section .text: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ + 0020 00000000 00000000 00000000 00000000 ................ + 0030 00000000 00000000 00000000 00000000 ................ + 0040 00000000 00000000 00000000 00000000 ................ + 0050 00000000 00000000 00000000 3c010000 ............<... + 0060 03e00008 c4200040 00000000 00000000 ..... .@........ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 00000000 00000000 00000000 00000000 ................ + 00a0 00000000 00000000 00000000 00000000 ................ + 00b0 00000000 00000000 00000000 00000000 ................ + 00c0 00000000 00802025 00000000 00000000 ...... %........ + 00d0 00000000 03e00008 00802025 2c81000a .......... %,... + 00e0 10200022 00047880 3c010000 002f0821 . ."..x.<..../.! + 00f0 8c2f0000 01e00008 00000000 24840001 ./..........$... + 0100 24840001 24840001 24840001 24840001 $...$...$...$... + 0110 24840001 24840001 24840001 24840001 $...$...$...$... + 0120 24840001 24840001 24840001 24840001 $...$...$...$... + 0130 24840001 24840001 24840001 24840001 $...$...$...$... + 0140 24840001 24840001 24840001 24840001 $...$...$...$... + 0150 24840001 24840001 24840001 24840001 $...$...$...$... + 0160 24840001 03e00008 24820001 24020002 $.......$...$... + 0170 03e00008 00000000 00802025 00000000 .......... %.... + 0180 00000000 03e00008 00802025 3c010000 .......... %<... + 0190 03e00008 c42000f8 00000000 00000000 ..... .......... +Contents of section .rodata: + 0000 3ff00000 00000000 40000000 00000000 ?.......@....... + 0010 40080000 00000000 40100000 00000000 @.......@....... + 0020 40140000 00000000 40180000 00000000 @.......@....... + 0030 401c0000 00000000 40200000 00000000 @.......@ ...... + 0040 3f8ccccd 3f800000 40000000 00000000 ?...?...@....... + 0050 40080000 00000000 40100000 00000000 @.......@....... + 0060 40140000 00000000 40180000 00000000 @.......@....... + 0070 401c0000 00000000 40200000 00000000 @.......@ ...... + 0080 40220000 00000000 41200000 000000fc @"......A ...... + 0090 00000100 00000104 00000108 0000010c ................ + 00a0 00000110 00000114 00000118 0000011c ................ + 00b0 00000120 00000124 00000128 0000012c ... ...$...(..., + 00c0 00000130 00000134 00000138 0000013c ...0...4...8...< + 00d0 00000140 00000144 00000148 0000014c ...@...D...H...L + 00e0 00000150 00000154 00000158 0000015c ...P...T...X...\ + 00f0 00000160 00000164 3f99999a 00000000 ...`...d?....... +Contents of section .options: + 0000 01200000 00000000 80004002 00000000 . ........@..... + 0010 000000f1 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 8000c016 00000000 000000f1 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/late_rodata_jtbl_mips1.c b/tools/asm-processor/tests/late_rodata_jtbl_mips1.c new file mode 100644 index 0000000..505f4c1 --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_jtbl_mips1.c @@ -0,0 +1,155 @@ +// COMPILE-FLAGS: -O2 +// COMPILE-ISET: -mips1 +// exact copy of late_rodata_jtbl.c except for the -mips1 addition +GLOBAL_ASM( +.late_rodata +.double 1 +.double 2 +.double 3 +.double 4 +.double 5 +.double 6 +.double 7 +.double 8 +.text +glabel doubles1 +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +) + +float a(void) { return 1.1f; } + +GLOBAL_ASM( +.late_rodata +.float 1 +.double 2 +.double 3 +.double 4 +.double 5 +.double 6 +.double 7 +.double 8 +.double 9 +.float 10 +.text +glabel doubles2 +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +) + +GLOBAL_ASM( +glabel a2 +move $a0, $a0 +nop +nop +nop +jr $ra +move $a0, $a0 +) + +GLOBAL_ASM( +.late_rodata + +glabel jtbl +.word case0, case1, case2, case3, case4, case5, case6, case7, case8, case9, case10 +.word case11, case12, case13, case14, case15, case16, case17, case18, case19, case20 +.word case21, case22, case23, case24, case25, case26 + +.text +glabel foo +sltiu $at, $a0, 0xa +beqz $at, .L756E659B + sll $t7, $a0, 2 +lui $at, %hi(jtbl) +addu $at, $at, $t7 +lw $t7, %lo(jtbl)($at) +jr $t7 + nop +case0: addiu $a0, $a0, 1 +case1: addiu $a0, $a0, 1 +case2: addiu $a0, $a0, 1 +case3: addiu $a0, $a0, 1 +case4: addiu $a0, $a0, 1 +case5: addiu $a0, $a0, 1 +case6: addiu $a0, $a0, 1 +case7: addiu $a0, $a0, 1 +case8: addiu $a0, $a0, 1 +case9: addiu $a0, $a0, 1 +case10: addiu $a0, $a0, 1 +case11: addiu $a0, $a0, 1 +case12: addiu $a0, $a0, 1 +case13: addiu $a0, $a0, 1 +case14: addiu $a0, $a0, 1 +case15: addiu $a0, $a0, 1 +case16: addiu $a0, $a0, 1 +case17: addiu $a0, $a0, 1 +case18: addiu $a0, $a0, 1 +case19: addiu $a0, $a0, 1 +case20: addiu $a0, $a0, 1 +case21: addiu $a0, $a0, 1 +case22: addiu $a0, $a0, 1 +case23: addiu $a0, $a0, 1 +case24: addiu $a0, $a0, 1 +case25: addiu $a0, $a0, 1 +case26: +jr $ra + addiu $v0, $a0, 1 + +.L756E659B: +addiu $v0, $zero, 2 +jr $ra + nop +) + +GLOBAL_ASM( +glabel b2 +move $a0, $a0 +nop +nop +jr $ra +move $a0, $a0 +) + +float b(void) { return 1.2f; } diff --git a/tools/asm-processor/tests/late_rodata_jtbl_mips1.objdump b/tools/asm-processor/tests/late_rodata_jtbl_mips1.objdump new file mode 100644 index 0000000..d37c8bb --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_jtbl_mips1.objdump @@ -0,0 +1,110 @@ + +tests/late_rodata_jtbl_mips1.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000001a0 .text +00000000 l d .rodata 00000100 .rodata +00000000 l d .text 00000000 +0000005c g F .text 00000010 a +00000190 g F .text 00000010 b +00000000 g F .text 0000005c doubles1 +0000006c g F .text 0000005c doubles2 +000000c8 g F .text 00000018 a2 +000000e0 g F .text 0000009c foo +0000008c g .rodata 00000000 jtbl +0000017c g F .text 00000014 b2 + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +0000005c R_MIPS_HI16 .rodata +00000060 R_MIPS_LO16 .rodata +00000190 R_MIPS_HI16 .rodata +00000194 R_MIPS_LO16 .rodata +000000ec R_MIPS_HI16 jtbl +000000f4 R_MIPS_LO16 jtbl + + +RELOCATION RECORDS FOR [.rodata]: +OFFSET TYPE VALUE +0000008c R_MIPS_32 +00000090 R_MIPS_32 +00000094 R_MIPS_32 +00000098 R_MIPS_32 +0000009c R_MIPS_32 +000000a0 R_MIPS_32 +000000a4 R_MIPS_32 +000000a8 R_MIPS_32 +000000ac R_MIPS_32 +000000b0 R_MIPS_32 +000000b4 R_MIPS_32 +000000b8 R_MIPS_32 +000000bc R_MIPS_32 +000000c0 R_MIPS_32 +000000c4 R_MIPS_32 +000000c8 R_MIPS_32 +000000cc R_MIPS_32 +000000d0 R_MIPS_32 +000000d4 R_MIPS_32 +000000d8 R_MIPS_32 +000000dc R_MIPS_32 +000000e0 R_MIPS_32 +000000e4 R_MIPS_32 +000000e8 R_MIPS_32 +000000ec R_MIPS_32 +000000f0 R_MIPS_32 +000000f4 R_MIPS_32 + + +Contents of section .text: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ + 0020 00000000 00000000 00000000 00000000 ................ + 0030 00000000 00000000 00000000 00000000 ................ + 0040 00000000 00000000 00000000 00000000 ................ + 0050 00000000 00000000 00000000 3c010000 ............<... + 0060 c4200040 03e00008 00000000 00000000 . .@............ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 00000000 00000000 00000000 00000000 ................ + 00a0 00000000 00000000 00000000 00000000 ................ + 00b0 00000000 00000000 00000000 00000000 ................ + 00c0 00000000 00000000 00802025 00000000 .......... %.... + 00d0 00000000 00000000 03e00008 00802025 .............. % + 00e0 2c81000a 10200022 00047880 3c010000 ,.... ."..x.<... + 00f0 002f0821 8c2f0000 01e00008 00000000 ./.!./.......... + 0100 24840001 24840001 24840001 24840001 $...$...$...$... + 0110 24840001 24840001 24840001 24840001 $...$...$...$... + 0120 24840001 24840001 24840001 24840001 $...$...$...$... + 0130 24840001 24840001 24840001 24840001 $...$...$...$... + 0140 24840001 24840001 24840001 24840001 $...$...$...$... + 0150 24840001 24840001 24840001 24840001 $...$...$...$... + 0160 24840001 24840001 03e00008 24820001 $...$.......$... + 0170 24020002 03e00008 00000000 00802025 $............. % + 0180 00000000 00000000 03e00008 00802025 .............. % + 0190 3c010000 c42000f8 03e00008 00000000 <.... .......... +Contents of section .rodata: + 0000 3ff00000 00000000 40000000 00000000 ?.......@....... + 0010 40080000 00000000 40100000 00000000 @.......@....... + 0020 40140000 00000000 40180000 00000000 @.......@....... + 0030 401c0000 00000000 40200000 00000000 @.......@ ...... + 0040 3f8ccccd 3f800000 40000000 00000000 ?...?...@....... + 0050 40080000 00000000 40100000 00000000 @.......@....... + 0060 40140000 00000000 40180000 00000000 @.......@....... + 0070 401c0000 00000000 40200000 00000000 @.......@ ...... + 0080 40220000 00000000 41200000 00000100 @"......A ...... + 0090 00000104 00000108 0000010c 00000110 ................ + 00a0 00000114 00000118 0000011c 00000120 ............... + 00b0 00000124 00000128 0000012c 00000130 ...$...(...,...0 + 00c0 00000134 00000138 0000013c 00000140 ...4...8...<...@ + 00d0 00000144 00000148 0000014c 00000150 ...D...H...L...P + 00e0 00000154 00000158 0000015c 00000160 ...T...X...\...` + 00f0 00000164 00000168 3f99999a 00000000 ...d...h?....... +Contents of section .options: + 0000 01200000 00000000 80004002 00000000 . ........@..... + 0010 000000f1 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 8000c016 00000000 000000f1 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/late_rodata_misaligned_doubles.c b/tools/asm-processor/tests/late_rodata_misaligned_doubles.c new file mode 100644 index 0000000..a453dbd --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_misaligned_doubles.c @@ -0,0 +1,77 @@ +GLOBAL_ASM( +.late_rodata + .float 4.01 + .word 0 + .double 4.02 +.text +glabel a + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +double foo(void) { return 4.03; } + +GLOBAL_ASM( +.late_rodata + .float 4.04 + .double 4.05 +.text +glabel b + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + +double bar(void) { return 4.06; } +float baz(void) { return 4.07f; } + +GLOBAL_ASM( +.late_rodata + .double 4.08 +.text +glabel c + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +) + diff --git a/tools/asm-processor/tests/late_rodata_misaligned_doubles.objdump b/tools/asm-processor/tests/late_rodata_misaligned_doubles.objdump new file mode 100644 index 0000000..cdba84d --- /dev/null +++ b/tools/asm-processor/tests/late_rodata_misaligned_doubles.objdump @@ -0,0 +1,56 @@ + +tests/late_rodata_misaligned_doubles.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000120 .text +00000000 l d .rodata 00000040 .rodata +00000040 g F .text 0000001c foo +0000009c g F .text 0000001c bar +000000b8 g F .text 0000001c baz +00000000 g F .text 00000040 a +0000005c g F .text 00000040 b +000000d4 g F .text 00000040 c + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000040 R_MIPS_HI16 .rodata +00000048 R_MIPS_LO16 .rodata +0000009c R_MIPS_HI16 .rodata +000000a4 R_MIPS_LO16 .rodata +000000b8 R_MIPS_HI16 .rodata +000000c0 R_MIPS_LO16 .rodata + + +Contents of section .text: + 0000 00000000 00000000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ + 0020 00000000 00000000 00000000 00000000 ................ + 0030 00000000 00000000 00000000 00000000 ................ + 0040 3c010000 03e00008 d4200010 03e00008 <........ ...... + 0050 00000000 03e00008 00000000 00000000 ................ + 0060 00000000 00000000 00000000 00000000 ................ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 00000000 00000000 00000000 3c010000 ............<... + 00a0 03e00008 d4200028 03e00008 00000000 ..... .(........ + 00b0 03e00008 00000000 3c010000 03e00008 ........<....... + 00c0 c4200030 03e00008 00000000 03e00008 . .0............ + 00d0 00000000 00000000 00000000 00000000 ................ + 00e0 00000000 00000000 00000000 00000000 ................ + 00f0 00000000 00000000 00000000 00000000 ................ + 0100 00000000 00000000 00000000 00000000 ................ + 0110 00000000 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 408051ec 00000000 4010147a e147ae14 @.Q.....@..z.G.. + 0010 40101eb8 51eb851f 00000000 408147ae @...Q.......@.G. + 0020 40103333 33333333 40103d70 a3d70a3d @.333333@.=p...= + 0030 40823d71 00000000 401051eb 851eb852 @.=q....@.Q....R +Contents of section .options: + 0000 01200000 00000000 80000002 00000000 . .............. + 0010 000000f3 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000002 00000000 000000f3 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/line-continuation-separate-file.s b/tools/asm-processor/tests/line-continuation-separate-file.s new file mode 100644 index 0000000..e130180 --- /dev/null +++ b/tools/asm-processor/tests/line-continuation-separate-file.s @@ -0,0 +1,4 @@ +.rdata + label: .asciiz "1\n\ +2", \ + "34", "56" diff --git a/tools/asm-processor/tests/line-continuation.asmproc.d b/tools/asm-processor/tests/line-continuation.asmproc.d new file mode 100644 index 0000000..687dd1a --- /dev/null +++ b/tools/asm-processor/tests/line-continuation.asmproc.d @@ -0,0 +1,3 @@ +tests/line-continuation.o: tests/line-continuation-separate-file.s + +tests/line-continuation-separate-file.s: diff --git a/tools/asm-processor/tests/line-continuation.c b/tools/asm-processor/tests/line-continuation.c new file mode 100644 index 0000000..d5ab093 --- /dev/null +++ b/tools/asm-processor/tests/line-continuation.c @@ -0,0 +1,22 @@ +void foo(void) { "abcdef"; } + +GLOBAL_ASM( +.rdata + .ascii "AB" \ + "CD", "EF" + .ascii "GH\n\n\n\0\11\222\3333\44444\x1234567\n\nIJK" +) + +void bar(void) { "hello"; } + +GLOBAL_ASM( +.rdata + .asciiz "1\ +2" + .asciiz "34", "56" + .asciiz "78\n\n\n\0\11\222\3333\44444\x1234567\n\n9A" +) + +void baz(void) { "ghijkl"; } + +GLOBAL_ASM("tests/line-continuation-separate-file.s") diff --git a/tools/asm-processor/tests/line-continuation.objdump b/tools/asm-processor/tests/line-continuation.objdump new file mode 100644 index 0000000..038766f --- /dev/null +++ b/tools/asm-processor/tests/line-continuation.objdump @@ -0,0 +1,30 @@ + +tests/line-continuation.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000030 .text +00000000 l d .rodata 00000060 .rodata +00000000 g F .text 00000010 foo +00000010 g F .text 00000010 bar +00000020 g F .text 00000010 baz + + +Contents of section .text: + 0000 03e00008 00000000 03e00008 00000000 ................ + 0010 03e00008 00000000 03e00008 00000000 ................ + 0020 03e00008 00000000 03e00008 00000000 ................ +Contents of section .rodata: + 0000 61626364 65660000 41424344 45464748 abcdef..ABCDEFGH + 0010 0a0a0a00 0992db33 24343467 0a0a494a .......3$44g..IJ + 0020 4b000000 68656c6c 6f000000 31320033 K...hello...12.3 + 0030 34003536 0037380a 0a0a0009 92db3324 4.56.78.......3$ + 0040 3434670a 0a394100 6768696a 6b6c0000 44g..9A.ghijkl.. + 0050 310a3200 33340035 36000000 00000000 1.2.34.56....... +Contents of section .options: + 0000 01200000 00000000 80000000 00000000 . .............. + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000000 00000000 00000000 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/o0.c b/tools/asm-processor/tests/o0.c new file mode 100644 index 0000000..6f8e5e4 --- /dev/null +++ b/tools/asm-processor/tests/o0.c @@ -0,0 +1,28 @@ +// COMPILE-FLAGS: -O0 + +int a(void) { return 1; } +GLOBAL_ASM( +glabel foo +addiu $a0, $a0, 1 +addiu $a0, $a0, 2 +addiu $a0, $a0, 3 +jr $ra +addiu $a0, $a0, 4 +) +float b(void) { return 1.2f; } +GLOBAL_ASM( +.late_rodata +glabel float1 +.float 12.34 + +.text +glabel bar +addiu $a0, $a0, 5 +addiu $a0, $a0, 6 +addiu $a0, $a0, 7 +addiu $a0, $a0, 8 +lui $v0, %hi(float1 + 1) +jr $ra +addiu $v0, $v0, %lo(float1 + 1) +) +float c(void) { return 1.3f; } diff --git a/tools/asm-processor/tests/o0.objdump b/tools/asm-processor/tests/o0.objdump new file mode 100644 index 0000000..f94ec7a --- /dev/null +++ b/tools/asm-processor/tests/o0.objdump @@ -0,0 +1,44 @@ + +tests/o0.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000090 .text +00000000 l d .rodata 00000010 .rodata +00000000 g F .text 0000001c a +00000030 g F .text 00000020 b +0000006c g F .text 00000020 c +0000001c g F .text 00000014 foo +00000050 g F .text 0000001c bar +00000004 g .rodata 00000000 float1 + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000030 R_MIPS_HI16 .rodata +00000034 R_MIPS_LO16 .rodata +0000006c R_MIPS_HI16 .rodata +00000070 R_MIPS_LO16 .rodata +00000060 R_MIPS_HI16 float1 +00000068 R_MIPS_LO16 float1 + + +Contents of section .text: + 0000 24020001 03e00008 00000000 03e00008 $............... + 0010 00000000 03e00008 00000000 24840001 ............$... + 0020 24840002 24840003 03e00008 24840004 $...$.......$... + 0030 3c010000 c4200000 03e00008 00000000 <.... .......... + 0040 03e00008 00000000 03e00008 00000000 ................ + 0050 24840005 24840006 24840007 24840008 $...$...$...$... + 0060 3c020000 03e00008 24420001 3c010000 <.......$B..<... + 0070 c4200008 03e00008 00000000 03e00008 . .............. + 0080 00000000 03e00008 00000000 00000000 ................ +Contents of section .rodata: + 0000 3f99999a 414570a4 3fa66666 00000000 ?...AEp.?.ff.... +Contents of section .options: + 0000 01200000 00000000 80000006 00000000 . .............. + 0010 00000011 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000016 00000000 00000011 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/o2.c b/tools/asm-processor/tests/o2.c new file mode 100644 index 0000000..144a604 --- /dev/null +++ b/tools/asm-processor/tests/o2.c @@ -0,0 +1,26 @@ +// COMPILE-FLAGS: -O2 + +int a(void) { return 1; } +GLOBAL_ASM( +glabel foo +addiu $a0, $a0, 1 +addiu $a0, $a0, 2 +addiu $a0, $a0, 3 +jr $ra +addiu $a0, $a0, 4 +) +float b(void) { return 1.2f; } +GLOBAL_ASM( +.late_rodata +glabel float1 +.float 12.34 + +.text +glabel bar +addiu $a0, $a0, 5 +addiu $a0, $a0, 6 +lui $v0, %hi(float1 + 1) +jr $ra +addiu $v0, $v0, %lo(float1 + 1) +) +float c(void) { return 1.3f; } diff --git a/tools/asm-processor/tests/o2.objdump b/tools/asm-processor/tests/o2.objdump new file mode 100644 index 0000000..61e3fb0 --- /dev/null +++ b/tools/asm-processor/tests/o2.objdump @@ -0,0 +1,40 @@ + +tests/o2.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000050 .text +00000000 l d .rodata 00000010 .rodata +00000000 g F .text 00000008 a +0000001c g F .text 0000000c b +0000003c g F .text 0000000c c +00000008 g F .text 00000014 foo +00000028 g F .text 00000014 bar +00000004 g .rodata 00000000 float1 + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +0000001c R_MIPS_HI16 .rodata +00000024 R_MIPS_LO16 .rodata +0000003c R_MIPS_HI16 .rodata +00000044 R_MIPS_LO16 .rodata +00000030 R_MIPS_HI16 float1 +00000038 R_MIPS_LO16 float1 + + +Contents of section .text: + 0000 03e00008 24020001 24840001 24840002 ....$...$...$... + 0010 24840003 03e00008 24840004 3c010000 $.......$...<... + 0020 03e00008 c4200000 24840005 24840006 ..... ..$...$... + 0030 3c020000 03e00008 24420001 3c010000 <.......$B..<... + 0040 03e00008 c4200008 00000000 00000000 ..... .......... +Contents of section .rodata: + 0000 3f99999a 414570a4 3fa66666 00000000 ?...AEp.?.ff.... +Contents of section .options: + 0000 01200000 00000000 80000006 00000000 . .............. + 0010 00000011 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80000016 00000000 00000011 00000000 ................ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/pascal.objdump b/tools/asm-processor/tests/pascal.objdump new file mode 100644 index 0000000..cb3740f --- /dev/null +++ b/tools/asm-processor/tests/pascal.objdump @@ -0,0 +1,137 @@ + +tests/pascal.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000000e0 .text +00000000 l d .rodata 00000030 .rodata +00000000 l d .data 00000010 .data +00000000 l d .bss 00000010 .bss +00000000 l O .bss 00000000 $dat +00000000 g F .text 0000000c foo +000000d0 g F .text 0000000c bar +0000000c g F .text 00000004 test +00000048 g F .text 00000004 test2 +0000008c g F .text 00000044 test3 +00000000 *UND* 00000000 get +00000000 *UND* 00000000 put +00000000 *UND* 00000000 pascal_close +00000000 *UND* 00000000 fflush +00000000 *UND* 00000000 filesize +00000000 *UND* 00000000 curpos +00000000 *UND* 00000000 seek +00000000 *UND* 00000000 eof +00000000 *UND* 00000000 eoln +00000000 *UND* 00000000 page +00000000 *UND* 00000000 reset +00000000 *UND* 00000000 rewrite +00000000 *UND* 00000000 cos +00000000 *UND* 00000000 exp +00000000 *UND* 00000000 sqrt +00000000 *UND* 00000000 log +00000000 *UND* 00000000 atan +00000000 *UND* 00000000 sin +00000000 *UND* 00000000 __random_float +00000000 *UND* 00000000 clock +00000000 *UND* 00000000 exit +00000000 *UND* 00000000 __date +00000000 *UND* 00000000 __time +00000000 *UND* 00000000 get_arg +00000000 *UND* 00000000 new +00000000 *UND* 00000000 dispose +00000000 *UND* 00000000 initfile +00000000 *UND* 00000000 peek_char +00000000 *UND* 00000000 next_char +00000000 *UND* 00000000 readln +00000000 *UND* 00000000 read_int64 +00000000 *UND* 00000000 read_card64 +00000000 *UND* 00000000 read_integer +00000000 *UND* 00000000 read_cardinal +00000000 *UND* 00000000 read_integer_range +00000000 *UND* 00000000 read_real +00000000 *UND* 00000000 read_double +00000000 *UND* 00000000 read_extended +00000000 *UND* 00000000 read_string +00000000 *UND* 00000000 read_enum +00000000 *UND* 00000000 read_char +00000000 *UND* 00000000 read_char_range +00000000 *UND* 00000000 read_boolean +00000000 *UND* 00000000 read_set +00000000 *UND* 00000000 writeln +00000000 *UND* 00000000 write_int64 +00000000 *UND* 00000000 write_card64 +00000000 *UND* 00000000 write_integer +00000000 *UND* 00000000 write_cardinal +00000000 *UND* 00000000 write_boolean +00000000 *UND* 00000000 write_char +00000000 *UND* 00000000 write_real +00000000 *UND* 00000000 write_double +00000000 *UND* 00000000 write_extended +00000000 *UND* 00000000 write_string +00000000 *UND* 00000000 write_enum +00000000 *UND* 00000000 write_set +00000000 *UND* 00000000 caseerror +00000000 *UND* 00000000 __pc_nloc_goto +00000000 *UND* 00000000 memcpy +00000000 *UND* 00000000 __in_range +00000000 *UND* 00000000 __ll_mul +00000000 *UND* 00000000 __ll_div +00000000 *UND* 00000000 __ull_div +00000000 *UND* 00000000 __ll_mod +00000000 *UND* 00000000 __ll_rem +00000000 *UND* 00000000 __ull_rem +00000000 *UND* 00000000 __ll_lshift +00000000 *UND* 00000000 __ll_rshift +00000000 *UND* 00000000 __ll_to_f +00000000 *UND* 00000000 __ull_to_f +00000000 *UND* 00000000 __ll_to_d +00000000 *UND* 00000000 __ull_to_d +00000000 *UND* 00000000 __f_ll_ll +00000000 *UND* 00000000 __f_to_ull +00000000 *UND* 00000000 __d_to_ll +00000000 *UND* 00000000 __d_to_ull +00000000 *UND* 00000000 round64 +00000000 *UND* 00000000 trunc64 +00000000 *UND* 00000000 max64 +00000000 *UND* 00000000 min64 +00000000 *UND* 00000000 abs64 +00000000 *UND* 00000000 odd64 +00000000 *UND* 00000000 trapNaN +00000000 *UND* 00000008 input +00000000 *UND* 00000008 output +00000000 *UND* 00000008 err +00000000 *UND* 00000008 __Argc + + +RELOCATION RECORDS FOR [.text]: (none) + +RELOCATION RECORDS FOR [.rodata]: (none) + +Contents of section .text: + 0000 00041080 03e00008 00441023 27bdffe8 .........D.#'... + 0010 18a00009 afa00004 8fae0004 008e7821 ..............x! + 0020 a1e00000 8fb80004 27190001 0325082a ........'....%.* + 0030 1420fff9 afb90004 10000001 00000000 . .............. + 0040 03e00008 27bd0018 00000000 00000000 ....'........... + 0050 00000000 00000000 00000000 00000000 ................ + 0060 00000000 00000000 00000000 00000000 ................ + 0070 00000000 00000000 00000000 00000000 ................ + 0080 00000000 00000000 00000000 00000000 ................ + 0090 00000000 00000000 00000000 00000000 ................ + 00a0 00000000 00000000 00000000 00000000 ................ + 00b0 00000000 00000000 00000000 00000000 ................ + 00c0 00000000 00000000 00000000 00000000 ................ + 00d0 00041080 03e00008 00441023 00000000 .........D.#.... +Contents of section .rodata: + 0000 00123123 00456456 00789789 00000001 ..1#.EdV.x...... + 0010 3ff19999 9999999a 00000002 00000003 ?............... + 0020 4000cccc cccccccd 00000000 00000000 @............... +Contents of section .data: + 0000 00002323 00003434 00000000 00000000 ..##..44........ +Contents of section .options: + 0000 01200000 00000000 80004016 00000000 . ........@..... + 0010 000000f0 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a300c036 00000000 000000f0 00000000 ...6............ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/pascal.p b/tools/asm-processor/tests/pascal.p new file mode 100644 index 0000000..0886126 --- /dev/null +++ b/tools/asm-processor/tests/pascal.p @@ -0,0 +1,95 @@ +{ COMPILE-FLAGS: -O2 } + +function foo(x: integer): integer; +begin + foo := x * 3 +end; + +GLOBAL_ASM( +.section .data +.word 0x2323 + +.late_rodata +.word 0x123123 +.word 0x456456 +.word 0x789789 +.text +glabel test +/* 000090 00400090 27BDFFF8 */ addiu $sp, $sp, -24 +/* 000094 00400094 18A00009 */ blez $a1, .L004000BC +/* 000098 00400098 AFA00004 */ sw $zero, 4($sp) +.L0040009C: +/* 00009C 0040009C 8FAE0004 */ lw $t6, 4($sp) +/* 0000A0 004000A0 008E7821 */ addu $t7, $a0, $t6 +/* 0000A4 004000A4 A1E00000 */ sb $zero, ($t7) +/* 0000A8 004000A8 8FB80004 */ lw $t8, 4($sp) +/* 0000AC 004000AC 27190001 */ addiu $t9, $t8, 1 +/* 0000B0 004000B0 0325082A */ slt $at, $t9, $a1 +/* 0000B4 004000B4 1420FFF9 */ bnez $at, .L0040009C +/* 0000B8 004000B8 AFB90004 */ sw $t9, 4($sp) +.L004000BC: +/* 0000BC 004000BC 10000001 */ b .L004000C4 +/* 0000C0 004000C0 00000000 */ nop +.L004000C4: +/* 0000C4 004000C4 03E00008 */ jr $ra +/* 0000C8 004000C8 27BD0008 */ addiu $sp, $sp, 24 +) + +GLOBAL_ASM( +.section .data +.word 0x3434 + +.late_rodata +.word 0x1 +.double 1.1 +.word 0x2, 0x3 +.text +glabel test2 +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +) + +GLOBAL_ASM( +.late_rodata +.double 2.1 +.text +glabel test3 +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +) + +function bar(x: integer): integer; +begin + return x * 3 +end; + diff --git a/tools/asm-processor/tests/static-global.c b/tools/asm-processor/tests/static-global.c new file mode 100644 index 0000000..a7f6169 --- /dev/null +++ b/tools/asm-processor/tests/static-global.c @@ -0,0 +1,33 @@ +// COMPILE-FLAGS: -O2 +// ASMP-FLAGS: --convert-statics=global +static int xtext(int a, int b, int c); +const int rodata1[] = {1}; +static const int rodata2[] = {2}; +int data1[] = {3}; +static int data2[] = {4}; +int bss1; +static int bss2; + +GLOBAL_ASM( +glabel bar +lui $a0, %hi(rodata2) +lw $a0, %lo(rodata2)($a0) +lui $a1, %hi(data2) +lw $a1, %lo(data2)($a0) +lui $a2, %hi(bss2) +lw $a2, %lo(bss2)($a0) +jal xtext +nop +jr $ra +nop +nop +nop +) + +static int xtext(int a, int b, int c) { + return 1; +} + +void baz(void) { + xtext(bss2, rodata2[0], data2[0]); +} diff --git a/tools/asm-processor/tests/static-global.objdump b/tools/asm-processor/tests/static-global.objdump new file mode 100644 index 0000000..a519e4f --- /dev/null +++ b/tools/asm-processor/tests/static-global.objdump @@ -0,0 +1,58 @@ + +tests/static-global.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000080 .text +00000000 l d .rodata 00000010 .rodata +00000000 l d .data 00000010 .data +00000000 l d .bss 00000010 .bss +00000000 g O .rodata 00000004 rodata1 +00000000 g O .data 00000004 data1 +00000000 g O .bss 00000004 bss1 +00000044 g F .text 00000034 baz +00000000 g F .text 00000030 bar +00000004 g O .rodata 00000000 rodata2 +00000004 g O .data 00000000 data2 +00000004 g O .bss 00000000 bss2 +00000030 g F .text 00000000 xtext + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +0000004c R_MIPS_HI16 .bss +00000064 R_MIPS_LO16 .bss +00000050 R_MIPS_HI16 .rodata +0000005c R_MIPS_LO16 .rodata +00000054 R_MIPS_HI16 .data +00000058 R_MIPS_LO16 .data +00000060 R_MIPS_26 .text +00000000 R_MIPS_HI16 rodata2 +00000004 R_MIPS_LO16 rodata2 +00000008 R_MIPS_HI16 data2 +0000000c R_MIPS_LO16 data2 +00000010 R_MIPS_HI16 bss2 +00000014 R_MIPS_LO16 bss2 +00000018 R_MIPS_26 xtext + + +Contents of section .text: + 0000 3c040000 8c840000 3c050000 8c850000 <.......<....... + 0010 3c060000 8c860000 0c000000 00000000 <............... + 0020 03e00008 00000000 00000000 00000000 ................ + 0030 afa40000 afa50004 afa60008 03e00008 ................ + 0040 24020001 27bdffe8 afbf0014 3c040000 $...'.......<... + 0050 3c050000 3c060000 8cc60004 8ca50004 <...<........... + 0060 0c00000c 8c840004 8fbf0014 27bd0018 ............'... + 0070 03e00008 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 00000001 00000002 00000000 00000000 ................ +Contents of section .data: + 0000 00000003 00000004 00000000 00000000 ................ +Contents of section .options: + 0000 01200000 00000000 a0000074 00000000 . .........t.... + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a0000074 00000000 00000000 00000000 ...t............ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/static.c b/tools/asm-processor/tests/static.c new file mode 100644 index 0000000..c265021 --- /dev/null +++ b/tools/asm-processor/tests/static.c @@ -0,0 +1,32 @@ +// COMPILE-FLAGS: -O2 +static int xtext(int a, int b, int c); +const int rodata1[] = {1}; +static const int rodata2[] = {2}; +int data1[] = {3}; +static int data2[] = {4}; +int bss1; +static int bss2; + +GLOBAL_ASM( +glabel bar +lui $a0, %hi(rodata2) +lw $a0, %lo(rodata2)($a0) +lui $a1, %hi(data2) +lw $a1, %lo(data2)($a0) +lui $a2, %hi(bss2) +lw $a2, %lo(bss2)($a0) +jal xtext +nop +jr $ra +nop +nop +nop +) + +static int xtext(int a, int b, int c) { + return 1; +} + +void baz(void) { + xtext(bss2, rodata2[0], data2[0]); +} diff --git a/tools/asm-processor/tests/static.objdump b/tools/asm-processor/tests/static.objdump new file mode 100644 index 0000000..dd62c94 --- /dev/null +++ b/tools/asm-processor/tests/static.objdump @@ -0,0 +1,58 @@ + +tests/static.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 00000080 .text +00000000 l d .rodata 00000010 .rodata +00000000 l d .data 00000010 .data +00000000 l d .bss 00000010 .bss +00000004 l O .rodata 00000000 rodata2 +00000004 l O .data 00000000 data2 +00000004 l O .bss 00000000 bss2 +00000030 l F .text 00000000 xtext +00000000 g O .rodata 00000004 rodata1 +00000000 g O .data 00000004 data1 +00000000 g O .bss 00000004 bss1 +00000044 g F .text 00000034 baz +00000000 g F .text 00000030 bar + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +0000004c R_MIPS_HI16 .bss +00000064 R_MIPS_LO16 .bss +00000050 R_MIPS_HI16 .rodata +0000005c R_MIPS_LO16 .rodata +00000054 R_MIPS_HI16 .data +00000058 R_MIPS_LO16 .data +00000060 R_MIPS_26 .text +00000000 R_MIPS_HI16 rodata2 +00000004 R_MIPS_LO16 rodata2 +00000008 R_MIPS_HI16 data2 +0000000c R_MIPS_LO16 data2 +00000010 R_MIPS_HI16 bss2 +00000014 R_MIPS_LO16 bss2 +00000018 R_MIPS_26 xtext + + +Contents of section .text: + 0000 3c040000 8c840000 3c050000 8c850000 <.......<....... + 0010 3c060000 8c860000 0c000000 00000000 <............... + 0020 03e00008 00000000 00000000 00000000 ................ + 0030 afa40000 afa50004 afa60008 03e00008 ................ + 0040 24020001 27bdffe8 afbf0014 3c040000 $...'.......<... + 0050 3c050000 3c060000 8cc60004 8ca50004 <...<........... + 0060 0c00000c 8c840004 8fbf0014 27bd0018 ............'... + 0070 03e00008 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 00000001 00000002 00000000 00000000 ................ +Contents of section .data: + 0000 00000003 00000004 00000000 00000000 ................ +Contents of section .options: + 0000 01200000 00000000 a0000074 00000000 . .........t.... + 0010 00000000 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a0000074 00000000 00000000 00000000 ...t............ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/test1.c b/tools/asm-processor/tests/test1.c new file mode 100644 index 0000000..475555a --- /dev/null +++ b/tools/asm-processor/tests/test1.c @@ -0,0 +1,71 @@ + +GLOBAL_ASM( +.rdata +.word 0x1212 +) + +GLOBAL_ASM( +.late_rodata +.word 0x123123 +.text +glabel test +/* 000090 00400090 27BDFFF8 */ addiu $sp, $sp, -24 +/* 000094 00400094 18A00009 */ blez $a1, .L004000BC +/* 000098 00400098 AFA00004 */ sw $zero, 4($sp) +.L0040009C: +/* 00009C 0040009C 8FAE0004 */ lw $t6, 4($sp) +/* 0000A0 004000A0 008E7821 */ addu $t7, $a0, $t6 +/* 0000A4 004000A4 A1E00000 */ sb $zero, ($t7) +/* 0000A8 004000A8 8FB80004 */ lw $t8, 4($sp) +/* 0000AC 004000AC 27190001 */ addiu $t9, $t8, 1 +/* 0000B0 004000B0 0325082A */ slt $at, $t9, $a1 +/* 0000B4 004000B4 1420FFF9 */ bnez $at, .L0040009C +/* 0000B8 004000B8 AFB90004 */ sw $t9, 4($sp) +.L004000BC: +/* 0000BC 004000BC 10000001 */ b .L004000C4 +/* 0000C0 004000C0 00000000 */ nop +.L004000C4: +/* 0000C4 004000C4 03E00008 */ jr $ra +/* 0000C8 004000C8 27BD0008 */ addiu $sp, $sp, 24 +) + +char bss1[3]; +GLOBAL_ASM( +.bss +bss2: +.space 3 +) +char bss3[3]; +char bss4[3]; +const int rodata1[2] = {1}; +extern int some_rodata; + +unsigned g(float, int); +unsigned f(void) { + return g(1.1f, some_rodata); +} + +GLOBAL_ASM( +.rdata +glabel some_rodata +.word 0x1313 +.text +.late_rodata +.word 0x321321 +.text +glabel g +/* 0000C0 004000C0 27BDFFE8 */ addiu $sp, $sp, -0x18 +/* 0000C4 004000C4 AFBF0014 */ sw $ra, 0x14($sp) +/* 0000C8 004000C8 240E0004 */ addiu $t6, $zero, 4 +/* 0000CC 004000CC 3C010041 */ lui $at, %hi(D_410100) +/* 0000D0 004000D0 AC2E0100 */ sw $t6, %lo(D_410100)($at) +/* 0000D4 004000D4 0C10002C */ jal func_004000B0 +/* 0000D8 004000D8 00000000 */ nop +/* 0000DC 004000DC 10000001 */ b .L004000E4 +/* 0000E0 004000E0 00000000 */ nop +.L004000E4: +/* 0000E4 004000E4 8FBF0014 */ lw $ra, 0x14($sp) +/* 0000E8 004000E8 27BD0018 */ addiu $sp, $sp, 0x18 +/* 0000EC 004000EC 03E00008 */ jr $ra +/* 0000F0 004000F0 00000000 */ nop +) diff --git a/tools/asm-processor/tests/test1.objdump b/tools/asm-processor/tests/test1.objdump new file mode 100644 index 0000000..b97ae46 --- /dev/null +++ b/tools/asm-processor/tests/test1.objdump @@ -0,0 +1,54 @@ + +tests/test1.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000000b0 .text +00000000 l d .rodata 00000020 .rodata +00000000 l d .bss 00000010 .bss +00000000 g O .bss 00000003 bss1 +00000008 g O .bss 00000003 bss3 +0000000c g O .bss 00000003 bss4 +00000004 g O .rodata 00000008 rodata1 +0000003c g F .text 0000003c f +00000000 g F .text 0000003c test +0000000c g .rodata 00000000 some_rodata +00000078 g F .text 00000004 g +00000000 *UND* 00000000 D_410100 +00000000 *UND* 00000000 func_004000B0 + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000044 R_MIPS_HI16 .rodata +00000054 R_MIPS_LO16 .rodata +00000048 R_MIPS_HI16 some_rodata +0000004c R_MIPS_LO16 some_rodata +00000050 R_MIPS_26 g +00000084 R_MIPS_HI16 D_410100 +00000088 R_MIPS_LO16 D_410100 +0000008c R_MIPS_26 func_004000B0 + + +Contents of section .text: + 0000 27bdffe8 18a00009 afa00004 8fae0004 '............... + 0010 008e7821 a1e00000 8fb80004 27190001 ..x!........'... + 0020 0325082a 1420fff9 afb90004 10000001 .%.*. .......... + 0030 00000000 03e00008 27bd0018 27bdffe8 ........'...'... + 0040 afbf0014 3c010000 3c050000 8ca50000 ....<...<....... + 0050 0c000000 c42c0014 10000003 00000000 .....,.......... + 0060 10000001 00000000 8fbf0014 27bd0018 ............'... + 0070 03e00008 00000000 27bdffe8 afbf0014 ........'....... + 0080 240e0004 3c010000 ac2e0000 0c000000 $...<........... + 0090 00000000 10000001 00000000 8fbf0014 ................ + 00a0 27bd0018 03e00008 00000000 00000000 '............... +Contents of section .rodata: + 0000 00001212 00000001 00000000 00001313 ................ + 0010 00123123 3f8ccccd 00321321 00000000 ..1#?....2.!.... +Contents of section .options: + 0000 01200000 00000000 a0000022 00000000 . .........".... + 0010 00001010 00000000 00000000 00007ff0 ................ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a300c032 00000000 00001010 00000000 ...2............ + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/test2.c b/tools/asm-processor/tests/test2.c new file mode 100644 index 0000000..15969fe --- /dev/null +++ b/tools/asm-processor/tests/test2.c @@ -0,0 +1,69 @@ +const char buf1[1] = {1}; +float func1(void) { + "func1"; + return 0.1f; +} +const char buf2[1] = {2}; +void func2(void) { + *(volatile float*)0 = -3.5792360305786133f; + *(volatile float*)0 = -3.5792362689971924f; + // "func2"; + // return 0.2f; +} +const char buf3[1] = {3}; +int func3(int x) { + switch(x) { + case 0: + return 1; + case 1: + return 2; + case 2: + return 3; + case 3: + return 4; + case 4: + return 5; + case 5: + return 4; + case 6: + return 4; + case 7: + return 4; + default: + return 3; + } +} + +#if 1 +GLOBAL_ASM( +.rdata +.word 0x66756e63 # func +.word 0x34000000 # 4\0\0\0 +.word jumptarget + 4 + +.late_rodata +glabel rv +.word 0x3e4ccccd # 0.2f +.word jumptarget + 8 + +.text +glabel func4 +lui $at, %hi(rv) +glabel jumptarget +jr $ra +lwc1 $f0, %lo(rv)($at) +jr $ra +nop +jr $ra +nop +jr $ra +nop +jr $ra +nop +) +#else +float func4(void) { + "func4"; + return 0.2f; +} +#endif diff --git a/tools/asm-processor/tests/test2.objdump b/tools/asm-processor/tests/test2.objdump new file mode 100644 index 0000000..276ed9f --- /dev/null +++ b/tools/asm-processor/tests/test2.objdump @@ -0,0 +1,76 @@ + +tests/test2.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000000f0 .text +00000000 l d .rodata 00000060 .rodata +00000000 g O .rodata 00000001 buf1 +00000000 g F .text 0000001c func1 +0000000c g O .rodata 00000001 buf2 +0000001c g F .text 00000028 func2 +00000010 g O .rodata 00000001 buf3 +00000044 g F .text 0000007c func3 +000000c4 g F .text 00000000 jumptarget +000000c0 g F .text 0000000c func4 +0000004c g .rodata 00000000 rv + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000000 R_MIPS_HI16 .rodata +00000008 R_MIPS_LO16 .rodata +0000001c R_MIPS_HI16 .rodata +00000020 R_MIPS_LO16 .rodata +00000028 R_MIPS_HI16 .rodata +0000002c R_MIPS_LO16 .rodata +00000054 R_MIPS_HI16 .rodata +0000005c R_MIPS_LO16 .rodata +000000c0 R_MIPS_HI16 rv +000000c8 R_MIPS_LO16 rv + + +RELOCATION RECORDS FOR [.rodata]: +OFFSET TYPE VALUE +0000002c R_MIPS_32 .text +00000030 R_MIPS_32 .text +00000034 R_MIPS_32 .text +00000038 R_MIPS_32 .text +0000003c R_MIPS_32 .text +00000040 R_MIPS_32 .text +00000044 R_MIPS_32 .text +00000048 R_MIPS_32 .text +0000001c R_MIPS_32 jumptarget +00000050 R_MIPS_32 jumptarget + + +Contents of section .text: + 0000 3c010000 03e00008 c4200020 03e00008 <........ . .... + 0010 00000000 03e00008 00000000 3c010000 ............<... + 0020 c4240024 e4040000 3c010000 c4260028 .$.$....<....&.( + 0030 e4060000 03e00008 00000000 03e00008 ................ + 0040 00000000 2c810008 10200017 00000000 ....,.... ...... + 0050 00047080 3c010000 002e0821 8c2e002c ..p.<......!..., + 0060 01c00008 00000000 03e00008 24020001 ............$... + 0070 03e00008 24020002 03e00008 24020003 ....$.......$... + 0080 03e00008 24020004 03e00008 24020005 ....$.......$... + 0090 03e00008 24020004 03e00008 24020004 ....$.......$... + 00a0 03e00008 24020004 03e00008 24020003 ....$.......$... + 00b0 03e00008 00000000 03e00008 00000000 ................ + 00c0 3c010000 03e00008 c4200000 03e00008 <........ ...... + 00d0 00000000 03e00008 00000000 03e00008 ................ + 00e0 00000000 03e00008 00000000 00000000 ................ +Contents of section .rodata: + 0000 01000000 66756e63 31000000 02000000 ....func1....... + 0010 03000000 66756e63 34000000 00000004 ....func4....... + 0020 3dcccccd c0651234 c0651235 00000068 =....e.4.e.5...h + 0030 00000070 00000078 00000080 00000088 ...p...x........ + 0040 00000090 00000098 000000a0 3e4ccccd ............>L.. + 0050 00000008 00000000 00000000 00000000 ................ +Contents of section .options: + 0000 01200000 00000000 80004016 00000000 . ........@..... + 0010 00000051 00000000 00000000 00007ff0 ...Q............ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 80004016 00000000 00000051 00000000 ..@........Q.... + 0010 00000000 00007ff0 ........ diff --git a/tools/asm-processor/tests/test3.c b/tools/asm-processor/tests/test3.c new file mode 100644 index 0000000..d74bb4c --- /dev/null +++ b/tools/asm-processor/tests/test3.c @@ -0,0 +1,70 @@ + +GLOBAL_ASM( +.rdata +.word 321321 +.text +glabel test +/* 000090 00400090 27BDFFF8 */ addiu $sp, $sp, -24 +/* 000094 00400094 18A00009 */ blez $a1, .L004000BC +/* 000098 00400098 AFA00004 */ sw $zero, 4($sp) +.L0040009C: +/* 00009C 0040009C 8FAE0004 */ lw $t6, 4($sp) +/* 0000A0 004000A0 008E7821 */ addu $t7, $a0, $t6 +/* 0000A4 004000A4 A1E00000 */ sb $zero, ($t7) +/* 0000A8 004000A8 8FB80004 */ lw $t8, 4($sp) +/* 0000AC 004000AC 27190001 */ addiu $t9, $t8, 1 +/* 0000B0 004000B0 0325082A */ slt $at, $t9, $a1 +/* 0000B4 004000B4 1420FFF9 */ bnez $at, .L0040009C +/* 0000B8 004000B8 AFB90004 */ sw $t9, 4($sp) +.L004000BC: +/* 0000BC 004000BC 10000001 */ b .L004000C4 +/* 0000C0 004000C0 00000000 */ nop +.L004000C4: +/* 0000C4 004000C4 03E00008 */ jr $ra +/* 0000C8 004000C8 27BD0008 */ addiu $sp, $sp, 24 +) + +// static -> no symbols +// bss +char globalBuf[4]; +const char constBuf[4]; + +// data +char globalBufInit[4] = {1}; + +// rodata +const char constBufInit[4] = {1}; +const char constBufInit2[1] = {2}; +const char constBufInit3[1] = {3}; + +unsigned g(void); +unsigned f(void) { + // aligns to 4 or 8 byte boundary (char -> 4, double -> 8) + double x = 5.1; + float y = 5.2f; + float z = 5.3f; + "Hello "; + "World"; + return g(); +} + +GLOBAL_ASM( +.rdata +.word 123123 +.text +glabel g +/* 0000C0 004000C0 27BDFFE8 */ addiu $sp, $sp, -0x18 +/* 0000C4 004000C4 AFBF0014 */ sw $ra, 0x14($sp) +/* 0000C8 004000C8 240E0004 */ addiu $t6, $zero, 4 +/* 0000CC 004000CC 3C010041 */ lui $at, %hi(D_410100) +/* 0000D0 004000D0 AC2E0100 */ sw $t6, %lo(D_410100)($at) +/* 0000D4 004000D4 0C10002C */ jal func_004000B0 +/* 0000D8 004000D8 00000000 */ nop +/* 0000DC 004000DC 10000001 */ b .L004000E4 +/* 0000E0 004000E0 00000000 */ nop +.L004000E4: +/* 0000E4 004000E4 8FBF0014 */ lw $ra, 0x14($sp) +/* 0000E8 004000E8 27BD0018 */ addiu $sp, $sp, 0x18 +/* 0000EC 004000EC 03E00008 */ jr $ra +/* 0000F0 004000F0 00000000 */ nop +) diff --git a/tools/asm-processor/tests/test3.objdump b/tools/asm-processor/tests/test3.objdump new file mode 100644 index 0000000..bfa7f6e --- /dev/null +++ b/tools/asm-processor/tests/test3.objdump @@ -0,0 +1,64 @@ + +tests/test3.o: file format elf32-tradbigmips + +SYMBOL TABLE: +00000000 l d .text 000000d0 .text +00000000 l d .rodata 00000040 .rodata +00000000 l d .data 00000010 .data +00000000 l d .bss 00000010 .bss +00000000 g O .bss 00000004 globalBuf +00000004 g O .bss 00000004 constBuf +00000000 g O .data 00000004 globalBufInit +00000004 g O .rodata 00000004 constBufInit +00000008 g O .rodata 00000001 constBufInit2 +0000000c g O .rodata 00000001 constBufInit3 +0000003c g F .text 00000054 f +00000000 g F .text 00000004 test +00000090 g F .text 00000004 g +00000000 *UND* 00000000 D_410100 +00000000 *UND* 00000000 func_004000B0 + + +RELOCATION RECORDS FOR [.text]: +OFFSET TYPE VALUE +00000044 R_MIPS_HI16 .rodata +00000048 R_MIPS_LO16 .rodata +00000050 R_MIPS_HI16 .rodata +00000054 R_MIPS_LO16 .rodata +0000005c R_MIPS_HI16 .rodata +00000060 R_MIPS_LO16 .rodata +00000068 R_MIPS_26 g +0000009c R_MIPS_HI16 D_410100 +000000a0 R_MIPS_LO16 D_410100 +000000a4 R_MIPS_26 func_004000B0 + + +Contents of section .text: + 0000 27bdffe8 18a00009 afa00004 8fae0004 '............... + 0010 008e7821 a1e00000 8fb80004 27190001 ..x!........'... + 0020 0325082a 1420fff9 afb90004 10000001 .%.*. .......... + 0030 00000000 03e00008 27bd0018 27bdffd8 ........'...'... + 0040 afbf0014 3c010000 d4240028 f7a40020 ....<....$.(... + 0050 3c010000 c4260030 e7a6001c 3c010000 <....&.0....<... + 0060 c4280034 e7a80018 0c000000 00000000 .(.4............ + 0070 10000003 00000000 10000001 00000000 ................ + 0080 8fbf0014 27bd0028 03e00008 00000000 ....'..(........ + 0090 27bdffe8 afbf0014 240e0004 3c010000 '.......$...<... + 00a0 ac2e0000 0c000000 00000000 10000001 ................ + 00b0 00000000 8fbf0014 27bd0018 03e00008 ........'....... + 00c0 00000000 00000000 00000000 00000000 ................ +Contents of section .rodata: + 0000 0004e729 01000000 02000000 03000000 ...)............ + 0010 48656c6c 6f202000 576f726c 64000000 Hello .World... + 0020 0001e0f3 00000000 40146666 66666666 ........@.ffffff + 0030 40a66666 40a9999a 00000000 00000000 @.ff@........... +Contents of section .data: + 0000 01000000 00000000 00000000 00000000 ................ +Contents of section .options: + 0000 01200000 00000000 a0000002 00000000 . .............. + 0010 00000170 00000000 00000000 00007ff0 ...p............ + 0020 07100000 00000000 00000000 00000000 ................ + 0030 08100000 00000000 00000000 00000000 ................ +Contents of section .reginfo: + 0000 a300c032 00000000 00000170 00000000 ...2.......p.... + 0010 00000000 00007ff0 ........ |
