diff options
author | Nick Clifton <nickc@redhat.com> | 2001-01-11 21:20:20 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2001-01-11 21:20:20 +0000 |
commit | 0d2bcfafbfc1ede123ec9d61813745d775c5251c (patch) | |
tree | ae4a63e1af9df831594f61ef175e7f7a6e4a2567 /opcodes/arc-ext.c | |
parent | 8805103910cfd8201e621cb766f404c585f3e46e (diff) | |
download | gdb-0d2bcfafbfc1ede123ec9d61813745d775c5251c.zip gdb-0d2bcfafbfc1ede123ec9d61813745d775c5251c.tar.gz gdb-0d2bcfafbfc1ede123ec9d61813745d775c5251c.tar.bz2 |
Updated ARC assembler from arccores.com
Diffstat (limited to 'opcodes/arc-ext.c')
-rw-r--r-- | opcodes/arc-ext.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/opcodes/arc-ext.c b/opcodes/arc-ext.c new file mode 100644 index 0000000..0b10677 --- /dev/null +++ b/opcodes/arc-ext.c @@ -0,0 +1,259 @@ +/* ARC target-dependent stuff. Extension structure access functions + Copyright (C) 1995, 1997, 2000 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; 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 2 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 + MERCHANTABILITY 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <stdlib.h> +#include <stdio.h> +#include "bfd.h" +#include "arc-ext.h" +#include "libiberty.h" + +/* Extension structure */ +static struct arcExtMap arc_extension_map; + +/* Get the name of an extension instruction. */ + +const char * +arcExtMap_instName(int opcode, int minor, int *flags) +{ + if (opcode == 3) + { + /* FIXME: ??? need to also check 0/1/2 in bit0 for (3f) brk/sleep/swi */ + if (minor < 0x09 || minor == 0x3f) + return 0; + else + opcode = 0x1f - 0x10 + minor - 0x09 + 1; + } + else + if (opcode < 0x10) + return 0; + else + opcode -= 0x10; + if (!arc_extension_map.instructions[opcode]) + return 0; + *flags = arc_extension_map.instructions[opcode]->flags; + return arc_extension_map.instructions[opcode]->name; +} + +/* Get the name of an extension core register. */ + +const char * +arcExtMap_coreRegName(int value) +{ + if (value < 32) + return 0; + return (const char *) arc_extension_map.coreRegisters[value-32]; +} + +/* Get the name of an extension condition code. */ + +const char * +arcExtMap_condCodeName(int value) +{ + if (value < 16) + return 0; + return (const char *) arc_extension_map.condCodes[value-16]; +} + +/* Get the name of an extension aux register. */ + +const char * +arcExtMap_auxRegName(long address) +{ + /* walk the list of aux reg names and find the name */ + struct ExtAuxRegister *r; + + for (r = arc_extension_map.auxRegisters; r; r = r->next) { + if (r->address == address) + return (const char *) r->name; + } + return 0; +} + +/* Recursively free auxilliary register strcture pointers until + the list is empty. */ + +static void +clean_aux_registers(struct ExtAuxRegister *r) +{ + if (r -> next) + { + clean_aux_registers( r->next); + free(r -> name); + free(r -> next); + r ->next = NULL; + } + else + free(r -> name); +} + +/* Free memory that has been allocated for the extensions. */ + +static void +cleanup_ext_map(void) +{ + struct ExtAuxRegister *r; + struct ExtInstruction *insn; + int i; + + /* clean aux reg structure */ + r = arc_extension_map.auxRegisters; + if (r) + { + (clean_aux_registers(r)); + free(r); + } + + /* clean instructions */ + for (i = 0; i < NUM_EXT_INST; i++) + { + insn = arc_extension_map.instructions[i]; + if (insn) + free(insn->name); + } + + /* clean core reg struct */ + for (i = 0; i < NUM_EXT_CORE; i++) + { + if (arc_extension_map.coreRegisters[i]) + free(arc_extension_map.coreRegisters[i]); + } + + for (i = 0; i < NUM_EXT_COND; i++) { + if (arc_extension_map.condCodes[i]) + free(arc_extension_map.condCodes[i]); + } + + memset(&arc_extension_map, 0, sizeof(struct arcExtMap)); +} + +int +arcExtMap_add(void *base, unsigned long length) +{ + unsigned char *block = base; + unsigned char *p = block; + + /* Clean up and reset everything if needed. */ + cleanup_ext_map(); + + while (p && p < (block + length)) + { + /* p[0] == length of record + p[1] == type of record + For instructions: + p[2] = opcode + p[3] = minor opcode (if opcode == 3) + p[4] = flags + p[5]+ = name + For core regs and condition codes: + p[2] = value + p[3]+ = name + For aux regs: + p[2..5] = value + p[6]+ = name + (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]) */ + + if (p[0] == 0) + return -1; + + switch (p[1]) + { + case EXT_INSTRUCTION: + { + char opcode = p[2]; + char minor = p[3]; + char * insn_name = (char *) xmalloc(( (int)*p-5) * sizeof(char)); + struct ExtInstruction * insn = + (struct ExtInstruction *) xmalloc(sizeof(struct ExtInstruction)); + + if (opcode==3) + opcode = 0x1f - 0x10 + minor - 0x09 + 1; + else + opcode -= 0x10; + insn -> flags = (char) *(p+4); + strcpy(insn_name, (p+5)); + insn -> name = insn_name; + arc_extension_map.instructions[(int) opcode] = insn; + } + break; + + case EXT_CORE_REGISTER: + { + char * core_name = (char *) xmalloc(((int)*p-3) * sizeof(char)); + + strcpy(core_name, (p+3)); + arc_extension_map.coreRegisters[p[2]-32] = core_name; + } + break; + + case EXT_COND_CODE: + { + char * cc_name = (char *) xmalloc( ((int)*p-3) * sizeof(char)); + strcpy(cc_name, (p+3)); + arc_extension_map.condCodes[p[2]-16] = cc_name; + } + break; + + case EXT_AUX_REGISTER: + { + /* trickier -- need to store linked list to these */ + struct ExtAuxRegister *newAuxRegister = + (struct ExtAuxRegister *)malloc(sizeof(struct ExtAuxRegister)); + char * aux_name = (char *) xmalloc ( ((int)*p-6) * sizeof(char)); + + strcpy (aux_name, (p+6)); + newAuxRegister->name = aux_name; + newAuxRegister->address = p[2]<<24 | p[3]<<16 | p[4]<<8 | p[5]; + newAuxRegister->next = arc_extension_map.auxRegisters; + arc_extension_map.auxRegisters = newAuxRegister; + } + break; + + default: + return -1; + + } + p += p[0]; /* move to next record */ + } + + return 0; +} + +/* Load hw extension descibed in .extArcMap ELF section. */ + +void +build_ARC_extmap (text_bfd) + bfd *text_bfd; +{ + char *arcExtMap; + bfd_size_type count; + asection *p; + + for (p = text_bfd->sections; p != NULL; p = p->next) + if (!strcmp (p->name, ".arcextmap")) + { + count = p->_raw_size; + arcExtMap = (char *) xmalloc (count); + if (bfd_get_section_contents (text_bfd, p, (PTR) arcExtMap, 0, count)) + { + arcExtMap_add ((PTR) arcExtMap, count); + break; + } + free ((PTR) arcExtMap); + } +} |