URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
[/] [zipcpu/] [trunk/] [sw/] [gas-zippatch.patch] - Rev 209
Compare with Previous | Blame | View Log
diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/archures.c binutils-2.27-zip/bfd/archures.c --- binutils-2.27-original/bfd/archures.c 2016-08-03 03:36:50.000000000 -0400 +++ binutils-2.27-zip/bfd/archures.c 2017-01-04 14:22:45.000000000 -0500 @@ -525,6 +525,8 @@ .#define bfd_mach_nios2r2 2 . bfd_arch_visium, {* Visium *} .#define bfd_mach_visium 1 +. bfd_arch_zip, {* ZipCPU *} +.#define bfd_mach_zip 0 . bfd_arch_last . }; */ @@ -655,6 +657,7 @@ extern const bfd_arch_info_type bfd_xgate_arch; extern const bfd_arch_info_type bfd_z80_arch; extern const bfd_arch_info_type bfd_z8k_arch; +extern const bfd_arch_info_type bfd_zip_arch; static const bfd_arch_info_type * const bfd_archures_list[] = { @@ -744,6 +747,7 @@ &bfd_xgate_arch, &bfd_z80_arch, &bfd_z8k_arch, + &bfd_zip_arch, #endif 0 }; diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/bfd-in2.h binutils-2.27-zip/bfd/bfd-in2.h --- binutils-2.27-original/bfd/bfd-in2.h 2016-08-03 03:36:50.000000000 -0400 +++ binutils-2.27-zip/bfd/bfd-in2.h 2017-01-04 22:04:11.000000000 -0500 @@ -2336,6 +2336,8 @@ #define bfd_mach_nios2r2 2 bfd_arch_visium, /* Visium */ #define bfd_mach_visium 1 + bfd_arch_zip, /* ZipCPU */ +#define bfd_mach_zip 0 bfd_arch_last }; @@ -6335,6 +6337,22 @@ BFD_RELOC_VISIUM_HI16_PCREL, BFD_RELOC_VISIUM_LO16_PCREL, BFD_RELOC_VISIUM_IM16_PCREL, + +/* ZipCPU - 32 bit absolute value for LJMP instruction */ + BFD_RELOC_ZIP_VALUE, + +/* ZipCPU - 18-bit PC-relative offset for BRA (ADD #x,PC) instructions */ + BFD_RELOC_ZIP_BRANCH, + +/* ZipCPU value relocations */ + BFD_RELOC_ZIP_OPB_IMM, + BFD_RELOC_ZIP_OPB_OFFSET, + BFD_RELOC_ZIP_OPB_PCREL, + BFD_RELOC_ZIP_MOV_OFFSET, + BFD_RELOC_ZIP_MOV_PCREL, + BFD_RELOC_ZIP_LDI, + BFD_RELOC_ZIP_LLO, + BFD_RELOC_ZIP_BREV, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/config.bfd binutils-2.27-zip/bfd/config.bfd --- binutils-2.27-original/bfd/config.bfd 2016-08-03 03:36:50.000000000 -0400 +++ binutils-2.27-zip/bfd/config.bfd 2016-12-31 17:11:00.961307172 -0500 @@ -1742,6 +1742,10 @@ targ_underscore=yes ;; + zip*) + targ_defvec=zip_elf32_vec + ;; + *-*-ieee*) targ_defvec=ieee_vec ;; diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/configure binutils-2.27-zip/bfd/configure --- binutils-2.27-original/bfd/configure 2016-08-03 04:33:36.000000000 -0400 +++ binutils-2.27-zip/bfd/configure 2016-12-31 17:12:22.360697343 -0500 @@ -14542,6 +14542,7 @@ xtensa_elf32_le_vec) tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;; z80_coff_vec) tb="$tb coff-z80.lo reloc16.lo $coffgen" ;; z8k_coff_vec) tb="$tb coff-z8k.lo reloc16.lo $coff" ;; + zip_elf32_vec) tb="$tb elf32-zip.lo elf32.lo $elf" ;; # These appear out of order in targets.c srec_vec) tb="$tb srec.lo" ;; @@ -14924,6 +14925,9 @@ x86_64-*-netbsd* | x86_64-*-openbsd*) COREFILE=netbsd-core.lo ;; + zip*) + COREFILE=netbsd-core.lo + ;; esac case "$COREFILE" in diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/configure.ac binutils-2.27-zip/bfd/configure.ac --- binutils-2.27-original/bfd/configure.ac 2016-08-03 03:36:50.000000000 -0400 +++ binutils-2.27-zip/bfd/configure.ac 2016-12-31 17:13:38.600136486 -0500 @@ -717,6 +717,7 @@ xtensa_elf32_le_vec) tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;; z80_coff_vec) tb="$tb coff-z80.lo reloc16.lo $coffgen" ;; z8k_coff_vec) tb="$tb coff-z8k.lo reloc16.lo $coff" ;; + zip_elf32_vec) tb="$tb elf32-zip.lo elf32.lo $elf" ;; # These appear out of order in targets.c srec_vec) tb="$tb srec.lo" ;; @@ -1092,6 +1093,9 @@ x86_64-*-netbsd* | x86_64-*-openbsd*) COREFILE=netbsd-core.lo ;; + zip*) + COREFILE=netbsd-core.lo + ;; esac case "$COREFILE" in diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/cpu-zip.c binutils-2.27-zip/bfd/cpu-zip.c --- binutils-2.27-original/bfd/cpu-zip.c 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/bfd/cpu-zip.c 2017-01-04 14:26:27.000000000 -0500 @@ -0,0 +1,65 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: tc-zip.c +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: BFD support for the Zip CPU architecture. +// +// This file is part of BFD, the Binary File Descriptor library. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016-2017, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" + +const bfd_arch_info_type +bfd_zip_arch = +{ + 32, // There's 32 bits_per_word. + 32, // There's 34 bits_per_address. + 8, // There's 32 bits_per_byte. + bfd_arch_zip, // One of enum bfd_architecture, defined + // in archures.c and provided in + // generated header files. + bfd_mach_zip, // Random BFD-internal number for this + // machine, similarly listed in + // archures.c. Not emitted in output. + "zip", // The arch_name. + "zip", // The printable name is the same. + 2, // Section alignment power; each section + // is aligned to (only) 2^2 (i.e. 4) bytes. + TRUE, // This is the default "machine". + bfd_default_compatible, // Architecture comparison function + bfd_default_scan, // String to architecture conversion + bfd_arch_default_fill, // Default fill. + NULL // Pointer to next bfd_arch_info_type in + // the same family. +}; + diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/doc/archures.texi binutils-2.27-zip/bfd/doc/archures.texi --- binutils-2.27-original/bfd/doc/archures.texi 2016-08-03 04:36:22.000000000 -0400 +++ binutils-2.27-zip/bfd/doc/archures.texi 2016-12-31 17:14:43.103668704 -0500 @@ -492,6 +492,8 @@ #define bfd_mach_nios2r2 2 bfd_arch_visium, /* Visium */ #define bfd_mach_visium 1 + bfd_mach_zip, +#define bfd_mach_zip 0 bfd_arch_last @}; @end example diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/doc/bfd.info binutils-2.27-zip/bfd/doc/bfd.info --- binutils-2.27-original/bfd/doc/bfd.info 2016-08-03 04:36:22.000000000 -0400 +++ binutils-2.27-zip/bfd/doc/bfd.info 2017-01-04 14:40:21.000000000 -0500 @@ -8466,6 +8466,8 @@ #define bfd_mach_nios2r2 2 bfd_arch_visium, /* Visium */ #define bfd_mach_visium 1 + bfd_arch_zip, /* ZipCPU */ + #define bfd_mach_zip 0 bfd_arch_last }; diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/doc/reloc.texi binutils-2.27-zip/bfd/doc/reloc.texi --- binutils-2.27-original/bfd/doc/reloc.texi 2016-08-03 04:36:22.000000000 -0400 +++ binutils-2.27-zip/bfd/doc/reloc.texi 2016-12-31 17:17:15.950640091 -0500 @@ -4214,6 +4214,19 @@ @deffnx {} BFD_RELOC_VISIUM_IM16_PCREL Visium Relocations. @end deffn +@deffn {} BFD_RELOC_ZIP_VALUE +@deffnx {} BFD_RELOC_OPB_IMM +@deffnx {} BFD_RELOC_OPB_OFFSET +@deffnx {} BFD_RELOC_OPB_PCREL +@deffnx {} BFD_RELOC_OPB_GOTREL +@deffnx {} BFD_RELOC_MOV_OFFSET +@deffnx {} BFD_RELOC_MOV_PCREL +@deffnx {} BFD_RELOC_MOV_GOTREL +@deffnx {} BFD_RELOC_ZIP_LDI +@deffnx {} BFD_RELOC_ZIP_LLO +@deffnx {} BFD_RELOC_ZIP_LHI +ZipCPU relocations +@end deffn @example diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/elf32-zip.c binutils-2.27-zip/bfd/elf32-zip.c --- binutils-2.27-original/bfd/elf32-zip.c 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/bfd/elf32-zip.c 2017-01-24 13:54:25.214097101 -0500 @@ -0,0 +1,1134 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: tc-zip.c +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: Zip-specific support for 32-bit ELF. +// +// This file is part of BFD, the Binary File Descriptor library. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#include "sysdep.h" +#include "bfd.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elf/zip.h" +#include <limits.h> +#include <stdint.h> + +#define zip_relocation bfd_elf_generic_reloc + +static bfd_reloc_status_type +zip_brev_relocation(bfd *, arelent *, asymbol *, void *, asection *, + bfd *, char **error_messsage); +static uint32_t zip_bitreverse(uint32_t v); + +/* Forward declarations. */ +static reloc_howto_type zip_elf_howto_table [] = +{ + /* This reloc does nothing. */ + HOWTO (R_ZIP_NONE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 32 bit absolute relocation. */ + HOWTO (R_ZIP_VALUE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_VALUE", /* name */ + FALSE, /* partial_inplace */ + 0x00000000, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_ZIP_BREV, /* type -- LDIHI, but with bitreverse */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + zip_brev_relocation, /* special_function--needed for the bitreverse */ + "R_ZIP_BREV", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0003ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_ZIP_LLO, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 23, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* don't complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_LLO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_ZIP_LDI, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 23, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_LDI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x007fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* An 18 bit pc-relative relocation. */ + HOWTO (R_ZIP_BRANCH, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_BRANCH", /* name */ + FALSE, /* partial_inplace */ + 0x00000000, /* src_mask */ + 0x0003fffc, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* An 18 bit operand B immediate. */ + HOWTO (R_ZIP_OPB_IMM, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_OPB_IMM", /* name */ + FALSE, /* partial_inplace */ + 0x00000000, /* src_mask */ + 0x0003ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* An 18 bit relocation. */ + HOWTO (R_ZIP_OPB_OFFSET, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 14, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_OPB_OFFSET", /* name */ + FALSE, /* partial_inplace */ + 0x00000000, /* src_mask */ + 0x00003fff, /* dst_mask-14 bits */ + FALSE), /* pcrel_offset */ + + /* An 18 bit operand B immediate, but relative to the current PC. */ + HOWTO (R_ZIP_OPB_PCREL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 14, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_OPB_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0x00000000, /* src_mask */ + 0x00003fff, /* dst_mask-14 bits */ + TRUE), /* pcrel_offset */ + + /* An 18 bit operand B immediate, but relative to the Global Offset Table. */ + //HOWTO (R_ZIP_OPB_GOTREL, /* type */ + //0, /* rightshift */ + //2, /* size (0 = byte, 1 = short, 2 = long) */ + //18, /* bitsize */ + //FALSE, /* pc_relative */ + //0, /* bitpos */ + //complain_overflow_signed, /* complain_on_overflow */ + //zip_relocation, /* special_function */ + //"R_ZIP_OPB_GOTREL", /* name */ + //FALSE, /* partial_inplace */ + //0x00000000, /* src_mask */ + //0x0003ffff, /* dst_mask-14 bits */ + //FALSE), /* pcrel_offset */ + + /* */ + HOWTO (R_ZIP_MOV_OFFSET, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 13, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_MOV_OFFSET", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x00001fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* */ + HOWTO (R_ZIP_MOV_PCREL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 13, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + zip_relocation, /* special_function */ + "R_ZIP_MOV_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x00001fff, /* dst_mask */ + TRUE) /* pcrel_offset */ + + /* */ + //HOWTO (R_ZIP_MOV_GOTREL, /* type */ + //0, /* rightshift */ + //2, /* size (0 = byte, 1 = short, 2 = long) */ + //13, /* bitsize */ + //FALSE, /* pc_relative */ + //0, /* bitpos */ + //complain_overflow_signed, /* complain_on_overflow */ + //zip_relocation, /* special_function */ + //"R_ZIP_MOV_GOTREL", /* name */ + //FALSE, /* partial_inplace */ + //0, /* src_mask */ + //0x00001fff, /* dst_mask */ + //FALSE), /* pcrel_offset */ + +}; + +/* This structure is used to map BFD reloc codes to Zip ELF relocations */ + +struct elf_reloc_map +{ + bfd_reloc_code_real_type bfd_reloc_val; + unsigned int elf_reloc_val; +}; + +static const struct elf_reloc_map zip_reloc_map [] = +{ + { BFD_RELOC_NONE, R_ZIP_NONE }, + { BFD_RELOC_ZIP_VALUE, R_ZIP_VALUE }, + { BFD_RELOC_ZIP_BRANCH, R_ZIP_BRANCH }, + { BFD_RELOC_ZIP_OPB_IMM, R_ZIP_OPB_IMM }, + { BFD_RELOC_ZIP_OPB_OFFSET, R_ZIP_OPB_OFFSET }, + { BFD_RELOC_ZIP_MOV_OFFSET, R_ZIP_MOV_OFFSET }, + { BFD_RELOC_ZIP_LDI, R_ZIP_LDI }, + { BFD_RELOC_ZIP_LLO, R_ZIP_LLO }, + { BFD_RELOC_ZIP_BREV, R_ZIP_BREV }, + { BFD_RELOC_14, R_ZIP_OPB_OFFSET }, + { BFD_RELOC_16, R_ZIP_LLO }, + { BFD_RELOC_32, R_ZIP_VALUE }, + { BFD_RELOC_ZIP_OPB_PCREL, R_ZIP_OPB_PCREL }, + { BFD_RELOC_ZIP_MOV_PCREL, R_ZIP_MOV_PCREL } + // { BFD_RELOC_ZIP_OPB_GOTREL, R_ZIP_OPB_GOTREL }, + // { BFD_RELOC_ZIP_MOV_GOTREL, R_ZIP_MOV_GOTREL }, +}; + +/* Given a BFD reloc code, return the howto structure for the corresponding + * Zip ELF relocation. */ +static reloc_howto_type * +zip_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + unsigned int i; + + for (i = 0; i < sizeof (zip_reloc_map) / sizeof (zip_reloc_map[0]); i++) + if (zip_reloc_map [i].bfd_reloc_val == code) + return & zip_elf_howto_table [(int)zip_reloc_map[i].elf_reloc_val]; + + return NULL; +} + +static reloc_howto_type * +zip_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (zip_elf_howto_table) / sizeof (zip_elf_howto_table[0]); + i++) + if (zip_elf_howto_table[i].name != NULL + && strcasecmp (zip_elf_howto_table[i].name, r_name) == 0) + return &zip_elf_howto_table[i]; + + return NULL; +} + +/* Given an ELF reloc, fill in the howto field of a relent. */ +static void +zip_elf_info_to_howto(bfd * abfd ATTRIBUTE_UNUSED, + arelent * cache_ptr, + Elf_Internal_Rela * dst) +{ + unsigned int r; + + r = ELF32_R_TYPE(dst->r_info); + BFD_ASSERT (r < (unsigned int) R_ZIP_max); + cache_ptr->howto = &zip_elf_howto_table [r]; +} + +static bfd_boolean +zip_elf_relocate_section(bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel, *relend; + + symtab_hdr = &elf_tdata(input_bfd)->symtab_hdr; + sym_hashes = elf_sym_hashes(input_bfd); + relend = relocs+input_section->reloc_count; + + for(rel=relocs; rel<relend; rel++) { + reloc_howto_type *howto; + unsigned long r_symndx; + Elf_Internal_Sym *sym; + asection *sec; + struct elf_link_hash_entry *h; + bfd_vma relocation; + bfd_reloc_status_type r; + const char *name = NULL; + int r_type; + + r_type = ELF32_R_TYPE(rel->r_info); + r_symndx = ELF32_R_SYM(rel->r_info); + + if ((r_type < 0) || (r_type >= (int)R_ZIP_max)) + { + bfd_set_error(bfd_error_bad_value); + return FALSE; + } + + howto = zip_elf_howto_table + ELF32_R_TYPE(rel->r_info); + h = NULL; + sym = NULL; + sec = NULL; + + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + relocation = _bfd_elf_rela_local_sym(output_bfd, sym, &sec, rel); + name = bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name); + name = (name == NULL) ? bfd_section_name(input_bfd, sec) + : name; + } else { + bfd_boolean unresolved_reloc, warned, ignored; + + RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, + rel, r_symndx, symtab_hdr, sym_hashes, h, sec, + relocation, unresolved_reloc, warned, ignored); + } + + if ((sec != NULL)&&(discarded_section(sec))) { + RELOC_AGAINST_DISCARDED_SECTION(info, input_bfd, + input_section, rel, 1, relend, howto, 0, + contents); + } + + if (bfd_link_relocatable(info)) + continue; + + if (howto->type == R_ZIP_BREV) { + if (rel->r_offset > bfd_get_section_limit(input_bfd, input_section)) { + r = bfd_reloc_outofrange; + } else { + uint32_t brev_reloc; + bfd_byte *location; + bfd_vma insn; + + location = contents + rel->r_offset * bfd_octets_per_byte(input_bfd); + + relocation += rel->r_addend; + brev_reloc= zip_bitreverse(relocation); + insn = bfd_get_32(input_bfd, location); + insn = ((insn & ~howto->dst_mask) + |(((insn & howto->src_mask)+brev_reloc)&howto->dst_mask)); + bfd_put_32(input_bfd, insn, location); + r = bfd_reloc_ok; + } + } else { + r = _bfd_final_link_relocate(howto, input_bfd, + input_section, + contents, rel->r_offset, + relocation, + rel->r_addend); + } + + + if (r != bfd_reloc_ok) + { + const char *msg = NULL; + + switch(r) + { + case bfd_reloc_overflow: + info->callbacks->reloc_overflow( + info, (h?&h->root:NULL), + name, howto->name, + (bfd_vma)0, input_bfd, + input_section, rel->r_offset); + break; + case bfd_reloc_undefined: + info->callbacks->undefined_symbol( + info, name, input_bfd, + input_section, rel->r_offset, + TRUE); + break; + case bfd_reloc_outofrange: + msg = _("internal error: out of range error"); + break; + case bfd_reloc_notsupported: + msg = _("internal error: unsupported relocation"); + break; + case bfd_reloc_dangerous: + msg = _("internal error: dangerous relocation"); + break; + default: + msg = _("internal error: unknown error"); + break; + } + + if (msg) + info->callbacks->warning(info, msg, name, + input_bfd, input_section, + rel->r_offset); + + if (!r) + return FALSE; + } + } + return TRUE; +} + +static uint32_t +zip_bitreverse(uint32_t v) { + unsigned r = 0, b; + + for(b=0; b<32; b++, v>>=1) + r = (r<<1)|(v&1); + + return r; +} + +static bfd_reloc_status_type +zip_brev_relocation(bfd *abfd, + arelent *reloc_entry, + asymbol *symbol, + void *data, + asection *input_section, + bfd *output_bfd, + char **error_message) +{ + bfd_vma relocation; + bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte(abfd); + bfd_vma output_base = 0; + reloc_howto_type *howto = reloc_entry->howto; + + // If this isn't a final relocation, then just use the generic + // relocation function. + if (output_bfd != NULL) { + return zip_relocation(abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); + } + + // Otherwise, we need to adjust our file itself with this value ... + // Check that our relocation lies within the file, and particularly + // the section we think it should. (This should really be an assert...) + if (reloc_entry->address > bfd_get_section_limit(abfd, input_section)) + return bfd_reloc_outofrange; + + // Get symbol value + if (bfd_is_com_section(symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + /* Convert input-section relative symbol value to absolute */ + if ((!howto->partial_inplace) + ||(symbol->section->output_section == NULL)) + output_base = 0; + else + output_base = symbol->section->output_section->vma; + + relocation += output_base + symbol->section->output_offset; + + /* Add in supplied addend. */ + relocation += reloc_entry->addend; + + // BREV does not handle PC relative offsets + + // Ignore overflow checking ... BREV handles the top 18 bits of a 32-bit + // number. Overflow would mean overflowing the 32-bit address space-- + // not possible. + // + // if howto->complain_on_overflow ... + + // relocation >>= howto->rightshift; // = 0 + // relocation <<= howto->bitpos; // = 0 + + // Logic (nearly) copied from reloc.c:bfd_perform_relocation + unsigned insn = bfd_get_32(abfd, (bfd_byte *)data + octets); + + // Here's why we are going through this pain! + insn = zip_bitreverse((unsigned)insn); + + // Now we can continue as before.... + insn = ((insn&(~howto->dst_mask)) + |(((insn&howto->src_mask)+relocation)&howto->dst_mask)); + bfd_put_32(abfd, (bfd_vma)insn, (bfd_byte *)data + octets); + + return bfd_reloc_ok; +} + +// Zip Defines +#define TARGET_BIG_SYM zip_elf32_vec +#define TARGET_BIG_NAME "elf32-zip" + +#define ELF_ARCH bfd_arch_zip +// #define ELF_TARGET_ID ZIP_ELF_DATA +#define ELF_MACHINE_CODE EM_ZIP + +#define ELF_MAXPAGESIZE 0x1000 +#define ARCH_SIZE 32 + + +#define bfd_elf32_bfd_define_common_symbol bfd_generic_define_common_symbol + + +#define bfd_elf32_bfd_reloc_type_lookup zip_elf_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup zip_elf_reloc_name_lookup +#define elf_info_to_howto_rel 0 +#define elf_info_to_howto zip_elf_info_to_howto +#define elf_backend_relocate_section zip_elf_relocate_section +#define elf_backend_rela_normal 1 + +// Default ELF32 defines from elf32-target.h that we would've normally included +// here, had we not been a OCTETS_PER_BYTE=4 machine + +#define bfd_elf32_close_and_cleanup _bfd_elf_close_and_cleanup +#define bfd_elf32_bfd_free_cached_info _bfd_free_cached_info +#define bfd_elf32_get_section_contents _bfd_generic_get_section_contents +#define bfd_elf32_canonicalize_dynamic_symtab \ + _bfd_elf_canonicalize_dynamic_symtab +#define bfd_elf32_get_synthetic_symtab _bfd_elf_get_synthetic_symtab +#define bfd_elf32_canonicalize_reloc _bfd_elf_canonicalize_reloc +#define bfd_elf32_find_nearest_line _bfd_elf_find_nearest_line +#define bfd_elf32_find_line _bfd_elf_find_line +#define bfd_elf32_find_inliner_info _bfd_elf_find_inliner_info +#define bfd_elf32_read_minisymbols _bfd_elf_read_minisymbols +#define bfd_elf32_minisymbol_to_symbol _bfd_elf_minisymbol_to_symbol +#define bfd_elf32_get_dynamic_symtab_upper_bound \ + _bfd_elf_get_dynamic_symtab_upper_bound +#define bfd_elf32_get_lineno _bfd_elf_get_lineno +#define bfd_elf32_get_reloc_upper_bound _bfd_elf_get_reloc_upper_bound +#define bfd_elf32_get_symbol_info _bfd_elf_get_symbol_info +#define bfd_elf32_get_symbol_version_string _bfd_elf_get_symbol_version_string +#define bfd_elf32_canonicalize_symtab _bfd_elf_canonicalize_symtab +#define bfd_elf32_get_symtab_upper_bound _bfd_elf_get_symtab_upper_bound +#define bfd_elf32_make_empty_symbol _bfd_elf_make_empty_symbol +#define bfd_elf32_new_section_hook _bfd_elf_new_section_hook +#define bfd_elf32_set_arch_mach _bfd_elf_set_arch_mach +#define bfd_elf32_set_section_contents _bfd_elf_set_section_contents +#define bfd_elf32_sizeof_headers _bfd_elf_sizeof_headers +#define bfd_elf32_write_object_contents _bfd_elf_write_object_contents +#define bfd_elf32_write_corefile_contents _bfd_elf_write_corefile_contents + +#define bfd_elf32_get_section_contents_in_window \ + _bfd_generic_get_section_contents_in_window + +#define elf_backend_can_refcount 0 +#define elf_backend_want_got_plt 0 +#define elf_backend_plt_readonly 0 +#define elf_backend_want_plt_sym 0 +#define elf_backend_plt_not_loaded 0 +#define elf_backend_plt_alignment 2 +#define elf_backend_want_dynbss 1 +#define elf_backend_want_p_paddr_set_to_zero 0 +#define elf_backend_default_execstack 1 +#define elf_backend_caches_rawsize 0 +#define elf_backend_extern_protected_data 0 +#define elf_backend_stack_align 4 +#define elf_backend_strtab_flags 0 + +#define bfd_elf32_bfd_debug_info_start bfd_void +#define bfd_elf32_bfd_debug_info_end bfd_void +#define bfd_elf32_bfd_debug_info_accumulate \ + ((void (*) (bfd*, struct bfd_section *)) bfd_void) + +#define bfd_elf32_bfd_get_relocated_section_contents \ + bfd_generic_get_relocated_section_contents + +#define bfd_elf32_bfd_relax_section bfd_generic_relax_section + +#define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 0 +#define elf_backend_want_got_sym 1 +#define elf_backend_gc_keep _bfd_elf_gc_keep +#define elf_backend_gc_mark_dynamic_ref bfd_elf_gc_mark_dynamic_ref_symbol +#define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook +#define elf_backend_gc_mark_extra_sections _bfd_elf_gc_mark_extra_sections +#define elf_backend_gc_sweep_hook NULL +#define bfd_elf32_bfd_gc_sections bfd_elf_gc_sections + +#ifndef bfd_elf32_bfd_merge_sections +#define bfd_elf32_bfd_merge_sections _bfd_elf_merge_sections +#endif + +#ifndef bfd_elf32_bfd_is_group_section +#define bfd_elf32_bfd_is_group_section bfd_elf_is_group_section +#endif + +#ifndef bfd_elf32_bfd_discard_group +#define bfd_elf32_bfd_discard_group bfd_generic_discard_group +#endif + +#ifndef bfd_elf32_section_already_linked +#define bfd_elf32_section_already_linked _bfd_elf_section_already_linked +#endif + +#ifndef bfd_elf32_bfd_define_common_symbol +#define bfd_elf32_bfd_define_common_symbol bfd_generic_define_common_symbol +#endif + +#ifndef bfd_elf32_bfd_lookup_section_flags +#define bfd_elf32_bfd_lookup_section_flags bfd_elf_lookup_section_flags +#endif + +#ifndef bfd_elf32_bfd_make_debug_symbol +#define bfd_elf32_bfd_make_debug_symbol \ + ((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr) +#endif + +#ifndef bfd_elf32_bfd_copy_private_symbol_data +#define bfd_elf32_bfd_copy_private_symbol_data _bfd_elf_copy_private_symbol_data +#endif + +#ifndef bfd_elf32_bfd_copy_private_section_data +#define bfd_elf32_bfd_copy_private_section_data \ + _bfd_elf_copy_private_section_data +#endif +#ifndef bfd_elf32_bfd_copy_private_header_data +#define bfd_elf32_bfd_copy_private_header_data \ + _bfd_elf_copy_private_header_data +#endif +#ifndef bfd_elf32_bfd_copy_private_bfd_data +#define bfd_elf32_bfd_copy_private_bfd_data \ + _bfd_elf_copy_private_bfd_data +#endif +#ifndef bfd_elf32_bfd_print_private_bfd_data +#define bfd_elf32_bfd_print_private_bfd_data \ + _bfd_elf_print_private_bfd_data +#endif +#ifndef bfd_elf32_bfd_merge_private_bfd_data +#define bfd_elf32_bfd_merge_private_bfd_data \ + ((bfd_boolean (*) (bfd *, bfd *)) bfd_true) +#endif +#ifndef bfd_elf32_bfd_set_private_flags +#define bfd_elf32_bfd_set_private_flags \ + ((bfd_boolean (*) (bfd *, flagword)) bfd_true) +#endif +#ifndef bfd_elf32_bfd_is_local_label_name +#define bfd_elf32_bfd_is_local_label_name _bfd_elf_is_local_label_name +#endif +#ifndef bfd_elf32_bfd_is_target_special_symbol +#define bfd_elf32_bfd_is_target_special_symbol \ + ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) +#endif + +#ifndef bfd_elf32_get_dynamic_reloc_upper_bound +#define bfd_elf32_get_dynamic_reloc_upper_bound \ + _bfd_elf_get_dynamic_reloc_upper_bound +#endif +#ifndef bfd_elf32_canonicalize_dynamic_reloc +#define bfd_elf32_canonicalize_dynamic_reloc _bfd_elf_canonicalize_dynamic_reloc +#endif + +#define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create +#define bfd_elf32_bfd_link_add_symbols bfd_elf_link_add_symbols +#define bfd_elf32_bfd_final_link bfd_elf_final_link + +#define bfd_elf32_bfd_link_just_syms _bfd_elf_link_just_syms + +#define bfd_elf32_bfd_copy_link_hash_symbol_type \ + _bfd_elf_copy_link_hash_symbol_type + +#define bfd_elf32_bfd_link_split_section _bfd_generic_link_split_section +#define bfd_elf32_bfd_link_check_relocs _bfd_generic_link_check_relocs +#define bfd_elf32_archive_p bfd_generic_archive_p +#define bfd_elf32_write_archive_contents _bfd_write_archive_contents +#define bfd_elf32_mkobject bfd_elf_make_object +#define bfd_elf32_mkcorefile bfd_elf_mkcorefile +#define bfd_elf32_mkarchive _bfd_generic_mkarchive +#define bfd_elf32_print_symbol bfd_elf_print_symbol +#define elf_symbol_leading_char 0 + +#define elf_backend_arch_data NULL + +#ifndef ELF_TARGET_ID +#define ELF_TARGET_ID GENERIC_ELF_DATA +#endif + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +#define ELF_COMMONPAGESIZE ELF_MAXPAGESIZE +#define ELF_MINPAGESIZE ELF_COMMONPAGESIZE + +#if ELF_COMMONPAGESIZE > ELF_MAXPAGESIZE +# error ELF_COMMONPAGESIZE > ELF_MAXPAGESIZE +#endif +#if ELF_MINPAGESIZE > ELF_COMMONPAGESIZE +# error ELF_MINPAGESIZE > ELF_COMMONPAGESIZE +#endif + +#ifndef ELF_DYNAMIC_SEC_FLAGS +/* Note that we set the SEC_IN_MEMORY flag for these sections. */ +#define ELF_DYNAMIC_SEC_FLAGS \ + (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS \ + | SEC_IN_MEMORY | SEC_LINKER_CREATED) +#endif + +#define elf_backend_collect FALSE +#define elf_backend_type_change_ok FALSE + +#define elf_backend_sym_is_global 0 +#define elf_backend_object_p 0 +#define elf_backend_symbol_processing 0 +#define elf_backend_symbol_table_processing 0 +#define elf_backend_get_symbol_type 0 +#define elf_backend_archive_symbol_lookup _bfd_elf_archive_symbol_lookup +#define elf_backend_name_local_section_symbols 0 +#define elf_backend_section_processing 0 +#define elf_backend_section_from_shdr _bfd_elf_make_section_from_shdr +#define elf_backend_section_flags 0 +#define elf_backend_get_sec_type_attr _bfd_elf_get_sec_type_attr +#define elf_backend_section_from_phdr _bfd_elf_make_section_from_phdr +#define elf_backend_fake_sections 0 +#define elf_backend_section_from_bfd_section 0 +#define elf_backend_add_symbol_hook 0 +#define elf_backend_link_output_symbol_hook 0 +#define elf_backend_create_dynamic_sections 0 +#define elf_backend_omit_section_dynsym _bfd_elf_link_omit_section_dynsym +#define elf_backend_relocs_compatible _bfd_elf_default_relocs_compatible +#define elf_backend_check_relocs 0 +#define elf_backend_check_directives 0 +#define elf_backend_notice_as_needed _bfd_elf_notice_as_needed +#define elf_backend_adjust_dynamic_symbol 0 +#define elf_backend_always_size_sections 0 +#define elf_backend_size_dynamic_sections 0 +#define elf_backend_init_index_section \ + ((void (*) (bfd *, struct bfd_link_info *)) bfd_void) +#define elf_backend_finish_dynamic_symbol 0 +#define elf_backend_finish_dynamic_sections 0 +#define elf_backend_begin_write_processing 0 +#define elf_backend_final_write_processing 0 +#define elf_backend_additional_program_headers 0 +#define elf_backend_modify_segment_map 0 +#ifndef elf_backend_modify_program_headers +#define elf_backend_modify_program_headers 0 +#endif +#ifndef elf_backend_ecoff_debug_swap +#define elf_backend_ecoff_debug_swap 0 +#endif +#ifndef elf_backend_bfd_from_remote_memory +#define elf_backend_bfd_from_remote_memory _bfd_elf32_bfd_from_remote_memory +#endif +#ifndef elf_backend_got_header_size +#define elf_backend_got_header_size 0 +#endif +#ifndef elf_backend_got_elt_size +#define elf_backend_got_elt_size _bfd_elf_default_got_elt_size +#endif +#ifndef elf_backend_obj_attrs_vendor +#define elf_backend_obj_attrs_vendor NULL +#endif +#ifndef elf_backend_obj_attrs_section +#define elf_backend_obj_attrs_section NULL +#endif +#ifndef elf_backend_obj_attrs_arg_type +#define elf_backend_obj_attrs_arg_type NULL +#endif +#ifndef elf_backend_obj_attrs_section_type +#define elf_backend_obj_attrs_section_type SHT_GNU_ATTRIBUTES +#endif +#ifndef elf_backend_obj_attrs_order +#define elf_backend_obj_attrs_order NULL +#endif +#define elf_backend_obj_attrs_handle_unknown NULL +#define elf_backend_static_tls_alignment 1 +#define elf_backend_post_process_headers _bfd_elf_post_process_headers +#define elf_backend_print_symbol_all NULL +#define elf_backend_output_arch_local_syms NULL +#define elf_backend_output_arch_syms NULL +#define elf_backend_copy_indirect_symbol _bfd_elf_link_hash_copy_indirect +#define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol +#define elf_backend_fixup_symbol NULL +#define elf_backend_merge_symbol_attribute NULL +#define elf_backend_get_target_dtag NULL +#define elf_backend_ignore_undef_symbol NULL +#define elf_backend_emit_relocs _bfd_elf_link_output_relocs +#define elf_backend_count_relocs NULL +#define elf_backend_count_additional_relocs NULL +#define elf_backend_sort_relocs_p NULL +#define elf_backend_grok_prstatus NULL +#define elf_backend_grok_psinfo NULL +#define elf_backend_write_core_note NULL +#define elf_backend_lookup_section_flags_hook NULL +#define elf_backend_reloc_type_class _bfd_elf_reloc_type_class +#define elf_backend_discard_info NULL +#define elf_backend_ignore_discarded_relocs NULL +#define elf_backend_action_discarded _bfd_elf_default_action_discarded +#define elf_backend_eh_frame_address_size _bfd_elf_eh_frame_address_size +#define elf_backend_can_make_relative_eh_frame _bfd_elf_can_make_relative +#define elf_backend_can_make_lsda_relative_eh_frame _bfd_elf_can_make_relative +#define elf_backend_encode_eh_address _bfd_elf_encode_eh_address +#define elf_backend_write_section NULL +#define elf_backend_mips_irix_compat NULL +#define elf_backend_mips_rtype_to_howto NULL + +/* Previously, backends could only use SHT_REL or SHT_RELA relocation + sections, but not both. They defined USE_REL to indicate SHT_REL + sections, and left it undefined to indicated SHT_RELA sections. + For backwards compatibility, we still support this usage. */ +#ifndef USE_REL +#define USE_REL 0 +#endif + +/* Use these in new code. */ +#define elf_backend_may_use_rel_p USE_REL +#define elf_backend_may_use_rela_p !USE_REL +#define elf_backend_default_use_rela_p !USE_REL +#define elf_backend_rela_plts_and_copies_p elf_backend_default_use_rela_p + +#ifndef elf_backend_rela_normal +#define elf_backend_rela_normal 0 +#endif + +#define elf_backend_plt_sym_val NULL +#define elf_backend_relplt_name NULL + +#define ELF_MACHINE_ALT1 0 +#define ELF_MACHINE_ALT2 0 + +#ifndef elf_backend_size_info +#define elf_backend_size_info _bfd_elf32_size_info +#endif + +#define elf_backend_special_sections NULL +#define elf_backend_sign_extend_vma 0 +#define elf_backend_link_order_error_handler _bfd_default_error_handler +#define elf_backend_common_definition _bfd_elf_common_definition +#define elf_backend_common_section_index _bfd_elf_common_section_index +#define elf_backend_common_section _bfd_elf_common_section + +#define elf_backend_merge_symbol NULL +#define elf_backend_hash_symbol _bfd_elf_hash_symbol +#define elf_backend_is_function_type _bfd_elf_is_function_type +#define elf_backend_maybe_function_sym _bfd_elf_maybe_function_sym +#define elf_backend_get_reloc_section _bfd_elf_get_reloc_section +#define elf_backend_copy_special_section_fields NULL +#define elf_backend_compact_eh_encoding NULL +#define elf_backend_cant_unwind_opcode 0 + +#define elf_match_priority \ + (ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0) + +extern const struct elf_size_info _bfd_elf32_size_info; + +static struct elf_backend_data elf32_bed = +{ + ELF_ARCH, /* arch */ + ELF_TARGET_ID, /* target_id */ + ELF_MACHINE_CODE, /* elf_machine_code */ + ELF_OSABI, /* elf_osabi */ + ELF_MAXPAGESIZE, /* maxpagesize */ + ELF_MINPAGESIZE, /* minpagesize */ + ELF_COMMONPAGESIZE, /* commonpagesize */ + ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */ + elf_backend_arch_data, + elf_info_to_howto, + elf_info_to_howto_rel, + elf_backend_sym_is_global, + elf_backend_object_p, + elf_backend_symbol_processing, + elf_backend_symbol_table_processing, + elf_backend_get_symbol_type, + elf_backend_archive_symbol_lookup, + elf_backend_name_local_section_symbols, + elf_backend_section_processing, + elf_backend_section_from_shdr, + elf_backend_section_flags, + elf_backend_get_sec_type_attr, + elf_backend_section_from_phdr, + elf_backend_fake_sections, + elf_backend_section_from_bfd_section, + elf_backend_add_symbol_hook, + elf_backend_link_output_symbol_hook, + elf_backend_create_dynamic_sections, + elf_backend_omit_section_dynsym, + elf_backend_relocs_compatible, + elf_backend_check_relocs, + elf_backend_check_directives, + elf_backend_notice_as_needed, + elf_backend_adjust_dynamic_symbol, + elf_backend_always_size_sections, + elf_backend_size_dynamic_sections, + elf_backend_init_index_section, + elf_backend_relocate_section, + elf_backend_finish_dynamic_symbol, + elf_backend_finish_dynamic_sections, + elf_backend_begin_write_processing, + elf_backend_final_write_processing, + elf_backend_additional_program_headers, + elf_backend_modify_segment_map, + elf_backend_modify_program_headers, + elf_backend_gc_keep, + elf_backend_gc_mark_dynamic_ref, + elf_backend_gc_mark_hook, + elf_backend_gc_mark_extra_sections, + elf_backend_gc_sweep_hook, + elf_backend_post_process_headers, + elf_backend_print_symbol_all, + elf_backend_output_arch_local_syms, + elf_backend_output_arch_syms, + elf_backend_copy_indirect_symbol, + elf_backend_hide_symbol, + elf_backend_fixup_symbol, + elf_backend_merge_symbol_attribute, + elf_backend_get_target_dtag, + elf_backend_ignore_undef_symbol, + elf_backend_emit_relocs, + elf_backend_count_relocs, + elf_backend_count_additional_relocs, + elf_backend_sort_relocs_p, + elf_backend_grok_prstatus, + elf_backend_grok_psinfo, + elf_backend_write_core_note, + elf_backend_lookup_section_flags_hook, + elf_backend_reloc_type_class, + elf_backend_discard_info, + elf_backend_ignore_discarded_relocs, + elf_backend_action_discarded, + elf_backend_eh_frame_address_size, + elf_backend_can_make_relative_eh_frame, + elf_backend_can_make_lsda_relative_eh_frame, + elf_backend_encode_eh_address, + elf_backend_write_section, + elf_backend_mips_irix_compat, + elf_backend_mips_rtype_to_howto, + elf_backend_ecoff_debug_swap, + elf_backend_bfd_from_remote_memory, + elf_backend_plt_sym_val, + elf_backend_common_definition, + elf_backend_common_section_index, + elf_backend_common_section, + elf_backend_merge_symbol, + elf_backend_hash_symbol, + elf_backend_is_function_type, + elf_backend_maybe_function_sym, + elf_backend_get_reloc_section, + elf_backend_copy_special_section_fields, + elf_backend_link_order_error_handler, + elf_backend_relplt_name, + ELF_MACHINE_ALT1, + ELF_MACHINE_ALT2, + &elf_backend_size_info, + elf_backend_special_sections, + elf_backend_got_header_size, + elf_backend_got_elt_size, + elf_backend_obj_attrs_vendor, + elf_backend_obj_attrs_section, + elf_backend_obj_attrs_arg_type, + elf_backend_obj_attrs_section_type, + elf_backend_obj_attrs_order, + elf_backend_obj_attrs_handle_unknown, + elf_backend_compact_eh_encoding, + elf_backend_cant_unwind_opcode, + elf_backend_static_tls_alignment, + elf_backend_stack_align, + elf_backend_strtab_flags, + elf_backend_collect, + elf_backend_type_change_ok, + elf_backend_may_use_rel_p, + elf_backend_may_use_rela_p, + elf_backend_default_use_rela_p, + elf_backend_rela_plts_and_copies_p, + elf_backend_rela_normal, + elf_backend_sign_extend_vma, + elf_backend_want_got_plt, + elf_backend_plt_readonly, + elf_backend_want_plt_sym, + elf_backend_plt_not_loaded, + elf_backend_plt_alignment, + elf_backend_can_gc_sections, + elf_backend_can_refcount, + elf_backend_want_got_sym, + elf_backend_want_dynbss, + elf_backend_want_p_paddr_set_to_zero, + elf_backend_default_execstack, + elf_backend_caches_rawsize, + elf_backend_extern_protected_data +}; + +/* Forward declaration for use when initialising alternative_target field. */ + +#ifdef TARGET_BIG_SYM +const bfd_target TARGET_BIG_SYM = +{ + /* name: identify kind of target */ + TARGET_BIG_NAME, + + /* flavour: general indication about file */ + bfd_target_elf_flavour, + + /* byteorder: data is big endian */ + BFD_ENDIAN_BIG, + + /* header_byteorder: header is also big endian */ + BFD_ENDIAN_BIG, + + /* object_flags: mask of all file flags */ + (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS + | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS + | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON), + + /* section_flags: mask of all section flags */ + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY + | SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES + | SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP), + + /* leading_symbol_char: is the first char of a user symbol + predictable, and if so what is it */ + elf_symbol_leading_char, + + /* ar_pad_char: pad character for filenames within an archive header + FIXME: this really has nothing to do with ELF, this is a characteristic + of the archiver and/or os and should be independently tunable */ + '/', + + /* ar_max_namelen: maximum number of characters in an archive header + FIXME: this really has nothing to do with ELF, this is a characteristic + of the archiver and should be independently tunable. The System V ABI, + Chapter 7 (Formats & Protocols), Archive section sets this as 15. */ + 15, + + elf_match_priority, + + /* Routines to byte-swap various sized integers from the data sections */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, + + /* Routines to byte-swap various sized integers from the file headers */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, + + /* bfd_check_format: check the format of a file being read */ + { _bfd_dummy_target, /* unknown format */ + bfd_elf32_object_p, /* assembler/linker output (object file) */ + bfd_elf32_archive_p, /* an archive */ + bfd_elf32_core_file_p /* a core file */ + }, + + /* bfd_set_format: set the format of a file being written */ + { bfd_false, + bfd_elf32_mkobject, + bfd_elf32_mkarchive, + bfd_elf32_mkcorefile + }, + + /* bfd_write_contents: write cached information into a file being written */ + { bfd_false, + bfd_elf32_write_object_contents, + bfd_elf32_write_archive_contents, + bfd_elf32_write_corefile_contents, + }, + + BFD_JUMP_TABLE_GENERIC (bfd_elf32), + BFD_JUMP_TABLE_COPY (bfd_elf32), + BFD_JUMP_TABLE_CORE (bfd_elf32), +#ifdef bfd_elf32_archive_functions + BFD_JUMP_TABLE_ARCHIVE (bfd_elf32_archive), +#else + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), +#endif + BFD_JUMP_TABLE_SYMBOLS (bfd_elf32), + BFD_JUMP_TABLE_RELOCS (bfd_elf32), + BFD_JUMP_TABLE_WRITE (bfd_elf32), + BFD_JUMP_TABLE_LINK (bfd_elf32), + BFD_JUMP_TABLE_DYNAMIC (bfd_elf32), + + /* Alternative endian target. */ +#ifdef TARGET_LITTLE_SYM + & TARGET_LITTLE_SYM, +#else + NULL, +#endif + + /* backend_data: */ + &elf32_bed +}; +#endif + diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/libbfd.h binutils-2.27-zip/bfd/libbfd.h --- binutils-2.27-original/bfd/libbfd.h 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/bfd/libbfd.h 2017-01-04 22:04:11.000000000 -0500 @@ -3125,6 +3125,16 @@ "BFD_RELOC_VISIUM_HI16_PCREL", "BFD_RELOC_VISIUM_LO16_PCREL", "BFD_RELOC_VISIUM_IM16_PCREL", + "BFD_RELOC_ZIP_VALUE", + "BFD_RELOC_ZIP_BRANCH", + "BFD_RELOC_ZIP_OPB_IMM", + "BFD_RELOC_ZIP_OPB_OFFSET", + "BFD_RELOC_ZIP_OPB_PCREL", + "BFD_RELOC_ZIP_MOV_OFFSET", + "BFD_RELOC_ZIP_MOV_PCREL", + "BFD_RELOC_ZIP_LDI", + "BFD_RELOC_ZIP_LLO", + "BFD_RELOC_ZIP_BREV", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/Makefile.am binutils-2.27-zip/bfd/Makefile.am --- binutils-2.27-original/bfd/Makefile.am 2016-08-03 03:36:50.000000000 -0400 +++ binutils-2.27-zip/bfd/Makefile.am 2016-12-31 17:26:07.151146300 -0500 @@ -173,7 +173,8 @@ cpu-xstormy16.lo \ cpu-xtensa.lo \ cpu-z80.lo \ - cpu-z8k.lo + cpu-z8k.lo \ + cpu-zip.lo ALL_MACHINES_CFILES = \ cpu-aarch64.c \ @@ -260,7 +261,8 @@ cpu-xstormy16.c \ cpu-xtensa.c \ cpu-z80.c \ - cpu-z8k.c + cpu-z8k.c \ + cpu-zip.c # The .o files needed by all of the 32 bit vectors that are configured into # target_vector in targets.c if configured with --enable-targets=all. @@ -382,6 +384,7 @@ elf32-xgate.lo \ elf32-xstormy16.lo \ elf32-xtensa.lo \ + elf32-zip.lo \ elf32.lo \ elflink.lo \ elfxx-sparc.lo \ @@ -574,6 +577,7 @@ elf32-xgate.c \ elf32-xstormy16.c \ elf32-xtensa.c \ + elf32-zip.c \ elf32.c \ elflink.c \ elfxx-sparc.c \ diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/Makefile.in binutils-2.27-zip/bfd/Makefile.in --- binutils-2.27-original/bfd/Makefile.in 2016-08-03 04:06:27.000000000 -0400 +++ binutils-2.27-zip/bfd/Makefile.in 2017-01-04 14:29:55.000000000 -0500 @@ -505,7 +505,8 @@ cpu-xstormy16.lo \ cpu-xtensa.lo \ cpu-z80.lo \ - cpu-z8k.lo + cpu-z8k.lo \ + cpu-zip.lo ALL_MACHINES_CFILES = \ cpu-aarch64.c \ @@ -592,7 +593,8 @@ cpu-xstormy16.c \ cpu-xtensa.c \ cpu-z80.c \ - cpu-z8k.c + cpu-z8k.c \ + cpu-zip.c # The .o files needed by all of the 32 bit vectors that are configured into @@ -715,6 +717,7 @@ elf32-xgate.lo \ elf32-xstormy16.lo \ elf32-xtensa.lo \ + elf32-zip.lo \ elf32.lo \ elflink.lo \ elfxx-sparc.lo \ @@ -907,6 +910,7 @@ elf32-xgate.c \ elf32-xstormy16.c \ elf32-xtensa.c \ + elf32-zip.c \ elf32.c \ elflink.c \ elfxx-sparc.c \ @@ -1437,6 +1441,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-xtensa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-z80.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-z8k.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-zip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf2.Plo@am__quote@ diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/merge.c binutils-2.27-zip/bfd/merge.c --- binutils-2.27-original/bfd/merge.c 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/bfd/merge.c 2017-01-02 14:48:54.000000000 -0500 @@ -826,7 +826,7 @@ else { contents = NULL; - pos = sec->output_section->filepos + sec->output_offset; + pos = sec->output_section->filepos + sec->output_offset * bfd_octets_per_byte(output_bfd); if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) return FALSE; } diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/reloc.c binutils-2.27-zip/bfd/reloc.c --- binutils-2.27-original/bfd/reloc.c 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/bfd/reloc.c 2017-01-04 22:03:52.000000000 -0500 @@ -7697,7 +7697,32 @@ BFD_RELOC_VISIUM_IM16_PCREL ENUMDOC Visium Relocations. - +ENUM + BFD_RELOC_ZIP_VALUE +ENUMDOC + ZipCPU - 32 bit absolute value for LJMP instruction +ENUM + BFD_RELOC_ZIP_BRANCH +ENUMDOC + ZipCPU - 18-bit PC-relative offset for BRA (ADD #x,PC) instructions +ENUM + BFD_RELOC_ZIP_OPB_IMM +ENUMX + BFD_RELOC_ZIP_OPB_OFFSET +ENUMX + BFD_RELOC_ZIP_OPB_PCREL +ENUMX + BFD_RELOC_ZIP_MOV_OFFSET +ENUMX + BFD_RELOC_ZIP_MOV_PCREL +ENUMX + BFD_RELOC_ZIP_LDI +ENUMX + BFD_RELOC_ZIP_LLO +ENUMX + BFD_RELOC_ZIP_BREV +ENUMDOC + ZipCPU value relocations ENDSENUM BFD_RELOC_UNUSED CODE_FRAGMENT diff -Naur '--exclude=*.swp' binutils-2.27-original/bfd/targets.c binutils-2.27-zip/bfd/targets.c --- binutils-2.27-original/bfd/targets.c 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/bfd/targets.c 2016-12-31 17:37:14.021847080 -0500 @@ -910,6 +910,7 @@ extern const bfd_target xtensa_elf32_le_vec; extern const bfd_target z80_coff_vec; extern const bfd_target z8k_coff_vec; +extern const bfd_target zip_elf32_vec; /* These are always included. */ extern const bfd_target srec_vec; @@ -1441,6 +1442,8 @@ &z80_coff_vec, &z8k_coff_vec, + + &zip_elf32_vec, #endif /* not SELECT_VECS */ /* Always support S-records, for convenience. */ diff -Naur '--exclude=*.swp' binutils-2.27-original/binutils/readelf.c binutils-2.27-zip/binutils/readelf.c --- binutils-2.27-original/binutils/readelf.c 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/binutils/readelf.c 2016-12-31 17:40:19.908241961 -0500 @@ -154,6 +154,7 @@ #include "elf/xgate.h" #include "elf/xstormy16.h" #include "elf/xtensa.h" +#include "elf/zip.h" #include "getopt.h" #include "libiberty.h" @@ -800,6 +801,7 @@ case EM_XTENSA_OLD: case EM_MICROBLAZE: case EM_MICROBLAZE_OLD: + case EM_ZIP: return TRUE; case EM_68HC05: @@ -1476,6 +1478,10 @@ case EM_ALTERA_NIOS2: rtype = elf_nios2_reloc_type (type); break; + + case EM_ZIP: + rtype = elf_zip_reloc_type (type); + break; } if (rtype == NULL) @@ -2339,6 +2345,7 @@ case EM_TILEGX: return "Tilera TILE-Gx multicore architecture family"; case EM_CUDA: return "NVIDIA CUDA architecture"; case EM_XGATE: return "Motorola XGATE embedded processor"; + case EM_ZIP: return "Gisselquist Technology ZipCPU"; default: snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine); return buff; @@ -11659,6 +11666,8 @@ case EM_XTENSA_OLD: case EM_XTENSA: return reloc_type == 1; /* R_XTENSA_32. */ + case EM_ZIP: + return reloc_type == 1; /* R_ZIP_32. */ default: { static unsigned int prev_warn = 0; @@ -11735,6 +11744,8 @@ case EM_XTENSA_OLD: case EM_XTENSA: return reloc_type == 14; /* R_XTENSA_32_PCREL. */ + case EM_ZIP: + return FALSE; /* */ default: /* Do not abort or issue an error message here. Not all targets use pc-relative 32-bit relocs in their DWARF debug information and we @@ -11944,6 +11955,7 @@ case EM_TI_C6000:/* R_C6000_NONE. */ case EM_X86_64: /* R_X86_64_NONE. */ case EM_XC16X: + case EM_ZIP: return reloc_type == 0; case EM_AARCH64: diff -Naur '--exclude=*.swp' binutils-2.27-original/config.sub binutils-2.27-zip/config.sub --- binutils-2.27-original/config.sub 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/config.sub 2017-01-11 14:20:34.804049801 -0500 @@ -316,7 +316,7 @@ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) + | z8k | z80 ) basic_machine=$basic_machine-unknown ;; c54x) @@ -355,6 +355,14 @@ xscaleel) basic_machine=armel-unknown ;; + zip-*-linux*) + basic_machine=zip + os=-linux + ;; + zip*) + basic_machine=zip-unknown + os=-elf + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and diff -Naur '--exclude=*.swp' binutils-2.27-original/configure binutils-2.27-zip/configure --- binutils-2.27-original/configure 2016-08-03 03:54:55.000000000 -0400 +++ binutils-2.27-zip/configure 2017-01-08 20:37:33.566336786 -0500 @@ -3548,6 +3548,9 @@ ft32-*-*) noconfigdirs="$noconfigdirs ${libgcj}" ;; + zip*) + noconfigdirs="$noconfigdirs ${libgcj}" + ;; *-*-lynxos*) noconfigdirs="$noconfigdirs ${libgcj}" ;; @@ -3575,6 +3578,9 @@ *-*-aix*) noconfigdirs="$noconfigdirs target-libgo" ;; + zip*) + noconfigdirs="$noconfigdirs target-libgo" + ;; esac fi @@ -3974,6 +3980,9 @@ vax-*-*) noconfigdirs="$noconfigdirs target-newlib target-libgloss" ;; + zip*) + noconfigdirs="$noconfigdirs gdb gprof" + ;; esac # If we aren't building newlib, then don't build libgloss, since libgloss diff -Naur '--exclude=*.swp' binutils-2.27-original/configure.ac binutils-2.27-zip/configure.ac --- binutils-2.27-original/configure.ac 2016-08-03 04:37:38.000000000 -0400 +++ binutils-2.27-zip/configure.ac 2017-01-08 20:41:54.836485336 -0500 @@ -884,6 +884,9 @@ ft32-*-*) noconfigdirs="$noconfigdirs ${libgcj}" ;; + zip*) + noconfigdirs="$noconfigdirs ${libgcj}" + ;; *-*-lynxos*) noconfigdirs="$noconfigdirs ${libgcj}" ;; @@ -911,6 +914,9 @@ *-*-aix*) noconfigdirs="$noconfigdirs target-libgo" ;; + zip*) + noconfigdirs="$noconfigdirs target-libgo" + ;; esac fi @@ -1310,6 +1316,9 @@ vax-*-*) noconfigdirs="$noconfigdirs target-newlib target-libgloss" ;; + zip*) + noconfigdirs="$noconfigdirs ${libgcj} gdb sim gprof" + ;; esac # If we aren't building newlib, then don't build libgloss, since libgloss diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/config/tc-zip.c binutils-2.27-zip/gas/config/tc-zip.c --- binutils-2.27-original/gas/config/tc-zip.c 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/config/tc-zip.c 2019-02-14 20:54:05.341671631 -0500 @@ -0,0 +1,3403 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: tc-zip.c +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: This is the main file associated with the Zip Assembler. By +// that I mean that it handles all of the ZipCPU specifics. The +// rest of the files you find in this directory, mostly tc-cpuname.c and +// such, handle other CPUs. This one handles the ZipCPU. The goal in +// doing this is so that nothing else changes when changes need to be made +// to a CPU, and that changes to the assembler in general shouldn't impact +// the CPU specific processing. +// +// I'll let you be the judge as to how well this file meets that goal. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016-2018, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#include "as.h" + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <ctype.h> + +#include "frags.h" +#include "struc-symbol.h" +#include "symbols.h" +#include "config/tc-zip.h" +#include "elf/zip.h" + +// #define ZIP_DEBUG + +const char comment_chars[] = ";#"; +const char line_comment_chars[] = ";#"; +// Characters which separate lines (newline need to be listed) +const char line_separator_chars[] = ""; + +// Characters defining floating point numbers, such as 0f<floatingpt#> +const char FLT_CHARS[] = "fFrR"; + +// Characters that may be used for an exponent in floating point numbers +const char EXP_CHARS[] = "eE"; + +static int cis_mergable = 0; // tc_check_label, tc_frob_label + +// zip_param_got is a flag that we'll set to know if we need to reference a +// global offset table. Since nothing we've done has yet needed that table, +// we'll keep this undefined for now. +// +// static int zip_param_got = 0; +static int zip_param_cis = 1; +static int zip_param_small = 0; +static int zip_param_use_machine = 1; + +typedef struct { + int m_known; + int32_t m_value; + symbolS *m_addsy, *m_subsy; +} MACHINEVALUE; + +typedef struct { + MACHINEVALUE r[ZIP_USER_REGS]; +} MACHINEREGS; + +MACHINEREGS zipm; + +static void zip_clear_machine(MACHINEREGS *pzipm); + +void md_begin(void) { + cis_mergable = FALSE; + // + record_alignment(text_section, 2); + record_alignment(data_section, 2); + // + lex_type['['] = lex_type['A']; + // + zip_clear_machine(&zipm); +} + +void md_end(void) { } + +void zip_cons_align(int n) { + int lg; + for(lg=0; ((1<<lg)<n)&&(lg<2); lg++) + ; + do_align(lg, NULL, 0, (1<<lg)-1); +} + +void zip_flush_pending_output(void) { + // If the Assembler is going to stuff things into our output stream, + // then we need to make certain that any instructions that follow + // dont try to merge with anything previous. i.e., CIS = false. + cis_mergable = FALSE; +} + +int zip_address_bytes(void) { return 4; } + +const pseudo_typeS md_pseudo_table[] = +{ + { "word", cons, 4 }, // ZipCPU word size is 4, not 2 + { "long", cons, 8 }, // ZipCPU longs are 64-bits, not 32 + { "quad", cons,16 }, // ZipCPU QUAD-words are 128-bits, not 64 + { NULL, NULL, 0 } +}; + +#define ZIP_CC_SLEEP 0x010 +#define ZIP_CC_GIE 0x020 +#define ZIP_CC_STEP 0x040 + +#define SIM_OPCODE 0x77800000 // 0111.x111.1000. .... 0_111.x_111.10.... +#define NOOP_OPCODE 0x77c00000 // 0111.x111.1100. .... 0_111.x_111.11.... + +typedef struct { + bfd_reloc_code_real_type r_type; + symbolS *r_sym; + int r_pcrel; + long r_fr_offset; + fixS *r_fix; + // Could also be char *name and bfd_reloc_code_real_type +} ZIPRELOC; + +// In case the instruction ... +#define ZIP_MAX_NAUX 3 // Number of auxilliary instruction codes used +typedef struct { + int i_naux; + unsigned i_code, // The actual machine language instruction + i_aux[ZIP_MAX_NAUX]; + ZIP_OPCODE i_op; + ZIP_CONDITION i_cnd; + ZIP_REG i_areg; // = ZIP_RNONE for no register + ZIP_REG i_breg; + int i_imm; + ZIPRELOC *i_rp; +} ZIPIS; + +static ZIPIS * +zip_copy_insn(const ZIPIS *old) { + ZIPIS *nw = (ZIPIS *)xmalloc(sizeof(ZIPIS)); + + memcpy((char *)nw, (char *)old, sizeof(ZIPIS)); + + return nw; +} + +static int fits_within(int nbits, int value) { + // -2 fits_within two bits + // -1 fits_within two bits + // 1 fits_within two bits + // 2 does not + // + if (value > 0) + return (value < (1l<<(nbits-1))) ? 1:0; + else + return (value >= -(1l<<(nbits-1))) ? 1:0; +} + +static uint32_t +zip_brev(uint32_t v) { + unsigned r=0, b; + + for(b=0; b<32; b++, v>>=1) + r = (r<<1)|(v&1); + + return r; +} + +static const int MACH_VUNKNOWN = 0, MACH_VKNOWN = 1, MACH_VUPPERKNOWN = 2, + MACH_VSYMKNOWN = 3; + +static void +zip_clear_machine(MACHINEREGS *pzipm) { + int i; + +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, CLEAR\n"); +#endif + for(i=0; i<ZIP_USER_REGS; i++) + pzipm->r[i].m_known = MACH_VUNKNOWN; + for(i=0; i<ZIP_USER_REGS; i++) + pzipm->r[i].m_addsy = NULL; + for(i=0; i<ZIP_USER_REGS; i++) + pzipm->r[i].m_subsy = NULL; +} + +static void +zip_advance_machine(MACHINEREGS *pzipm, ZIPIS *insn) { + int bval = insn->i_imm; + int bknown; + MACHINEVALUE *av, *bv; + + if (!zip_param_use_machine) { + // zip_clear_machine(pzipm); + return; + } + + // The next three instructions don't change any machine values + if((insn->i_op == ZIPO_SW)||(insn->i_op == ZIPO_SH) + ||(insn->i_op==ZIPO_SB) + ||(insn->i_op == ZIPO_CMP)||(insn->i_op == ZIPO_TST)) + return; + + // + // What remains to be done is to include symbols into the machine + // state. For now, we state that anything with a symbol becomes + // unknown. + // + if ((insn->i_op == ZIPO_LJSR)||(insn->i_op == ZIPO_JSR)) { + zip_clear_machine(pzipm); + return; + } + if ((insn->i_rp)&&(insn->i_areg<ZIP_CC)) { + bknown = MACH_VUNKNOWN; + if((insn->i_op==ZIPO_LDI)&&(insn->i_cnd == ZIPC_ALWAYS)) { + pzipm->r[insn->i_areg].m_known = MACH_VSYMKNOWN; + pzipm->r[insn->i_areg].m_value = insn->i_imm; + pzipm->r[insn->i_areg].m_addsy = insn->i_rp->r_sym; + pzipm->r[insn->i_areg].m_subsy = NULL; + return; + } else if ((insn->i_breg == ZIP_PC)&&(insn->i_op == ZIPO_MOV) + &&(insn->i_cnd == ZIPC_ALWAYS)) { + pzipm->r[insn->i_areg].m_known = MACH_VSYMKNOWN; + pzipm->r[insn->i_areg].m_value = insn->i_imm; + pzipm->r[insn->i_areg].m_addsy = insn->i_rp->r_sym; + pzipm->r[insn->i_areg].m_subsy = NULL; + return; + } + } else if (insn->i_rp) + bknown = MACH_VUNKNOWN; + else if (ZIP_RNONE == insn->i_breg) + // B-Op is an immediate only + bknown = MACH_VKNOWN; + else if (insn->i_breg >= ZIP_CC) + bknown = MACH_VUNKNOWN; + else if (insn->i_imm == 0) + bknown = (pzipm->r[insn->i_breg].m_known); + else // If we have an immediate plus a value, can't know UPPER anymore + bknown = (pzipm->r[insn->i_breg].m_known == MACH_VKNOWN) + ? MACH_VKNOWN : MACH_VUNKNOWN; + + if (insn->i_breg < ZIP_USER_REGS) + bval += pzipm->r[insn->i_breg].m_value; + + if (insn->i_areg >= ZIP_USER_REGS) { +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, A-REG[%02x] out of bounds\n", insn->i_areg); +#endif + return; // Nothing to do -- no change to machine + } else if (insn->i_areg == ZIP_PC) { +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, CLEAR ON JUMP\n"); +#endif + zip_clear_machine(pzipm); + return; + } else if ((insn->i_areg == ZIP_CC)&&(insn->i_op == ZIPO_AND)) { +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, CLEAR ON ANDing to CC\n"); +#endif + zip_clear_machine(pzipm); + } else if ((insn->i_areg == ZIP_CC)&&( + (insn->i_op == ZIPO_LDI) + ||(insn->i_op == ZIPO_LW) + ||(insn->i_op == ZIPO_CLR) + ||(insn->i_op == ZIPO_LDILO))) { +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, CLEAR ON setting CC\n"); +#endif + zip_clear_machine(pzipm); + return; + } else if (insn->i_areg >= ZIP_CC) { +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, Not tracking CC or PC changes\n"); +#endif + pzipm->r[insn->i_areg].m_known = MACH_VUNKNOWN; + return; + } + + av = &pzipm->r[insn->i_areg]; + if (insn->i_breg < ZIP_CC) + bv = &pzipm->r[insn->i_breg]; + else + bv = NULL; + + if (ZIPC_ALWAYS != insn->i_cnd) { +#ifdef ZIP_DEBUG + fprintf(stderr, "\tMACHINE, CONDITIONAL operation\n"); +#endif + if ((ZIPO_LDILO == insn->i_op) + &&((av->m_known == MACH_VKNOWN) + ||(av->m_known == MACH_VUPPERKNOWN))) { + av->m_known = MACH_VUPPERKNOWN; + } else if ((ZIPO_LDI == insn->i_op)||(ZIPO_LDIn == insn->i_op)){ + if (((av->m_known == MACH_VKNOWN) + ||(av->m_known == MACH_VUPPERKNOWN)) + &&(((insn->i_imm ^ av->m_value)&& ~0x0ffff)==0)) { + av->m_known = MACH_VUPPERKNOWN; + } else + av->m_known = MACH_VUNKNOWN; + } else { + av->m_known = MACH_VUNKNOWN; +} + } switch(insn->i_op) { + case ZIPO_SUB: + av->m_known = (av->m_known==MACH_VKNOWN) + ? MACH_VKNOWN:MACH_VUNKNOWN; + av->m_value -= bval; + if (bknown != MACH_VKNOWN) + av->m_known = MACH_VUNKNOWN; + break; + case ZIPO_AND: + av->m_value &= bval; + if ((bknown == MACH_VUPPERKNOWN)&&(bval == 0)) { + if (av->m_known == MACH_VKNOWN) + av->m_known = MACH_VUPPERKNOWN; + else if (av->m_known != MACH_VUPPERKNOWN) + av->m_known = MACH_VUNKNOWN; + } else if (bknown != MACH_VKNOWN) + av->m_known = MACH_VUNKNOWN; + break; + case ZIPO_ADD: + av->m_value += bval; + if (bknown != MACH_VKNOWN) + av->m_known = MACH_VUNKNOWN; + break; + case ZIPO_OR: + av->m_value |= bval; + if (bknown == MACH_VUPPERKNOWN) { + if (av->m_known == MACH_VKNOWN) + av->m_known = MACH_VUPPERKNOWN; + else if (av->m_known != MACH_VUPPERKNOWN) + av->m_known = MACH_VUNKNOWN; + } else if (bknown != MACH_VKNOWN) + av->m_known = MACH_VUNKNOWN; + break; + case ZIPO_XOR: + av->m_value ^= bval; + if (bknown == MACH_VUPPERKNOWN) { + if (av->m_known == MACH_VKNOWN) + av->m_known = MACH_VUPPERKNOWN; + else if (av->m_known != MACH_VUPPERKNOWN) + av->m_known = MACH_VUNKNOWN; + } else if (bknown != MACH_VKNOWN) + av->m_known = MACH_VUNKNOWN; + break; + case ZIPO_LDI: case ZIPO_LDIn: + // Although the h/w instruction has no conditions, our + // decoding may have conditions until we finish + // working out what the actual result is. Hence, we + // need to be aware of any conditions from above. +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, LDI -> %02x\n", insn->i_areg); +#endif + av->m_value = bval; + if (insn->i_cnd != ZIPC_ALWAYS) { + // if ((bknown)&&(bvalue == insn->i_imm)) + // pzipm->r[insn->i_areg].m_known = MACH_VKNOWN; + } else { + av->m_known = MACH_VKNOWN; + } break; + case ZIPO_LDILO: +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, LDILO -> %02x\n", insn->i_areg); +#endif + av->m_value &= ~0x0ffff; + av->m_value |= bval &0x0ffff; + if ((av->m_known == MACH_VUPPERKNOWN) + &&(bknown == MACH_VKNOWN) + &&(ZIPC_ALWAYS == insn->i_cnd)) + av->m_known = MACH_VKNOWN; + break; + case ZIPO_BREV: + av->m_value = zip_brev(bval); + if (ZIPC_ALWAYS == insn->i_cnd) + av->m_known = (bknown == MACH_VKNOWN)?MACH_VKNOWN:MACH_VUNKNOWN; + else if ((bknown == MACH_VKNOWN) + &&( (av->m_known == MACH_VKNOWN) + ||(av->m_known == MACH_VUPPERKNOWN)) + &&((((zip_brev(bval)^av->m_value)&0x0ffff)==0))) + av->m_known = MACH_VUPPERKNOWN; + break; + case ZIPO_MOV: +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, MOV -> %02x\n", insn->i_areg); +#endif + av->m_value = bval; + if (ZIPC_ALWAYS == insn->i_cnd) { + av->m_known = bknown; + if (bknown == MACH_VSYMKNOWN) { + if (!bv) { av->m_known = MACH_VUNKNOWN;} + else { + av->m_value = bv->m_value + insn->i_imm; + av->m_addsy = bv->m_addsy; + av->m_subsy = bv->m_subsy; + } + } + } else if ( + ((av->m_known == MACH_VKNOWN) + ||(av->m_known == MACH_VUPPERKNOWN)) + &&((bknown == MACH_VKNOWN) + ||(bknown == MACH_VUPPERKNOWN)) + &&(((bval^av->m_value)&0xffff0000)==0)) + av->m_known = MACH_VUPPERKNOWN; + else + av->m_known = MACH_VUNKNOWN; + av->m_value = bval; + break; + case ZIPO_CLR: + if (insn->i_cnd == ZIPC_ALWAYS) + av->m_known = MACH_VKNOWN; + else if ((av->m_value & 0xffff0000)==0) { + if (((av->m_known == MACH_VKNOWN) + ||(av->m_known == MACH_VUPPERKNOWN)) + &&(((av->m_value ^ bval)&0xffff0000)==0)) + av->m_known = MACH_VUPPERKNOWN; + else + av->m_known = MACH_VUNKNOWN; + } av->m_value = 0; + break; + // Store's don't change any regs + case ZIPO_SW: case ZIPO_SH: case ZIPO_SB: + case ZIPO_SIM: case ZIPO_NOOP: + case ZIPO_SDUMP: case ZIPO_NDUMP: + case ZIPO_BREAK: case ZIPO_LOCK: + case ZIPO_CMP: case ZIPO_TST: + // These don't change any registers + break; + // Result of loading a byte or halfword always clears the upper + // half word + case ZIPO_LB: case ZIPO_LH: + if (insn->i_cnd == ZIPC_ALWAYS) { + av->m_known = MACH_VUPPERKNOWN; + av->m_value = 0; + } else + av->m_known = MACH_VUNKNOWN; + break; + case ZIPO_LW: + default: +#ifdef ZIP_DEBUG + fprintf(stderr, "MACHINE, DEFAULT, %02x -> unknown\n", insn->i_areg); +#endif + av->m_known = MACH_VUNKNOWN; + break; + } + + pzipm->r[ZIP_CC].m_known = MACH_VUNKNOWN; + pzipm->r[ZIP_PC].m_known = MACH_VUNKNOWN; +} + +static int zip_findnearreg_machine(MACHINEREGS *pzipm, unsigned value) { + int bestrg = ZIP_RNONE, bestd, d; + int rg; + + bestd = 0x7fffffff; + bestrg= ZIP_RNONE; + + for(rg=0; rg<ZIP_CC; rg++) { + if (pzipm->r[rg].m_known == MACH_VUNKNOWN) + continue; + if (pzipm->r[rg].m_known == MACH_VSYMKNOWN) + continue; + if (pzipm->r[rg].m_known == MACH_VUPPERKNOWN) + continue; + gas_assert(pzipm->r[rg].m_known == MACH_VKNOWN); + + if (pzipm->r[rg].m_addsy) + continue; + if (pzipm->r[rg].m_subsy) + continue; + + d = abs(pzipm->r[rg].m_value - value); + if (d < bestd) { + bestd = d; + bestrg = rg; + } + } + + if (fits_within(18,bestd)) + return bestrg; + return ZIP_RNONE; +} + +#ifdef ZIP_DEBUG +static void +zip_debug_machine(MACHINEREGS *pzipm) { + int i; + for(i=0; i<ZIP_USER_REGS; i++) { + if (pzipm->r[i].m_known == MACH_VKNOWN) + fprintf(stderr, "MACH-KNOW[Y][%2x] = %08x\n", + i, pzipm->r[i].m_value); + else if (pzipm->r[i].m_known == MACH_VUPPERKNOWN) + fprintf(stderr, "MACH-KNOW[U][%2x] = %04x\n", + i, (pzipm->r[i].m_value>>16)&0x0ffff); + } +} +#endif + + +/* + * Option processing + * + * While not yet implemented, we do have a need for multiple options. These + * include: + * + * (not yet supported) + * -got Use a global offset table to place unknown jump locations into. + * + * (not yet supported) + * -relax Implement only relaxed instructions. This implies that all + * branches fit within 18-bits of the current PC, or equivalently + * that all of the code fits within 1MB. + * + * (not yet supported) + * -no-relax Don't relax any instructions. That means that all + * branches will be implemented as LOD (PC),PC ; .int #Address + * and all conditional branches as LOD 1(PC),PC; BRA 1; .int #addr. + * This also implies LDI's of unknown values will always be + * converted to LDILO/LDIHI pairs and never converted back to + * LDI's--even when the final value is known. + * + * -cis Attempt to compress instructions into the CIS instruction + * set. + * + * (Something for stating the starting address of the routine in memory...) + * + * Other (not yet supported) long options + * + * -nopipe Attempts to use a lock instruction will result in an error. + * -nomul Attempts to use multiply instructions will result in an error. + * -nodiv Attempts to use divide instructions will result in an error. + * -nofpu Attempts to use floating point unit insn will cause an error. + * + * + */ +#define OPTION_CIS (OPTION_MD_BASE+1) +#define OPTION_NOCIS (OPTION_MD_BASE+2) +#define OPTION_ZIPM (OPTION_MD_BASE+3) +#define OPTION_NOZIPM (OPTION_MD_BASE+4) +#define OPTION_GOT (OPTION_MD_BASE+5) +#define OPTION_SMALL (OPTION_MD_BASE+6) // No LW(PC),PC insns + +const char *md_shortopts = ""; +struct option md_longopts[] = +{ + { "cis", no_argument, NULL, OPTION_CIS }, + { "nocis", no_argument, NULL, OPTION_NOCIS }, + { "zipm", no_argument, NULL, OPTION_ZIPM }, + { "nozipm", no_argument, NULL, OPTION_NOZIPM }, + { "small", no_argument, NULL, OPTION_SMALL }, + // { "got", no_argument, NULL, OPTION_GOT }, + { NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof(md_longopts); + +/* We have no target specific options yet, so these next two fucntions are + * are empty. + */ +int +md_parse_option(int c, const char *arg ATTRIBUTE_UNUSED) +{ + // printf("Option %d, %s\n", c, (arg)?arg : "(Null)"); + if (c==0) + return 1; + switch(c) { + case 0: return 1; + case OPTION_CIS: zip_param_cis = 1; return 1; break; + case OPTION_NOCIS: zip_param_cis = 0; return 1; break; + case OPTION_ZIPM: zip_param_use_machine = 1; return 1; break; + case OPTION_NOZIPM: zip_param_use_machine = 0; return 1; break; + // case OPTION_GOT : zip_param_got = 1; return 1; break; + default: break; + } + return 0; // We didn't handle this option +} + +void +md_show_usage(FILE *stream ATTRIBUTE_UNUSED) +{ + fprintf(stream, _("Zip CPU options:\n")); + fprintf(stream, _("\n" +"-cis\t\tAttempt to compress instructions into two instructions per word.\n")); + //fprintf(stream, _( +// "-got\t\tGenerate position independent code by referencing all symbols\n" +// "\t\tthrough a Global Offset Table.\n")); +} + + +symbolS * +md_undefined_symbol(char *name ATTRIBUTE_UNUSED) +{ +//#warning "This is where other architectures check for any GOT references" + return NULL; +} + +void +md_operand(expressionS *op ATTRIBUTE_UNUSED) +{ + /* Empty for now -- what is this for? */ +} + +#ifdef ZIP_DEBUG +static void +zip_dump_sym(symbolS *sym) +{ + if (!sym) { + fprintf(stderr, "SYM(NULL)"); + } else { + fprintf(stderr, "Dumping symbol fields\n"); + fprintf(stderr, "SYM(%s) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s - 0x%08x\n", + S_GET_NAME(sym), + (S_IS_LOCAL(sym))?"Local ":"", + (S_IS_DEFINED(sym))?"Defined ":"", + (S_IS_EXTERNAL(sym))?"extern ":"", + (S_IS_FUNCTION(sym))?"(func) ":"", + (S_IS_WEAK(sym))?"Weak ":"", + (S_IS_WEAKREFD(sym))?"(Weak Ref-D) ":"", + (S_IS_WEAKREFR(sym))?"(Weak Refr) ":"", + (S_IS_DEBUG(sym))?"DEBUG ":"", + (S_IS_VOLATILE(sym))?"Volatile ":"", + (S_IS_FORWARD_REF(sym))?"Fwd Ref ":"", + (S_IS_COMMON(sym))?"Common ":"", + (S_GET_SEGMENT(sym)==absolute_section)?"AbsoluteS ":"", + (S_GET_SEGMENT(sym)==expr_section)?"ExpressionS ":"", + (S_GET_SEGMENT(sym)==reg_section)?"RegisterS ":"", + (S_GET_SEGMENT(sym)==undefined_section)?"UndefinedS ":"", + (symbol_resolved_p(sym))?"Resolved ":"", + (unsigned)S_GET_VALUE(sym)); + } +} + +static void +zip_dump_insn(ZIPIS *insn) { + fprintf(stderr, "INSN:DUMP "); + switch(insn->i_op) { + case ZIPO_SUB: fprintf(stderr, "%7s", "SUB"); break; + case ZIPO_AND: fprintf(stderr, "%7s", "AND"); break; + case ZIPO_ADD: fprintf(stderr, "%7s", "ADD"); break; + case ZIPO_OR: fprintf(stderr, "%7s", "OR"); break; + case ZIPO_XOR: fprintf(stderr, "%7s", "XOR"); break; + case ZIPO_LSR: fprintf(stderr, "%7s", "LSR"); break; + case ZIPO_LSL: fprintf(stderr, "%7s", "LSL"); break; + case ZIPO_ASR: fprintf(stderr, "%7s", "ASR"); break; + case ZIPO_LDI: fprintf(stderr, "%7s", "LDI"); break; + case ZIPO_MPYUHI:fprintf(stderr, "%7s", "MPYUHI");break; + case ZIPO_MPYSHI:fprintf(stderr, "%7s", "MPYSHI");break; + case ZIPO_LDILO: fprintf(stderr, "%7s", "LDILO"); break; + case ZIPO_BREV: fprintf(stderr, "%7s", "BREV"); break; + case ZIPO_MOV: fprintf(stderr, "%7s", "MOV"); break; + case ZIPO_CMP: fprintf(stderr, "%7s", "CMP"); break; + case ZIPO_TST: fprintf(stderr, "%7s", "TST"); break; + case ZIPO_LW: fprintf(stderr, "%7s", "LW"); break; + case ZIPO_SW: fprintf(stderr, "%7s", "SW"); break; + case ZIPO_LH: fprintf(stderr, "%7s", "LH"); break; + case ZIPO_SH: fprintf(stderr, "%7s", "SH"); break; + case ZIPO_LB: fprintf(stderr, "%7s", "LB"); break; + case ZIPO_SB: fprintf(stderr, "%7s", "SB"); break; + case ZIPO_DIVU: fprintf(stderr, "%7s", "DIVU"); break; + case ZIPO_DIVS: fprintf(stderr, "%7s", "DIVS"); break; + case ZIPO_FPADD: fprintf(stderr, "%7s", "FPADD"); break; + case ZIPO_FPSUB: fprintf(stderr, "%7s", "FPSUB"); break; + // + case ZIPO_NOOP: fprintf(stderr, "%7s", "NOOP"); break; + case ZIPO_BREAK: fprintf(stderr, "%7s", "BREAK"); break; + case ZIPO_LOCK: fprintf(stderr, "%7s", "LOCK"); break; + case ZIPO_TRAP: fprintf(stderr, "%7s", "TRAP"); break; + case ZIPO_CLR: fprintf(stderr, "%7s", "CLR"); break; + case ZIPO_HALT: fprintf(stderr, "%7s", "HALT"); break; + case ZIPO_WAIT: fprintf(stderr, "%7s", "WAIT"); break; + case ZIPO_STEP: fprintf(stderr, "%7s", "STEP"); break; + case ZIPO_RTU: fprintf(stderr, "%7s", "RTU"); break; + case ZIPO_BRA: fprintf(stderr, "%7s", "BRA"); break; + case ZIPO_BUSY: fprintf(stderr, "%7s", "BUSY"); break; + case ZIPO_JMP: fprintf(stderr, "%7s", "JMP"); break; + case ZIPO_NOT: fprintf(stderr, "%7s", "NOT"); break; + case ZIPO_NEG: fprintf(stderr, "%7s", "NEG"); break; + // + case ZIPO_SIM: fprintf(stderr, "%7s", "SIM"); break; + case ZIPO_SDUMP: fprintf(stderr, "%7s", "SDUMP"); break; + case ZIPO_SEXIT: fprintf(stderr, "%7s", "SEXIT"); break; + case ZIPO_SOUT: fprintf(stderr, "%7s", "SOUT"); break; + case ZIPO_NDUMP: fprintf(stderr, "%7s", "NDUMP"); break; + case ZIPO_NEXIT: fprintf(stderr, "%7s", "NEXIT"); break; + case ZIPO_NOUT: fprintf(stderr, "%7s", "NOUT"); break; + // + case ZIPO_LJMP: fprintf(stderr, "%7s", "LJMP"); break; + case ZIPO_LJSR: fprintf(stderr, "%7s", "LJSR"); break; + // + case ZIPO_SEXTH:fprintf(stderr, "%7s", "SEXTH"); break; + case ZIPO_SEXTB:fprintf(stderr, "%7s", "SEXTB"); break; + default: + fprintf(stderr, "%d", insn->i_op); break; + } + switch(insn->i_cnd) { + case ZIPC_Z: fprintf(stderr, "%-3s", ".Z"); break; + case ZIPC_LT: fprintf(stderr, "%-3s", ".LT"); break; + case ZIPC_C: fprintf(stderr, "%-3s", ".C"); break; + case ZIPC_V: fprintf(stderr, "%-3s", ".V"); break; + case ZIPC_NZ: fprintf(stderr, "%-3s", ".NE"); break; + case ZIPC_GE: fprintf(stderr, "%-3s", ".GE"); break; + case ZIPC_NC: fprintf(stderr, "%-3s", ".NC"); break; + case ZIPC_ALWAYS: + default: + break; + } fprintf(stderr, " %d", (int)insn->i_cnd); + + fprintf(stderr, "\n\tAREG = %d\n\tB = ", insn->i_areg); + if (insn->i_rp) { + if (insn->i_imm != 0) + fprintf(stderr, "$%d + ", insn->i_imm); + fprintf(stderr, "%s ", (insn->i_rp->r_sym) ? + S_GET_NAME(insn->i_rp->r_sym) : "(null)"); + } else + fprintf(stderr, "%d[%08x] (no sym)", insn->i_imm, insn->i_imm); + if (insn->i_breg != ZIP_RNONE) + fprintf(stderr, "+ R%d", insn->i_breg); + fprintf(stderr, "\n"); + if (insn->i_rp) + fprintf(stderr, "\t@%ld (offset w/in instruction frag)\n", insn->i_rp->r_fr_offset); + fprintf(stderr, "\tINSN:CODE %08x", insn->i_code); + { + int i; + for(i=0; (i<insn->i_naux)&&(i<ZIP_MAX_NAUX); i++) + fprintf(stderr, ":%08x", insn->i_aux[i]); + } + fprintf(stderr, "\n\tDUMPED\n"); +} +#endif + +static ZIP_CONDITION +zip_negate_condition(ZIP_CONDITION c) { + switch(c) { + case ZIPC_Z: return ZIPC_NZ; break; + case ZIPC_LT: return ZIPC_GE; break; + case ZIPC_C: return ZIPC_NC; break; + case ZIPC_NZ: return ZIPC_Z; break; + case ZIPC_GE: return ZIPC_LT; break; + case ZIPC_NC: return ZIPC_C; break; + case ZIPC_ALWAYS: return ZIPC_ALWAYS; break; + default: + break; + } gas_assert((0)&&("Cannot negate condition\n")); + return ZIPC_ALWAYS; +} + +static const char *zip_skip_white_spaces(const char *str) { + if (!str) + return NULL; + while((*str)&&(isspace(*str))) + str++; + return str; +} + +static const char * +zip_parse_condition(const char *str, ZIP_CONDITION *condn) { + if ((strcasecmp(str, "Z")==0) + ||(strcasecmp(str, "EQ")==0)) { + *condn = ZIPC_Z; + } else if ((strcasecmp(str, "LT")==0) + ||(strcasecmp(str, "N")==0)) { + *condn = ZIPC_LT; + } else if ((strcasecmp(str, "C")==0) + ||(strcasecmp(str, "LTU")==0)) { + *condn = ZIPC_C; + } else if (strcasecmp(str, "V")==0) { + *condn = ZIPC_V; + } else if((strcasecmp(str, "NZ")==0) + ||(strcasecmp(str, "NE")==0)) { + *condn = ZIPC_NZ; + } else if ((strcasecmp(str, "GE")==0) + ||(strcasecmp(str, "GTE")==0)) { + *condn = ZIPC_GE; + } else if ((strcasecmp(str, "NC")==0) + ||(strcasecmp(str, "GEU")==0)) { + *condn = ZIPC_NC; + } else { + return "Unrecognized condition"; + } + + return NULL; +} + +static const char *zip_parse_reg(const char *str, ZIP_REG *regid) { + const char *ustr = str; + int userreg = 0; + + if ((!str)||(str[0]=='\0')) + return "No register given"; + ustr = zip_skip_white_spaces(str); + + if (toupper(ustr[0]) == 'U') { + ustr = str+1; + userreg = 0x10; + } else if ((toupper(ustr[0]) == 'S')&&(strcasecmp(ustr, "SP")!=0)) { + ustr = str+1; + } + + /* + if (strcasecmp(ustr, "GBL")==0) { + *regid = userreg + 11; + ustr += 3; + } else + */ + if (strcasecmp(ustr, "LR")==0) { + *regid = userreg + 0; + ustr += 2; + } else if (strcasecmp(ustr, "FP")==0) { + *regid = userreg + 12; + ustr += 2; + } else if (strcasecmp(ustr, "SP")==0) { + *regid = userreg + 13; + ustr += 2; + } else if (strcasecmp(ustr, "CC")==0) { + *regid = userreg + 14; + ustr += 2; + } else if (strcasecmp(ustr, "PC")==0) { + *regid = userreg + 15; + ustr += 2; + } else if (('r' == tolower(ustr[0])) + &&(isdigit(ustr[1])) + &&((!isdigit(ustr[2])) + ||(!isdigit(ustr[3])))) { + *regid = atoi(ustr+1); + if ((*regid > 15)||(*regid < 0)) + return "Register does not exist"; + *regid += userreg; + + if (!isdigit(ustr[2])) + ustr+=2; + else + ustr+=3; + } else { + *regid = ZIP_RNONE; + return "Unknown register"; + } + + // Registers names are terminated by something other than letters + // and numbers. Things like ')', ',', or '\0' should terminate a + // register. Here, we only double check that the register is not + // terminated by another letter or a number. + if ((*ustr)&&((isalpha(*ustr))||(isdigit(*ustr)))) + return "Unrecognized register"; + + return NULL; +} + +// Parse a 'B' operand +static const char * +zip_parse_bop(const char *bop, ZIPIS *insn) { + // There are a couple forms for what we can expect in a B operand: + // The first three require no relocations ... + // 1. A simple number + // 2. Number + Register + // 3. Number(Register) + // 4. Register by itself + // Good form is to replace this number with the possibility + // of a constant expression ... The number may be any of + // [+-](0[xX][0-9a-fA-F]+|(0[0-7]+)|(0-9)+) + // The next four may require a relocation + // 4. Label + Register + // 5. Label(Register) + // 6. Label (Register is implied: PC, if moving or jumping + // to the PC, or GBL if loading a value or if + // the offset ends up being unknown) + // Good form allows an expression instead of a label, + // that can be evaluated at ... sometime. + // 7. Number(Label) + // + // We will support: + // (Number|Label)?( "("Register")" | "+"Register ) + // + char lbl[512], *lblp = lbl; + const char *ptr; + insn->i_imm = 0; + *lblp = '\0'; + + if (strlen(bop)>sizeof(lbl)-1) + as_fatal( _("Label length too long")); + // printf("RAW-OP-B: %s %s\n", bop, (insn->i_rp)?"(i_rp != NULL)":""); + + // Do we start with a number? + { + int sgn = 0; + + ptr = zip_skip_white_spaces(bop); + if ('$' == *ptr) + ptr = zip_skip_white_spaces(ptr+1); + + if ('+' == *ptr) + ptr++; + else if ('-' == *ptr) { + sgn = 1; + ptr++; + } + + if ('$' == *ptr) + ptr = zip_skip_white_spaces(ptr+1); + ptr = zip_skip_white_spaces(ptr); + if ('$' == *ptr) + ptr = zip_skip_white_spaces(ptr+1); + + if ((*ptr)&&(isdigit(*ptr))) { + char *end = (char *)ptr; + unsigned long v = strtoul(ptr, &end, 0); + // We start with a number + if (sgn) + insn->i_imm = (int)(-v); + else + insn->i_imm = (int)(v); + ptr = (const char *)end; + + // Permit a string of Num [[+-] Num]* + // This is necessary for the DI instructions within the + // compiler. + while( ((*ptr == '+')||(*ptr == '-')) + &&(isdigit(ptr[1])) ) { + sgn = (*ptr == '-'); + v = strtoul(&ptr[1], &end, 0); + if (sgn) v = -v; + insn->i_imm += (int)v; + ptr = (const char *)end; + } + } else if ((*ptr)&&( + (isalpha(*ptr)) + ||('*'==*ptr) + ||('.'==*ptr) + ||('_'==*ptr))) { + // We start with an identifier + // printf("OP-B ( \'%s\' ) starts with an identifier (%c)\n", + // bop, *ptr); + + // Skip any compiler inserted prefix (if present) + if ('*' == *ptr) + ptr++; + while((*ptr)&&( + (isalpha(*ptr)) + ||(isdigit(*ptr)) + ||('_' == *ptr) + ||('$' == *ptr) + ||('.' == *ptr))) + *lblp++ = *ptr++; + *lblp = '\0'; + // printf("LBL was %s\n", lbl); + + // This could still be a register ... can't tell yet + if (sgn) + return "ERR: Not expecting a signed label!"; + + ptr = zip_skip_white_spaces(ptr); + } + } + + ptr = zip_skip_white_spaces(ptr); + + const char *err = NULL; + + if ((*ptr == '+')&&(ptr[1] == '(')) + ptr++; + if ((*ptr)&&(*ptr == '(')) { + // Form #3: Number(register) + char *end = strchr(ptr+1, ')'); + if (NULL == end) + return "Un-matched \'(\', cannot find \')\'"; + *end = '\0'; + // printf("Looking for a register in %s\n", ptr+1); + err = zip_parse_reg(ptr+1, &insn->i_breg); + if (err) { + // Must've been a symbol + if (lbl[0] != '\0') // Already have a symbol in this + return err; // expression! + ptr++; + while((*ptr)&&( + (isalpha(*ptr)) + ||(isdigit(*ptr)) + ||('_' == *ptr) + ||('$' == *ptr) + ||('.' == *ptr))) + *lblp++ = *ptr++; + *lblp = '\0'; + insn->i_breg = ZIP_RNONE; + ptr = zip_skip_white_spaces(ptr); + if (*ptr != '\0') + return "ERR: Expression within parenthesis not supported"; + err = NULL; + } + // printf("Found a register, %s -> %d\n", ptr+1, insn->i_breg); + } else if ((*ptr)&&((*ptr == '+')||(*ptr == '-'))) { + if ((*lbl)&&(zip_parse_reg(lbl, &insn->i_breg) == NULL)) { + // Register+Number + // Skip to the end to process what follows + *lbl = '\0'; // Label wasn't a symbol, so let's clear it + } else { + // Number/label+Register + while((('+' == *ptr)||('-' == *ptr)) + &&(ptr[1]) + &&((isdigit(ptr[1])) + ||((ptr[0] == '+') + &&(ptr[1] == '-') + &&(ptr[2]) + &&(isdigit(ptr[2]))))) { + char *end; + + if ((*ptr == '+')&&(isdigit(ptr[1]))) + insn->i_imm += strtoul(ptr, &end, 0); + else if ((*ptr == '+')&&(ptr[1] == '-') + &&(isdigit(ptr[2]))) + insn->i_imm -= strtoul(ptr+2, &end, 0); + else if ((*ptr == '-')&&(isdigit(ptr[1]))) + insn->i_imm -= strtoul(ptr+1, &end, 0); + else { + fprintf(stderr, "GAS: Cannot comprehend %s\n", ptr); + gas_assert((0)&&("Should never get here")); + } + ptr = (const char *)end; + } + if (('+' == *ptr)&&((err = zip_parse_reg(ptr+1, &insn->i_breg))==NULL)) { + // Let's skip to the end of the register + ptr++; + while(isalpha(*ptr)) + ptr++; + while(isdigit(*ptr)) + ptr++; + } else if (('(' == *ptr)&&((err = zip_parse_reg(ptr+1, &insn->i_breg))==NULL)) { + ptr++; + while((*ptr)&&(')' != *ptr)) + ptr++; + ptr++; + } else { + // OOps!! Must've been a label + number + err = NULL; + } + } + } else if ((*lbl)&&(NULL == zip_parse_reg(lbl, &insn->i_breg))) { + // Form: Register (only) + insn->i_imm = 0; + // printf("OP-B ( \'%s\' ) Had a register, %s -> %d\n", bop, + // lbl, insn->i_breg); + *lbl = '\0'; + } else if (*lbl) { + // Form: Label or Number (only) + insn->i_breg = ZIP_RNONE; + } + + // Look for a +number at the end + if ((*ptr)&&((*ptr == '+')||(*ptr == '-'))) { + // printf("Looking at a plus: %s\n", ptr); + int sgn = (*ptr == '-')?1:0; + + if (sgn) { + // printf("... I meant a minus\n"); + ptr++; + } + + ptr = zip_skip_white_spaces(ptr); + if ('$' == *ptr) + ptr = zip_skip_white_spaces(ptr+1); + + if ('+' == *ptr) + ptr++; + if ('-' == *ptr) { + sgn = !sgn; + ptr++; + } + + ptr = zip_skip_white_spaces(ptr); + if ('$' == *ptr) + ptr = zip_skip_white_spaces(ptr+1); + if ('-' == *ptr) { + sgn = !sgn; + ptr++; + } + + if ((*ptr)&&(isdigit(*ptr))) { + char *end = (char *)ptr; + + // printf("Parsing #: %s\n", ptr); + // While the following might make the most sense, + // if (sgn) *--ptr = '-'; + // the string is read-only, so we can't change it. + // Instead we do ... + unsigned long v = (sgn)? + -strtoul(ptr, &end, 0) : strtoul(ptr, &end, 0); + insn->i_imm += v; + ptr = (const char *)end; + } + } + + if (*lbl) { + // printf("i_rp = %s\n", (insn->i_rp)?"(Null)":"not NULL"); + symbolS *sym = symbol_find_or_make(lbl); + sym->sy_flags.sy_used = TRUE; + // segT seg = S_GET_SEGMENT(sym); +#ifdef ZIP_DEBUG + zip_dump_sym(sym); +#endif + if (insn->i_breg == ZIP_PC) { + // New pc-relative relocation, + // ??? + // symbolP = symbol_create(FAKE_LABEL_NAME, + // absolute_section, 0 &zero_address_frag); + // symbol_set_value_expression(symbolP, expressionP); + // resolve_symbol_value(symbolP); + insn->i_rp =(ZIPRELOC *)xmalloc(sizeof(ZIPRELOC)); + insn->i_rp->r_sym = sym; + insn->i_rp->r_pcrel = TRUE; + insn->i_rp->r_fr_offset = 0; + insn->i_rp->r_fix = NULL; + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_PCREL; + // symbol_make(name??) + // symbol_find_or_make(name) + // symbol_relc_make_sym + // symbol_relc_make_value + // symbol_find(name) + // symbol_find_noref(name, noref) + // symbol_find_exact(name) + // symbol_find_exact_noref(name, noref) + // symbol_find_or_make(name) + // symbol_make(name) + // symbol_new(name, seg, value, frag) + // preferred call over symbol create + // calls symbol_create internal + // symbol_create(name, segment, value, frag) + // + // local_symbol_make(name, section, value, frag) + // symbol_clone(sym, int) + // symbol_temp_new(seg, value, frag) + // symbol_temp_new_now(void) + // symbol_temp_make(void) + // colon(void) + // Called when symbol: starts a line + // Calls symbol_new(name, now_seg, frag_now_fix(), + // frag_now); + // symbol_table_insert(symbolP) + // + // expr_build_dot returns a symbol pointing to the + // current location ... + // + // Useful: + // frag_now is current frag + // S_SET_VALUE(symbolP, frag_now_fix()) ??? + // now_seg must be the current segment + // S_SET_SETGMENT(symbolP, now_seg); + /* + } else if((zip_param_got)&&(insn->i_breg == ZIP_GBL)) { + // New GOT-relative relocation + insn->i_rp =(ZIPRELOC *)xmalloc(sizeof(ZIPRELOC)); + insn->i_rp->r_sym = sym; + insn->i_rp->r_pcrel = FALSE; + insn->i_rp->r_fr_offset = 0; + insn->i_rp->r_fix = NULL; + */ + } else { + insn->i_rp =(ZIPRELOC *)xmalloc(sizeof(ZIPRELOC)); + insn->i_rp->r_sym = sym; + insn->i_rp->r_pcrel = FALSE; + insn->i_rp->r_fr_offset = 0; + insn->i_rp->r_fix = NULL; + if (insn->i_breg != ZIP_RNONE) + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_OFFSET; + else + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_IMM; + } + } + + return err; +} + +static const char *zip_parse(const char *line, ZIPIS *insn) { + const char *err = NULL, *opstr = NULL; + char *alt; + int i; + char *cndp = NULL; + // Two (possible) tokens left: + // the left of the comma, and the right of the comma + const char *left, *right, *eol; + typedef enum { + TWO_OP, // Standard for most instructions + IMM_OP, // Immediate operand only + BACKWARDS_TWO, // Only used by STO REG,Off(REG) + NO_OP, // Used by NOOP, BUSY, HALT, RTU, LOCK, etc + ONE_OR_TWO_OP, // Only used by TST + MAYBE_ONE_IMM, // Only used by BREAK, NOOP, SIM + MAYBE_ONE_REG, // Only used by SDUMP, NDUMP + MAYBE_ONE_IMM_OR_REG, // Only used by SEXIT, NEXIT, SOUT, NOUT + MAYBE_OPB, // Only used by TRAP + ONE_REGISTER, // Only used by CLR, CLRF, and NOT + OP_ADDRESS, // Only used by BRA, BRA.C, and LINK + OP_B, // Only used by JMP + TWO_REGISTER, // Only used by FP instructions + ILLEGAL_FORM // Never used, for debugging only + } FORMTYPE; + + FORMTYPE insn_form = ILLEGAL_FORM; // Make sure we set this + + + +#ifdef ZIP_DEBUG + fprintf(stderr, "\n**** Parsing %s\n", line); +#endif + + insn->i_naux = 0; + insn->i_op = ZIPO_NOOP; + insn->i_cnd = ZIPC_ALWAYS; + insn->i_areg = ZIP_RNONE; + insn->i_breg = ZIP_RNONE; + insn->i_imm = 0; + insn->i_rp = NULL; + insn->i_code = NOOP_OPCODE; + for(i=0; i<ZIP_MAX_NAUX; i++) + insn->i_aux[i] = NOOP_OPCODE; + + // The opcode is given between whitespace and a period, or whitespace + // and whitespace + alt = strdup(zip_skip_white_spaces(line)); + if ((*alt)=='[') { + // Instruction starts with condition codes-- a feature we + // needed to add in order to support GCC conditional execution + // macro + cndp = strtok(alt,"] \t")+1; + if (!cndp) + return "Mismatched parenthesis--an attempt at a condition?"; + if (strlen(cndp) > 3) + return "Invalid condition (too long)"; + + opstr = strtok(NULL, " \t"); + if (!opstr) + return "Condition not followed by valid opcode"; + } else { + opstr = strtok(alt, " \t"); // Get our opcode + if (!opstr) { + free(alt); + return "Invalid Instruction"; + } + } + // See if our token contains a '.' within it + // GCC allows conditions beginning a line, as in ... + // (CND) Opcode B,A + // such a condition, if present, was detected above. + // + // If not, we now look for a condition written in our original + // format of ... + // Opcode.CND B,A + // and we look for it here. + // + if (!cndp) { + cndp = strchr(opstr, '.'); + // If we found such a condition, we need to fix the opstr + // so that it no longer includes the condition. Hence, let's + // place a NULL within the alt string and push our condition + // forward to the first non '.' value. + if (cndp) + *cndp++ = '\0'; + } + if (strcasecmp(opstr, "SUB")==0) { + insn->i_op = ZIPO_SUB; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "AND")==0) { + insn->i_op = ZIPO_AND; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "ADD")==0) { + insn->i_op = ZIPO_ADD; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "OR")==0) { + insn->i_op = ZIPO_OR; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "XOR")==0) { + insn->i_op = ZIPO_XOR; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "LSR")==0) { + insn->i_op = ZIPO_LSR; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "LSL")==0) { + insn->i_op = ZIPO_LSL; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "ASR")==0) { + insn->i_op = ZIPO_ASR; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "BREV")==0) { + insn->i_op = ZIPO_BREV; // BREV b+Rb,Ra, or + insn_form = ONE_OR_TWO_OP; // BREV Rx -> BREV Rx,Rx + } else if((strcasecmp(opstr, "LDILO")==0) + ||(strcasecmp(opstr, "LLO")==0)) { + insn->i_op = ZIPO_LDILO; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "MPYUHI")==0) { // MPUHI + insn->i_op = ZIPO_MPYUHI; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "MPYSHI")==0) { // MPSHI + insn->i_op = ZIPO_MPYSHI; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "MPY")==0) { + insn_form = TWO_OP; + insn->i_op = ZIPO_MPY; + } else if (strcasecmp(opstr, "MOV")==0) { + insn->i_op = ZIPO_MOV; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "DIVU")==0) { + insn->i_op = ZIPO_DIVU; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "DIVS")==0) { + insn->i_op = ZIPO_DIVS; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "CMP")==0) { + insn->i_op = ZIPO_CMP; + insn_form = TWO_OP; + } else if ((strcasecmp(opstr, "TST")==0) + ||(strcasecmp(opstr, "TEST")==0)) { + insn->i_op = ZIPO_TST; // TST b+Rb,Ra, or + insn_form = ONE_OR_TWO_OP; // TST Rx -> TST -1,Rx + } else if (strcasecmp(opstr, "LW")==0) { + insn->i_op = ZIPO_LW; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "SW")==0) { + insn->i_op = ZIPO_SW; + insn_form = BACKWARDS_TWO; + } else if (strcasecmp(opstr, "LH")==0) { + insn->i_op = ZIPO_LH; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "SH")==0) { + insn->i_op = ZIPO_SH; + insn_form = BACKWARDS_TWO; + } else if (strcasecmp(opstr, "LB")==0) { + insn->i_op = ZIPO_LB; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "SB")==0) { + insn->i_op = ZIPO_SB; + insn_form = BACKWARDS_TWO; + } else if (strcasecmp(opstr, "LDI")==0) { + insn->i_op = ZIPO_LDI; + insn_form = IMM_OP; + } else if (strcasecmp(opstr, "FPADD")==0) { + insn->i_op = ZIPO_FPADD; + insn_form = TWO_REGISTER; + } else if (strcasecmp(opstr, "FPSUB")==0) { + insn->i_op = ZIPO_FPSUB; + insn_form = TWO_REGISTER; + } else if (strcasecmp(opstr, "FPMUL")==0) { + insn->i_op = ZIPO_FPMPY; + insn_form = TWO_REGISTER; + } else if (strcasecmp(opstr, "FPDIV")==0) { + insn->i_op = ZIPO_FPDIV; + insn_form = TWO_REGISTER; + } else if (strcasecmp(opstr, "FPI2F")==0) { + insn->i_op = ZIPO_FPI2F; + insn_form = TWO_OP; + } else if (strcasecmp(opstr, "FPF2I")==0) { + insn->i_op = ZIPO_FPF2I; + insn_form = TWO_REGISTER; + } else if ((strcasecmp(opstr, "BRK")==0) + ||(strcasecmp(opstr, "BREAK")==0)) { + insn->i_op = ZIPO_BREAK; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM; + } else if (strcasecmp(opstr, "LOCK")==0) { + insn->i_op = ZIPO_LOCK; + insn_form = NO_OP; + // Now for some derived instructions + } else if (strcasecmp(opstr, "TRAP")==0) { + insn->i_op = ZIPO_TRAP; + insn_form = MAYBE_OPB; + } else if (strcasecmp(opstr, "CLR")==0) { + insn->i_op = ZIPO_CLR; + insn_form = ONE_REGISTER; + } else if (strcasecmp(opstr, "BRA")==0) { + insn->i_op = ZIPO_BRA; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "LJMP")==0) { + insn->i_op = ZIPO_LJMP; + insn->i_breg = ZIP_RNONE; + insn->i_imm = 0; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BZ")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_Z; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BLT")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_LT; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BC")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_C; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BV")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_V; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BNZ")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_NZ; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BGE")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_GE; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "BNC")==0) { + insn->i_op = ZIPO_BRA; + insn->i_cnd = ZIPC_NC; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "HALT")==0) { + insn->i_op = ZIPO_HALT; + insn->i_imm = ZIP_CC_SLEEP; + insn->i_areg= ZIP_CC; + insn_form = NO_OP; + } else if (strcasecmp(opstr, "WAIT")==0) { + insn->i_op = ZIPO_WAIT; + insn->i_imm = ZIP_CC_SLEEP | ZIP_CC_GIE; + insn->i_areg= ZIP_CC; + insn_form = NO_OP; + } else if (strcasecmp(opstr, "STEP")==0) { + insn->i_op = ZIPO_STEP; + insn->i_imm = ZIP_CC_STEP | ZIP_CC_GIE; + insn->i_areg= ZIP_CC; + insn_form = NO_OP; + } else if ((strcasecmp(opstr, "RTU")==0) + ||(strcasecmp(opstr, "IRET")==0)) { + insn->i_op = ZIPO_RTU; + insn->i_imm = ZIP_CC_GIE; + insn->i_areg = ZIP_CC; + insn_form = NO_OP; + } else if (strcasecmp(opstr, "BUSY")==0) { + insn->i_op = ZIPO_BUSY; + insn->i_imm= -4; + insn->i_areg = ZIP_PC; + insn->i_breg = ZIP_RNONE; + insn_form = NO_OP; + } else if (strcasecmp(opstr, "JMP")==0) { + insn->i_op = ZIPO_JMP; + insn->i_areg = ZIP_PC; + insn_form = OP_B; + } else if ((strcasecmp(opstr, "RETN")==0) + ||(strcasecmp(opstr, "RTN")==0)) { + insn->i_op = ZIPO_JMP; + insn->i_areg = ZIP_PC; + insn->i_breg = ZIP_LR; + insn->i_imm = 0; + insn_form = NO_OP; + } else if (strcasecmp(opstr, "NOT")==0) { + insn->i_op = ZIPO_NOT; + insn->i_imm = -1; + insn_form = ONE_REGISTER; + } else if (strcasecmp(opstr, "NEG")==0) { + insn->i_op = ZIPO_NEG; + insn->i_imm = 0; + insn_form = ONE_OR_TWO_OP; + } else if (strcasecmp(opstr, "LJSR")==0) { + insn->i_op = ZIPO_LJSR; + insn->i_breg = ZIP_RNONE; + insn->i_imm = 0; + insn_form = OP_ADDRESS; + } else if (strcasecmp(opstr, "JSR")==0) { + insn->i_op = ZIPO_JSR; + insn->i_imm = 0; + insn_form = OP_ADDRESS; + } else if ((strcasecmp(opstr, "NOP")==0) + ||(strcasecmp(opstr, "NOOP")==0)) { + insn->i_op = ZIPO_NOOP; + insn_form = MAYBE_ONE_IMM; + } else if (strcasecmp(opstr, "SIM")==0) { + insn->i_op = ZIPO_SIM; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM; + } else if (strcasecmp(opstr, "SNOOP")==0) { + insn->i_op = ZIPO_SIM; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM; + } else if (strcasecmp(opstr, "SDUMP")==0) { + insn->i_op = ZIPO_SDUMP; + insn->i_imm= 0; + insn_form = MAYBE_ONE_REG; + } else if (strcasecmp(opstr, "SEXIT")==0) { + insn->i_op = ZIPO_SEXIT; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM_OR_REG; + } else if (strcasecmp(opstr, "SOUT")==0) { + insn->i_op = ZIPO_SOUT; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM_OR_REG; + } else if (strcasecmp(opstr, "NDUMP")==0) { + insn->i_op = ZIPO_NDUMP; + insn->i_imm= 0; + insn_form = MAYBE_ONE_REG; + } else if (strcasecmp(opstr, "NEXIT")==0) { + insn->i_op = ZIPO_NEXIT; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM_OR_REG; + } else if (strcasecmp(opstr, "SEXTB")==0) { + insn->i_op = ZIPO_SEXTB; + insn->i_imm= 0; + insn_form = ONE_REGISTER; + } else if (strcasecmp(opstr, "SEXTH")==0) { + insn->i_op = ZIPO_SEXTH; + insn->i_imm= 0; + insn_form = ONE_REGISTER; + } else if (strcasecmp(opstr, "NOUT")==0) { + insn->i_op = ZIPO_NOUT; + insn->i_imm= 0; + insn_form = MAYBE_ONE_IMM_OR_REG; + } else { + free(alt); + return "Unrecognized op-code"; + } + + if (cndp) { + // We have a condition + if (insn->i_cnd != ZIPC_ALWAYS) { + err = "Instruction cannot take an additional condition"; + } else { + err = zip_parse_condition(cndp, &insn->i_cnd); + } + } if (err) { + free(alt); + return err; + } + + if (strchr(line, ',')!=NULL) + left = strtok(NULL, ","); + else + left = strtok(NULL, " \t,"); + right = (left) ? strtok(NULL, " \t") : NULL; + eol = (right) ? strtok(NULL, " \t") : NULL; + if (eol != NULL) { + free(alt); + return "Too many tokens on one line"; + } + + switch(insn_form) { + case TWO_OP: + err = zip_parse_bop(left,insn); + if (!err) + err = zip_parse_reg(right,&insn->i_areg); + break; + case IMM_OP: + err = zip_parse_bop(left,insn); + if ((!err)&&(insn->i_breg == ZIP_RNONE)) + err = zip_parse_reg(right,&insn->i_areg); + else if (!err) + err = "LDI can only load immediates, not registers"; + break; + case BACKWARDS_TWO: + err = zip_parse_reg(left,&insn->i_areg); + if (!err) + err = zip_parse_bop(right,insn); + break; + case MAYBE_ONE_IMM: + if (NULL != right) + err = "Wrong number of operands!"; + else if (left) { + err = zip_parse_bop(left,insn); + if ((!err)&&(insn->i_breg != ZIP_RNONE)) + err = "BREAK arguments can only be immediates"; + } + break; + case MAYBE_ONE_IMM_OR_REG: + if (NULL != right) + err = "Wrong number of operands!"; + else if (left) { + err = zip_parse_bop(left,insn); + if ((!err)&&(insn->i_breg != ZIP_RNONE) + &&(insn->i_imm != 0)) + err = "EXIT arguments can only be immediates or register, not both"; + } + break; + case MAYBE_ONE_REG: + if (NULL != right) + err = "Wrong number of operands!"; + else if (left) { + err = zip_parse_bop(left,insn); + if ((!err)&&(insn->i_breg != ZIP_RNONE)&&(insn->i_imm)) + err = "xDUMP instructions can handle immediates or registers, not both"; + } else { + insn->i_breg = ZIP_RNONE; + insn->i_imm = 0; + } break; + case NO_OP: + if ((NULL != left)||(NULL != right)) + err = "Wrong number of operands!"; + break; + case ONE_OR_TWO_OP: + // This is a reference to the test instruction, which + // can either be + // A. TEST a,Rx, or TEST Rx,. + // or B. BRA a,Rx, or BRA Rx,. + if (NULL != right) { + err = zip_parse_bop(left,insn); + if (!err) + err = zip_parse_reg(right,&insn->i_areg); + if (!err) + err = zip_parse_bop(left,insn); + } else { + zip_parse_reg(left, &insn->i_areg); + if (insn->i_op == ZIPO_BREV) { + insn->i_breg = insn->i_areg; + insn->i_imm = 0; + } else { + insn->i_breg = ZIP_RNONE; + insn->i_imm = -1; + } + } break; + case ONE_REGISTER: + // CLR, CLRF, or NOT + insn->i_breg = ZIP_RNONE; + if (NULL != right) + err = "Instruction opcode expects only one operand"; + else + err = zip_parse_reg(left,&insn->i_areg); + break; + case OP_ADDRESS: + // JSR or BRA instruction + // This is different from OP_B below, in that this + // form implies a PC relative addressing, which + // may not be clear from the operands given + if (NULL != right) + err = "Instruction opcode expects only one operand"; + else { + if ((NULL == left)||(left[0] == '\0')) { + err = "No address given"; + } else if ((NULL == strchr(left,'(')) + &&(NULL == strchr(left,'+'))) { + char *longerstr = (char *)xmalloc(strlen(left)+6); + // If not stated, assume PC relative + strcpy(longerstr,left); + strcat(longerstr, "(PC)"); + err = zip_parse_bop(longerstr, insn); + free(longerstr); + } else + err = zip_parse_bop(left, insn); + } + + break; + case MAYBE_OPB: + // JMP or TRAP instruction + if (NULL != right) + err = "Instruction opcode expects only one operand"; + else if (NULL == left) { + insn->i_breg = ZIP_RNONE; + insn->i_imm = 0; + break; + } // Fall through + case OP_B: // Operand B only (A is implied) + // JMP or TRAP instruction + if (NULL != right) + err = "Instruction opcode expects only one operand"; + else + err = zip_parse_bop(left, insn); + if (insn->i_op == ZIPO_JMP) + insn->i_areg = ZIP_PC; + else // if insn->i_op == TRAP + insn->i_areg = ZIP_CC; + break; + case TWO_REGISTER: + // These are the floating point instructions, which + // can't handle immediate offsets. + err = zip_parse_reg(right, &insn->i_areg); + if (!err) + err = zip_parse_reg(left, &insn->i_breg); + break; + default: // case ILLEGAL_FORM + err = "Unknown instruction format!"; + break; + } + + if (err) + return (err); + + switch(insn->i_op) { + case ZIPO_SUB: case ZIPO_AND: case ZIPO_ADD: case ZIPO_OR: + case ZIPO_XOR: case ZIPO_LSR: case ZIPO_LSL: case ZIPO_ASR: + case ZIPO_BREV: + case ZIPO_MPYUHI: case ZIPO_MPYSHI: + case ZIPO_MPY: + break; + case ZIPO_LDILO: + if (!fits_within(16, insn->i_imm)) + gas_assert((insn->i_imm & (~0x0ffff))==0); + insn->i_imm &= 0x0ffff; + break; + case ZIPO_DIVU: case ZIPO_DIVS: + if (0x0e == (insn->i_areg & 0x0f)) + err = "Divide instructions cannot result in CC or PC regs"; + else if (insn->i_rp) + err = "Relocations not applicable for divides"; + break; + break; + case ZIPO_MOV: + if (insn->i_breg == ZIP_RNONE) + insn->i_op = ZIPO_LDI; + break; + case ZIPO_CMP: case ZIPO_TST: + break; + case ZIPO_LW: case ZIPO_SW: + case ZIPO_LH: case ZIPO_SH: + case ZIPO_LB: case ZIPO_SB: + break; + case ZIPO_LDI: case ZIPO_LDIn: + break; + case ZIPO_FPADD: case ZIPO_FPSUB: + case ZIPO_FPMPY: case ZIPO_FPDIV: + case ZIPO_FPF2I: case ZIPO_FPI2F: + if (0x0e == (insn->i_areg & 0x0f)) + err = "Floating point operations cannot result in CC or PC regs"; + else if (insn->i_rp) + err = "Relocations not applicable for floating point ops"; + break; + case ZIPO_TRAP: + insn->i_areg = ZIP_CC; + if (insn->i_breg == ZIP_RNONE) { + // TRAP instructions *ALWAYS* clear the GIE bit + insn->i_imm &= (~0x0020); + if (insn->i_cnd == ZIPC_ALWAYS) + insn->i_op = ZIPO_LDI; + else if (fits_within(16, insn->i_imm)) + insn->i_op = ZIPO_LDILO; + else if (fits_within(18, zip_brev(insn->i_imm))) + insn->i_op = ZIPO_BREV; + else + err = "TRAP 18+ bit immediate not supported"; + } else + insn->i_op = ZIPO_MOV; + break; + case ZIPO_CLR: + insn->i_op = ZIPO_LDI; + insn->i_imm = 0; + break; + case ZIPO_JMP: + if (insn->i_breg != ZIP_RNONE) + insn->i_op = ZIPO_MOV; // JMP A+Rx + else + insn->i_op = ZIPO_BRA; // JMP lbl = BRA lbl + // Fall through + case ZIPO_BRA: // Leave as ZIPO_BRA until we assemble it + insn->i_areg = ZIP_PC; + break; + case ZIPO_HALT: case ZIPO_WAIT: case ZIPO_RTU: case ZIPO_STEP: + insn->i_op = ZIPO_OR; + break; + case ZIPO_BUSY: + insn->i_op = ZIPO_ADD; + break; + case ZIPO_NOT: + insn->i_op = ZIPO_XOR; + insn->i_imm = -1; + insn->i_breg = ZIP_RNONE; + break; + case ZIPO_NEG: + if (insn->i_breg == ZIP_RNONE) { + insn->i_breg = insn->i_areg; + // This would've been set to -1 by the ONE or + // TWO op code. Here, we set it back to zero. + insn->i_imm = 0; + } + // insn->i_op = ZIPO_NEG; /// Can't collapse this yet + break; + case ZIPO_BREAK: + insn->i_op = ZIPO_BREAK; + insn->i_areg = ZIP_RNONE; + insn->i_breg = ZIP_RNONE; + // insn->i_imm = ... whatever it was set to + break; + case ZIPO_LOCK: + insn->i_op = ZIPO_LOCK; + insn->i_areg = ZIP_RNONE; + insn->i_breg = ZIP_RNONE; + insn->i_imm = 0; + break; + case ZIPO_SDUMP: + insn->i_op = ZIPO_SIM; + if (insn->i_breg != ZIP_RNONE) { + insn->i_imm = (int)insn->i_breg + 0x0200; + insn->i_breg = ZIP_RNONE; + } else + insn->i_imm = 0x2ff; + break; + case ZIPO_NDUMP: + insn->i_op = ZIPO_NOOP; + if (insn->i_breg != ZIP_RNONE) { + insn->i_imm = (int)insn->i_breg + 0x0200; + insn->i_breg = ZIP_RNONE; + } else + insn->i_imm = 0x2ff; + break; + case ZIPO_SEXIT: + insn->i_op = ZIPO_SIM; + if (insn->i_breg != ZIP_RNONE) + insn->i_imm = 0x300 + (insn->i_breg & 0x01f); + else + insn->i_imm = 0x100 + (insn->i_imm & 0x0ff); + insn->i_breg = ZIP_RNONE; + break; + case ZIPO_NEXIT: + insn->i_op = ZIPO_NOOP; + if (insn->i_breg != ZIP_RNONE) + insn->i_imm = 0x300 + (insn->i_breg & 0x01f); + else + insn->i_imm = 0x100 + (insn->i_imm & 0x0ff); + insn->i_breg = ZIP_RNONE; + break; + case ZIPO_SOUT: + insn->i_op = ZIPO_SIM; + if (insn->i_breg != ZIP_RNONE) + insn->i_imm = 0x220 + (insn->i_breg & 0x01f); + else + insn->i_imm = 0x400 + (insn->i_imm & 0x0ff); + insn->i_breg = ZIP_RNONE; + break; + case ZIPO_NOUT: + insn->i_op = ZIPO_NOOP; + if (insn->i_breg != ZIP_RNONE) + insn->i_imm = 0x220 + (insn->i_breg & 0x01f); + else + insn->i_imm = 0x400 + (insn->i_imm & 0x0ff); + insn->i_breg = ZIP_RNONE; + break; + case ZIPO_SIM: + case ZIPO_NOOP: + break; + case ZIPO_LJMP: case ZIPO_LJSR: + if (insn->i_breg == ZIP_PC) + insn->i_breg = ZIP_RNONE; + if (insn->i_breg != ZIP_RNONE) { + err = "Indirect long jumps and long JSRs are not supported"; + } break; + case ZIPO_JSR: + break; + case ZIPO_SEXTB: case ZIPO_SEXTH: + break; + default: + return "Internal error -- unrecognized internal opcode"; + break; + } if (err) { + free(alt); + return err; + } + + if ((insn->i_op != ZIPO_MOV)&&( + ((insn->i_areg != ZIP_RNONE)&&(insn->i_areg >= 0x10)) + ||((insn->i_breg != ZIP_RNONE)&&(insn->i_breg >= 0x10)))) { + if (insn->i_rp) + free(insn->i_rp); + insn->i_rp = NULL; + free(alt); + return "Only MOV instructions can reference explicit user registers"; + } + + free(alt); + + // We do nothing more to build the opcode here --- all we are doing + // is parsing. + return err; +} + +#define NOOPGROUP(OP,IMM) ((0x78000000)|((((OP)+0x1c-ZIPO_BREAK)&0x01f)<<22)|((IMM) & 0x003fffff)) +#define DBLREGOP(OP,CND,IMM,B,A) ((((OP)&0x01f)<<22)|(((A)&0x0f)<<27) \ + | (((CND)&0x07)<<19)|(1<<18)|(((B)&0x0f)<<14) \ + | ((IMM) & 0x03fff)) +#define SMPLMOV(CND,IMM,B,A) (((ZIPO_MOV&0x01f)<<22)|(((A)&0x0f)<<27) \ + | (((CND)&0x07)<<19)|(((B)&0x0f)<<14)|((IMM) & 0x01fff)) +#define IMMOP(OP,CND,IMM,A) ((((OP)&0x01f)<<22)|(((A)&0x0f)<<27) \ + | (((CND)&0x07)<<19)|((IMM) & 0x03ffff)) +#define LDIOP(IMM,A) ((ZIPO_LDI<<22)|(((A)&0x0f)<<27)|((IMM) & 0x07fffff)) + + +/* + * CIS support code + * + * Assuming that the instruction (a) is not a CIS instruction, this looks + * up the immediate value encoded in the instruction. The purpose is to + * determine whether or not this instruction can be merged with the + * previous (or next) instruction in CIS mode. + * + */ +static int +zip_non_cis_immediate(const unsigned a) +{ + ZIP_OPCODE op = (ZIP_OPCODE)((a>>22)&0x1f); + int imm; + + switch(op) { + case ZIPO_MOV: + imm = (a & 0x01fff); if (a&0x1000) imm |= -0x1000; break; + case ZIPO_LDI: + imm = (a & 0x03fffff); break; + case ZIPO_LDIn: + imm = (a & 0x03fffff); imm |= -0x0200000; break; +/* + * While this makes conceptual sense, it doesn't match the CPU. Hence let's + * comment it out and make certain things still work. + case ZIPO_LDILO: +#ifndef LONG_MPY + case ZIPO_LDIHI: // BREVx would rm LDIHI +#endif + imm = (a & 0x0ffff); break; +*/ + default: + if (a & 0x040000) { + imm = (a & 0x03fff); + if (a & 0x2000) imm |= -0x02000; + } else { + imm = (a & 0x03ffff); + if (a & 0x020000) + imm |= -0x020000; + } + } + + return imm; +} + +static int +zip_can_merge(const unsigned a, const unsigned b) +{ + // Can't merge instructions if merging isnt turned on + if (!zip_param_cis) + return 0; + + // 1. Can't merge anything that's already merged + if ((a|b) & 0x80000000) + return 0; + + ZIP_OPCODE opa, opb; + ZIP_CONDITION ac, bc; + int imma, immb; + + // Get the 5-bit operands for each + opa = (a>>22)&0x1f; + opb = (b>>22)&0x1f; + + // 2. Can only merge if both are unconditional + ac = ((a>>19)&0x07); + bc = ((b>>19)&0x07); + if ((opa != ZIPO_LDI)&&(opa != ZIPO_LDIn)&&(ac != ZIPC_ALWAYS)) + return 0; + if ((opb != ZIPO_LDI)&&(opb != ZIPO_LDIn)&&(bc != ZIPC_ALWAYS)) + return 0; + + // Only some instructions can be merged + switch(opa) { + case ZIPO_SUB: case ZIPO_AND: case ZIPO_ADD: case ZIPO_CMP: + case ZIPO_LW: case ZIPO_SW: case ZIPO_LDI: case ZIPO_MOV: + case ZIPO_LDIn: + break; + default: + return 0; + } switch(opb) { + case ZIPO_SUB: case ZIPO_AND: case ZIPO_ADD: case ZIPO_CMP: + case ZIPO_LW: case ZIPO_SW: case ZIPO_LDI: case ZIPO_MOV: + case ZIPO_LDIn: + break; + default: + return 0; + } + + // Prohibit moves to/from user regs to merge + if ((opa == ZIPO_MOV)&&(a & 0x42000)) + return 0; + if ((opb == ZIPO_MOV)&&(b & 0x42000)) + return 0; + + imma = zip_non_cis_immediate(a); + immb = zip_non_cis_immediate(b); + + if (!fits_within(8,imma)) { + return 0; + } if (!fits_within(8,immb)) { + return 0; + } + + // if abreg & 0x010, or bbreg & 0x010, then the register is being + // used. + int aareg = (a>>27)&0x00f; + int abreg = (a>>14)&0x01f; + int bbreg = (b>>14)&0x01f; + + switch(opa) { + case ZIPO_MOV: + if (!fits_within(3,imma)) + return 0; + // Prohibit a MOV x(PC),Ry to move into a first + // instruction position. While the CPU supports it, + // making sure x remains valid isn't yet supported + // here. + if ((ZIP_PC == aareg)||(ZIP_CC == aareg)) + return 0; + break; + case ZIPO_LDI: case ZIPO_LDIn: + if (!fits_within(8,imma)) + return 0; + if (aareg == ZIP_CC) + return 0; + break; + case ZIPO_ADD: case ZIPO_SUB: case ZIPO_AND: + if (aareg == ZIP_CC) + return 0; + case ZIPO_CMP: + if ((abreg&0x10)==0) { + if (!fits_within(7,imma)) { + return 0; + } + } else { // if (abreg&0x10) + if (!fits_within(3,imma)) + return 0; + } break; + case ZIPO_LW: case ZIPO_SW: + if (aareg == ZIP_CC) + return 0; + if ((abreg&0x010)==0) { + return 0; + } else if (abreg== 0x10 + ZIP_SP) { + if (!fits_within(7,imma)) + return 0; + } else { + if (!fits_within(3,imma)) + return 0; + } break; + default: + fprintf(stderr, "Unknown op, %d\n", opa); + return 0; + } + + switch(opb) { + case ZIPO_MOV: + if (!fits_within(3,immb)) { + return 0; + } break; + case ZIPO_LDI: case ZIPO_LDIn: + if (!fits_within(8,immb)) { + return 0; + } break; + case ZIPO_ADD: case ZIPO_SUB: case ZIPO_CMP: case ZIPO_AND: + if ((bbreg&0x10)==0) { + if (!fits_within(7,immb)) + return 0; + } else { // if (bbreg&0x10) + if (!fits_within(3,immb)) + return 0; + } break; + case ZIPO_LW: case ZIPO_SW: + if ((bbreg&0x010)==0) { + return 0; + } else if (bbreg== 0x10+ZIP_SP) { + if (!fits_within(7,immb)) + return 0; + } else { + if (!fits_within(3,immb)) + return 0; + } break; + default: + return 0; + } + + return 1; +} + +static unsigned +zip_insn_merge(const unsigned a, const unsigned b) +{ + // 1. We already know we can merge these, so skip our can-merge checks + ZIP_OPCODE opa, opb; + unsigned int retv = 0; + + // Get our two opcodes + opa = (a>>22)&0x1f; opb = (b>>22)&0x1f; + + // Truncate LDI opcodes back to their original values + if (opa == 0x019) opa = 0x018; + if (opb == 0x019) opb = 0x018; + retv = 0x80008000; + + // Start with the destination registers + retv |= (a & 0x78000000); + retv |= (b & 0x78000000) >> (27-11); + + // Then the new OpCodes + switch(opa) { + case ZIPO_SUB: retv |= (ZIPV_SUB<<24); break; + case ZIPO_AND: retv |= (ZIPV_AND<<24); break; + case ZIPO_ADD: retv |= (ZIPV_ADD<<24); break; + case ZIPO_CMP: retv |= (ZIPV_CMP<<24); break; + case ZIPO_LW: retv |= (ZIPV_LW <<24); break; + case ZIPO_SW: retv |= (ZIPV_SW <<24); break; +// 8e40 +// 1.0001.110_0100_0000 + case ZIPO_LDI: retv |= (ZIPV_LDI<<24); break; + case ZIPO_MOV: retv |= (ZIPV_MOV<<24); break; + default: gas_assert(0); + } + + switch(opb) { + case ZIPO_SUB: retv |= (ZIPV_SUB<<8); break; + case ZIPO_AND: retv |= (ZIPV_AND<<8); break; + case ZIPO_ADD: retv |= (ZIPV_ADD<<8); break; + case ZIPO_CMP: retv |= (ZIPV_CMP<<8); break; + case ZIPO_LW: retv |= (ZIPV_LW <<8); break; + case ZIPO_SW: retv |= (ZIPV_SW <<8); break; + case ZIPO_LDI: retv |= (ZIPV_LDI<<8); break; + case ZIPO_MOV: retv |= (ZIPV_MOV<<8); break; + default: gas_assert(0); + } + + // The new CIS has no condition codes + + // Now for OpB, instruction A + if (opa == ZIPO_LDI) + retv |= (a & 0xff)<<16; + else if (opa == ZIPO_MOV) { + retv |= 1<<23; // Using a register? always4mov + retv |= ((a>>14)&0x0f)<<19; // OpB register + retv |= (a & 0x7)<<16; // Offset + } else if(((opa == ZIPO_LW)||(opa == ZIPO_SW)) + &&(((a>>14)&0x1f)==0x10 + ZIP_SP)) { + // 7-bit immediate for loads or stores referencing the stack + retv |= (a & 0x07f)<<16; + } else if ((a>>18)&1) { + // OpB ... with a register + retv |= 1<<23; // Using a register? + retv |= ((a>>14)&0x0f)<<19; // OpB register + retv |= (a&0x07)<<16; // OpB constant + } else { + // OpB ... with constant offsets only + retv |= (a&0x07f)<<16; + } + + + // Now for OpB, instruction B + if (opb == ZIPO_LDI) + retv |= (b & 0xff); + else if (opb == ZIPO_MOV) { + retv |= (1<<7); // Using a register? always4mov + retv |= ((b>>14)&0x0f)<<3; // OpB register + retv |= (b & 0x7); // Offset + } else if(((opb == ZIPO_LW)||(opb == ZIPO_SW)) + &&(((b>>14)&0x1f)==0x10 + ZIP_SP)) { + retv |= (b & 0x07f); + } else if ((b>>18)&1) { + // OpB ... with a register + retv |= 1<<7; // Using a register? + retv |= ((b>>14)&0x0f)<<3; // OpB register + retv |= (b&0x07); // OpB constant + } else { + // OpB ... with constant offsets only + retv |= (b&0x07f); + } + + return retv; +} + +void +zip_check_label(symbolS *label ATTRIBUTE_UNUSED) +{ + // On any symbol, we need to make sure that we can jump to this + // address, therefore we cannot merge the previous instruction with + // another one that might follow. + cis_mergable = FALSE; + // + // Likewise, our shadow virtual machine values may be ... unknown + // upon any jump to this location. Hence, we declare them unknown + // here. + zip_clear_machine(&zipm); +} + +// UNITS: +// Offset (target byte units) +// Address (host byte units) +// Sym (target byte units) +// Stretch (target byte units) +// +static void +zip_assemble_insn_words(fragS *fragP, segT seg, ZIPIS *insn, int relax_state, + long stretch, MACHINEREGS *pzipm) +{ +#ifdef ZIP_DEBUG +fprintf(stderr, "ZIP-ASSEMBLE-INSN-WORDS\n"); + zip_dump_insn(insn); + if ((insn->i_rp)||(relax_state)) + zip_dump_sym(insn->i_rp->r_sym); +#endif + unsigned long symv = 0; + int sym_defined = 0, this_segment = 0, sym_known = 0; + symbolS *sym = NULL; + unsigned immv = insn->i_imm; + + if (insn->i_rp) { + fragS *sym_frag; + + sym = insn->i_rp->r_sym; + symv = ((sym)&&(S_IS_DEFINED(sym))) ? (S_GET_VALUE(sym)) : 0; + sym_frag = symbol_get_frag(sym); + this_segment = (S_GET_SEGMENT(sym) == seg); + +#ifdef ZIP_DEBUG + fprintf(stderr, "SYMV(%s) = %08lx + %08lx -> %08lx\n", + S_GET_NAME(sym), + S_GET_VALUE(sym), fragP->fr_offset, + S_GET_VALUE(sym) + fragP->fr_offset); +#endif + symv += fragP->fr_offset; + // The immediate value has been included in the fragP->fr_offset + // So, to keep us from applying it twice, we'll zero it here. + immv = 0; + +#ifdef ZIP_DEBUG + { int this_frag = (sym_frag == fragP); + fprintf(stderr, "Determined symbol is %sin this frag, and %sin this segment\n", (this_frag)?"":"not ", (this_segment)?"":"not "); + } +#endif + + if ((stretch != 0) + &&( sym_frag->relax_marker != fragP->relax_marker) + &&(this_segment)) { + if ((stretch < 0) + ||(sym_frag->region == fragP->region)) + symv += stretch; + else if (symv < fragP->fr_address) + symv = fragP->fr_next->fr_address; + } + } + + // At this point, if the symbol is "defined" that only means that + // the address is known--not that we can know it via GET_VALUE above + // here. There are a couple of possibilities: it could be a known + // offset into a fragment, it could be a known offset into a segment, + // it could be a known memory address, or it could be a known value. + // + // If the value is an offset into our current fragment, then we can + // get at it via PC relative addressing. + // + // If the symbol is an offset into our current segment, often the + // .text segment, we may also be able to get to it via PC relative + // addressing. However, we won't know until the fragment's are placed + // together to create this segment. This will be before writing + // the file to disk. + // + // If the symbol is in the absolute segment, then we should try to + // get to it via an absolute 32-bit offset reference--since we don't + // know (and won't know until the final link) where we are currently + // located within memory. + // + // The same is true of the undefined segment--we just don't know any + // PC offsets to that segment. + // + // But if the address is to a GOT segment, we should be able to assume + // it's offset from the beginning of that segment. + // + // + if ((relax_state)&&(insn->i_rp)) + sym_defined = S_IS_DEFINED(insn->i_rp->r_sym); + + /* + sym_known = (sym_defined)&& + ((S_GET_SEGMENT(sym) == absolute_section) + ||(S_GET_SEGMENT(sym) == expr_section) + ||(this_frag) + ||((this_segment)&&(fragP->fr_address != 0)) + ); + */ + sym_known = (sym_defined)&&(insn->i_rp->r_pcrel)&&(this_segment); + if ((!sym_known)&&(sym_defined)&&(!S_FORCE_RELOC(sym, 0))) { + if (this_segment) + sym_known = 1; + else if (S_GET_SEGMENT(sym)==absolute_section) + sym_known = 1; + } +#ifdef ZIP_DEBUG + if (sym_known) + fprintf(stderr, "%08lx@%08lx/%08lx - SYM(%s)-KNOWN %s%s%s%s%s\n", + (unsigned long)fragP->fr_literal, + fragP->fr_address, + (unsigned long)symv, S_GET_NAME(sym), + (S_GET_SEGMENT(sym) == absolute_section)?" abs":"", + (S_GET_SEGMENT(sym) == expr_section)?" expr":"", + (symbol_get_frag(sym)==fragP)?" this-frag ":"", + ((this_segment)&&(fragP->fr_address != 0))?" this-seg ":"", + insn->i_rp->r_pcrel?" (PC-REL)":" (ABS)"); + else if (insn->i_rp) + fprintf(stderr, "%08lx@%08lx/%08lx - SYM(%s) -- not known (yet) %s%s%s%s%s%s\n", + (unsigned long)fragP->fr_literal, fragP->fr_address, + (unsigned long)symv, S_GET_NAME(sym), + (!sym_defined)?"-- not defined":"", + (S_GET_SEGMENT(sym) == absolute_section)?" abs":"", + (S_GET_SEGMENT(sym) == expr_section)?" expr":"", + (symbol_get_frag(sym)==fragP)?" this-frag ":"", + (this_segment)?" this-seg ":"", + ((this_segment)&&(fragP->fr_address != 0))?" this-off ":"" + ); + + fprintf(stderr, "SYM-DEF %d,%d,%d,%d, IMM = %08x\n", + sym_defined, sym_known, + (insn->i_rp)&&(symbol_get_frag(insn->i_rp->r_sym)==fragP)?1:0, + this_segment, insn->i_imm); +#endif + int rg; + + switch(insn->i_op) { + case ZIPO_LDI: // May or may not be conditional + if ((sym_known)&&(this_segment) + &&(fits_within(15,immv+symv-fragP->fr_address-insn->i_rp->r_fr_offset-sizeof(uint32_t)))) { + // Turn this into a MOV x(PC),Rx + // + // Although moves can normally only handle 13 bits, + // when the immediate is an offset to the PC, the bottom + // two bits are always zero, and so the immediate + // gets an extra two free bits--hence the test for + // fitting into 15 bits above. + insn->i_breg = ZIP_PC; + insn->i_op = ZIPO_MOV; + insn->i_naux = 0; + zip_assemble_insn_words(fragP, seg, insn, relax_state, + stretch, pzipm); + // Tested--this works + return; + } + + // 0.111.x111.11 + insn->i_aux[0] = 0x7fc00000; // NOOP -- if never used. + immv += symv; + if ((insn->i_cnd == ZIPC_ALWAYS) + &&(zip_param_cis) + &&(zip_param_use_machine)&&(pzipm) + &&(!fits_within(8,immv))) { + // Convert an LDI instruction to a MOV instruction if + // it would make that instruction CIS-able. + + if ((rg=zip_findnearreg_machine(pzipm, immv)) + != ZIP_RNONE) { + int d; + d = immv - pzipm->r[rg].m_value; + if (fits_within(3,d)) { + insn->i_op = ZIPO_MOV; + insn->i_breg = rg; + insn->i_naux = 0; + insn->i_imm = d; + zip_assemble_insn_words(fragP, + seg, insn, relax_state, + stretch, pzipm); + return; + } + } + } + + if ((!insn->i_rp)&&(insn->i_cnd == ZIPC_ALWAYS) + &&(fits_within(23, immv))) { + // Can we do this with an ordinary load immediate + // instruction? + // + // If we do this, we'll avoid any opportunity to use + // the ZipMachine and move something into this address + insn->i_naux = 0; + insn->i_code = LDIOP(immv,insn->i_areg); + } else if (((!insn->i_rp)||(sym_known)) + &&(fits_within(18, zip_brev(immv)))) { + // Can we do this with a BREV instruction using an + // immediate? If so, we can then conditionally load + // the top 18 bist of any value ... + // + insn->i_naux = 0; + insn->i_code = IMMOP(ZIPO_BREV, insn->i_cnd, + zip_brev(immv), + insn->i_areg&0x0f); + if (insn->i_rp) + insn->i_rp->r_type = BFD_RELOC_NONE; +// 0000 1110 0000 0000 0000 0000 0100 0000 + } else if ((zip_param_use_machine)&&(pzipm) + &&((!insn->i_rp)||(sym_known)) + &&(pzipm->r[insn->i_areg].m_known) + &&(0==((immv^pzipm->r[insn->i_areg].m_value) + & 0x0ffff0000))) { + // Replace LDI with LDILO + insn->i_naux = 0; + insn->i_code=IMMOP(ZIPO_LDILO, insn->i_cnd, + (immv&0x0ffff), insn->i_areg); + + pzipm->r[insn->i_areg].m_value = immv; + if (ZIPC_ALWAYS == insn->i_cnd) { + // Henceforth, we only know the bottom 16bits + // of this register + pzipm->r[insn->i_areg].m_known = MACH_VUPPERKNOWN; + } else + pzipm->r[insn->i_areg].m_known = MACH_VKNOWN; + } else if ((zip_param_use_machine)&&(pzipm) + &&((!insn->i_rp)||(sym_known)) + &&(pzipm->r[insn->i_areg].m_known) + &&((rg=zip_findnearreg_machine(pzipm, immv))!= ZIP_RNONE) + &&(fits_within(13,pzipm->r[rg].m_value - immv))) { + // Replace LDI with a MOV instruction + insn->i_op = ZIPO_MOV; + insn->i_breg = rg; + insn->i_naux = 0; + insn->i_imm = pzipm->r[rg].m_value - immv; + zip_assemble_insn_words(fragP, seg, insn, + relax_state, stretch, pzipm); + return; + } else if ((zip_param_use_machine)&&(pzipm) + &&((!insn->i_rp)||(sym_known)) + &&(pzipm->r[insn->i_areg].m_known) + &&((rg=zip_findnearreg_machine(pzipm, zip_brev(immv)))!= ZIP_RNONE) + &&(fits_within(14,zip_brev(pzipm->r[rg].m_value - immv)))) { + // Replace LDI with a MOV instruction + insn->i_op = ZIPO_BREV; + insn->i_breg = rg; + insn->i_naux = 0; + insn->i_imm = zip_brev(pzipm->r[rg].m_value - immv); + zip_assemble_insn_words(fragP, seg, insn, + relax_state, stretch, pzipm); + return; + } else { + // + // If the symbol isn't defined, then any immv value + // will work--we have to come back anyway. + // + // BREV Extension would modify this statement + insn->i_naux = 1; + insn->i_code = IMMOP(ZIPO_BREV, insn->i_cnd, + zip_brev(immv)&0x01ffff, insn->i_areg); + insn->i_aux[0]=IMMOP(ZIPO_LDILO, insn->i_cnd, + (immv&0x0ffff), insn->i_areg); + if (insn->i_rp) + insn->i_rp->r_type = BFD_RELOC_ZIP_LDI; + else if ((zip_param_cis)&&(zip_can_merge(insn->i_code, insn->i_aux[0]))) { + insn->i_code = zip_insn_merge(insn->i_code, insn->i_aux[0]); + insn->i_naux = 0; + } + } +#ifdef ZIP_DEBUG + fprintf(stderr, "LDI %04x:%04x,%d Instruction assembled into %08x : %08x\n", + (immv>>16)&0x0ffff, + immv & 0x0ffff, insn->i_areg, + insn->i_code, insn->i_aux[0]); +#endif + break; + case ZIPO_BRA: // Includes both conditional and unconditional branches +#ifdef ZIP_DEBUG + fprintf(stderr, "ZIPO--BRA (ADDR = %08lx, OFFSET = %08lx)\n", + fragP->fr_address, + (insn->i_rp)?insn->i_rp->r_fr_offset:0); +#endif + if (insn->i_rp) + immv += (int)(symv + - fragP->fr_address + - (insn->i_rp->r_fr_offset+sizeof(uint32_t))); + +#ifdef ZIP_DEBUG + if (!fits_within(18,immv)) + fprintf(stderr, "doesn't fit in 18 bits\n"); +#endif + if (zip_param_small) { + // + // We can fit (or so we are told), so short jump code + // to an unknown location ... + // + insn->i_naux = 0; + insn->i_aux[0] = NOOP_OPCODE; + insn->i_aux[1] = NOOP_OPCODE; + insn->i_code = IMMOP(ZIPO_ADD, insn->i_cnd, + immv, ZIP_PC); // Add value to PC + insn->i_rp->r_pcrel = TRUE; + // No relocation is required--we just did it + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_PCREL; + // Tested--this works + } else if ((!sym_known)||(!fits_within(18,immv))) { + insn->i_op = ZIPO_LJMP; + + zip_assemble_insn_words(fragP, seg, insn, relax_state, stretch, pzipm); + insn->i_op = ZIPO_BRA; + } else { + // + // We can fit, so short jump code ... + // + insn->i_naux = 0; + insn->i_aux[0] = NOOP_OPCODE; + insn->i_aux[1] = NOOP_OPCODE; + insn->i_code = IMMOP(ZIPO_ADD, insn->i_cnd, + immv, ZIP_PC); // Add value to PC + insn->i_rp->r_pcrel = TRUE; + // No relocation is required--we just did it + insn->i_rp->r_type = BFD_RELOC_NONE; + } +#ifdef ZIP_DEBUG + fprintf(stderr, "BRA %08lx->%08x(%d,%d) assembled into(%d) %08x : %08x : %08x\n", + symv, immv, sym_defined, relax_state, + insn->i_naux, insn->i_code, + insn->i_aux[0], insn->i_aux[1]); +#endif + break; + case ZIPO_LJMP: + // + // Long jump code + // + // I expect this to be true, since we should always + // be branching (or jumping) to a location defined by a + // symbol. + if (insn->i_rp) { + insn->i_rp->r_pcrel = FALSE; + insn->i_rp->r_type = BFD_RELOC_ZIP_VALUE; + } insn->i_breg = ZIP_RNONE; +#ifdef ZIP_DEBUG + fprintf(stderr, "LJMP IMM = %08x = %d\n", immv, immv); +#endif + if (insn->i_cnd == ZIPC_ALWAYS) { + insn->i_naux = 1; + insn->i_code=DBLREGOP(ZIPO_LW,ZIPC_ALWAYS, + 0,ZIP_PC,ZIP_PC); // Load into PC register + insn->i_aux[0] = 0; // Value to load + } else { + // A conditional long jump + insn->i_naux = 2; + insn->i_code=DBLREGOP(ZIPO_LW,insn->i_cnd, + 1,ZIP_PC,ZIP_PC); // Conditional load to PC + insn->i_aux[0]=IMMOP(ZIPO_ADD,ZIPC_ALWAYS, + 1,ZIP_PC); // Skip an instruction + insn->i_aux[1] = 0; + } if (!insn->i_rp) + insn->i_aux[insn->i_naux-1] = immv; + break; + case ZIPO_MOV: + // + // We could go a little wild here: + // MOV val,Rx + // Could be quietly compiled into + // LDI val,Rx (if Rx is not a user register) + // whereas + // MOV BIGVAL(Ry),Rx + // could be quietly compiled into + // LDI BIGVAL,Rx + // ADD.Z Ry,Rx (Note the contortions to avoid adjusting + // ADD.NZ Ry,Rx ... the flag bits) + // This would give us access to full 32-bit offsets ... + // as long as neither Rx nor Ry was a user register. On the + // other hand, if we knew the flag bits would be set between + // now and the next conditional instruction, we could do a + // LDI BIGVAL,Rx + // ADD Ry,Rx + // and be okay with it. + // + // For now we just handle our normal 13 bit signed immediate + // offsets. + // + if (insn->i_rp) { + // MOV label(Rb),Ra + insn->i_rp->r_pcrel = (insn->i_breg == ZIP_PC); + immv += symv; + if (insn->i_breg == ZIP_PC) { + immv +=(int)(-fragP->fr_address + -insn->i_rp->r_fr_offset-sizeof(uint32_t)); + immv >>= 2; + if ((sym_known)&&(this_segment)) { + // Tested--this works + insn->i_rp->r_type = BFD_RELOC_NONE; + } else { +#ifdef ZIP_DEBUG + fprintf(stderr, "ZIP_MOV_PCREL relocation needed for %s, pcrel = %d\n", S_GET_NAME(sym), insn->i_rp->r_pcrel); +#endif + insn->i_rp->r_type = BFD_RELOC_ZIP_MOV_PCREL; + } + + +// } else if((zip_param_got)&&(insn->i_breg == ZIP_GBL)) { +// immv = symv; +// insn->i_rp->r_type = BFD_RELOC_ZIP_MOV_GOTREL; +// as_bad("MOV x(GOT),Ry not yet implemented"); + } else { + // Do we really want to assume this is an + // address? + insn->i_rp->r_type = BFD_RELOC_ZIP_MOV_OFFSET; + } + } else if ((zip_param_use_machine)&&(pzipm) + &&(insn->i_breg<ZIP_CC)&&(insn->i_areg<ZIP_CC) + &&(ZIPC_ALWAYS == insn->i_cnd) + &&(pzipm->r[insn->i_breg].m_known==MACH_VKNOWN) + &&(fits_within(4,pzipm->r[insn->i_breg].m_value + +immv))) { + // MOV Rb,Ra + // turn this into an LDI instruction, rather than a + // move instruction + insn->i_op = ZIPO_LDI; + insn->i_imm += pzipm->r[insn->i_breg].m_value; + insn->i_breg = ZIP_RNONE; + + insn->i_code = LDIOP(insn->i_imm, insn->i_areg); + insn->i_naux = 0; + } + /* + // Handle offsets greater than 13 bits --- up to 32 bits + // Only works if we have no symbol in question, and when the + // target isn't the PC register (or CC for that matter). + else if ((!fits_within(13,insn->i_imm)) + &&(insn->i_areg < ZIP_CC) + &&(insn->i_breg < ZIP_CC)) { + // Alternate instruction sequence: + // but .... these make conditional insns from + // unconditional!! + // MOV.always A,Rx -> LDI A,Rx + // MOV.always A(Ry),Rx -> LDI A,Rx, ADD Ry,Rx + // this works for conditional moves, since ADD.C + // doesn't set conditions + // MOV.C A(Ry),Rx -> LDI.C A,Rx, ADD.C Ry,Rx + + return; + } + */ + + if (insn->i_op == ZIPO_MOV) { // If we haven't changed insns, + gas_assert(fits_within(13, insn->i_imm)); + insn->i_code = SMPLMOV(insn->i_cnd, immv, insn->i_breg, + insn->i_areg); + // + // Now for the extra two register bits only present + // in move instructions + // + insn->i_code |= (insn->i_areg&0x10)?0x40000:0; + insn->i_code |= (insn->i_breg&0x10)?0x02000:0; + } +#ifdef ZIP_DEBUG + fprintf(stderr, "MOV Instruction assembled into %08x\n", insn->i_code); +#endif + break; + case ZIPO_NEG: + insn->i_naux = 1; + if (insn->i_rp) + as_bad("NEG cannot handle symbols"); + gas_assert(fits_within(13, -1+insn->i_imm)); + insn->i_code = SMPLMOV(insn->i_cnd, + (-1+immv), insn->i_breg, insn->i_areg); + insn->i_code &= 0xfffbdfff; + insn->i_aux[0] = IMMOP(ZIPO_XOR, insn->i_cnd, -1, + insn->i_areg); + // printf("NEG Instruction assembled into %08x:%08x\n", + // insn->i_code, insn->i_aux[0]); + break; + case ZIPO_BREAK: case ZIPO_LOCK: case ZIPO_SIM: case ZIPO_NOOP: + if (insn->i_cnd != ZIPC_ALWAYS) + as_bad("NOOP/BREAK/LOCK/SIM instructions cannot handle conditions\n"); + insn->i_code = NOOPGROUP(insn->i_op, insn->i_imm); + insn->i_naux = 0; + break; + case ZIPO_SDUMP: case ZIPO_NDUMP: case ZIPO_SEXIT: case ZIPO_NEXIT: + case ZIPO_SOUT: case ZIPO_NOUT: + // These instructions *should*ve been turned into NOOP and SIM + // instructions by now. Getting here with them is therefore + // an error. + gas_assert(0); + case ZIPO_SEXTB: { + insn->i_naux = 1; + insn->i_code = IMMOP(ZIPO_LSL, insn->i_cnd, 24, insn->i_areg); + insn->i_aux[0] = IMMOP(ZIPO_ASR, insn->i_cnd, 24, insn->i_areg); + } break; + case ZIPO_SEXTH: { + insn->i_naux = 1; + insn->i_code = IMMOP(ZIPO_LSL, insn->i_cnd, 16, insn->i_areg); + insn->i_aux[0] = IMMOP(ZIPO_ASR, insn->i_cnd, 16, insn->i_areg); + } break; + case ZIPO_JSR: + if ((zip_param_cis)&&(insn->i_cnd == ZIPC_ALWAYS) + &&(insn->i_rp)) { + insn->i_op = ZIPO_LJSR; + zip_assemble_insn_words(fragP, seg, insn, relax_state, stretch, pzipm); + insn->i_op = ZIPO_JSR; + } else if ((zip_param_cis)&&(insn->i_cnd == ZIPC_ALWAYS) + &&(insn->i_breg != ZIP_RNONE) + &&(insn->i_imm == 0)) { + // JSR (Register) + insn->i_naux = 0; + insn->i_code = 0x80008000 + | (ZIPV_MOV<<24) + | 0x00f90000 // MOV OpB = PC+1 + | 0x0f880 // MOV into PC + | ((insn->i_breg&0x0f)<<3) + | (ZIPV_MOV << 8); // The LW instruction + + gas_assert(!insn->i_rp); + } else if ((!insn->i_rp)&&(insn->i_breg != ZIP_RNONE)) { + gas_assert(fits_within(13,immv)); + // JSR offset+register, implemented as two moves + insn->i_naux = 1; + insn->i_code = SMPLMOV(insn->i_cnd, 1, ZIP_PC, ZIP_LR); + insn->i_aux[0] = SMPLMOV(insn->i_cnd, immv, insn->i_breg, ZIP_PC); + insn->i_aux[1] = NOOP_OPCODE; + } else { + if (insn->i_rp) + immv += (int)(symv + - fragP->fr_address + - (insn->i_rp->r_fr_offset+sizeof(uint32_t))); + if ((zip_param_small)||((sym_known)&&(fits_within(18,immv-4)))) { + // MOV.C 1(PC),R0 + // BRA.C _somewhere_ + insn->i_naux = 1; + insn->i_code = SMPLMOV(insn->i_cnd, 1, ZIP_PC, + ZIP_LR); + // Bias the branch by -4, since we're one word + // into this instruction + insn->i_aux[0] = IMMOP(ZIPO_ADD, insn->i_cnd, + immv-4, ZIP_PC); + insn->i_aux[1] = NOOP_OPCODE; + insn->i_rp->r_pcrel = TRUE; + insn->i_rp->r_type = BFD_RELOC_NONE; + } else { + // If all else fails, call for a long JSR + insn->i_op = ZIPO_LJSR; + zip_assemble_insn_words(fragP, seg, insn, + relax_state, stretch, pzipm); + insn->i_op = ZIPO_JSR; + } + } break; + case ZIPO_LJSR: + if (insn->i_rp) + immv += (int)(symv + - fragP->fr_address + - (insn->i_rp->r_fr_offset+sizeof(uint32_t))); + if (insn->i_rp) { + insn->i_rp->r_pcrel = FALSE; + insn->i_rp->r_type = BFD_RELOC_ZIP_VALUE; + } insn->i_breg = ZIP_RNONE; + if (insn->i_cnd == ZIPC_ALWAYS) { + if (zip_param_cis) { + insn->i_naux = 1; + insn->i_code = 0x80008000 + | (ZIPV_MOV<<24) + | 0x00fa0000 // MOV OpB = PC+2 + | 0x0f8f8 // (LW) into PC + | (ZIPV_LW << 8); // The LW instruction + insn->i_aux[0] = 0; // To be filled in with address value + } else { // If unconditional + // MOV 1(PC),R0 + // LW (PC),PC + // _somewhere_ + insn->i_naux = 2; + insn->i_code = SMPLMOV(insn->i_cnd, 2, ZIP_PC, + ZIP_LR); + insn->i_aux[0] = DBLREGOP(ZIPO_LW,ZIPC_ALWAYS, + 0,ZIP_PC,ZIP_PC); // Load into PC register + insn->i_aux[1] = 0; + } + } else { + // If conditional, naux = 3 + // BRA.!cnd (for whatever condition) +3 + // MOV 4(PC),R0 + // LW (PC),PC + // address + insn->i_naux = 3; + insn->i_aux[2] = 0; + if (insn->i_cnd != ZIPC_V) { + ZIP_CONDITION cnd = + zip_negate_condition(insn->i_cnd); + insn->i_code = IMMOP(ZIPO_ADD, cnd, 12, ZIP_PC); + insn->i_aux[0] = SMPLMOV(ZIPC_ALWAYS, 2, ZIP_PC, + ZIP_LR); + insn->i_aux[1] = DBLREGOP(ZIPO_LW, ZIPC_ALWAYS, + 0,ZIP_PC,ZIP_PC); // Load into PC register + } else { + insn->i_code = SMPLMOV(ZIPC_V, 3, ZIP_PC, + ZIP_LR); + insn->i_aux[0] = DBLREGOP(ZIPO_LW, ZIPC_V, + 0,ZIP_PC,ZIP_PC); // Load into PC register + insn->i_aux[1] = IMMOP(ZIPO_ADD, ZIPC_ALWAYS, 4, ZIP_PC); + } + } if (!insn->i_rp) + insn->i_aux[insn->i_naux-1] = immv; + break; + default: + if (insn->i_rp) { + insn->i_rp->r_pcrel = FALSE; + immv += symv; + if (insn->i_breg == ZIP_PC) { + immv+=(int)(-fragP->fr_address + -insn->i_rp->r_fr_offset-sizeof(uint32_t)); + insn->i_rp->r_pcrel= TRUE; + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_PCREL; + if ((sym_known)&&(this_segment)) + insn->i_rp->r_type = BFD_RELOC_NONE; +// } else if((zip_param_got)&&(insn->i_breg == ZIP_GBL)) { +// as_bad("<OP> x(GOT),Ry not yet implemented"); +// immv += symv; +// insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_GOTREL; + } else { + // Do we really want to assume this is an + // address? + immv += symv; + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_OFFSET; + } + } if (insn->i_breg != ZIP_RNONE) { + if (insn->i_breg == ZIP_PC) + immv >>= 2; + if (!fits_within(14, insn->i_imm)) { + fprintf(stderr, "ERR: (%d) 0x%08x does not fit within 18 bits!\n", insn->i_imm, insn->i_imm); + gas_assert(fits_within(14, insn->i_imm)); + } + insn->i_code = DBLREGOP(insn->i_op, insn->i_cnd, + immv, insn->i_breg, insn->i_areg); + if (insn->i_rp) { + if (insn->i_breg == ZIP_PC) { + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_PCREL; + insn->i_rp->r_pcrel = TRUE; +// } else if((zip_param_got)&&(insn->i_breg == ZIP_GBL)) { +// insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_GOTREL; + } else + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_OFFSET; + } + } else { + if (!fits_within(18, insn->i_imm)) { + fprintf(stderr, "ERR: (%d) 0x%08x does not fit within 18 bits!\n", insn->i_imm, insn->i_imm); + gas_assert(fits_within(18, insn->i_imm)); + } + insn->i_code = IMMOP(insn->i_op, insn->i_cnd, + immv, insn->i_areg); + if (insn->i_rp) + insn->i_rp->r_type = BFD_RELOC_ZIP_OPB_IMM; + } +#ifdef ZIP_DEBUG + fprintf(stderr, "Instruction assembled into %08x%s\n", insn->i_code, + (insn->i_rp)?" w/ Symbol":""); +#endif + break; + } +} + +void +md_assemble(char *line) { + const char *linep; + char *p; + + linep = (char *)zip_skip_white_spaces(line); + if ((strncasecmp(linep, "nstr", 4)==0) + ||(strncasecmp(linep, "sstr", 4)==0)) { + uint32_t base; + const char *sbeg; + + if ((linep[0] =='n')||(linep[0] == 'N')) + base = 0x0400 + NOOP_OPCODE; + else + base = 0x0400 + SIM_OPCODE; + + sbeg = strchr(line, '\"'); + if (!sbeg) + as_bad("String instruction with no quotes found"); + sbeg++; + while(*sbeg != '\"') { + unsigned v = *sbeg++; + if (v == '\\') { + switch(*sbeg++) { + case 'a': v = '\a'; break; + case 'b': v = '\b'; break; + case 'f': v = '\f'; break; + case 'n': v = '\n'; break; + case 'r': v = '\r'; break; + case 't': v = '\t'; break; + case '\\': v = '\\'; break; + case '\"': v = '\"'; break; + case '\'': v = '\''; break; + default: sbeg--; + } + } + p = frag_more(sizeof(uint32_t)); + md_number_to_chars(p,base+(v&0x0ff),sizeof(uint32_t)); + } + + return; + } + + + // Decode an instruction from op_str + // Determine the opcode + // any conditions + // the result register + // any immediate + // any "B" register + ZIPIS insnv, *insn = &insnv; + const char *error = zip_parse(line, insn); + +#ifdef ZIP_DEBUG + fprintf(stderr, "ZIP-ASSEMBLE %s\n", line); +#endif + + if (error) { + as_bad("%s \'%s\'", error, line); + return; + } + + zip_assemble_insn_words(frag_now, now_seg, insn, 0, 0, &zipm); + if (zip_param_use_machine) + zip_advance_machine(&zipm, insn); +#ifdef ZIP_DEBUG + zip_debug_machine(&zipm); +#endif + + // Then, if the instruction is valid we ... + // for branches ... + // symbolS *symp = reloc->reloc_expression.X_add_symbol; + // offsetT offset = reloc->reloc_expression.X_add_number; + // char *f; + // f = frag_var(?, 4, 4, BRANCH_SUBTYPE, symp, offset, NULL); + // md_number_to_chars(f, insn->insn_code, 4); // ??? + // + // + if ((!insn->i_rp)&&(cis_mergable)&&(insn->i_naux == 0) + &&(frag_now_fix_octets()>=4)) { + // ZIPI lcode = md_number_from_chars(p, 4); + unsigned int last_iword; + char *buf; + + buf = &frag_now->fr_literal[frag_now_fix_octets() - 4]; + last_iword = (buf[3]&0x0ff)|((buf[2]&0x0ff)<<8) + |((buf[1]&0x0ff)<<16)|((buf[0]&0x0ff)<<24); + if ((buf >= frag_now->fr_literal) + &&(zip_can_merge(last_iword,insn->i_code))) { + p = buf; + insn->i_code =zip_insn_merge(last_iword, insn->i_code); + md_number_to_chars(p, insn->i_code, sizeof(uint32_t)); + } else { + p = frag_more(sizeof(uint32_t)*(1+insn->i_naux)); + md_number_to_chars(p, insn->i_code, sizeof(uint32_t)); + } + } else { + int i; + ZIPRELOC *rp = insn->i_rp; + + if ((insn->i_naux == 0)||(NULL == insn->i_rp)) { + // If we have no need of any symbols, we come here. + // If we have no need of any extra 4-byte instructions, + // we come here. + p = frag_more(sizeof(uint32_t)*(1+insn->i_naux)); + + if (insn->i_rp) { + // Generate a fixup for when we finally + // know where this symbol links to + insn->i_rp->r_fr_offset = + (p - frag_now->fr_literal); + insn->i_rp->r_fix = fix_new(frag_now, + insn->i_rp->r_fr_offset, // where w/in frag? + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm, // Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + insn->i_rp->r_type); // Reloc type + insn->i_rp = NULL; + } + } else { + // First, grow our fragment so we know we have the + // size we'll need. + frag_grow(sizeof(uint32_t)*(1+insn->i_naux)); + + // Then p, the place where we'd get more from, is + // where our instruction will be installed. We know + // there's room for it there now. + p = frag_more(0); + // Record where in the frag our relaxable instruction + // will be installed + insn->i_rp->r_fr_offset = ( p - frag_now->fr_literal ); + // Now tell the assembler about what we've done. + // This'll close off the frag as well, so this is the + // last we'll see of this frag--even though frag_now + // may yet point to it (or not) for a while. + frag_var(rs_machine_dependent, // Relaxation type + sizeof(uint32_t)*(1+insn->i_naux), + sizeof(uint32_t)*(1+insn->i_naux), + rs_machine_dependent, // Subtype + insn->i_rp->r_sym, // Symbol + insn->i_imm, // Offset (to be added to symbol) + (char *)zip_copy_insn(insn)); // Opcode + + } + md_number_to_chars(p, insn->i_code, sizeof(uint32_t)); + for(i=0; i< insn->i_naux; i++) + md_number_to_chars(&p[sizeof(uint32_t)*(1+i)], insn->i_aux[i], sizeof(uint32_t)); + + if (rp) { + cis_mergable = FALSE; + } else { + cis_mergable = (zip_param_cis)&&(insn->i_naux == 0); + } + } +#ifdef ZIP_DEBUG + zip_dump_insn(insn); +#endif +} + +/* Turn a string in input_line_pointer into a floating point constant + * of type type, and store the appropriate bytes in *LITP. The number of + * LIITTLENUMS emitted is stored in *SIZEP. An error message is returned, or + * NULL on OK. + */ +const char * +md_atof(int type, char *litP, int *sizeP) { + int prec; + LITTLENUM_TYPE words[4]; + char *t; + int i; + + switch(type) { + case 'f': + prec = 2; break; + case 'd': + prec = 4; break; + default: + *sizeP = 0; + return _("Unsupported floating point format"); + } + + t = atof_ieee(input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * 2; + + for(i=prec-1; i>= 0; i--) { + md_number_to_chars(litP, (valueT)words[i], 2); + litP += 2; + } + + return NULL; +} +#define AS_BAD_FIX(FXP,STR) as_bad_where(FXP->fx_file,FXP->fx_line,_(STR)) + +/* Apply a fixup to the object file + * + * This function will only be called once all of the details of the fixup are + * known, before the object file heads to the linker (if at all). + */ +void +md_apply_fix(fixS *fixP, valueT *val, segT seg ATTRIBUTE_UNUSED) +{ + unsigned int iword, mask, final_fix; + + final_fix = (fixP->fx_addsy == NULL) ? TRUE : FALSE; + + bfd_byte *buf = (bfd_byte *)&fixP->fx_frag->fr_literal[fixP->fx_where]; + iword = (buf[3]&0x0ff)|((buf[2]&0x0ff)<<8) + |((buf[1]&0x0ff)<<16)|((buf[0]&0x0ff)<<24); + (*val) &= 0x0ffffffff; + +#ifdef ZIP_DEBUG + fprintf(stderr, "MD-APPLY-FIX: FRAG=%08x@%08x+%08x(%d), IWORD = %08x Val=%08x (RTYP=%d->%s)%s%s, ADDEND=%08lx\n", + ((unsigned)((unsigned long)fixP->fx_frag->fr_literal)), + ((unsigned)((unsigned long)fixP->fx_frag->fr_address)), + ((unsigned)((unsigned long)fixP->fx_where)), + ((unsigned)((unsigned long)fixP->fx_size)), + iword, (unsigned)(*val), fixP->fx_r_type, + bfd_get_reloc_code_name(fixP->fx_r_type), + (fixP->fx_pcrel)?" PC-Rel ":" std ", + (fixP->fx_addsy)?"":"(Null Sym)", + fixP->fx_offset); +#endif + switch(fixP->fx_r_type) { + case BFD_RELOC_NONE: + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_OPB_IMM: + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_OPB_IMM\n"); + mask = 0x3ffff; iword = (iword &(~mask))|((*val)&mask); + (*val) &= 0x03ffff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_OPB_PCREL: + { + uint32_t oval; + oval = *val; + oval = (*val>>2); + oval &= 0x03fff; + mask = 0x3fff; iword = (iword &(~mask))|((oval)&mask); + *val = oval; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + } break; + case BFD_RELOC_ZIP_OPB_OFFSET: +// case BFD_RELOC_ZIP_OPB_GOTREL: + case BFD_RELOC_14: + // if (fixP->fx_r_type == BFD_RELOC_ZIP_OPB_OFFSET) + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_OPB_OFFSET\n"); + // else if (fixP->fx_r_type == BFD_RELOC_ZIP_OPB_PCREL) + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_OPB_PCREL\n"); + // else + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_OPB_GOTREL\n"); + mask = 0x3fff; iword = (iword &(~mask))|((*val)&mask); + (*val) &= 0x03fff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_MOV_PCREL: + (*val) &= 0x07fff; (*val)>>=2; + mask = 0x1fff; iword = (iword &(~mask))|((*val)&mask); + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_MOV_OFFSET: + // case BFD_RELOC_ZIP_MOV_GOTREL: +#ifdef ZIP_DEBUG + if (fixP->fx_r_type == BFD_RELOC_ZIP_MOV_OFFSET) + fprintf(stderr, "\tMD-APPLY-FIX: BFD_RELOC_ZIP_MOV_OFFSET\n"); + //else if (fixP->fx_r_type == BFD_RELOC_ZIP_MOV_PCREL) + // fprintf(stderr, "\tMD-APPLY-FIX: BFD_RELOC_ZIP_MOV_PCREL\n"); + // else + // fprintf(stderr, "\tMD-APPLY-FIX: BFD_RELOC_ZIP_MOV_GOTREL\n"); + fprintf(stderr, "Final-fix = %d\n", final_fix); +#endif + mask = 0x1fff; iword = (iword &(~mask))|((*val)&mask); + (*val) &= 0x01fff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_LDI: + // If the value were known at build time, we wouldn't need + // to drop the lower two address bits. However, since we're + // doing a fixup, we know val must reference an address, + // hence we shift down two bits. + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_LDI\n"); + iword |= (*val)&0x03fffff; + (*val) &= 0x03fffff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_LLO: + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_LLO\n"); + iword |= (*val)&0x0ffff; + (*val) &= 0x0ffff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_ZIP_BREV: + // (*val) &= 0x0fffe0000; + iword &= (~0x1ffff); + iword |= zip_brev(*val)&0x01ffff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; +#ifdef USE_R_ZIP_LHI + case BFD_RELOC_ZIP_LHI: + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_LHI\n"); + iword |= ((*val)>>16)&0x0ffff; + (*val) &= 0x0ffff0000; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; +#endif + case BFD_RELOC_32: + case BFD_RELOC_ZIP_VALUE: + // printf("\tMD-APPLY-FIX: BFD_RELOC_ZIP_VALUE/32\n"); + iword = (*val); + (*val) &= 0x0ffffffff; + md_number_to_chars((char *)buf, iword, sizeof(uint32_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_16: + iword = (*val)&0x0ffff; + (*val) &= 0x0ffff; + md_number_to_chars((char *)buf, iword, sizeof(uint16_t)); + fixP->fx_done = final_fix; + break; + case BFD_RELOC_8: + iword = buf[0] & 0x0ff; + iword |= (*val)&0x0ff; (*val) &= 0x0ff; + md_number_to_chars((char *)buf, iword, sizeof(uint8_t)); + fixP->fx_done = final_fix; + break; + default: + fprintf(stderr, "RELOC #\%d not supported\n", fixP->fx_r_type); + // abort(); + break; + } +} + +/* Generate a machine-dependent relocation. */ +arelent * +tc_gen_reloc(asection *section ATTRIBUTE_UNUSED, fixS *fixP) +{ +#ifdef ZIP_DEBUG + fprintf(stderr, "Call to TC-GEN-RELOC(%s,FIX,%s,+%ld);\n", segment_name(section), + S_GET_NAME(fixP->fx_addsy),fixP->fx_offset); +#endif + + arelent *relP; + + relP = xmalloc(sizeof(arelent)); + gas_assert(relP != 0); + relP->sym_ptr_ptr = (asymbol **)xmalloc(sizeof(asymbol *)); + *relP->sym_ptr_ptr = symbol_get_bfdsym(fixP->fx_addsy); + relP->address = (fixP->fx_frag->fr_address + fixP->fx_where); + // The addend value is added to the symbols value after the value is + // is resolved. It is useful for PC relative addressing, as well as + // instructions giving offsets to symbols, such as LDI .x+50,R0. + relP->addend = fixP->fx_offset; + if (fixP->fx_r_type == BFD_RELOC_ZIP_OPB_PCREL) + relP->addend -= 4; + else if (fixP->fx_r_type == BFD_RELOC_ZIP_MOV_PCREL) + relP->addend -= 4; +#ifdef ZIP_DEBUG + fprintf(stderr, "ADDEND = %08lx\n", relP->addend); +#endif + relP->howto = bfd_reloc_type_lookup(stdoutput, fixP->fx_r_type); + if (! relP->howto) { + const char *name; + name = S_GET_NAME(fixP->fx_addsy); + if (name == NULL) + name = _("<unknown>"); + as_fatal( _("Cannot generate relocation type for symbol %s, code %s"), + name, bfd_get_reloc_code_name(fixP->fx_r_type)); + } +#ifdef ZIP_DEBUG + else { + const char *name; + name = S_GET_NAME(fixP->fx_addsy); + if (name == NULL) + name = _("<unknown>"); + fprintf(stderr, "GENERATING-RELOC(%20s, %4d=0x%04x) for %s\n", + bfd_get_reloc_code_name(fixP->fx_r_type), + fixP->fx_r_type, fixP->fx_r_type, name); + } +#endif + return relP; +} + +// Size is estimated in host bytes (octets) +int +zip_estimate_size_before_relax(fragS *fragP, segT seg) { + ZIPIS *insn = (ZIPIS *)(fragP->fr_opcode); + offsetT last_fix = fragP->fr_fix; + + zip_assemble_insn_words(fragP, seg, insn, 1, 0, NULL); + + // Goal is to estimate the total size of the fragment before any + // relaxations. We need to return the difference between that + // new estimate of total size and the current value of fragP->fr_fix. +#ifdef ZIP_DEBUG + fprintf(stderr, "(%s): SZ-ESTIMATE %3ld + %d*(1+%d) - %3ld = %3ld\n", + S_GET_NAME(insn->i_rp->r_sym), + insn->i_rp->r_fr_offset, OCTETS_PER_BYTE, insn->i_naux, + fragP->fr_fix, + insn->i_rp->r_fr_offset + (1+insn->i_naux)*sizeof(uint32_t) - fragP->fr_fix); +#endif + // zip_dump_insn(insn); + fragP->fr_fix = insn->i_rp->r_fr_offset + (1+insn->i_naux) * sizeof(uint32_t); + return fragP->fr_fix - last_fix; +} + +#define RELAX_STATE(FRAG) (FRAG->fr_subtype) +long +zip_relax_frag(segT seg, fragS *fragP, long stretch) +{ + ZIPIS *insn = (ZIPIS *)(fragP->fr_opcode); + char *p =&fragP->fr_literal[insn->i_rp->r_fr_offset]; + long growth; + int i, old_naux = insn->i_naux; + +#ifdef ZIP_DEBUG + fprintf(stderr, "--- FIX --- @%08x/%08x, Sym %s (zip_relax_frag), stretch = %ld/offset = %08lx, addr=%08x\n", + (int)((long)(fragP->fr_literal)), + (unsigned)fragP->fr_address, + (insn->i_rp->r_sym)? S_GET_NAME(insn->i_rp->r_sym) + :"(Null)", + stretch, insn->i_rp->r_fr_offset, + insn->i_imm); + // zip_dump_insn(insn); +#endif + + { + fragS *lclfP; + for(lclfP = fragP; lclfP; lclfP = lclfP->fr_next) + gas_assert(lclfP->fr_type < 256); + } + + // We need to rebuild the instruction since we could relax it + // multiple times + zip_assemble_insn_words(fragP, seg, insn, 1, stretch, NULL); + { + fragS *lclfP; + for(lclfP = fragP; lclfP; lclfP = lclfP->fr_next) + gas_assert(lclfP->fr_type < 256); + } + + md_number_to_chars(p, insn->i_code, sizeof(uint32_t)); + { + fragS *lclfP; + for(lclfP = fragP; lclfP; lclfP = lclfP->fr_next) + gas_assert(lclfP->fr_type < 256); + } + + for(i=0; i< insn->i_naux; i++) + md_number_to_chars(&p[sizeof(uint32_t)*(1+i)], insn->i_aux[i], + sizeof(uint32_t)); + + { + fragS *lclfP; + for(lclfP = fragP; lclfP; lclfP = lclfP->fr_next) + gas_assert(lclfP->fr_type < 256); + } + + // The change in size of this fragment + growth = (insn->i_naux - old_naux) * sizeof(uint32_t); +#ifdef ZIP_DEBUG + fprintf(stderr, "GROWING BY %3ld bytes (insn->i_naux = %d->%d, fr_fix was %ld)\n", + growth, old_naux, insn->i_naux, fragP->fr_fix); + gas_assert(fragP->fr_fix >= 0); + gas_assert(fragP->fr_fix + growth>= 0); +#endif + { + fragS *lclfP; + for(lclfP = fragP; lclfP; lclfP = lclfP->fr_next) + gas_assert(lclfP->fr_type < 256); + } + + return growth; +} + +void +zip_convert_frag(bfd *headers ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) +{ + ZIPIS *insn = (ZIPIS *)fragP->fr_opcode; + // char *p = fragP->fr_literal+ insn->i_rp->r_fr_offset; + +#ifdef ZIP_DEBUG + fprintf(stderr, "CVT-FRAG: ADDR = %08lx, FIX = %3ld, VAR = %3ld\n", + fragP->fr_address, fragP->fr_fix, fragP->fr_var); + + zip_dump_insn(insn); +#endif + + if ((insn->i_rp)&&(insn->i_rp->r_type != BFD_RELOC_NONE) + &&(!insn->i_rp->r_fix)) { + if (insn->i_op == ZIPO_LDI) { + if (insn->i_naux == 1) { + // BREV extension would go here + // + fix_new(fragP, + insn->i_rp->r_fr_offset, // where w/in frag? + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm,// Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + BFD_RELOC_ZIP_BREV); // Reloc type + fix_new(fragP, + (insn->i_rp->r_fr_offset+sizeof(uint32_t)), // where w/in frag? + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm,// Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + BFD_RELOC_ZIP_LLO); // Reloc type + } else { + insn->i_rp->r_fix = fix_new(fragP, + (insn->i_rp->r_fr_offset), // where w/in frag? + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm, // Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + BFD_RELOC_ZIP_LDI); // Reloc type + } + } else if ((insn->i_op == ZIPO_BRA)&&(insn->i_naux >= 1)) { +#ifdef ZIP_DEBUG + fprintf(stderr, "--- CVT-FRAG --- Creating a BRA fixup\n"); +#endif + fix_new(fragP, + insn->i_rp->r_fr_offset +insn->i_naux*sizeof(uint32_t), + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm, // Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + BFD_RELOC_ZIP_VALUE); // Reloc type + } else if (insn->i_rp->r_type == BFD_RELOC_ZIP_VALUE) { + // Use the CIS LW (PC),PC method + fix_new(fragP, + insn->i_rp->r_fr_offset + + insn->i_naux*sizeof(uint32_t), + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm, // Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + BFD_RELOC_ZIP_VALUE); // Reloc type + } else { +#ifdef ZIP_DEBUG + fprintf(stderr, "--- CVT-FRAG --- Creating a more generic fixup (%d)\n", + insn->i_rp->r_type); +#endif + fix_new(fragP, + // where w/in frag? + insn->i_rp->r_fr_offset+insn->i_naux * sizeof(uint32_t), + 4, // 1,2, or 4 usually ... ?? + insn->i_rp->r_sym, // Add symbol, + insn->i_imm, // Fixed/known offset to the symbol + insn->i_rp->r_pcrel, // T if PC-Relative reloc + insn->i_rp->r_type); // Reloc type + } + } +} diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/config/tc-zip.h binutils-2.27-zip/gas/config/tc-zip.h --- binutils-2.27-original/gas/config/tc-zip.h 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/config/tc-zip.h 2017-03-03 09:35:34.527310651 -0500 @@ -0,0 +1,191 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: tc-zip.h +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016-2017, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef TC_ZIPCPU +#define TC_ZIPCPU + +#define TC_ZIP 1 + +/* This macro, when defined as zero, means our target in little endian like a + * PC. A 1 would mean it was big endian. Since the Zip CPU is big endian, we + * set this to one here.. + */ +#define TARGET_BYTES_BIG_ENDIAN 1 + +/* If WORKING_DOT_WORD is defined, GAS will not do broken word processing + * (*note Broken Words ...). Otherwise, you should set 'md_short_jump_size' + * to the size of a short jump (a jump that is just long enough to jump + * around a long jmp) and 'md_long_jump_size' to the size of a long jump + * (a jump that can go anywhere in the function). You should define + * md_create_short_jump to create a short jump around a long jump, and define + * md_create_long_jump to creat a long jump. Here, we'll just skip these + * and so we define WORKING_DOT_WORD. + */ +#define WORKING_DOT_WORD + +/* TC_ADDRESS_BYTES ... Define this macro to specify the number of bytes used + * to store an address. Used to implement dc.a. The target must have a reloc + * for this size. + */ +#define TC_ADDRESS_BYTES zip_address_bytes + +/* TC_PREDICATE_START_CHAR ... I can't find this in the documentation, but I'm + * guessing if a line begins with this character, the line beginning will be + * taken care of specially. + */ +#define TC_PREDICATE_START_CHAR '[' +#define TC_PREDICATE_END_CHAR ']' + + +/* md_cons_align ... You may define this macro to do any special alignment + * before a data allocation pseudo-op. + * + */ +#define md_cons_align(N) zip_cons_align(N) +extern void zip_cons_align(int); + +#define md_flush_pending_output zip_flush_pending_output +extern void zip_flush_pending_output(void); + + +/* This macro is the BFD target name to use when creating the output +* file. This will normally depend upon the OBJ_FMT macro. */ +#define TARGET_FORMAT "elf32-zip" +#define TARGET_ARCH bfd_arch_zip + +#define md_estimate_size_before_relax zip_estimate_size_before_relax +#define md_relax_frag zip_relax_frag +#define md_convert_frag zip_convert_frag +extern long zip_relax_frag(segT, fragS *, long); +extern int zip_estimate_size_before_relax(fragS *, segT); +extern void zip_convert_frag(bfd *, segT, fragS *); +extern int zip_address_bytes(void); + +/* These macros must be defined, but it will be a fatal assembler error if we +* ever hit them. */ +// #define md_estimate_size_before_relax(A, B) (as_fatal (_("estimate size\n")),0) +#define md_pcrel_from(FIX) (((FIX)->fx_where+(FIX)->fx_frag->fr_address+4)>>OCTETS_PER_BYTE_POWER) + +// What do we need to define here to align on 32-bit boundaries? +#define md_section_align(SEGMENT, SIZE) (SIZE) + +// Check label is called right after any label (lbl: ) is found in the +// assembly of the program. We need to make certain this is called, so that +// in VLIW mode we don't try to merge an instruction pair into a new +// instruction sequence where the label calls for jumping into the middle +// of that sequence. +// +#define tc_check_label zip_check_label +extern void zip_check_label(symbolS *); + + +extern void md_assemble(char *op_str); +extern void md_end(void); +extern void md_begin(void); +// extern symbolS *md_undefined_symbol(char *name); +// extern void md_operand(expressionS *name); + +#if (TARGET_BYTES_BIG_ENDIAN==0) +#define md_number_to_chars number_to_chars_littleendian +#else +#define md_number_to_chars number_to_chars_bigendian +#endif + + +#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" + +// typedef uint32_t ZIPI, ZIPA; +// typedef int ZIPIMM; + +// LR = Link Register, R0 +// FP = Frame Pointer, R12 +// SP = Stack Pointer, R13 +// CC = Condition Codes, R14 +// PC = Program Counter, R15 +typedef enum { + ZIP_LR=0, ZIP_R1, ZIP_R2, ZIP_R3, ZIP_R4, ZIP_R5, ZIP_R6, ZIP_R7, + ZIP_R8, ZIP_R9, ZIP_R10, ZIP_R11, ZIP_FP, + ZIP_SP, ZIP_CC, ZIP_PC, + ZIP_uLR, ZIP_uR1, ZIP_uR2, ZIP_uR3, ZIP_uR4, ZIP_uR5, ZIP_uR6, ZIP_uR7, + ZIP_uR8, ZIP_uR9, ZIP_uR10, ZIP_uR11, ZIP_uFP, + ZIP_uSP, ZIP_uCC, ZIP_uPC, + ZIP_RNONE=48 +} ZIP_REG; + +#define ZIP_USER_REGS 16 + +typedef enum { + ZIPC_ALWAYS, ZIPC_Z, ZIPC_LT, ZIPC_C, + ZIPC_V, ZIPC_NZ, ZIPC_GE, ZIPC_NC +} ZIP_CONDITION; + +typedef enum { + // 16 ALU instructions + ZIPO_SUB=0, ZIPO_AND, ZIPO_ADD, ZIPO_OR, // 5'h000xx + ZIPO_XOR, ZIPO_LSR, ZIPO_LSL, ZIPO_ASR, // 5'h001xx + ZIPO_BREV, ZIPO_LDILO, ZIPO_MPYUHI, ZIPO_MPYSHI,// 5'h010xx + ZIPO_MPY, ZIPO_MOV, ZIPO_DIVU, ZIPO_DIVS, // 5'h011xx +// + ZIPO_CMP, ZIPO_TST, // 5'h1000x + ZIPO_LW, ZIPO_SW, ZIPO_LH, ZIPO_SH, ZIPO_LB, ZIPO_SB, // 5'h10xxw + ZIPO_LDI, ZIPO_LDIn, // 5'h1100x + ZIPO_FPADD=0x1a, ZIPO_FPSUB, // 5'h1101x + ZIPO_FPMPY, ZIPO_FPDIV, // 5'h1110x + ZIPO_FPI2F, ZIPO_FPF2I, // 5'h1111x + // Pseudo-ops + ZIPO_BREAK, ZIPO_LOCK, ZIPO_SIM, ZIPO_NOOP, + ZIPO_TRAP, ZIPO_CLR, + // + ZIPO_BRA, ZIPO_BLT, ZIPO_BZ, ZIPO_BC, + ZIPO_BV, ZIPO_BGE, ZIPO_BNZ, ZIPO_BNC, + // + ZIPO_HALT, ZIPO_WAIT, ZIPO_RTU, ZIPO_BUSY, + ZIPO_STEP, ZIPO_JMP, ZIPO_NOT, ZIPO_NEG, + // + ZIPO_SDUMP, ZIPO_NDUMP, + ZIPO_SOUT, ZIPO_NOUT, + ZIPO_SEXIT, ZIPO_NEXIT, + ZIPO_SEXTB, ZIPO_SEXTH, + ZIPO_JSR, ZIPO_LJSR, ZIPO_LJMP +} ZIP_OPCODE; + +typedef enum { + // 8 instructions + ZIPV_SUB=0, ZIPV_AND, ZIPV_ADD, ZIPV_CMP, // 3'h0xx + ZIPV_LW, ZIPV_SW, ZIPV_LDI, ZIPV_MOV, // 3'h1xx +} ZIP_VLIWCODE; + +#endif + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/configure.tgt binutils-2.27-zip/gas/configure.tgt --- binutils-2.27-original/gas/configure.tgt 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/gas/configure.tgt 2016-12-31 17:44:37.270167826 -0500 @@ -112,6 +112,7 @@ x86_64*) cpu_type=i386 arch=x86_64;; xgate) cpu_type=xgate ;; xtensa*) cpu_type=xtensa arch=xtensa ;; + zip*) cpu_type=zip endian=big ;; *) cpu_type=${cpu} ;; esac @@ -472,6 +473,8 @@ z8k-*-coff | z8k-*-sim) fmt=coff ;; + zip*) fmt=elf ;; + *-*-aout | *-*-scout) fmt=aout ;; *-*-cloudabi*) fmt=elf ;; *-*-dragonfly*) fmt=elf em=dragonfly ;; diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/Makefile.am binutils-2.27-zip/gas/Makefile.am --- binutils-2.27-original/gas/Makefile.am 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/gas/Makefile.am 2016-12-31 17:45:17.941851449 -0500 @@ -200,6 +200,7 @@ config/tc-xtensa.c \ config/tc-z80.c \ config/tc-z8k.c \ + config/tc-zip.c \ config/xtensa-relax.c TARGET_CPU_HFILES = \ @@ -273,6 +274,7 @@ config/tc-xtensa.h \ config/tc-z80.h \ config/tc-z8k.h \ + config/tc-zip.h \ config/xtensa-relax.h # OBJ files in config diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/Makefile.in binutils-2.27-zip/gas/Makefile.in --- binutils-2.27-original/gas/Makefile.in 2016-08-03 04:16:28.000000000 -0400 +++ binutils-2.27-zip/gas/Makefile.in 2016-12-31 17:49:43.603837948 -0500 @@ -494,6 +494,7 @@ config/tc-xtensa.c \ config/tc-z80.c \ config/tc-z8k.c \ + config/tc-zip.c \ config/xtensa-relax.c TARGET_CPU_HFILES = \ @@ -567,6 +568,7 @@ config/tc-xtensa.h \ config/tc-z80.h \ config/tc-z8k.h \ + config/tc-zip.h \ config/xtensa-relax.h @@ -922,6 +924,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-xtensa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-z80.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-z8k.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-zip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/te-vms.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xtensa-relax.Po@am__quote@ @@ -1941,6 +1944,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-z8k.obj `if test -f 'config/tc-z8k.c'; then $(CYGPATH_W) 'config/tc-z8k.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-z8k.c'; fi` +tc-zip.o: config/tc-zip.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-zip.o -MD -MP -MF $(DEPDIR)/tc-zip.Tpo -c -o tc-zip.o `test -f 'config/tc-zip.c' || echo '$(srcdir)/'`config/tc-zip.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-zip.Tpo $(DEPDIR)/tc-zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-zip.c' object='tc-zip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-zip.o `test -f 'config/tc-zip.c' || echo '$(srcdir)/'`config/tc-zip.c + +tc-zip.obj: config/tc-zip.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-zip.obj -MD -MP -MF $(DEPDIR)/tc-zip.Tpo -c -o tc-zip.obj `if test -f 'config/tc-zip.c'; then $(CYGPATH_W) 'config/tc-zip.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-zip.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-zip.Tpo $(DEPDIR)/tc-zip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-zip.c' object='tc-zip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-zip.obj `if test -f 'config/tc-zip.c'; then $(CYGPATH_W) 'config/tc-zip.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-zip.c'; fi` + xtensa-relax.o: config/xtensa-relax.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xtensa-relax.o -MD -MP -MF $(DEPDIR)/xtensa-relax.Tpo -c -o xtensa-relax.o `test -f 'config/xtensa-relax.c' || echo '$(srcdir)/'`config/xtensa-relax.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xtensa-relax.Tpo $(DEPDIR)/xtensa-relax.Po diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip.exp binutils-2.27-zip/gas/testsuite/gas/zip/zip.exp --- binutils-2.27-original/gas/testsuite/gas/zip/zip.exp 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip.exp 2017-01-12 22:12:40.839206088 -0500 @@ -0,0 +1,17 @@ +# ZipCPU assembler testsuite + +if [istarget zip*] { + run_dump_test "zip_insn_add" + run_dump_test "zip_insn_bratest" + run_dump_test "zip_insn_ctest" + run_dump_test "zip_insn_lditest" + run_dump_test "zip_insn_prologue" + run_dump_test "zip_insn_prologuev" + run_dump_test "zip_insn_specials" + run_dump_test "zip_insn_optest" + run_dump_test "zip_insn_mov" + run_dump_test "zip_insn_vliw" + # run_dump_test "zip_insn_fpu" + # run_dump_test "zip_insn_jsr" + # run_dump_test "zip_insn_jsrv" +} diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_add.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_add.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_add.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_add.d 2017-01-12 22:01:30.790982203 -0500 @@ -0,0 +1,41 @@ +#as: -novliw +#objdump: -dr +#name: Generic OpB instruction test + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <add_insn_test>: + 0: 00 83 e0 00 ADD +\$-8192,R0 + 4: 00 84 a0 00 ADD +\$-8192\+R2,R0 + 8: 08 82 00 00 ADD +\$-131072,R1 + c: 00 80 1f ff ADD +\$8191,R0 + 10: 00 84 a0 01 ADD +\$-8191\+R2,R0 + 14: 08 81 ff ff ADD +\$131071,R1 + 18: 18 80 00 01 ADD +\$1,R3 + 1c: 18 85 00 01 ADD +\$1\+R4,R3 + 20: 30 87 c0 01 ADD +\$4\+PC,R6 + 24: 30 87 c0 01 ADD +\$4\+PC,R6 + 28: 30 87 c0 01 ADD +\$4\+PC,R6 + 2c: 30 87 c0 01 ADD +\$4\+PC,R6 + 30: 50 88 00 04 ADD.Z +\$4,R10 + 34: 50 a8 00 04 ADD.NZ +.4,R10 + 38: 50 90 00 04 ADD.LT +.4,R10 + 3c: 50 b0 00 04 ADD.GE +.4,R10 + 40: 50 98 00 04 ADD.C +.4,R10 + 44: 50 b8 00 04 ADD.NC +.4,R10 + 48: 50 a0 00 04 ADD.V +.4,R10 + 4c: 50 88 00 04 ADD.Z +.4,R10 + 50: 58 a8 00 04 ADD.NZ +.4,R11 + 54: 60 90 00 04 ADD.LT +.4,R12 + 58: 68 b0 00 04 ADD.GE +.4,SP + 5c: 70 98 00 04 ADD.C +.4,CC + 60: 78 b8 00 04 BNC +@0x00000068.*$ + 64: 68 a0 00 04 ADD.V +.4,SP + 68: 70 80 00 04 ADD +.4,CC + 6c: 78 80 00 04 BRA +@0x00000074.*$ + 70: 78 89 ff ff BZ +@0x00020073.*$ + 74: 78 aa 00 00 BNZ +@0xfffe0078.*$ + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_add.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_add.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_add.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_add.s 2017-01-10 12:00:50.870044337 -0500 @@ -0,0 +1,33 @@ + .text + +add_insn_test: + add -8192,R0 + add -8192+R2,R0 + add -131072,R1 + add 8191,R0 + add -8191+R2,R0 + add 131071,R1 + add 1,R3 + add 1(R4),R3 + add 5+pc,R6 + add 5+r15,R6 + add 5+spc,R6 + add 5+sr15,R6 + add.z 4,R10 + add.nz 4,R10 + add.lt 4,R10 + add.ge 4,R10 + add.c 4,R10 + add.nc 4,R10 + add.v 4,R10 + [z] add 4,R10 + [nz] add 4,R11 + [lt] add 4,R12 + [ge] add 4,R13 + [c] add 4,R14 + [nc] add 4,R15 + [v] add 4,sp + add 4,cc + add 4,pc + add.z 131071,pc + add.nz -131072,pc diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_bratest.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_bratest.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_bratest.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_bratest.d 2017-01-10 10:46:16.957469423 -0500 @@ -0,0 +1,22 @@ +#as: +#objdump: -dr +#name: Local branch (BRA) and conditional branch testing + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <bra_insn_test>: + 0: 78 80 00 20 BRA \$32 + 4: 78 88 00 1c BZ @0x00000024 // .. <bra_target> + 8: 78 a8 00 18 BNZ @0x00000024 // .. <bra_target> + c: 78 98 00 14 BC @0x00000024 // .. <bra_target> + 10: 78 b8 00 10 BNC @0x00000024 // .. <bra_target> + 14: 78 90 00 0c BLT @0x00000024 // .. <bra_target> + 18: 78 b0 00 08 BGE @0x00000024 // .. <bra_target> + 1c: 78 a0 00 04 BV @0x00000024 // .. <bra_target> + 20: 06 7f ff ff LDI \$-1,R0 + +00000024 <bra_target>: + 24: 7f c0 00 00 NOOP diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_bratest.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_bratest.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_bratest.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_bratest.s 2017-01-09 10:28:54.983992877 -0500 @@ -0,0 +1,14 @@ + .text + +bra_insn_test: + bra bra_target + bz bra_target + bnz bra_target + bc bra_target + bnc bra_target + blt bra_target + bge bra_target + bv bra_target + ldi -1,r0 +bra_target: + noop diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_ctest.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_ctest.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_ctest.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_ctest.d 2017-01-16 11:02:02.344009430 -0500 @@ -0,0 +1,39 @@ +#as: +#objdump: -dr +#name: Conditional predicate test(s) + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <conditional_tests>: + 0: 00 80 00 01 ADD +\$1,R0 + 4: 00 88 00 01 ADD.Z +\$1,R0 + 8: 00 88 00 01 ADD.Z +\$1,R0 + c: 00 a8 00 01 ADD.NZ +\$1,R0 + 10: 00 a8 00 01 ADD.NZ +\$1,R0 + 14: 00 b0 00 01 ADD.GE +\$1,R0 + 18: 00 b0 00 01 ADD.GE +\$1,R0 + 1c: 00 90 00 01 ADD.LT +\$1,R0 + 20: 00 90 00 01 ADD.LT +\$1,R0 + 24: 00 a0 00 01 ADD.V +\$1,R0 + 28: 00 98 00 01 ADD.C +\$1,R0 + 2c: 00 98 00 01 ADD.C +\$1,R0 + 30: 00 b8 00 01 ADD.NC +\$1,R0 + 34: 00 b8 00 01 ADD.NC +\$1,R0 + 38: 00 80 00 01 ADD +\$1,R0 + 3c: 00 88 00 01 ADD.Z +\$1,R0 + 40: 28 8b ff e0 ADD.Z +\$-32,R5 + 44: 00 88 00 01 ADD.Z +\$1,R0 + 48: 00 a8 00 01 ADD.NZ +\$1,R0 + 4c: 00 a8 00 01 ADD.NZ +\$1,R0 + 50: 00 b0 00 01 ADD.GE +\$1,R0 + 54: 00 b0 00 01 ADD.GE +\$1,R0 + 58: 00 90 00 01 ADD.LT +\$1,R0 + 5c: 00 90 00 01 ADD.LT +\$1,R0 + 60: 00 a0 00 01 ADD.V +\$1,R0 + 64: 00 98 00 01 ADD.C +\$1,R0 + 68: 00 98 00 01 ADD.C +\$1,R0 + 6c: 00 b8 00 01 ADD.NC +\$1,R0 + 70: 00 b8 00 01 ADD.NC +\$1,R0 diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_ctest.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_ctest.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_ctest.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_ctest.s 2017-01-16 10:55:53.054697861 -0500 @@ -0,0 +1,34 @@ + .text + +conditional_tests: + add 1,R0 + add.z 1,R0 + add.eq 1,R0 + add.nz 1,R0 + add.ne 1,R0 + add.ge 1,R0 + add.gte 1,R0 + add.lt 1,R0 + add.n 1,R0 + add.v 1,R0 + add.c 1,R0 + add.ltu 1,R0 + add.nc 1,R0 + add.geu 1,R0 + ; + add 1,R0 + [z] add 1,R0 + [z] add -32,R5 + [EQ] add 1,R0 + [nz] add 1,R0 + [ne] add 1,R0 + [ge] add 1,R0 + [gte] add 1,R0 + [lt] add 1,R0 + [n] add 1,R0 + [v] add 1,R0 + [c] add 1,R0 + [ltu] add 1,R0 + [nc] add 1,R0 + [geu] add 1,R0 + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_lditest.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_lditest.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_lditest.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_lditest.d 2017-01-10 11:31:45.633275455 -0500 @@ -0,0 +1,24 @@ +#as: -nozipm +#objdump: -dr +#name: Load-Immediate test + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <ldi_insn_test>: + 0: 06 00 00 00 CLR +R0 + 4: 0a 08 00 00 CLR.Z +\$0,R1 + 8: 16 00 20 00 LDI +\$8192,R2 + c: 1a 08 00 00 LDI.Z +0x00002000,R3.* + 10: 1a 48 20 00 + 14: 22 29 ff ff LDI.NZ +0xffffe000,R4.* + 18: 22 68 e0 00 + 1c: 2a 03 fe 00 BREV +\$-512,R5 + 20: 32 00 01 ff LDI +0xff800001,R6.* + 24: 32 40 00 01 + 28: 3a 00 01 ff BREV +\$511,R7 + 2c: 42 03 fe ff BREV +\$-257,R8 + 30: 4a 01 fe ff LDI +0xff7ffffe,R9.* + 34: 4a 40 ff fe diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_lditest.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_lditest.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_lditest.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_lditest.s 2017-01-09 10:28:37.472119620 -0500 @@ -0,0 +1,13 @@ + .text + +ldi_insn_test: + ldi 0,R0 + ldi.z 0,r1 + ldi 8192,r2 + ldi.z 8192,r3 + ldi.nz -8192,r4 + ldi 8388607,r5 + ldi -8388607,r6 + ldi -8388608,r7 + ldi -8388609,r8 + ldi -8388610,r9 diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_mov.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_mov.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_mov.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_mov.d 2017-01-12 22:09:54.925246052 -0500 @@ -0,0 +1,86 @@ +#as: -novliw -nozipm +#objdump: -dr +#name: Mov instruction special test + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <mov_insn_test>: + 0: 0b 40 10 00 MOV +\$-4096\+R0,R1 + 4: 1b 40 90 01 MOV +\$-4095\+R2,R3 + 8: 2b 41 0f ff MOV +\$4095\+R4,R5 + c: 3b 41 80 00 MOV +R6,R7 + +00000010 <mov_to_user>: + 10: 0b 44 10 00 MOV +\$-4096\+R0,uR1 + 14: 1b 44 90 01 MOV +\$-4095\+R2,uR3 + 18: 2b 45 0f ff MOV +\$4095\+R4,uR5 + 1c: 3b 45 80 00 MOV +R6,uR7 + +00000020 <mov_from_user>: + 20: 0b 40 30 00 MOV +\$-4096\+uR0,R1 + 24: 1b 40 b0 01 MOV +\$-4095\+uR2,R3 + 28: 2b 41 2f ff MOV +\$4095\+uR4,R5 + 2c: 3b 41 a0 00 MOV +uR6,R7 + +00000030 <mov_user_to_user>: + 30: 0b 44 30 00 MOV +\$-4096\+uR0,uR1 + 34: 1b 44 b0 01 MOV +\$-4095\+uR2,uR3 + 38: 2b 45 2f ff MOV +\$4095\+uR4,uR5 + 3c: 3b 45 a0 00 MOV +uR6,uR7 + +00000040 <move_from_upc>: + 40: 0b 47 f0 00 MOV +\$-4096\+uPC,uR1 + 44: 1b 47 f0 01 MOV +\$-4095\+uPC,uR3 + 48: 2b 47 ef ff MOV +\$4095\+uPC,uR5 + 4c: 3b 47 e0 00 MOV +uPC,uR7 + +00000050 <move_from_usp>: + 50: 0b 47 70 00 MOV +\$-4096\+uSP,uR1 + 54: 1b 47 70 01 MOV +\$-4095\+uSP,uR3 + 58: 2b 47 6f ff MOV +\$4095\+uSP,uR5 + 5c: 3b 47 60 00 MOV +uSP,uR7 + +00000060 <move_from_ucc>: + 60: 0b 47 b0 00 MOV +\$-4096\+uCC,uR1 + 64: 1b 47 b0 01 MOV +\$-4095\+uCC,uR3 + 68: 2b 47 af ff MOV +\$4095\+uCC,uR5 + 6c: 3b 47 a0 00 MOV +uCC,uR7 + +00000070 <move_to_upc>: + 70: 7b 44 10 00 MOV +\$-4096\+R0,uPC + 74: 7b 44 90 01 MOV +\$-4095\+R2,uPC + 78: 7b 45 0f ff MOV +\$4095\+R4,uPC + 7c: 7b 45 80 00 MOV +R6,uPC + +00000080 <move_to_usp>: + 80: 6b 44 10 00 MOV +\$-4096\+R0,uSP + 84: 6b 44 90 01 MOV +\$-4095\+R2,uSP + 88: 6b 45 0f ff MOV +\$4095\+R4,uSP + 8c: 6b 45 80 00 MOV +R6,uSP + +00000090 <move_to_ucc>: + 90: 73 44 10 00 MOV +\$-4096\+R0,uCC + 94: 73 44 90 01 MOV +\$-4095\+R2,uCC + 98: 73 45 0f ff MOV +\$4095\+R4,uCC + 9c: 73 45 80 00 MOV +R6,uCC + +000000a0 <move_to_pc>: + a0: 7b 40 10 00 JMP +\$-4096\+R0 + a4: 7b 40 90 01 JMP +\$-4095\+R2 + a8: 7b 41 0f ff JMP +\$4095\+R4 + ac: 7b 41 80 00 JMP +R6 + +000000b0 <move_to_sp>: + b0: 6b 40 10 00 MOV +\$-4096\+R0,SP + b4: 6b 40 90 01 MOV +\$-4095\+R2,SP + b8: 6b 41 0f ff MOV +\$4095\+R4,SP + bc: 6b 41 80 00 MOV +R6,SP + +000000c0 <move_to_cc>: + c0: 73 40 10 00 MOV +\$-4096\+R0,CC + c4: 73 40 90 01 MOV +\$-4095\+R2,CC + c8: 73 41 0f ff MOV +\$4095\+R4,CC + cc: 73 41 80 00 MOV +R6,CC diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_mov.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_mov.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_mov.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_mov.s 2017-01-12 16:45:17.027962005 -0500 @@ -0,0 +1,93 @@ + .text + +mov_insn_test: + mov -4096+R0,R1 + mov -4095+R2,R3 + mov 4095+R4,R5 + mov R6,R7 + ; +mov_to_user: + ; + mov -4096+R0,uR1 + mov -4095+R2,uR3 + mov 4095+R4,uR5 + mov R6,uR7 + ; +mov_from_user: + ; + mov -4096+uR0,R1 + mov -4095+uR2,R3 + mov 4095+uR4,R5 + mov uR6,R7 + ; +mov_user_to_user: + ; + mov -4096+uR0,uR1 + mov -4095+uR2,uR3 + mov 4095+uR4,uR5 + mov uR6,uR7 + ; + ; +move_from_upc: + ; + mov -4096+upc,uR1 + mov -4095+upc,uR3 + mov 4095+upc,uR5 + mov upc,uR7 + ; +move_from_usp: + ; + mov -4096+usp,uR1 + mov -4095+usp,uR3 + mov 4095+usp,uR5 + mov usp,uR7 + ; +move_from_ucc: + ; + mov -4096+ucc,uR1 + mov -4095+ucc,uR3 + mov 4095+ucc,uR5 + mov ucc,uR7 + ; +move_to_upc: + ; + mov -4096+r0,upc + mov -4095+r2,upc + mov 4095+r4,upc + mov r6,upc + ; +move_to_usp: + ; + mov -4096+r0,usp + mov -4095+r2,usp + mov 4095+r4,usp + mov r6,usp + ; +move_to_ucc: + ; + mov -4096+r0,ucc + mov -4095+r2,ucc + mov 4095+r4,ucc + mov r6,ucc + ; +move_to_pc: + ; + mov -4096+r0,pc + mov -4095+r2,pc + mov 4095+r4,pc + mov r6,pc + ; +move_to_sp: + ; + mov -4096+r0,sp + mov -4095+r2,sp + mov 4095+r4,sp + mov r6,sp + ; +move_to_cc: + ; + mov -4096+r0,cc + mov -4095+r2,cc + mov 4095+r4,cc + mov r6,cc + ; diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_optest.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_optest.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_optest.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_optest.d 2017-01-12 22:12:11.497444662 -0500 @@ -0,0 +1,98 @@ +#as: -novliw -nozipm +#objdump: -dr +#name: OpCode generation test + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <optest>: + 0: 00 00 00 04 SUB +\$4,R0 + 4: 08 40 00 04 AND +\$4,R1 + 8: 10 80 00 04 ADD +\$4,R2 + c: 19 00 00 04 XOR +\$4,R3 + 10: 20 c0 00 04 OR +\$4,R4 + 14: 29 40 00 04 LSR +\$4,R5 + 18: 31 80 00 04 LSL +\$4,R6 + 1c: 39 c0 00 04 ASR +\$4,R7 + 20: 02 40 00 03 LDILO +\$3,R0 + 24: 0a 00 00 02 BREV +\$2,R1 + 28: 12 80 00 03 MPYUHI +\$3,R2 + 2c: 1a c0 00 03 MPYSHI +\$3,R3 + 30: 23 00 00 03 MPY +\$3,R4 + 34: 2b 80 00 07 DIVU +\$7,R5 + 38: 33 c0 00 09 DIVS +\$9,R6 + 3c: 04 00 00 05 CMP +\$5,R0 + 40: 0c 40 00 05 TST +\$5,R1 + 44: 1c 43 ff ff TST +\$-1,R3 + 48: 24 43 ff ff TST +\$-1,R4 + 4c: 14 40 00 04 TST +\$4,R2 + 50: 0d 84 00 04 LB +4\(R0\),R1 + 54: 15 c4 40 04 SB +R2,\$4\(R1\) + 58: 1d 04 80 04 LH +4\(R2\),R3 + 5c: 25 44 c0 04 SH +R4,\$4\(R3\) + 60: 2c 85 00 04 LW +4\(R4\),R5 + 64: 34 c5 40 04 SW +R6,\$4\(R5\) + 68: 17 80 00 07 FPI2F +\$7,R2 + 6c: 17 84 40 03 FPI2F +\$3\+R1,R2 + 70: 16 84 c0 00 FPADD +R3,R2 + 74: 27 05 c0 00 FPMPY +R7,R4 + 78: 4f 45 80 00 FPDIV +R6,R9 + 7c: 57 c6 00 00 FPF2I +R8,R10 + 80: 00 07 00 07 SUB +\$7\+R12,R0 + 84: 08 47 00 07 AND +\$7\+R12,R1 + 88: 10 87 00 07 ADD +\$7\+R12,R2 + 8c: 19 07 00 07 XOR +\$7\+R12,R3 + 90: 20 c7 00 07 OR +\$7\+R12,R4 + 94: 29 47 00 07 LSR +\$7\+R12,R5 + 98: 31 87 00 07 LSL +\$7\+R12,R6 + 9c: 39 c7 00 07 ASR +\$7\+R12,R7 + a0: 00 07 3f fd SUB +\$-3\+R12,R0 + a4: 08 47 3f fd AND +\$-3\+R12,R1 + a8: 10 87 3f fd ADD +\$-3\+R12,R2 + ac: 19 07 3f fd XOR +\$-3\+R12,R3 + b0: 20 c7 3f fd OR +\$-3\+R12,R4 + b4: 29 47 3f fd LSR +\$-3\+R12,R5 + b8: 31 87 3f fd LSL +\$-3\+R12,R6 + bc: 39 c7 3f fd ASR +\$-3\+R12,R7 + c0: 02 47 01 66 LDILO +\$358\+R12,R0 + c4: 0a 04 7e 9a BREV +\$-358\+R1,R1 + c8: 12 84 7e 9a MPYUHI +\$-358\+R1,R2 + cc: 1a c4 7e 9a MPYSHI +\$-358\+R1,R3 + d0: 23 04 7e 9a MPY +\$-358\+R1,R4 + d4: 2b 84 7e 9a DIVU +\$-358\+R1,R5 + d8: 33 c4 7e 9a DIVS +\$-358\+R1,R6 + dc: 04 04 bf ed CMP +\$-19\+R2,R0 + e0: 0c 44 bf ed TST +\$-19\+R2,R1 + e4: 0d 80 01 04 LB +\(\$260\),R1 + e8: 15 c0 01 06 SB +R2,\(\$262\) + ec: 1d 00 01 10 LH +\(\$272\),R3 + f0: 25 40 01 12 SH +R4,\(\$274\) + f4: 2c 80 01 19 LW +\(\$281\),R5 + f8: 34 c0 01 ab SW +R6,\(\$427\) + fc: 00 02 00 00 SUB +\$-131072,R0 + 100: 00 02 00 00 SUB +\$-131072,R0 + 104: 08 42 00 00 AND +\$-131072,R1 + 108: 10 82 00 00 ADD +\$-131072,R2 + 10c: 19 02 00 00 XOR +\$-131072,R3 + 110: 20 c2 00 00 OR +\$-131072,R4 + 114: 29 42 00 00 LSR +\$-131072,R5 + 118: 31 82 00 00 LSL +\$-131072,R6 + 11c: 39 c2 00 00 ASR +\$-131072,R7 + 120: 02 40 14 85 LDILO +\$5253,R0 + 124: 0a 02 00 00 BREV +\$-131072,R1 + 128: 12 82 00 00 MPYUHI +\$-131072,R2 + 12c: 1a c2 00 00 MPYSHI +\$-131072,R3 + 130: 23 02 00 00 MPY +\$-131072,R4 + 134: 2b 82 00 00 DIVU +\$-131072,R5 + 138: 33 c2 00 00 DIVS +\$-131072,R6 + 13c: 04 02 00 00 CMP +\$-131072,R0 + 140: 0c 42 00 00 TST +\$-131072,R1 + 144: 0d 82 00 00 LB +\(\$-131072\),R1 + 148: 15 c2 00 00 SB +R2,\(\$-131072\) + 14c: 1d 02 00 00 LH +\(\$-131072\),R3 + 150: 25 42 00 00 SH +R4,\(\$-131072\) + 154: 2c 82 00 00 LW +\(\$-131072\),R5 + 158: 34 c2 00 00 SW +R6,\(\$-131072\) + 15c: 17 82 00 00 FPI2F +\$-131072,R2 diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_optest.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_optest.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_optest.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_optest.s 2017-01-12 16:28:47.212542071 -0500 @@ -0,0 +1,119 @@ + .text + +optest: + sub 4,R0 + and 4,R1 + add 4,R2 + xor 4,R3 + or 4,R4 + lsr 4,R5 + lsl 4,R6 + asr 4,R7 + ; + ldilo 3,R0 + brev 2,R1 + mpyuhi 3,R2 + mpyshi 3,R3 + mpy 3,R4 + divu 7,R5 + divs 9,r6 + ; mov R1,R2 + + ; + cmp 5,R0 + test 5,R1 + test R3 + tst R4 + tst 4,R2 + ; + lb 4(r0),r1 + sb r2,4(r1) + lh 4(r2),r3 + sh r4,4(r3) + lw 4(r4),r5 + sw r6,4(r5) + ; ldi + fpi2f 7,r2 + fpi2f 3(r1),r2 + fpadd r3,r2 + ; fpmpy r7,r4 + fpmul r7,r4 + fpdiv r6,r9 + fpf2i r8,r10 + ; + ; +; Now repeat, with Reg + Imm + sub 7(r12),R0 + and 7(r12),R1 + add 7(r12),R2 + xor 7(r12),R3 + or 7(r12),R4 + lsr 7(r12),R5 + lsl 7(r12),R6 + asr 7(r12),R7 + ; + sub -3+r12,R0 + and -3+r12,R1 + add -3+r12,R2 + xor -3+r12,R3 + or -3+r12,R4 + lsr -3+r12,R5 + lsl -3+r12,R6 + asr -3+r12,R7 + ; + ldilo 358+r12,R0 + brev -358+r1,R1 + mpyuhi -358+r1,R2 + mpyshi -358+r1,R3 + mpy -358+r1,R4 + divu -358+r1,R5 + divs -358+r1,r6 + ; mov R1,R2 + + ; + cmp -19+r2,R0 + test -19+r2,R1 + ; + lb 0x104,r1 + sb r2,0x106 + lh 0x110,r3 + sh r4,0x112 + lw 0x119,r5 + sw r6,0x1ab + ; ldi + ; floating point --- already done + + +; Ops with the minimum integer + sub -0x20000,R0 + sub -131072,R0 + and -131072,R1 + add -131072,R2 + xor -0x20000,R3 + or -131072,R4 + lsr -131072,R5 + lsl -131072,R6 + asr -131072,R7 + ; + ldilo 0x21485,R0 + brev -0x20000,R1 + mpyuhi -0x20000,R2 + mpyshi -0x20000,R3 + mpy -0x20000,R4 + divu -0x20000,R5 + divs -0x20000,r6 + ; mov R1,R2 + + ; + cmp -0x20000,R0 + test -0x20000,R1 + ; + lb -0x20000,r1 + sb r2,-0x20000 + lh -0x20000,r3 + sh r4,-0x20000 + lw -0x20000,r5 + sw r6,-0x20000 + ; ldi + fpi2f -0x20000,r2 + ; diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologue.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologue.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologue.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologue.d 2017-01-10 11:09:36.301473902 -0500 @@ -0,0 +1,32 @@ +#as: -novliw +#objdump: -dr +#name: Prologue test - Non-thumb + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <some_function>: + 0: 68 00 00 30 SUB +\$48,SP + 4: 04 c7 40 00 SW +R0,\(SP\) + 8: 2c c7 40 04 SW +R5,\$4\(SP\) + c: 34 c7 40 08 SW +R6,\$8\(SP\) + 10: 3c c7 40 0c SW +R7,\$12\(SP\) + 14: 44 c7 40 10 SW +R8,\$16\(SP\) + 18: 4c c7 40 14 SW +R9,\$20\(SP\) + 1c: 54 c7 40 18 SW +R10,\$24\(SP\) + 20: 5c c7 40 1c SW +R11,\$28\(SP\) + 24: 64 c7 40 20 SW +R12,\$32\(SP\) + 28: 38 84 80 00 ADD +R2,R7 + 2c: 04 87 40 00 LW +\(SP\),R0 + 30: 04 87 40 04 LW +4\(SP\),R0 + 34: 04 87 40 08 LW +8\(SP\),R0 + 38: 04 87 40 0c LW +12\(SP\),R0 + 3c: 04 87 40 10 LW +16\(SP\),R0 + 40: 04 87 40 14 LW +20\(SP\),R0 + 44: 04 87 40 18 LW +24\(SP\),R0 + 48: 04 87 40 1c LW +28\(SP\),R0 + 4c: 04 87 40 20 LW +32\(SP\),R0 + 50: 68 80 00 30 ADD +\$48,SP + 54: 7b 40 00 00 RTN + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologue.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologue.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologue.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologue.s 2017-01-09 07:25:40.495644200 -0500 @@ -0,0 +1,24 @@ +some_function: + SUB 48,SP + SW R0,(SP) + SW R5,4(SP) + SW R6,8(SP) + SW R7,12(SP) + SW R8,16(SP) + SW R9,20(SP) + SW R10,24(SP) + SW R11,28(SP) + SW R12,32(SP) + ADD R2,R7 + LW (SP),R0 + LW 4(SP),R0 + LW 8(SP),R0 + LW 12(SP),R0 + LW 16(SP),R0 + LW 20(SP),R0 + LW 24(SP),R0 + LW 28(SP),R0 + LW 32(SP),R0 + ADD 48,SP + RETN + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologuev.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologuev.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologuev.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologuev.d 2017-01-12 21:58:59.513900839 -0500 @@ -0,0 +1,21 @@ +#as: -nozipm -vliw +#objdump: -dr +#name: Prologue test - thumb + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <some_function>: + 0: e8 30 85 00 SUB +\$48,SP +| SW +R0,\(SP\) + 4: ad 04 b5 08 SW +R5,\$4\(SP\) +| SW +R6,$8\(SP\) + 8: bd 0c c5 10 SW +R7,\$12\(SP\) +| SW +R8,$16\(SP\) + c: cd 14 d5 18 SW +R9,\$20\(SP\) +| SW +R10,$24\(SP\) + 10: dd 1c e5 20 SW +R11,\$28\(SP\) +| SW +R12,$32\(SP\) + 14: ba 90 84 00 ADD +R2,R7 +| LW +\(SP\),R0 + 18: 84 04 84 08 LW +4\(SP\),R0 +| LW +8\(SP\),R0 + 1c: 84 0c 84 10 LW +12\(SP\),R0 +| LW +16\(SP\),R0 + 20: 84 14 84 18 LW +20\(SP\),R0 +| LW +24\(SP\),R0 + 24: 84 1c 84 20 LW +28\(SP\),R0 +| LW +32\(SP\),R0 + 28: ea 30 ff 80 ADD +\$48,SP +| MOV +R0,PC diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologuev.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologuev.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_prologuev.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_prologuev.s 2017-01-10 11:29:18.612449601 -0500 @@ -0,0 +1,24 @@ +some_function: + SUB 48,SP + SW R0,(SP) + SW R5,4(SP) + SW R6,8(SP) + SW R7,12(SP) + SW R8,16(SP) + SW R9,20(SP) + SW R10,24(SP) + SW R11,28(SP) + SW R12,32(SP) + ADD R2,R7 + LW (SP),R0 + LW 4(SP),R0 + LW 8(SP),R0 + LW 12(SP),R0 + LW 16(SP),R0 + LW 20(SP),R0 + LW 24(SP),R0 + LW 28(SP),R0 + LW 32(SP),R0 + ADD 48,SP + RETN + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_specials.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_specials.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_specials.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_specials.d 2017-01-24 08:03:32.892847657 -0500 @@ -0,0 +1,41 @@ +#as: +#objdump: -dr +#name: Special instruction(s) test + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <specials_test>: + 0: 7f 00 00 00 BRK + 4: 7f 00 00 11 BRK \$17 + 8: 7f c0 00 00 NOOP + c: 7f c0 02 ff NDUMP *$ + 10: 7f c0 02 07 NDUMP R7 + 14: 7f c0 02 03 NDUMP R3 + 18: 7f c0 02 14 NDUMP uR4 + 1c: 7f c0 01 00 NEXIT + 20: 7f c0 01 00 NEXIT + 24: 7f c0 01 fc NEXIT \$-4 + 28: 7f c0 01 f0 NEXIT \$-16 + 2c: 7f c0 03 07 NEXIT R7 + 30: 7f c4 00 23 NSIM \$262179 + 34: 7f 80 00 00 SIM +$ + 38: 7f 80 02 ff SDUMP *$ + 3c: 7f 80 02 07 SDUMP R7 + 40: 7f 80 02 03 SDUMP R3 + 44: 7f 80 02 14 SDUMP uR4 + 48: 7f 80 01 17 SEXIT \$23 + 4c: 7f 80 01 e9 SEXIT \$-23 + 50: 7f 80 01 00 SEXIT + 54: 7f 80 03 0f SEXIT PC + 58: 7f 80 03 0e SEXIT CC + 5c: 7f 84 00 23 SIM \$262179 + 60: 7f 87 0f 23 SIM \$462627 + 64: 7f 80 04 61 SOUT \$97 + 68: 7f c0 04 62 NOUT \$98 + 6c: 7f 80 02 22 SOUT R2 + 70: 7f c0 02 27 NOUT R7 + 74: 7f 80 02 33 SOUT uR3 + 78: 7f c0 02 38 NOUT uR8 diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_specials.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_specials.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_specials.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_specials.s 2017-01-19 07:18:13.405003668 -0500 @@ -0,0 +1,35 @@ + .text + +specials_test: + break + break 17 + noop + ndump + ndump R7 + ndump sR3 + ndump uR4 + nexit + nexit 0 + nexit -4 + nexit 240 + nexit R7 + noop 0x40023 + snoop + sdump + sdump R7 + sdump sR3 + sdump uR4 + sexit 23 + sexit -23 + sexit 0 + sexit PC + sexit CC + snoop 0x40023 + sim 0x70f23 + sout 'a' + nout 'b' + sout R2 + nout R7 + sout uR3 + nout uR8 + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_vliw.d binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_vliw.d --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_vliw.d 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_vliw.d 2017-01-12 21:50:28.719237156 -0500 @@ -0,0 +1,77 @@ +#as: -vliw +#objdump: -dr +#name: Thumb instruction set test + +.*: +file format elf32-zip + + +Disassembly of section .text: + +00000000 <vliw_merge_test>: + 0: 82 01 8a 01 ADD +\$1,R0 +| ADD +$1,R1 + 4: 10 88 00 01 ADD.Z +\$1,R2 + 8: 18 a8 00 01 ADD.NZ +\$1,R3 + c: 20 a0 00 01 ADD.V +\$1,R4 + 10: 00 80 00 7f ADD +\$127,R0 + 14: 00 80 00 80 ADD +\$128,R0 + 18: 00 80 00 81 ADD +\$129,R0 + 1c: 82 3e 82 3f ADD +\$62,R0 +| ADD +\$63,R0 * + 20: 00 80 00 40 ADD +\$64,R0 + 24: 00 80 00 41 ADD +\$65,R0 + 28: 82 88 82 89 ADD +R1,R0 +| ADD +\$1+R1,R0 * + 2c: 82 89 82 8a ADD +\$1\+R1,R0 +| ADD +\$2\+R1,R0 * + 30: 82 8a 82 8a ADD +\$2\+R1,R0 +| ADD +\$2\+R1,R0 * + 34: 00 84 40 03 ADD +\$3\+R1,R0 + 38: 00 84 40 04 ADD +\$4\+R1,R0 + 3c: 00 84 40 05 ADD +\$5\+R1,R0 + 40: 00 84 7f fb ADD +\$-5\+R1,R0 + 44: 82 8c 82 8d ADD +\$-4\+R1,R0 +| ADD +$-3+R1,R0 * + 48: 82 8e 82 8f ADD +\$-2\+R1,R0 +| ADD +$-1+R1,R0 * + 4c: 82 88 84 88 ADD +R1,R0 +| LW +(R1),R0 * + 50: 94 89 9c 8a LW +1\(R1\),R2 +| LW +2(R1),R3 * + 54: 24 84 40 03 LW +3\(R1\),R4 + 58: 2c 84 40 04 LW +4\(R1\),R5 + 5c: 84 00 94 01 LW +\(SP\),R0 +| LW +1\(SP\),R2 * + 60: 9c 02 a4 03 LW +2\(SP\),R3 +| LW +3\(SP\),R4 * + 64: ac 04 b4 3d LW +4\(SP\),R5 +| LW +61\(SP\),R6 * + 68: bc 3e c4 3f LW +62\(SP\),R7 +| LW +63\(SP\),R8 * + 6c: 4c 87 40 40 LW +64\(SP\),R9 + 70: 54 87 40 41 LW +65\(SP\),R10 + 74: 54 c7 7f bf SW +R10,\$-65\(SP\) + 78: cd 40 c5 41 SW +R9,\$-64\(SP\) +| SW +R8,$-63\(SP\) * + 7c: bd 42 b5 43 SW +R7,\$-62\(SP\) +| SW +R6,$-61\(SP\) * + 80: b5 44 87 f8 SW +R6,\$-60\(SP\) +| MOV +PC,R0 * + 84: 8f f9 97 fa MOV +\$4\+PC,R1 +| MOV +$8\+PC,R2 * + 88: 97 fa 9f fb MOV +\$8\+PC,R2 +| MOV +$12\+PC,R3 * + 8c: 23 43 c0 04 MOV +0x000000a0,R4.*$ + 90: 2b 43 c0 05 MOV +0x000000a8,R5.*$ + 94: 33 43 df fb MOV +0x00000084,R6.*$ + 98: bf fc c7 fd MOV +\$-16\+PC,R7 +| MOV +$-12\+PC,R8 * + 9c: cf fe 87 ff MOV +\$-8\+PC,R9 +| MOV +$-4\+PC,R0 * + a0: 13 43 c0 00 MOV +0x000000a4,R2.*$ + +000000a4 <vliw_ldi_test>: + a4: 86 00 8e 40 CLR +R0 +| LDI +\$64,R1 + a8: 16 00 00 7f LDI +\$127,R2 + ac: 1e 00 00 80 LDI +\$128,R3 + b0: 26 00 00 81 LDI +\$129,R4 + b4: 2e 00 00 82 LDI +\$130,R5 + b8: 36 7f ff 7e LDI +\$-130,R6 + bc: 3e 7f ff 7f LDI +\$-129,R7 + c0: c6 80 ce 81 LDI +\$-128,R8 +| LDI +\$-127,R9 + c4: d6 82 de 83 LDI +\$-126,R10 +| LDI +\$-125,R11 + +000000c8 <vliw_op_test>: + c8: 88 80 99 90 SUB +R0,R1 +| AND +R2,R3 *$ + cc: aa a0 bb b0 ADD +R4,R5 +| CMP +R6,uR7 *$ + d0: c4 b8 cd d0 LW +\(R7\),R8 +| SW +R9,\$-48\(SP\) *$ + d4: de 7c 9f 89 LDI +\$124,R11 +| MOV +$1+R1,R3 *$ + d8: c8 05 88 80 SUB +\$5,R9 +| SUB +R0,R1 *$ + dc: 99 90 aa a0 AND +R2,R3 +| ADD +R4,R5 *$ + e0: bb b0 c4 b8 CMP +R6,uR7 +| LW +(R7),R8 *$ + e4: cd d0 de 7c SW +R9,\$-48\(SP\) +| LDI +\$124,R11 *$ + e8: 9f 89 c8 0e MOV +\$1\+R1,R3 +| SUB +\$14,R9 *$ + ec: 99 11 aa 13 AND +\$17,R3 +| ADD +\$19,R5 *$ + f0: bb 3f c4 18 CMP +\$63\+R7,R7 +| LW 24\(SP\),R8 *$ + f4: cd 1c de 7c SW +R9,\$28\(SP\) +| LDI +\$124,R11 *$ + f8: 1b 40 40 01 MOV +\$1\+R1,R3 diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_vliw.s binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_vliw.s --- binutils-2.27-original/gas/testsuite/gas/zip/zip_insn_vliw.s 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/gas/testsuite/gas/zip/zip_insn_vliw.s 2017-01-12 16:55:54.690241718 -0500 @@ -0,0 +1,110 @@ + .text + +vliw_merge_test: + ; Simple: are merges enabled? + add 1,R0 + add 1,R1 + ; These should not merge with any neighbor + add.z 1,R2 + add.nz 1,R3 + add.v 1,R4 + add 127,R0 + add 128,R0 + add 129,R0 + add 62,R0 + add 63,R0 + add 64,R0 + add 65,R0 + add 0(R1),R0 + add 1(R1),R0 + add 1(R1),R0 + add 2(R1),R0 + add 2(R1),R0 + add 2(R1),R0 + add 3(R1),R0 + add 4(R1),R0 + add 5(R1),R0 + add -5(R1),R0 + add -4(R1),R0 + add -3(R1),R0 + add -2(R1),R0 + add -1(R1),R0 + add 0(R1),R0 + lw (r1),r0 + lw 1(r1),r2 + lw 2(r1),r3 + lw 3(r1),r4 + lw 4(r1),r5 + lw (sp),r0 + lw 1(sp),r2 + lw 2(sp),r3 + lw 3(sp),r4 + lw 4(sp),r5 + lw 61(sp),r6 + lw 62(sp),r7 + lw 63(sp),r8 + lw 64(sp),r9 + lw 65(sp),r10 + sw r10,-65(sp) + sw r9,-64(sp) + sw r8,-63(sp) + sw r7,-62(sp) + sw r6,-61(sp) + sw r6,-60(sp) + mov (PC),R0 + mov 1(PC),R1 + mov 2(PC),R2 + mov 2(PC),R2 + mov 3(PC),R3 + mov 4(PC),R4 + mov 5(PC),R5 + mov -5(PC),R6 + mov -4(PC),R7 + mov -3(PC),R8 + mov -2(PC),R9 + mov -1(PC),R0 + mov 0(PC),R2 + # LDI's +vliw_ldi_test: + LDI 0,R0 + LDI 64,R1 + LDI 127,R2 + LDI 128,R3 + LDI 129,R4 + LDI 130,R5 + LDI -130,R6 + LDI -129,R7 + LDI -128,R8 + LDI -127,R9 + LDI -126,R10 + LDI -125,R11 +vliw_op_test: + sub r0,r1 + and r2,r3 + add r4,r5 + cmp r6,r7 + lw (r7),r8 + sw r9,(r10) + ldi 124,r11 + mov 1+r1,r3 + # and with a touch of offset + sub 5,r9 + sub r0,r1 + and r2,r3 + add r4,r5 + cmp r6,r7 + lw (r7),r8 + sw r9,(r10) + ldi 124,r11 + mov 1+r1,r3 + # And now, so that they all have immediates instead of register + sub 14,r9 + and 17,r3 + add 19,r5 + cmp 63,r7 + lw 24(sp),r8 + sw r9,28(sp) + ldi 124,r11 + mov 1+r1,r3 + + diff -Naur '--exclude=*.swp' binutils-2.27-original/gas/write.c binutils-2.27-zip/gas/write.c --- binutils-2.27-original/gas/write.c 2016-08-03 03:36:51.000000000 -0400 +++ binutils-2.27-zip/gas/write.c 2016-12-31 17:51:52.470985149 -0500 @@ -2676,7 +2676,7 @@ case rs_org: { - addressT target = offset; + addressT target = offset * OCTETS_PER_BYTE; addressT after; if (symbolP) diff -Naur '--exclude=*.swp' binutils-2.27-original/include/dis-asm.h binutils-2.27-zip/include/dis-asm.h --- binutils-2.27-original/include/dis-asm.h 2016-08-03 03:36:53.000000000 -0400 +++ binutils-2.27-zip/include/dis-asm.h 2016-12-31 17:52:29.022758231 -0500 @@ -318,10 +318,12 @@ extern int print_insn_rl78_g10 (bfd_vma, disassemble_info *); extern int print_insn_rl78_g13 (bfd_vma, disassemble_info *); extern int print_insn_rl78_g14 (bfd_vma, disassemble_info *); +extern int print_insn_zip (bfd_vma, disassemble_info *); extern disassembler_ftype arc_get_disassembler (bfd *); extern disassembler_ftype cris_get_disassembler (bfd *); extern disassembler_ftype rl78_get_disassembler (bfd *); +extern disassembler_ftype zip_get_disassembler (bfd *); extern void print_aarch64_disassembler_options (FILE *); extern void print_i386_disassembler_options (FILE *); diff -Naur '--exclude=*.swp' binutils-2.27-original/include/elf/common.h binutils-2.27-zip/include/elf/common.h --- binutils-2.27-original/include/elf/common.h 2016-08-03 03:36:53.000000000 -0400 +++ binutils-2.27-zip/include/elf/common.h 2016-12-31 17:53:58.942198950 -0500 @@ -411,6 +411,9 @@ /* Old constant that might be in use by some software. */ #define EM_OPENRISC EM_OR1K +/* ZipCPU vs instruction set -- Use this until we get an official number */ +#define EM_ZIP 0xdad1 + /* See the above comment before you add a new EM_* value here. */ /* Values for e_version. */ diff -Naur '--exclude=*.swp' binutils-2.27-original/include/elf/zip.h binutils-2.27-zip/include/elf/zip.h --- binutils-2.27-original/include/elf/zip.h 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/include/elf/zip.h 2017-01-18 18:19:33.764898333 -0500 @@ -0,0 +1,58 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: zip.h +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016-2017, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef _ELF_ZIP_H +#define _ELF_ZIP_H + +#include "elf/reloc-macros.h" + +/* Relocations. */ +START_RELOC_NUMBERS(elf_zip_reloc_type) + RELOC_NUMBER (R_ZIP_NONE, 0) + RELOC_NUMBER (R_ZIP_VALUE, 1) + RELOC_NUMBER (R_ZIP_BREV, 2) + RELOC_NUMBER (R_ZIP_LLO, 3) + RELOC_NUMBER (R_ZIP_LDI, 4) + RELOC_NUMBER (R_ZIP_BRANCH, 5) + RELOC_NUMBER (R_ZIP_OPB_IMM, 6) + RELOC_NUMBER (R_ZIP_OPB_OFFSET, 7) + RELOC_NUMBER (R_ZIP_OPB_PCREL, 8) + RELOC_NUMBER (R_ZIP_MOV_OFFSET, 9) + RELOC_NUMBER (R_ZIP_MOV_PCREL, 10) + // RELOC_NUMBER (R_ZIP_OPB_GOTREL, 11) + // RELOC_NUMBER (R_ZIP_MOV_GOTREL, 12) +END_RELOC_NUMBERS(R_ZIP_max) + +#endif /* _ELF_ZIP_H */ diff -Naur '--exclude=*.swp' binutils-2.27-original/ld/configure.tgt binutils-2.27-zip/ld/configure.tgt --- binutils-2.27-original/ld/configure.tgt 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/ld/configure.tgt 2016-12-31 17:55:04.013793303 -0500 @@ -816,6 +816,8 @@ ;; z8k-*-coff) targ_emul=z8002; targ_extra_emuls=z8001 ;; +zip*) targ_emul=elf32zip; + ;; *-*-ieee*) targ_emul=vanilla ;; *-tandem-none) targ_emul=st2000 diff -Naur '--exclude=*.swp' binutils-2.27-original/ld/emulparams/elf32zip.sh binutils-2.27-zip/ld/emulparams/elf32zip.sh --- binutils-2.27-original/ld/emulparams/elf32zip.sh 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/ld/emulparams/elf32zip.sh 2017-01-05 08:22:45.000000000 -0500 @@ -0,0 +1,50 @@ +################################################################################ +# +# Filename: elf32zip.sh +# +# Project: Zip CPU backend for GNU Binutils +# +# Purpose: This is a simple shell script providing some variables used +# later and elsewhere by the ZipCPU linker. Some things to note +# are: 1) the TEXT_START_ADDR is set for the Basys-3 board I am using and +# will likely need to change as your platform changes, 2) there currently +# aren't any "pages" since the ZipCPU doesn't yet support a memory +# management unit, 3) the ENTRY point only works if a separate loader +# is loading the ZipCPU into RAM. In all other cases, place your startup +# code directly at the top of the .start segment, and set the ZipCPU +# to run from there. It'll start then at the first address loaded in +# memory. +# +# Creator: Dan Gisselquist, Ph.D. +# Gisselquist Technology, LLC +# +################################################################################ +# +# Copyright (C) 2016, Gisselquist Technology, LLC +# +# This program is free software (firmware): you can redistribute it and/or +# modify it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# License: GPL, v3, as defined and found on www.gnu.org, +# http://www.gnu.org/licenses/gpl.html +# +# +################################################################################ + +SCRIPT_NAME=elf +TEMPLATE_NAME=elf32 +ARCH=zip +OUTPUT_FORMAT="elf32-zip" +ENTRY="_start" +TEXT_START_ADDR="0x08000" +MAXPAGESIZE=0x01000 +COMMONPAGESIZE=0x1000 +EMBEDDED=yes + diff -Naur '--exclude=*.swp' binutils-2.27-original/ld/Makefile.am binutils-2.27-zip/ld/Makefile.am --- binutils-2.27-original/ld/Makefile.am 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/ld/Makefile.am 2016-12-31 17:57:39.684819835 -0500 @@ -286,6 +286,7 @@ eelf32xc16xs.c \ eelf32xstormy16.c \ eelf32xtensa.c \ + eelf32zip.c \ eelf_i386.c \ eelf_i386_be.c \ eelf_i386_chaos.c \ @@ -1309,6 +1310,9 @@ $(BFDDIR)/elf-bfd.h $(BFDDIR)/libbfd.h $(INCDIR)/elf/xtensa.h \ $(srcdir)/scripttempl/elfxtensa.sc ${GEN_DEPENDS} +eelf32zip.c: $(srcdir)/emulparams/elf32zip.sh $(ELF_DEPS) \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + eelf_i386.c: $(srcdir)/emulparams/elf_i386.sh \ $(ELF_X86_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} diff -Naur '--exclude=*.swp' binutils-2.27-original/ld/Makefile.in binutils-2.27-zip/ld/Makefile.in --- binutils-2.27-original/ld/Makefile.in 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/ld/Makefile.in 2016-12-31 17:59:30.788122513 -0500 @@ -654,6 +654,7 @@ eelf32xc16xs.c \ eelf32xstormy16.c \ eelf32xtensa.c \ + eelf32zip.c \ eelf_i386.c \ eelf_i386_be.c \ eelf_i386_chaos.c \ @@ -1314,6 +1315,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xc16xs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xstormy16.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32zip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Po@am__quote@ @@ -2897,6 +2899,9 @@ $(BFDDIR)/elf-bfd.h $(BFDDIR)/libbfd.h $(INCDIR)/elf/xtensa.h \ $(srcdir)/scripttempl/elfxtensa.sc ${GEN_DEPENDS} +eelf32zip.c: $(srcdir)/emulparams/elf32zip.sh $(ELF_DEPS) \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + eelf_i386.c: $(srcdir)/emulparams/elf_i386.sh \ $(ELF_X86_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/configure binutils-2.27-zip/opcodes/configure --- binutils-2.27-original/opcodes/configure 2016-08-03 04:33:39.000000000 -0400 +++ binutils-2.27-zip/opcodes/configure 2017-01-05 08:50:32.000000000 -0500 @@ -12685,7 +12685,7 @@ bfd_xtensa_arch) ta="$ta xtensa-dis.lo" ;; bfd_z80_arch) ta="$ta z80-dis.lo" ;; bfd_z8k_arch) ta="$ta z8k-dis.lo" ;; - + bfd_zip_arch) ta="$ta zip-dis.lo zip-opc.lo" ;; "") ;; *) as_fn_error "*** unknown target architecture $arch" "$LINENO" 5 ;; esac diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/configure.ac binutils-2.27-zip/opcodes/configure.ac --- binutils-2.27-original/opcodes/configure.ac 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/opcodes/configure.ac 2017-01-05 08:49:53.000000000 -0500 @@ -353,7 +353,7 @@ bfd_xtensa_arch) ta="$ta xtensa-dis.lo" ;; bfd_z80_arch) ta="$ta z80-dis.lo" ;; bfd_z8k_arch) ta="$ta z8k-dis.lo" ;; - + bfd_zip_arch) ta="$ta zip-dis.lo zip-opc.lo" ;; "") ;; *) AC_MSG_ERROR(*** unknown target architecture $arch) ;; esac diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/disassemble.c binutils-2.27-zip/opcodes/disassemble.c --- binutils-2.27-original/opcodes/disassemble.c 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/opcodes/disassemble.c 2016-12-31 18:02:03.139162969 -0500 @@ -98,6 +98,7 @@ #define ARCH_xtensa #define ARCH_z80 #define ARCH_z8k +#define ARCH_zip #define INCLUDE_SHMEDIA #endif @@ -495,6 +496,11 @@ disassemble = print_insn_z8002; break; #endif +#ifdef ARCH_zip + case bfd_arch_zip: + disassemble = zip_get_disassembler(abfd); + break; +#endif #ifdef ARCH_vax case bfd_arch_vax: disassemble = print_insn_vax; diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/Makefile.am binutils-2.27-zip/opcodes/Makefile.am --- binutils-2.27-original/opcodes/Makefile.am 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/opcodes/Makefile.am 2017-01-05 08:28:32.000000000 -0500 @@ -86,7 +86,9 @@ w65-opc.h \ xc16x-desc.h xc16x-opc.h \ xstormy16-desc.h xstormy16-opc.h \ - z8k-opc.h + z8k-opc.h \ + zip-opc.h \ + zip-dis.h # C source files that correspond to .o's ending up in libopcodes # for all machines. @@ -269,7 +271,9 @@ xgate-dis.c \ xgate-opc.c \ z80-dis.c \ - z8k-dis.c + z8k-dis.c \ + zip-dis.c \ + zip-opc.c # C source files that correspond to .o's ending up in libopcodes. LIBOPCODES_CFILES = \ @@ -346,7 +350,6 @@ touch stamp-lib libopcodes.a: stamp-lib ; @true - POTFILES = $(HFILES) $(CFILES) po/POTFILES.in: @MAINT@ Makefile for f in $(POTFILES); do echo $$f; done | LC_ALL=C sort > tmp \ diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/Makefile.in binutils-2.27-zip/opcodes/Makefile.in --- binutils-2.27-original/opcodes/Makefile.in 2016-08-03 03:36:54.000000000 -0400 +++ binutils-2.27-zip/opcodes/Makefile.in 2017-01-05 08:28:04.000000000 -0500 @@ -386,7 +386,9 @@ w65-opc.h \ xc16x-desc.h xc16x-opc.h \ xstormy16-desc.h xstormy16-opc.h \ - z8k-opc.h + z8k-opc.h \ + zip-opc.h \ + zip-dis.h # C source files that correspond to .o's ending up in libopcodes @@ -570,7 +572,9 @@ xgate-dis.c \ xgate-opc.c \ z80-dis.c \ - z8k-dis.c + z8k-dis.c \ + zip-dis.c \ + zip-opc.c # C source files that correspond to .o's ending up in libopcodes. @@ -974,6 +978,8 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xtensa-dis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/z80-dis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/z8k-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zip-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zip-opc.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/zip-dis.c binutils-2.27-zip/opcodes/zip-dis.c --- binutils-2.27-original/opcodes/zip-dis.c 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/opcodes/zip-dis.c 2018-03-22 17:57:34.688834861 -0400 @@ -0,0 +1,527 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: zip-dis.c +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016-2017, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory. Run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#include "config.h" + +#include <stdio.h> +#include <stdint.h> +#include <ctype.h> +#include <strings.h> +#include <string.h> +#include <assert.h> + +#include "zip-opc.h" +#include "zip-dis.h" + +static inline int +TWOWORD_LOAD(uint32_t one, uint32_t two) { + // BREV followed by LODILO + if (((one&0x87c40000)==0x02000000)&&((two&0x87c40000)==0x02400000) + // Must be to the same register too, and on the same condition + &&(((one^two)&0xf8380000)==0)) + return 1; + return 0; +} + +static inline int +OFFSET_PC_MOV(uint32_t ins) { + // 0.xxxx.01101.ccc.0.1111.0.iiiiiiiiiiiii + // 0xxx.x011.01cc.c011.110i.iiii.iiii.iiii + // + return ((ins & 0x87c7e000)==0x0343c000); +} + +static inline int +TWOWORD_LJMP(uint32_t iword) { + // LJMP a long jump instruction, for which the address of the target + // is found in the next word + if (iword==0x7c87c000) + return 1; + // Now, the CIS form ... an + // Unconditional LJMP in the second half word + if ((iword&0x80007fff)==0x80007cf8) + return 1; + return 0; +} + + +static inline int +TWOWORD_JSR(uint32_t iword, uint32_t nxtword) { + // First word moves the return address to R0 + if (iword != 0x0343c001) + return 0; + // Second word is a BRA statement to ... anywhere + // 0.1111.00010.ccc.0.iiiiiiiiiiiiiiiiii + // 0111.1000.10cc.c0ii.iiii.iiii.iiii.iiii + if ((nxtword&0xffc40000) == 0x78800000) + return 1; + // OR ... the second word could be a + // load into the PC + // 0.1111.10010.ccc.0.iiiiiiiiiiiiiiiiii LW.X #imm,PC + // 0.1111.10010.ccc.1.rrrr.iiiiiiiiiiiiii LW.X #(R),PC + // + // These must be unconditional, since the MOV above is + // also unconditional + // 0111.1100.10cc.cxxxxx.... LW.X #(R),PC + if ((nxtword&0xfff80000) == 0x7c800000) + return 1; + // + // OR ... the second word could be a + // Register move into the PC from the current + // register set + // 0.1111.01101.ccc.0.rrrr.0.iiiiiiiiiiiii MOV #(R),PC + // 0111.1011.01cc.c0rr.rr0i.iiiiiiiiiiii MOV #(R),PC + if ((nxtword&0xfffc2000) == 0x7b400000) + return 1; + // + return 0; +} + +static inline int +THREEWORD_LJSR(uint32_t iword, uint32_t nxtword) { + // First word moves the return address to R0 + if (iword!=0x0343c002) + return 0; + // Second word is an LJMP statement + if (nxtword==0x7c87c000) + return 1; + return 0; +} + +static inline int +TWOWORD_CIS_LJSR(uint32_t iword) { + // MOV 2(PC) | LOD (PC),PC + // + // 1.0000.111.1.1111.010 + // 1.1111.100.1.1111.000 + if (iword == 0x87fafcf8) + return 1; + return 0; +} + +static inline int +CIS_JSR(uint32_t iword __attribute__((unused)) ) { + if (TWOWORD_CIS_LJSR(iword)) + return 1; + // MOV 1(PC) | MOV Rx,PC + // + // 1.0000.111.1.1111.001 + // 1.1111.111.1.xxxx.000 + if ((iword&0xffffff87) == 0x87f9ff80) + return 1; + return 0; +} + +static inline int +POSSIBLE_TWOWORD_BEGINNING(uint32_t iword) { + // Unconditional LJMP + if (TWOWORD_LJMP(iword)) + return 1; + // MOV 1(PC),PC + if (iword == 0x0343c001) + return 1; + // MOV 2(PC),PC + if (iword == 0x0343c002) + return 1; + if (TWOWORD_CIS_LJSR(iword)) + return 1; + // The conditional LJMP is three words, which we don't handle ... + // Any BREV command could be the beginning of a twoword instruction + // + // Of course, the point here is to determine whether we should (or need + // to) read a second word from our read-memory function. Reading a + // second word, given that the first is a BREV, isn't a problem since a + // program can't end on/with a BREV instruction. + // + // BREV #,Rx + if ((iword&0x87c40000)==0x02000000) + return 1; + return 0; +} + +static uint32_t +zip_bitreverse(uint32_t v) { + uint32_t r=0, b; + for(b=0; b<32; b++, v>>=1) + r = (r<<1)|(v&1); + return r; +} + +static inline uint32_t +TWOWORD_VALUE(uint32_t one, uint32_t two) { + return ((two&0x0ffff)|(zip_bitreverse(one&0x0ffff))); +} + +static long +zip_sbits(const long val, const int bits) { + long r; + + r = val & ((1l<<bits)-1); + if (r & (1l << (bits-1))) + r |= (-1l << bits); + return r; +} + +static unsigned long +zip_ubits(const long val, const int bits) { + unsigned long r = val & ((1l<<bits)-1); + return r; +} + +static int +zip_getbits(const ZIPI ins, const int which) +{ + if (which & 0x40000000) { + return zip_sbits(ins>>(which & 0x03f), (which>>8)&0x03f); + } else { // if (which &0x03f) + return zip_ubits(ins>>(which & 0x03f), (which>>8)&0x03f) + + ((which>>16)&0x0ff); + } +} + +static void +zipi_to_halfstring(const uint32_t addr, const ZIPI ins, const ZIPI nxtword, char *line, const ZOPCODE *listp, uint32_t *refaddr) +{ + *refaddr = 0; + + if ((TWOWORD_LOAD(ins,nxtword))&&(listp==zip_oplist)) { + int cv = zip_getbits(ins, ZIP_BITFIELD(3,19)); // The condition + int dv = zip_getbits(ins, ZIP_REGFIELD(27)); // The destination + + *refaddr = TWOWORD_VALUE(ins,nxtword); + + sprintf(line, "%s%s", "LDI", zip_ccstr[cv]); + sprintf(line, "%-11s", line); + sprintf(line, "%s0x%08x", line, *refaddr); + sprintf(&line[strlen(line)], ",%s", zip_regstr[dv]); + + return; + } else if (TWOWORD_JSR(ins, nxtword)) { + if ((nxtword&0xffc40000) == 0x78800000) { + int cv = zip_getbits(nxtword, ZIP_BITFIELD(3,19)); + int iv = zip_sbits(nxtword, 18); + + *refaddr = iv + addr + 8; + sprintf(line, "%s%s", "JSR", zip_ccstr[cv]); + sprintf(line, "%-11s", line); + sprintf(line, "%s0x%08x", line, *refaddr); + + return; + } else if ((nxtword&0xfff80000) == 0x7c800000) { + // OR ... the second word could be a load into the PC + if ((nxtword>>18)&1) { + // LW #(Rw),PC + int iv = zip_sbits(nxtword, 14); + int rb = zip_ubits(nxtword>>14, 4); + + sprintf(line,"%-11s#%d(%s)", "IJSR", iv, + zip_regstr[rb]); + *refaddr = 0; + } else { + // LW (#),PC + int iv = zip_sbits(nxtword, 18); + sprintf(line,"%-11s(#%d)", "IJSR", iv); + *refaddr = iv; + } + return; + } else { // if ((nxtword&0xfffc2000) == 0x7b400000) + // OR ... the second word could be a register move into + // the PC from the current register set + int rb = zip_ubits(nxtword>>14, 4); + int iv = zip_sbits(nxtword, 13); + + *refaddr = 0; + if (iv == 0) + sprintf(line, "%-11s %s", "JSR", + zip_regstr[rb]); + else + sprintf(line, "%-11s#%d+%s", "JSR",iv, + zip_regstr[rb]); + + return; + } + } else if (TWOWORD_CIS_LJSR(ins)) { + *refaddr = nxtword; + sprintf(line, "%-11s", "LJSR"); + sprintf(line, "%s0x%08x", line, *refaddr); + return; + } else if (CIS_JSR(ins)) { + int ra = zip_getbits(ins, ZIP_REGFIELD(3)); + sprintf(line, "%-11s%s", "JSR", zip_regstr[ra]); + return; + } else if (OFFSET_PC_MOV(ins)) { + int cv = zip_getbits(ins, ZIP_BITFIELD(3,19)); + int dv = zip_getbits(ins, ZIP_REGFIELD(27)); + int iv = zip_sbits(ins, 13); + uint32_t ref; + + ref = (iv<<2) + addr + 4; + + sprintf(line, "%s%s", "MOV", zip_ccstr[cv]); + sprintf(line, "%-11s", line); + sprintf(line, "%s0x%08x", line, ref); + sprintf(line, "%s,%s", line, zip_regstr[dv]); + + *refaddr = ref; + return; + } + + int i; + for(i=0; i<nzip_oplist; i++) { + if (((~zip_oplist[i].s_mask)&zip_oplist[i].s_val)!=0) { + printf("Instruction %d, %s, fails consistency check\n", + i, zip_oplist[i].s_opstr); + printf("%08x & %08x = %08x != %08x\n", + zip_oplist[i].s_mask, + zip_oplist[i].s_val, + (~zip_oplist[i].s_mask)&zip_oplist[i].s_val, + 0); + assert(((~zip_oplist[i].s_mask)&zip_oplist[i].s_val)==0); + } + } line[0] = '\0'; + for(i=0; (listp[i].s_mask != 0); i++) { + // printf("%2d: %6s %08x & %08x == %08x\n", + // i, zip_oplist[i].s_opstr, ins, + // zip_oplist[i].s_mask, zip_oplist[i].s_val); + if ((ins & listp[i].s_mask) == listp[i].s_val) { + // Write the opcode onto our line + sprintf(line, "%s", listp[i].s_opstr); + if (listp[i].s_cf != ZIP_OPUNUSED) { + int bv = zip_getbits(ins, listp[i].s_cf); + strcat(line, zip_ccstr[bv]); + } sprintf(line, "%-11s", line); // Pad it to 11 chars + + int ra = -1, rb = -1, rr = -1, imv = 0; + + if (listp[i].s_result != ZIP_OPUNUSED) + rr = zip_getbits(ins, listp[i].s_result); + if (listp[i].s_ra != ZIP_OPUNUSED) + ra = zip_getbits(ins, listp[i].s_ra); + if (listp[i].s_rb != ZIP_OPUNUSED) + rb = zip_getbits(ins, listp[i].s_rb); + if (listp[i].s_i != ZIP_OPUNUSED) + imv = zip_getbits(ins, listp[i].s_i); + + if ((listp[i].s_rb != ZIP_OPUNUSED)&&(rb == 15)) + imv <<= 2; + + // Treat stores special + if ((strncasecmp("SW",listp[i].s_opstr, 2)==0) + ||(strncasecmp("SH",listp[i].s_opstr, 2)==0) + ||(strncasecmp("SB",listp[i].s_opstr, 2)==0)) { + strcat(line, zip_regstr[ra]); + strcat(line, ","); + + if (listp[i].s_i != ZIP_OPUNUSED) { + if (listp[i].s_rb == ZIP_OPUNUSED) + sprintf(&line[strlen(line)], + "($%d)", imv); + else if (imv != 0) + sprintf(&line[strlen(line)], + "$%d", imv); + } if (listp[i].s_rb != ZIP_OPUNUSED) { + sprintf(&line[strlen(line)], + "(%s)", zip_regstr[rb]); + } + // Treat long jumps special + } else if (strncasecmp("LJMP",listp[i].s_opstr, 3)==0) { + sprintf(&line[strlen(line)], "@0x%08x", nxtword); + *refaddr = nxtword; + // Treat relative jumps (branches) specially as well + } else if ((toupper(listp[i].s_opstr[0]=='B')) + &&(strcasecmp(listp[i].s_opstr,"BUSY")!=0) + &&(strcasecmp(listp[i].s_opstr,"BREV")!=0) + &&(strcasecmp(listp[i].s_opstr,"BRK")!=0) + &&(addr != 0)) { + // Branch instruction: starts with B and isn't + // BREV (bit reverse), BRK (break), or + // BUSY + uint32_t target = addr; + + target += zip_getbits(ins, listp[i].s_i)+4; + sprintf(&line[strlen(line)], "@0x%08x", target); + *refaddr = target; + } else { + int memop = 0; + if (('L'==toupper(listp[i].s_opstr[0])) + &&(('W'==toupper(listp[i].s_opstr[1])) + ||('H'==toupper(listp[i].s_opstr[1])) + ||('B'==toupper(listp[i].s_opstr[1]))) + &&(!listp[i].s_opstr[2])) + memop = 1; + + if (listp[i].s_i != ZIP_OPUNUSED) { + if((memop)&&(listp[i].s_rb == ZIP_OPUNUSED)) + sprintf(&line[strlen(line)], + "($%d)", imv); + else if((memop)&&(imv != 0)) + sprintf(&line[strlen(line)], + "%d", imv); + else if((!memop)&&((imv != 0)||(listp[i].s_rb == ZIP_OPUNUSED))) + sprintf(&line[strlen(line)], + "$%d%s", imv, + (listp[i].s_rb!=ZIP_OPUNUSED)?"+":""); + } if (listp[i].s_rb != ZIP_OPUNUSED) { + if (memop) + sprintf(&line[strlen(line)], + "(%s)", zip_regstr[rb]); + else + strcat(line, zip_regstr[rb]); + } if(((listp[i].s_i != ZIP_OPUNUSED)||(listp[i].s_rb != ZIP_OPUNUSED)) + &&((listp[i].s_ra != ZIP_OPUNUSED)||(listp[i].s_result != ZIP_OPUNUSED))) + strcat(line, ","); + + if (listp[i].s_ra != ZIP_OPUNUSED) { + strcat(line, zip_regstr[ra]); + } else if (listp[i].s_result != ZIP_OPUNUSED) { + strcat(line, zip_regstr[rr]); + } + } + break; + } + } if (line[0] == '\0') { + sprintf(line, "ILL %08x", ins); + } +} + +static void +zipi_to_double_string(const uint32_t addr, const ZIPI ins, const ZIPI nxtword, char *la, char *lb, uint32_t *refaddr) { + zipi_to_halfstring(addr, ins, nxtword, la, zip_oplist, refaddr); + if (lb) { + if ((ins & 0x80000000)&&(!CIS_JSR(ins))) { + zipi_to_halfstring(addr, ins, nxtword, + lb, zip_opbottomlist, refaddr); + *refaddr = 0; + } else lb[0] = '\0'; + } +} + +static int +print_zip_insn(bfd_vma vma, disassemble_info *info) +{ + ZIPI iword, nxtword; + char astr[80], bstr[80]; + unsigned char ibytes[12]; + uint32_t refaddr = 0; + + // Deal with misalignment ... + if ((vma & 3)!=0) { + int consumed = 0; + + // Consume up to four bytes, after a zero (possibly multiple), + // though, align ourselves + (*info->read_memory_func)(vma, ibytes, 4, info); + while((consumed<4)&&(ibytes[consumed]!=0)) + consumed++; + while((consumed<4)&&(ibytes[consumed]==0)) + consumed++; + if (consumed <= 1) + consumed = 1; + return consumed; + } + + // Always read the first word + (*info->read_memory_func)(vma, ibytes, 4, info); + iword = (ibytes[0]<<24)|(ibytes[1]<<16)|(ibytes[2]<<8)|(ibytes[3]); + // Only if we know we have a second do we read the second + if ((POSSIBLE_TWOWORD_BEGINNING(iword)) + // We also test for reading past the end of the buffer + &&((*info->read_memory_func)(vma, ibytes, 8, info) ==0)) { + nxtword= (ibytes[4]<<24)|(ibytes[5]<<16)|(ibytes[6]<<8)|(ibytes[7]); + } else { + const int NOOP_CODE = 0x76000000; + nxtword = NOOP_CODE; + } + + bstr[0] = '\0'; + + if (THREEWORD_LJSR(iword,nxtword)) { + sprintf(astr, "%-11s", "LJSR"); + if ((*info->read_memory_func)(vma, ibytes, 12, info) ==0) + refaddr = (ibytes[8]<<24)|(ibytes[9]<<16)|(ibytes[10]<<8)|(ibytes[11]); + sprintf(&astr[strlen(astr)], "@0x%08x", refaddr); + } else if (TWOWORD_CIS_LJSR(iword)) { + refaddr = nxtword; + sprintf(astr, "%-11s0x%08x", "JSR", refaddr); + } else + zipi_to_double_string(vma, iword, nxtword, astr, bstr,&refaddr); + + if (bstr[0]) + sprintf(astr, "%-25s | %s", astr,bstr); + + // Remove any trailing spaces + unsigned ln = strlen(astr); + while((ln > 0)&&(isspace(astr[ln-1]))) + astr[--ln] = '\0'; + + (*info->fprintf_func)(info->stream, "%s", astr); + + if ((info->print_address_func)&&(refaddr != 0)) { + if (ln < 25) + (*info->fprintf_func)(info->stream, "%*s", 25-ln, ""); + + (*info->fprintf_func)(info->stream, " // "); + (*info->print_address_func)(refaddr, info); + } + + // Normal LOD (PC),PC = 0x7c87c000 + // 1'b0, 4'hf, 5'h12, 3'h0, 1'b1, 4'hf, 14'h00 + // 0111 1100 1000 0111 1100 0000 0000 0000 + // or CIS x | LOD (PC),PC + // 1'b1, 4'hx 5'hx 1'b0 2'bx 5'hx 4'hf 5'h12 1'b1 4'hf + // 1xxx xxxx xx0x xxxx xx11 1110 0101 1111 + // 0x80203fff mask, val = 0x80003e5f + if (THREEWORD_LJSR(iword,nxtword)) + return 12; + if (TWOWORD_LJMP(iword)) + return 8; + // Two word load: Destination registers and conditional execution bits + // must match as well. + if (TWOWORD_LOAD(iword,nxtword)) + return 8; + if (TWOWORD_JSR(iword,nxtword)) + return 8; + if (TWOWORD_CIS_LJSR(iword)) + return 8; + return 4; +} + + +disassembler_ftype +zip_get_disassembler(bfd *abfd ATTRIBUTE_UNUSED) +{ + return print_zip_insn; +} + diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/zip-dis.h binutils-2.27-zip/opcodes/zip-dis.h --- binutils-2.27-original/opcodes/zip-dis.h 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/opcodes/zip-dis.h 2016-12-31 18:10:03.512012534 -0500 @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: zip-dis.h +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef ZIP_DIS_H +#define ZIP_DIS_H + +#include "config.h" +#include "dis-asm.h" + +extern disassembler_ftype +zip_get_disassembler(bfd *abfd); + +#endif diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/zip-opc.c binutils-2.27-zip/opcodes/zip-opc.c --- binutils-2.27-original/opcodes/zip-opc.c 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/opcodes/zip-opc.c 2018-06-07 10:35:06.439245343 -0400 @@ -0,0 +1,362 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: zip-opc.c +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015-2017, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory. Run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#include "zip-opc.h" + +const char *zip_regstr[49] = { + "R0", "R1", "R2", "R3", + "R4", "R5", "R6", "R7", + "R8", "R9", "R10","R11", + "R12","SP", "CC", "PC", + "uR0", "uR1", "uR2", "uR3", + "uR4", "uR5", "uR6", "uR7", + "uR8", "uR9", "uR10", "uR11", + "uR12", "uSP", "uCC", "uPC", + "sR0", "sR1", "sR2", "sR3", + "sR4", "sR5", "sR6", "sR7", + "sR8", "sR9", "sR10","sR11", + "sR12","sSP", "sCC", "sPC", "rILL" +}; + +const char *zip_ccstr[8] = { + "", ".Z", ".LT", ".C", + ".V",".NZ", ".GE", ".NC" +}; + +static const ZOPCODE zip_oplist_raw[] = { + // Special case instructions. These are general instructions, but with + // special opcodes + // Conditional branches + // 0.1111.0111.ccc.0.111.10iiiii-- + // 0111 1011 11cc c011 110i iiii iiii iiii + { "BUSY", 0xffc7fffc, 0x7883fffc, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + { "BZ", 0xfffc0000, 0x78880000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BLT", 0xfffc0000, 0x78900000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BC", 0xfffc0000, 0x78980000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BV", 0xfffc0000, 0x78a00000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BNZ", 0xfffc0000, 0x78a80000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BGE", 0xfffc0000, 0x78b00000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BNC", 0xfffc0000, 0x78b80000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_OPUNUSED }, + { "BRA", 0xffc40000, 0x78800000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + // Changes/updates to CC, based upon LDI + { "TRAP", 0xfffffff0, 0x76000000, ZIP_OPUNUSED,ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "TRAP", 0xff800000, 0x76000000, ZIP_OPUNUSED,ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // BREV based traps + { "TRAP", 0xffc7ffff, 0x72000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + // LDILO based traps + { "TRAP",0xffc4ffff, 0x72400000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + { "TRAP",0xffc40000, 0x72400000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + // CLR -- a LDI of zero + // 0.rrrr.1100.iiiiiii-- + // 0rrr r110 0... + { "CLR", 0x87ffffff, 0x06000000, ZIP_REGFIELD(27),ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // BREV based clears + { "CLR", 0x87c7ffff, 0x02000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + // HALT + // 0.1110.00011.ccc.0.0000000000010 + // 0111.0000.11cc.c000.0000.0000.0000.0010 + { "HALT", 0xffc7ffff, 0x70c00010, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + // The "wait" instruction is identical, with the only difference being + // the interrrupt context of the processor. Well, almost. To + // facilitate waits from supervisor mode, the wait instruction + // explicitly forces the CPU into user mode. + { "WAIT", 0xffc7ffff, 0x70c00030, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + // 1.0011.11000.000.0000...... 5f ? A carefully chosen illegal insn ?? + // "INT", 0xff10007f, 0x9e00005f, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19), + // Return to user space + { "RTU", 0xffc7ffff, 0x70c00020, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + // The return instruction: JMP R0 (possibly conditional) = MOV R0,PC + { "RTN", 0xffc7ffff, 0x7b400000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + // JMP (possibly a conditional jump, if not covered by branches above) + // 0.1111.01101.ccc.a.rrrr.biiiiiiiiiiiiiiii + // 0111.1011.01cc.c0rr.rrbi.iiii.iiii.iiii MOV x,PC + { "JMP", 0xffc40000, 0x7b400000, ZIP_OPUNUSED,ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(13,0), ZIP_BITFIELD(3,19) }, + // 0.1111.1100.ii.iiii.iiii.iiii.iiii.iiii.iiii + // 0111.1110.0iii.iiii.iiii.iiii.iiii.iiii LDI x,PC + { "JMPI", 0xff800000, 0x7e000000, ZIP_REGFIELD(27),ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(23,0), ZIP_OPUNUSED }, + // 0.1111.10010.000.1.1111.000000000000000 + // 0111.1100.1000.0111.11ii.iiii.iiii.iiii LOD (PC),PC + { "LJMP", 0xffffffff, 0x7c87c000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // NOT : XOR w/ -1 + // 0.rrrr.00100.ccc.0111.11111111111 + // 0rrr.r001.00cc.c011.f.f.f.f + // { "NOT", 0x87c7ffff, 0x0103ffff, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + // General instructions + // 0rrr.rooo.oocc.cxrr.rrii.iiii.iiii.iiii + { "SUB", 0x87c40000, 0x00000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "SUB", 0x87c40000, 0x00040000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "AND", 0x87c40000, 0x00400000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "AND", 0x87c40000, 0x00440000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "ADD", 0x87c40000, 0x00800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "ADD", 0x87c40000, 0x00840000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "OR", 0x87c40000, 0x00c00000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "OR", 0x87c40000, 0x00c40000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "XOR", 0x87c40000, 0x01000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "XOR", 0x87c40000, 0x01040000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "LSR", 0x87c40000, 0x01400000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "LSR", 0x87c40000, 0x01440000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "LSL", 0x87c40000, 0x01800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "LSL", 0x87c40000, 0x01840000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "ASR", 0x87c40000, 0x01c00000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "ASR", 0x87c40000, 0x01c40000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "BREV",0x87c40000, 0x02000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "BREV",0x87c40000, 0x02040000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "LDILO",0x87c40000, 0x02400000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "LDILO",0x87c40000, 0x02440000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + // + { "MPYUHI", 0x87c40000, 0x02800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "MPYUHI", 0x87c40000, 0x02840000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "MPYSHI", 0x87c40000, 0x02c00000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "MPYSHI", 0x87c40000, 0x02c40000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "MPY", 0x87c40000, 0x03000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "MPY", 0x87c40000, 0x03040000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "MOV", 0x87c42000, 0x03400000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(13,0), ZIP_BITFIELD(3,19) }, + { "MOV", 0x87c42000, 0x03440000, ZIP_URGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(13,0), ZIP_BITFIELD(3,19) }, + { "MOV", 0x87c42000, 0x03402000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_URGFIELD(14), ZIP_IMMFIELD(13,0), ZIP_BITFIELD(3,19) }, + { "MOV", 0x87c42000, 0x03442000, ZIP_URGFIELD(27), ZIP_OPUNUSED, ZIP_URGFIELD(14), ZIP_IMMFIELD(13,0), ZIP_BITFIELD(3,19) }, + // + { "DIVU", 0x87c40000, 0x03800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "DIVU", 0x87c40000, 0x03840000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "DIVS", 0x87c40000, 0x03c00000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "DIVS", 0x87c40000, 0x03c40000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "CMP", 0x87c40000, 0x04000000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "CMP", 0x87c40000, 0x04040000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + { "TST", 0x87c40000, 0x04400000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "TST", 0x87c40000, 0x04440000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "LW", 0x87c40000, 0x04800000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "LW", 0x87c40000, 0x04840000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "SW", 0x87c40000, 0x04c00000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "SW", 0x87c40000, 0x04c40000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "LH", 0x87c40000, 0x05000000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "LH", 0x87c40000, 0x05040000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "SH", 0x87c40000, 0x05400000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "SH", 0x87c40000, 0x05440000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "LB", 0x87c40000, 0x05800000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "LB", 0x87c40000, 0x05840000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + { "SB", 0x87c40000, 0x05c00000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "SB", 0x87c40000, 0x05c40000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + // 0rrr.r101.1 + { "LDI", 0x87800000, 0x06000000, ZIP_REGFIELD(27),ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(23,0), ZIP_OPUNUSED }, + // 0111.x111.00.xxxxxxxx + { "BREAK", 0xf7ffffff, 0x77000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "BREAK", 0xf7c00000, 0x77000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(22,0), ZIP_OPUNUSED }, + { "LOCK", 0xf7ffffff, 0x77400000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "LOCK", 0xf7c00000, 0x77400000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(22,0), ZIP_OPUNUSED }, + // 0.111x.00000.xxx.xxx.xxxx.xxxx.xxxx.xxxx + // 0111.x111.11.xxx.xxx.xxxx.xxxx.xxxx.xxxx + // SNOOP = SIM w/ no argument(s) + { "SIM", 0xf7ffffff, 0x77800000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SEXIT",0xf7ffffff, 0x77800100, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SEXIT",0xf7fffff0, 0x77800310, ZIP_OPUNUSED, ZIP_URGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SEXIT",0xf7ffffe0, 0x77800300, ZIP_OPUNUSED, ZIP_REGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SEXIT",0xf7ffff00, 0x77800100, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD( 8,0), ZIP_OPUNUSED }, + { "SDUMP",0xf7ffffff, 0x778002ff, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SDUMP",0xf7fffff0, 0x77800200, ZIP_OPUNUSED, ZIP_REGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SDUMP",0xf7fffff0, 0x77800210, ZIP_OPUNUSED, ZIP_URGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SOUT", 0xf7fffff0, 0x77800230, ZIP_OPUNUSED, ZIP_URGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SOUT", 0xf7ffffe0, 0x77800220, ZIP_OPUNUSED, ZIP_REGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "SOUT", 0xf7ffff00, 0x77800400, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD( 8,0), ZIP_OPUNUSED }, + { "SDUMP",0xf7ffff00, 0x77800200, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD( 8,0), ZIP_OPUNUSED }, + { "SIM", 0xf7c00000, 0x77800000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(22,0), ZIP_OPUNUSED }, + { "NOOP", 0xf7ffffff, 0x77c00000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NEXIT",0xf7ffffff, 0x77c00100, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NEXIT",0xf7ffff00, 0x77c00100, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD( 8,0), ZIP_OPUNUSED }, + { "NEXIT",0xf7fffff0, 0x77c00310, ZIP_OPUNUSED, ZIP_URGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NEXIT",0xf7ffffe0, 0x77c00300, ZIP_OPUNUSED, ZIP_REGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NDUMP",0xf7ffffff, 0x77c002ff, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NDUMP",0xf7fffff0, 0x77c00200, ZIP_OPUNUSED, ZIP_REGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NDUMP",0xf7fffff0, 0x77c00210, ZIP_OPUNUSED, ZIP_URGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + + { "NOUT", 0xf7fffff0, 0x77c00230, ZIP_OPUNUSED, ZIP_URGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NOUT", 0xf7ffffe0, 0x77c00220, ZIP_OPUNUSED, ZIP_REGFIELD(0), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NOUT", 0xf7ffff00, 0x77c00400, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD( 8,0), ZIP_OPUNUSED }, + { "NDUMP",0xf7ffff00, 0x77c00200, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + { "NSIM", 0xf7c00000, 0x77c00000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(22,0), ZIP_OPUNUSED }, + // + // + // 0rrr.r11f.ffcc.cxrr.rrii.iiii.iiii.iiii + { "FPADD",0x87c43fff, 0x06840000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + { "FPSUB",0x87c43fff, 0x06c40000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + { "FPMPY",0x87c43fff, 0x07040000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + { "FPDIV",0x87c43fff, 0x07440000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(14), ZIP_OPUNUSED, ZIP_BITFIELD(3,19) }, + { "FPI2F",0x87c40000, 0x07800000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(18,0), ZIP_BITFIELD(3,19) }, + { "FPI2F",0x87c40000, 0x07840000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + { "FPF2I",0x87c40000, 0x07c40000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(14), ZIP_IMMFIELD(14,0), ZIP_BITFIELD(3,19) }, + // + // + // + // + // + // 16-bit instructions, high side + // + // + // 1.1111.00010.xcc.0iiii.xxxx.xxxxx.xxxxx + // 1111.1000.10xc.c0ii.iixx.xxxx.xxxx.xxxx + // Mask, val, result, Ra, Rb, I, condition (no conditions for OP_UNDER_TEST) + // BRA: 1.1111.011.0.sssssss + { "BRA", 0xff800000, 0xf9000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + // CLR: 1.rrrr.110.00000000 + { "CLR", 0x87ff0000, 0x86000000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // RTN: 1.1111.111.0.0000.000, MOV R0,Pc + { "RTN", 0xffff0000, 0xff800000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // JMP: 1.1111.111.0.rrrrsss + { "JMP", 0xff800000, 0xff000000, ZIP_REGFIELD(27),ZIP_OPUNUSED, ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // LJSR: 1.000_0.011_.0.111_1.001 ?.1111.110.1.1111.000 + // { "LJSR",0xffffffff, 0x83797ef8, ZIP_REGFIELD(27),ZIP_OPUNUSED, ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // + // 1.rrrr.000.0.sssssss + // 1rrr.r000.0sss.ssss + { "SUB", 0x87800000, 0x80000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + // 1.rrrr.000.1.rrrrsss + { "SUB", 0x87800000, 0x80800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // + // 1.rrrr.001.0.sssssss + // 1.rrrr.001.1.rrrrsss + { "AND", 0x87800000, 0x81000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + { "AND", 0x87800000, 0x81800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // + // 1.rrrr.010.0.sssssss + // 1.rrrr.010.1.rrrrsss + { "ADD", 0x87800000, 0x82000000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + { "ADD", 0x87800000, 0x82800000, ZIP_REGFIELD(27), ZIP_REGFIELD(27), ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // + // 1.rrrr.011.a.rrrrsss + { "CMP", 0x87800000, 0x83000000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + { "CMP", 0x87800000, 0x83800000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // + // 1.rrrr.100.0.sssssss + // 1.rrrr.100.1.rrrrsss + { "LW", 0x87800000, 0x84000000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_SP, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + { "LW", 0x87800000, 0x84800000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // 1.rrrr.101.ssssssss + { "SW", 0x87800000, 0x85000000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_SP, ZIP_IMMFIELD(7,16), ZIP_OPUNUSED }, + // 1.rrrr.110.0.sssssss + { "SW", 0x87800000, 0x85800000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // 1.rrrr.110.iiiiiiii + { "LDI", 0x87000000, 0x86000000, ZIP_REGFIELD(27), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(8,16), ZIP_OPUNUSED }, + // 1.rrrr.111.1.sssssss + { "MOV", 0x87800000, 0x87800000, ZIP_OPUNUSED, ZIP_REGFIELD(27), ZIP_REGFIELD(19), ZIP_IMMFIELD(3,16), ZIP_OPUNUSED }, + // + // 1.rrrr.111.1.rrrrsss + // Illegal instruction !! + { "ILLV", 0x80000000, 0x80000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(32,16), ZIP_OPUNUSED }, + // Global illegal instruction + { "ILL", 0x00000000, 0x00000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(32,0), ZIP_OPUNUSED } +}; + +static const ZOPCODE zip_opbottomlist_raw[] = { + // + // + // + // 16-bit instructions, low side ... treat these as special + // + // + // Mask, val, result, Ra, Rb, I, condition (no conditions for OP_UNDER_TEST) + // BRA: 1.xxx_xxxx_xxxx_xxxx_?.111_1.011.0.sssssss + { "BRA", 0x80007f80, 0x80007900, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + // CLR: 1.xxx_xxxx_xxxx_xxxx_?.rrr_r.101.0000_0000 + { "CLR", 0x800007ff, 0x80000600, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // RTN: 1.1111.111.0.0000.000, MOV R0,Pc + { "RTN", 0x80007fff, 0x80007f80, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED }, + // JMP: 1.1111.111.0.rrrrsss + { "JMP", 0x80007f80, 0x80007f00, ZIP_REGFIELD(11),ZIP_OPUNUSED, ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // LJMP: 1.xxx_xxxx_xxxx_xxxx_?.111_1.100._1.111_1.000 + { "LJMP", 0x80007fff, 0x80007cf8, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // + // 1.rrrr.000.0.sssssss + { "SUB", 0x80000780, 0x80000000, ZIP_REGFIELD(11), ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + // 1.rrrr.000.1.rrrrsss + { "SUB", 0x80000780, 0x80000080, ZIP_REGFIELD(11), ZIP_REGFIELD(11), ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // + // 1.rrrr.001.0.sssssss + // 1.rrrr.001.1.rrrrsss + { "AND", 0x80000780, 0x80000100, ZIP_REGFIELD(11), ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + { "AND", 0x80000780, 0x80000180, ZIP_REGFIELD(11), ZIP_REGFIELD(11), ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // + // 1.rrrr.010.0.sssssss + // 1.rrrr.010.1.rrrrsss + { "ADD", 0x80000780, 0x80000200, ZIP_REGFIELD(11), ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + { "ADD", 0x80000780, 0x80000280, ZIP_REGFIELD(11), ZIP_REGFIELD(11), ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // + // 1.rrrr.011.a.rrrrsss + { "CMP", 0x80000780, 0x80000300, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + { "CMP", 0x80000780, 0x80000380, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // + // 1.rrrr.100.0.sssssss + // 1.rrrr.100.1.rrrrsss + { "LW", 0x80000780, 0x80000400, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_SP, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + { "LW", 0x80000780, 0x80000480, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // 1.rrrr.101.ssssssss + { "SW", 0x80000780, 0x80000500, ZIP_OPUNUSED, ZIP_REGFIELD(11), ZIP_SP, ZIP_IMMFIELD(7,0), ZIP_OPUNUSED }, + { "SW", 0x80000780, 0x80000580, ZIP_OPUNUSED, ZIP_REGFIELD(11), ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // 1.rrr_r.110.ssssssss + { "LDI", 0x80000700, 0x80000600, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(8,0), ZIP_OPUNUSED }, + // 1.rrr_r.111_.x.rrr_rsss + { "MOV", 0x80000780, 0x80000780, ZIP_REGFIELD(11), ZIP_OPUNUSED, ZIP_REGFIELD(3), ZIP_IMMFIELD(3,0), ZIP_OPUNUSED }, + // + // + // Illegal instruction !! + { "ILLV", 0x80000000, 0x80000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(15,0), ZIP_OPUNUSED }, + { "ILL", 0x00000000, 0x00000000, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_OPUNUSED, ZIP_IMMFIELD(15,0), ZIP_OPUNUSED } +}; + +const ZOPCODE *zip_oplist = zip_oplist_raw, + *zip_opbottomlist = zip_opbottomlist_raw; + +const int nzip_oplist = (sizeof(zip_oplist_raw)/sizeof(ZOPCODE)); +const int nzip_opbottom = (sizeof(zip_opbottomlist_raw)/sizeof(ZOPCODE)); + diff -Naur '--exclude=*.swp' binutils-2.27-original/opcodes/zip-opc.h binutils-2.27-zip/opcodes/zip-opc.h --- binutils-2.27-original/opcodes/zip-opc.h 1969-12-31 19:00:00.000000000 -0500 +++ binutils-2.27-zip/opcodes/zip-opc.h 2017-02-10 17:48:01.761470841 -0500 @@ -0,0 +1,77 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: zip-opc.h +// +// Project: Zip CPU backend for GNU Binutils +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// <http://www.gnu.org/licenses/> for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef ZIP_OPC_H +#define ZIP_OPC_H + +#include <stdint.h> + +// MACROS used in the instruction definition list. +#define ZIP_OPUNUSED -1 +#define ZIP_BITFIELD(LN,MN) (((LN&0x0ff)<<8)+(MN&0x0ff)) // A generic bitfield +#define ZIP_REGFIELD(MN) (0x00000400 +(MN&0x0ff)) // Normal register field +#define ZIP_URGFIELD(MN) (0x0100400 +(MN&0x0ff)) // User register field +#define ZIP_IMMFIELD(LN,MN) (0x40000000 + (((LN&0x0ff)<<8)+(MN&0x0ff))) // Sgn extnd +#define ZIP_SP 0xd0000 + +typedef uint32_t ZIPI; // A Zip CPU instruction + +typedef struct { + char s_opstr[8]; // OPCode name + ZIPI s_mask, // Bits that must match 4 this pattern to match + s_val; // What those masked bits must be + // + // The following describe not the value, but the bits where there + // respective vaules will be found within the instruction. For example, + // an instruction with no immediate will have an s_i value of -1 + // (ZIP_OPUNUSED), whereas an instruction with an immediate value of -1 + // might have an s_i value of ZIP_BITFIELD(14,0), or 0x0400. The + // opcode itself will tell you what the value is--not this structure + // describing the opcode. + // + int s_result, // Register where the result will be placed + s_ra, // A register, often the result + s_rb, // B register, source operand (if used) + s_i, // Immediate value, added to B if B is used + s_cf; // Condition flags. +} ZOPCODE; + +extern const char *zip_regstr[49], *zip_ccstr[8]; + +extern const ZOPCODE *zip_oplist, *zip_opbottomlist; +extern const int nzip_oplist, nzip_opbottom; + + +#endif