From 8aa13b877740406cde5ce6b4e4b6950bd8741ef6 Mon Sep 17 00:00:00 2001 From: Jim Kingdon Date: Fri, 3 May 1991 06:02:03 +0000 Subject: [PATCH] Make it run on wingnut (88k, DGUX). Complete list of changes in the ChangeLog. --- gdb/coffread.c | 68 +++++- gdb/m88k-opcode.h | 585 ++++++++++++++++++++++++++++++++++++++++++++ gdb/m88k-pinsn.c | 343 ++++++++++++++++++++++++++ gdb/m88k-tdep.c | 600 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/m88k-xdep.c | 340 ++++++++++++++++++++++++++ gdb/symtab.h | 7 + gdb/tm-m88k.h | 37 ++- gdb/utils.c | 5 +- gdb/xm-m88k.h | 7 +- 9 files changed, 1969 insertions(+), 23 deletions(-) create mode 100755 gdb/m88k-opcode.h create mode 100644 gdb/m88k-pinsn.c create mode 100644 gdb/m88k-tdep.c create mode 100644 gdb/m88k-xdep.c diff --git a/gdb/coffread.c b/gdb/coffread.c index 9ef0092ec9..7ebd3657cc 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -28,7 +28,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "symfile.h" +#if defined (TDESC) +/* Need to get C_VERSION and friends. */ +#include +#else /* not TDESC */ #include +#endif /* not TDESC */ + #include #include @@ -129,13 +135,17 @@ static int prev_line_number; static int line_vector_length; #ifdef TDESC +#include "tdesc.h" #define SEM int int_sem_val = 's' << 24 | 'e' << 16 | 'm' << 8 | '.'; int temp_sem_val; int last_coffsem = 2; +#if 0 + /* This isn't used currently. */ int last_coffsyn = 0; +#endif int debug_info = 0; /*used by tdesc */ -extern int tdesc_handle; +extern dc_dcontext_t tdesc_handle; extern int safe_to_init_tdesc_context; #endif @@ -429,7 +439,10 @@ start_symtab () last_source_file = 0; #ifdef TDESC last_coffsem = 2; +#if 0 + /* This isn't used currently. */ last_coffsyn = 0; +#endif #endif /* Initialize the source file information for this file. */ @@ -530,7 +543,11 @@ end_symtab () #ifdef TDESC symtab->coffsem = last_coffsem; +#if 0 + /* This isn't used currently. Besides, if this is really about "syntax", + it shouldn't need to stick around past symbol read-in time. */ symtab->coffsyn = last_coffsyn; +#endif #endif free_named_symtabs (symtab->filename); @@ -651,6 +668,21 @@ find_linenos (abfd, asect, vpinfo) maxoff = offset + size; if (maxoff > info->max_lineno_offset) info->max_lineno_offset = maxoff; +#ifdef TDESC + /* While we're at it, find the debug_info. It's in the s_relptr + (or, in BFD-speak, rel_filepos) of the text segment section header. */ + if (strcmp (bfd_section_name (abfd, asect), ".text") == 0) + { + /* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ + debug_info = asect->rel_filepos; + /* End of warning */ + if (tdesc_handle) + { + dc_terminate (tdesc_handle); + tdesc_handle = 0; + } + } +#endif /* TDESC */ } @@ -687,15 +719,6 @@ coff_symfile_read (sf, addr, mainline) stringtab_offset = symtab_offset + num_symbols * SYMESZ; /* String tab */ /* End of warning */ -#ifdef TDESC - debug_info = text_hdr.s_relptr; - if (tdesc_handle) - { - dc_terminate (tdesc_handle); - tdesc_handle = 0; - } -#endif - /* Read the line number table, all at once. */ info->min_lineno_offset = 0; info->max_lineno_offset = 0; @@ -1047,13 +1070,17 @@ read_coff_symtab (desc, nsyms) break; #ifdef TDESC case C_VERSION: +#if 0 + /* This isn't used currently. */ if (strcmp (cs->c_name, ".coffsyn") == 0) last_coffsyn = cs->c_value; - else if ((strcmp (cs->c_name, ".coffsem") == 0) && + else +#endif /* 0 */ + if ((strcmp (cs->c_name, ".coffsem") == 0) && (cs->c_value != 0)) last_coffsem = cs->c_value; break; -#endif +#endif /* TDESC */ default: #ifdef TDESC @@ -1255,8 +1282,14 @@ getfilename (aux_entry) extern char *rindex (); #ifndef COFF_NO_LONG_FILE_NAMES +#if defined (x_zeroes) + /* Data General. */ + if (aux_entry->x_zeroes == 0) + strcpy (buffer, stringtab + aux_entry->x_offset); +#else /* no x_zeroes */ if (aux_entry->x_file.x_n.x_zeroes == 0) strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset); +#endif /* no x_zeroes */ else #endif /* COFF_NO_LONG_FILE_NAMES */ { @@ -1711,11 +1744,14 @@ decode_base_type (cs, c_type, aux) /* shows up with "void (*foo)();" structure members */ return builtin_type_void; +#if 0 +/* DGUX actually defines both T_ARG and T_VOID to the same value. */ #ifdef T_ARG case T_ARG: /* Shows up in DGUX, I think. Not sure where. */ return builtin_type_void; /* shouldn't show up here */ #endif +#endif /* 0 */ #ifdef T_VOID case T_VOID: @@ -1994,7 +2030,15 @@ read_enum_type (index, length, lastsym) static struct sym_fns coff_sym_fns = { + /* This assumes that 88kbcs implies TDESC and TDESC implies 88kbcs. + If that's not true, this can be relaxed, but if it is true, + it will just cause users grief if we try to read the wrong kind + of symbol file. */ +#if defined (TDESC) + "m88kbcs", 8, +#else /* not TDESC */ "coff", 4, +#endif /* not TDESC */ coff_new_init, coff_symfile_init, coff_symfile_read, coff_symfile_discard }; diff --git a/gdb/m88k-opcode.h b/gdb/m88k-opcode.h new file mode 100755 index 0000000000..c5e643a1ff --- /dev/null +++ b/gdb/m88k-opcode.h @@ -0,0 +1,585 @@ +/* This file has been modified by Data General Corporation, November 1989. */ + + +/* +* Disassembler Instruction Table +* +* The first field of the table is the opcode field. If an opcode +* is specified which has any non-opcode bits on, a system error +* will occur when the system attempts the install it into the +* instruction table. The second parameter is a pointer to the +* instruction mnemonic. Each operand is specified by offset, width, +* and type. The offset is the bit number of the least significant +* bit of the operand with bit 0 being the least significant bit of +* the instruction. The width is the number of bits used to specify +* the operand. The type specifies the output format to be used for +* the operand. The valid formats are: register, register indirect, +* hex constant, and bit field specification. The last field is a +* pointer to the next instruction in the linked list. These pointers +* are initialized by init_disasm(). +* +* Structure Format +* +* struct INSTAB { +* UPINT opcode; +* char *mnemonic; +* struct OPSPEC op1,op2,op3; +* struct SIM_FLAGS flgs; +* struct INSTAB *next; +* } +* +* struct OPSPEC { +* UPINT offset:5; +* UPINT width:6; +* UPINT type:5; +* } +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date +* 1.1 02/05/86 Updated instruction mnemonic table MD +* 1.2 06/16/86 Updated SIM_FLAGS for floating point +* 1.3 09/20/86 Updated for new encoding +* 05/11/89 R. Trawick adapted from Motorola disassembler +*/ + +#include + + +/* + * This file contains the structures and constants needed to build the M88000 + * simulator. It is the main include file, containing all the + * structures, macros and definitions except for the floating point + * instruction set. + */ + +/* + * The following flag informs the Simulator as to what type of byte ordering + * will be used. For instance, a BOFLAG = 1 indicates a DEC VAX and IBM type + * of ordering shall be used. +*/ + +/* # define BOFLAG 1 /* BYTE ORDERING FLAG */ + +/* define the number of bits in the primary opcode field of the instruction, + * the destination field, the source 1 and source 2 fields. + */ +# define OP 8 /* size of opcode field */ +# define DEST 6 /* size of destination */ +# define SOURCE1 6 /* size of source1 */ +# define SOURCE2 6 /* size of source2 */ + +# define REGs 32 /* number of registers */ + +# define WORD long +# define FLAG unsigned +# define STATE short + +# define TRUE 1 +# define FALSE 0 + +# define READ 0 +# define WRITE 1 + +/* The next four equates define the priorities that the various classes + * of instructions have regarding writing results back into registers and + * signalling exceptions. + */ + +# define PINT 0 /* Integer Priority */ +# define PFLT 1 /* Floating Point Priority */ +# define PMEM 2 /* Memory Priority */ +# define NA 3 /* Not Applicable, instruction doesnt write to regs */ +# define HIPRI 3 /* highest of these priorities */ + +/* The instruction registers are an artificial mechanism to speed up + * simulator execution. In the real processor, an instruction register + * is 32 bits wide. In the simulator, the 32 bit instruction is kept in + * a structure field called rawop, and the instruction is partially decoded, + * and split into various fields and flags which make up the other fields + * of the structure. + * The partial decode is done when the instructions are initially loaded + * into simulator memory. The simulator code memory is not an array of + * 32 bit words, but is an array of instruction register structures. + * Yes this wastes memory, but it executes much quicker. + */ + +struct IR_FIELDS { + unsigned long op:OP, + dest: DEST, + src1: SOURCE1, + src2: SOURCE2; + int ltncy, + extime, + wb_pri; /* writeback priority */ + unsigned short imm_flags:2,/* immediate size */ + rs1_used:1, /* register source 1 used */ + rs2_used:1, /* register source 2 used */ + rsd_used:1, /* register source/dest. used */ + c_flag:1, /* complement */ + u_flag:1, /* upper half word */ + n_flag:1, /* execute next */ + wb_flag:1, /* uses writeback slot */ + dest_64:1, /* dest size */ + s1_64:1, /* source 1 size */ + s2_64:1, /* source 2 size */ + scale_flag:1, /* scaled register */ + brk_flg:1; + }; + +struct mem_segs { + struct mem_wrd *seg; /* pointer (returned by calloc) to segment */ + unsigned long baseaddr; /* base load address from file headers */ + unsigned long endaddr; /* Ending address of segment */ + int flags; /* segment control flags (none defined 12/5/86) */ +}; + +#define MAXSEGS (10) /* max number of segment allowed */ +#define MEMSEGSIZE (sizeof(struct mem_segs))/* size of mem_segs structure */ + + +#define BRK_RD (0x01) /* break on memory read */ +#define BRK_WR (0x02) /* break on memory write */ +#define BRK_EXEC (0x04) /* break on execution */ +#define BRK_CNT (0x08) /* break on terminal count */ + + +struct mem_wrd { + struct IR_FIELDS opcode; /* simulator instruction break down */ + union { + unsigned long l; /* memory element break down */ + unsigned short s[2]; + unsigned char c[4]; + } mem; +}; + +#define MEMWRDSIZE (sizeof(struct mem_wrd)) /* size of each 32 bit memory model */ + +/* External declarations */ + +extern struct mem_segs memory[]; +extern struct PROCESSOR m78000; + +struct PROCESSOR { + unsigned WORD + ip, /* execute instruction pointer */ + vbr, /* vector base register */ + psr; /* processor status register */ + + WORD S1bus, /* source 1 */ + S2bus, /* source 2 */ + Dbus, /* destination */ + DAbus, /* data address bus */ + ALU, + Regs[REGs], /* data registers */ + time_left[REGs], /* max clocks before reg is available */ + wb_pri[REGs], /* writeback priority of reg */ + SFU0_regs[REGs], /* integer unit control regs */ + SFU1_regs[REGs], /* floating point control regs */ + Scoreboard[REGs], + Vbr; + unsigned WORD scoreboard, + Psw, + Tpsw; + FLAG jump_pending:1; /* waiting for a jump instr. */ + }; + +# define i26bit 1 /* size of immediate field */ +# define i16bit 2 +# define i10bit 3 + +/* Definitions for fields in psr */ + +# define mode 31 +# define rbo 30 +# define ser 29 +# define carry 28 +# define sf7m 11 +# define sf6m 10 +# define sf5m 9 +# define sf4m 8 +# define sf3m 7 +# define sf2m 6 +# define sf1m 5 +# define mam 4 +# define inm 3 +# define exm 2 +# define trm 1 +# define ovfm 0 + +#define MODEMASK (1<<(mode-1)) +# define SILENT 0 /* simulate without output to crt */ +# define VERBOSE 1 /* simulate in verbose mode */ +# define PR_INSTR 2 /* only print instructions */ + +# define RESET 16 /* reset phase */ + +# define PHASE1 0 /* data path phases */ +# define PHASE2 1 + +/* the 1 clock operations */ + +# define ADDU 1 +# define ADDC 2 +# define ADDUC 3 +# define ADD 4 + +# define SUBU ADD+1 +# define SUBB ADD+2 +# define SUBUB ADD+3 +# define SUB ADD+4 + +# define AND ADD+5 +# define OR ADD+6 +# define XOR ADD+7 +# define CMP ADD+8 + +/* the LOADS */ + +# define LDAB CMP+1 +# define LDAH CMP+2 +# define LDA CMP+3 +# define LDAD CMP+4 + +# define LDB LDAD+1 +# define LDH LDAD+2 +# define LD LDAD+3 +# define LDD LDAD+4 +# define LDBU LDAD+5 +# define LDHU LDAD+6 + +/* the STORES */ + +# define STB LDHU+1 +# define STH LDHU+2 +# define ST LDHU+3 +# define STD LDHU+4 + +/* the exchange */ + +# define XMEMBU LDHU+5 +# define XMEM LDHU+6 + +/* the branches */ +# define JSR STD+1 +# define BSR STD+2 +# define BR STD+3 +# define JMP STD+4 +# define BB1 STD+5 +# define BB0 STD+6 +# define RTN STD+7 +# define BCND STD+8 + +/* the TRAPS */ +# define TB1 BCND+1 +# define TB0 BCND+2 +# define TCND BCND+3 +# define RTE BCND+4 +# define TBND BCND+5 + +/* the MISC instructions */ +# define MUL TBND + 1 +# define DIV MUL +2 +# define DIVU MUL +3 +# define MASK MUL +4 +# define FF0 MUL +5 +# define FF1 MUL +6 +# define CLR MUL +7 +# define SET MUL +8 +# define EXT MUL +9 +# define EXTU MUL +10 +# define MAK MUL +11 +# define ROT MUL +12 + +/* control register manipulations */ + +# define LDCR ROT +1 +# define STCR ROT +2 +# define XCR ROT +3 + +# define FLDCR ROT +4 +# define FSTCR ROT +5 +# define FXCR ROT +6 + + +# define NOP XCR +1 + +/* floating point instructions */ + +# define FADD NOP +1 +# define FSUB NOP +2 +# define FMUL NOP +3 +# define FDIV NOP +4 +# define FSQRT NOP +5 +# define FCMP NOP +6 +# define FIP NOP +7 +# define FLT NOP +8 +# define INT NOP +9 +# define NINT NOP +10 +# define TRNC NOP +11 +# define FLDC NOP +12 +# define FSTC NOP +13 +# define FXC NOP +14 + +# define UEXT(src,off,wid) ((((unsigned int)(src))>>(off)) & ((1<<(wid)) - 1)) +# define SEXT(src,off,wid) (((((int)(src))<<(32-((off)+(wid)))) >>(32-(wid))) ) +# define MAKE(src,off,wid) \ + ((((unsigned int)(src)) & ((1<<(wid)) - 1)) << (off)) + +# define opword(n) (unsigned long) (memaddr->mem.l) + +/* Constants and Masks */ + +#define SFU0 0x80000000 +#define SFU1 0x84000000 +#define SFU7 0x9c000000 +#define RRI10 0xf0000000 +#define RRR 0xf4000000 +#define SFUMASK 0xfc00ffe0 +#define RRRMASK 0xfc00ffe0 +#define RRI10MASK 0xfc00fc00 +#define DEFMASK 0xfc000000 +#define CTRL 0x0000f000 +#define CTRLMASK 0xfc00f800 + +/* Operands types */ + +#define HEX 1 +#define REG 2 +#define IND 3 +#define CONT 3 +#define IND 3 +#define BF 4 +#define REGSC 5 /* scaled register */ +#define CRREG 6 /* control register */ +#define FCRREG 7 /* floating point control register */ +#define PCREL 8 +#define CONDMASK 9 + +/* Hashing Specification */ + +#define HASHVAL 79 + +/* Type definitions */ + +typedef unsigned int UINT; + +/* Structure templates */ + +typedef struct { + unsigned int offset:5; + unsigned int width:6; + unsigned int type:5; +} OPSPEC; + + struct SIM_FLAGS { + int ltncy, /* latency (max number of clocks needed to execute) */ + extime, /* execution time (min number of clocks needed to execute) */ + wb_pri; /* writeback slot priority */ + unsigned long op:OP, /* simulator version of opcode */ + imm_flags:2, /* 10,16 or 26 bit immediate flags */ + rs1_used:1, /* register source 1 used */ + rs2_used:1, /* register source 2 used */ + rsd_used:1, /* register source/dest used */ + c_flag:1, /* complement */ + u_flag:1, /* upper half word */ + n_flag:1, /* execute next */ + wb_flag:1, /* uses writeback slot */ + dest_64:1, /* double precision dest */ + s1_64:1, /* double precision source 1 */ + s2_64:1, /* double precision source 2 */ + scale_flag:1; /* register is scaled */ +}; + +typedef struct INSTRUCTAB { + unsigned int opcode; + char *mnemonic; + OPSPEC op1,op2,op3; + struct SIM_FLAGS flgs; + struct INSTRUCTAB *next; +} INSTAB; + + +/* Opcode Mnemonic Op 1 Spec Op 2 Spec Op 3 Spec Simflags Next */ + +static INSTAB instructions[] = +{0xf400c800,"jsr ",{0,5,REG} ,{0,0,0} ,{0,0,0} , {2,2,NA,JSR , 0,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xf400cc00,"jsr.n ",{0,5,REG} ,{0,0,0} ,{0,0,0} , {1,1,NA,JSR , 0,0,1,0,0,0,1,1,0,0,0,0}, NULL, + 0xf400c000,"jmp ",{0,5,REG} ,{0,0,0} ,{0,0,0} , {2,2,NA,JMP , 0,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xf400c400,"jmp.n ",{0,5,REG} ,{0,0,0} ,{0,0,0} , {1,1,NA,JMP , 0,0,1,0,0,0,1,1,0,0,0,0}, NULL, + 0xc8000000,"bsr ",{0,26,PCREL},{0,0,0} ,{0,0,0} , {2,2,NA,BSR , i26bit,0,0,0,0,0,0,1,0,0,0,0}, NULL, + 0xcc000000,"bsr.n ",{0,26,PCREL},{0,0,0} ,{0,0,0} , {1,1,NA,BSR , i26bit,0,0,0,0,0,1,1,0,0,0,0}, NULL, + 0xc0000000,"br ",{0,26,PCREL},{0,0,0} ,{0,0,0} , {2,2,NA,BR , i26bit,0,0,0,0,0,0,1,0,0,0,0}, NULL, + 0xc4000000,"br.n ",{0,26,PCREL},{0,0,0} ,{0,0,0} , {1,1,NA,BR , i26bit,0,0,0,0,0,1,1,0,0,0,0}, NULL, + 0xd0000000,"bb0 ",{21,5,HEX} ,{16,5,REG} ,{0,16,PCREL},{2,2,NA,BB0, i16bit,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xd4000000,"bb0.n ",{21,5,HEX} ,{16,5,REG} ,{0,16,PCREL},{1,1,NA,BB0, i16bit,0,1,0,0,0,1,1,0,0,0,0}, NULL, + 0xd8000000,"bb1 ",{21,5,HEX},{16,5,REG} ,{0,16,PCREL},{2,2,NA,BB1, i16bit,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xdc000000,"bb1.n ",{21,5,HEX},{16,5,REG} ,{0,16,PCREL},{1,1,NA,BB1, i16bit,0,1,0,0,0,1,1,0,0,0,0}, NULL, + 0xf000d000,"tb0 ",{21,5,HEX} ,{16,5,REG} ,{0,10,HEX}, {2,2,NA,TB0 , i10bit,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xf000d800,"tb1 ",{21,5,HEX} ,{16,5,REG} ,{0,10,HEX}, {2,2,NA,TB1 , i10bit,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xe8000000,"bcnd ",{21,5,CONDMASK},{16,5,REG},{0,16,PCREL},{2,2,NA,BCND, i16bit,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xec000000,"bcnd.n ",{21,5,CONDMASK},{16,5,REG},{0,16,PCREL},{1,1,NA,BCND, i16bit,0,1,0,0,0,1,1,0,0,0,0}, NULL, + 0xf000e800,"tcnd ",{21,5,CONDMASK},{16,5,REG},{0,10,HEX}, {2,2,NA,TCND, i10bit,0,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xf8000000,"tbnd ",{16,5,REG} ,{0,16,HEX} ,{0,0,0} , {2,2,NA,TBND, i10bit,1,0,0,0,0,0,1,0,0,0,0}, NULL, + 0xf400f800,"tbnd ",{16,5,REG} ,{0,5,REG} ,{0,0,0} , {2,2,NA,TBND, 0,1,1,0,0,0,0,1,0,0,0,0}, NULL, + 0xf400fc00,"rte ",{0,0,0} ,{0,0,0} ,{0,0,0} , {2,2,NA,RTE , 0,0,0,0,0,0,0,1,0,0,0,0}, NULL, + 0x1c000000,"ld.b ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDB ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001c00,"ld.b ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDB , 0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0x0c000000,"ld.bu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDBU, i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4000c00,"ld.bu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDBU ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0x18000000,"ld.h ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDH ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001800,"ld.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDH ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001a00,"ld.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LDH ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL, + 0x08000000,"ld.hu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDHU, i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4000800,"ld.hu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDHU ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4000a00,"ld.hu ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LDHU ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL, + 0x14000000,"ld ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LD ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001400,"ld ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001600,"ld ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL, + 0x10000000,"ld.d ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDD ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001000,"ld.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDD ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001200,"ld.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LDD ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL, + 0xf4001500,"ld.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4001700,"ld.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL, + 0x2c000000,"st.b ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,STB ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4002c00,"st.b ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,STB ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0x28000000,"st.h ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,STH ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4002800,"st.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,STH ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4002a00,"st.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,STH ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL, + 0x24000000,"st ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,ST ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL, + 0xf4002400,"st ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4002600,"st ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL, + 0x20000000,"st.d ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,STD ,i16bit,0,1,0,0,0,0,1,0,0,0,0} ,NULL, + 0xf4002000,"st.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,STD ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4002200,"st.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,STD ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL, + 0xf4002500,"st.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4002700,"st.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL, + 0x00000000,"xmem.bu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,XMEMBU ,i16bit,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4000000,"xmem.bu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x04000000,"xmem ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,XMEM ,i16bit,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4000400,"xmem ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4000600,"xmem ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL, + 0xf4000500,"xmem.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0xf4000700,"xmem.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL, + 0xf4003e00,"lda.b ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAH, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL, + 0xf4003a00,"lda.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAH, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL, + 0xf4003600,"lda ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDA , 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL, + 0xf4003200,"lda.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAD, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL, + + 0x80004000,"ldcr ",{21,5,REG} ,{5,6,CRREG} ,{0,0,0} ,{1,1,PINT,LDCR, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0x80008000,"stcr ",{16,5,REG} ,{5,6,CRREG} ,{0,0,0} ,{1,1,PINT,STCR, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0x8000c000,"xcr ",{21,5,REG} ,{16,5,REG} ,{5,6,CRREG},{1,1,PINT,XCR, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + + 0xf4006000,"addu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006200,"addu.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006100,"addu.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006300,"addu.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006400,"subu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006600,"subu.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006500,"subu.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006700,"subu.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006900,"divu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {32,32,PINT,DIVU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4006d00,"mul ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,4,PINT,MUL, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007000,"add ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007200,"add.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007100,"add.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007300,"add.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007400,"sub ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007600,"sub.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007500,"sub.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007700,"sub.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007900,"div ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {32,32,PINT,DIV , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4007d00,"cmp ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,CMP, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + + 0x60000000,"addu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,ADDU, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x64000000,"subu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,SUBU, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + + 0x68000000,"divu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {32,32,PINT,DIVU, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x6c000000,"mul ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {4,1,PINT,MUL, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x70000000,"add ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,ADD, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x74000000,"sub ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,SUB, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x78000000,"div ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {32,32,PINT,DIV, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x7c000000,"cmp ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,CMP, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + + 0xf4004000,"and ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,AND ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4004400,"and.c ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,AND ,0,1,1,1,1,0,0,0,0,0,0,0} ,NULL, + 0xf4005800,"or ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,OR ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4005c00,"or.c ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,OR ,0,1,1,1,1,0,0,0,0,0,0,0} ,NULL, + 0xf4005000,"xor ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,XOR ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4005400,"xor.c ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,XOR ,0,1,1,1,1,0,0,0,0,0,0,0} ,NULL, + 0x40000000,"and ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,AND ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x44000000,"and.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,AND ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL, + 0x58000000,"or ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,OR ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x5c000000,"or.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,OR ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL, + 0x50000000,"xor ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,XOR ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x54000000,"xor.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,XOR ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL, + 0x48000000,"mask ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,MASK ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0x4c000000,"mask.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,MASK ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL, + 0xf400ec00,"ff0 ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {1,1,PINT,FF0 ,0,0,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf400e800,"ff1 ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {1,1,PINT,FF1 ,0,0,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf0008000,"clr ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,CLR ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf0008800,"set ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,SET ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf0009000,"ext ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,EXT ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf0009800,"extu ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,EXTU ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf000a000,"mak ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,MAK ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf000a800,"rot ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,ROT ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4008000,"clr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,CLR ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4008800,"set ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SET ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4009000,"ext ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,EXT ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf4009800,"extu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,EXTU ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf400a000,"mak ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,MAK ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + 0xf400a800,"rot ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ROT ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL, + + 0x84002800,"fadd.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {5,1,PFLT,FADD ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84002880,"fadd.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL, + 0x84002a00,"fadd.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL, + 0x84002a80,"fadd.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL, + 0x84002820,"fadd.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x840028a0,"fadd.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL, + 0x84002a20,"fadd.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL, + 0x84002aa0,"fadd.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL, + 0x84003000,"fsub.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {5,1,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84003080,"fsub.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL, + 0x84003200,"fsub.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL, + 0x84003280,"fsub.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL, + 0x84003020,"fsub.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x840030a0,"fsub.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL, + 0x84003220,"fsub.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL, + 0x840032a0,"fsub.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL, + 0x84000000,"fmul.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84000080,"fmul.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL, + 0x84000200,"fmul.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL, + 0x84000280,"fmul.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL, + 0x84000020,"fmul.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x840000a0,"fmul.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL, + 0x84000220,"fmul.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL, + 0x840002a0,"fmul.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL, + 0x84007000,"fdiv.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {30,30,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84007080,"fdiv.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL, + 0x84007200,"fdiv.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL, + 0x84007280,"fdiv.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL, + 0x84007020,"fdiv.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x840070a0,"fdiv.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL, + 0x84007220,"fdiv.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL, + 0x840072a0,"fdiv.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL, + 0x84007800,"fsqrt.ss ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84007880,"fsqrt.sd ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84007820,"fsqrt.ds ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x840078a0,"fsqrt.dd ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {6,1,PFLT,FLT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x84003800,"fcmp.ss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {5,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84003880,"fcmp.sd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL, + 0x84003a00,"fcmp.ds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x84003a80,"fcmp.dd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL, + 0x84002000,"flt.s ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84002020,"flt.d ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {6,1,PFLT,FLT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x84004800,"int.s ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,INT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84004880,"int.d ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {6,1,PFLT,INT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x84005000,"nint.s ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,INT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84005080,"nint.d ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {6,1,PFLT,INT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL, + 0x84005800,"trnc.s ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {5,1,PFLT,TRNC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x84005880,"trnc.d ",{21,5,REG} ,{0,5,REG} ,{0,0,0} , {6,1,PFLT,TRNC ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL, + + 0x80004800,"fldcr ",{21,5,REG} ,{5,6,FCRREG} ,{0,0,0} , {1,1,PFLT,FLDC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x80008800,"fstcr ",{16,5,REG} ,{5,6,FCRREG} ,{0,0,0} , {1,1,PFLT,FSTC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL, + 0x8000c800,"fxcr ",{21,5,REG} ,{16,5,REG} ,{5,6,FCRREG} , {1,1,PFLT,FXC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL}; + diff --git a/gdb/m88k-pinsn.c b/gdb/m88k-pinsn.c new file mode 100644 index 0000000000..bede269b0a --- /dev/null +++ b/gdb/m88k-pinsn.c @@ -0,0 +1,343 @@ +/* This file has been modified by Data General Corporation, November 1989. */ + +#include +#include "m88k-opcode.h" +#include "defs.h" +#include "symtab.h" + +void sprint_address (); + +/* Changed hashtab to hashtable to avoid naming conflict + with libdc.o (used for tdesc) for m88k. +*/ + +INSTAB *hashtable[HASHVAL] = {0}; + +/* +* Disassemble an M88000 Instruction +* +* +* This module decodes the first instruction in inbuf. It uses the pc +* to display pc-relative displacements. It writes the disassembled +* instruction in outbuf. +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date by Motorola +* 05/11/89 R. Trawick adapted to GDB interface. +*/ +#define MAXLEN 20 + +print_insn (memaddr, stream) + CORE_ADDR memaddr; + FILE *stream; +{ + unsigned char buffer[MAXLEN]; + /* should be expanded if disassembler prints symbol names */ + char outbuf[100]; + int n; + + /* Instruction addresses may have low two bits set. Clear them. */ + memaddr&= 0xfffffffc; + read_memory (memaddr, buffer, MAXLEN); + + n = m88kdis ((int)memaddr, buffer, outbuf); + + fputs (outbuf, stream); + + return (n); +} + +/* + * disassemble the first instruction in 'inbuf'. + * 'pc' should be the address of this instruction, it will + * be used to print the target address if this is a relative jump or call + * 'outbuf' gets filled in with the disassembled instruction. It should + * be long enough to hold the longest disassembled instruction. + * 100 bytes is certainly enough, unless symbol printing is added later + * The function returns the length of this instruction in bytes. + */ + +int m88kdis( pc, inbuf, outbuf ) + + int pc; + int *inbuf; + char *outbuf; + +{ static ihashtab_initialized = 0; + int instruction; + unsigned int opcode; + INSTAB *entry_ptr; + int opmask; + int class; + + instruction= *inbuf; + + if (!ihashtab_initialized) { + init_disasm(); + } + + /* create a the appropriate mask to isolate the opcode */ + opmask= DEFMASK; + class= instruction & DEFMASK; + if ((class >= SFU0) && (class <= SFU7)) { + if (instruction < SFU1) { + opmask= CTRLMASK; + } else { + opmask= SFUMASK; + } + } else if (class == RRR) { + opmask= RRRMASK; + } else if (class == RRI10) { + opmask= RRI10MASK; + } + + /* isolate the opcode */ + opcode= instruction & opmask; + + /* search the hash table with the isolated opcode */ + for (entry_ptr= hashtable[ opcode % HASHVAL ]; + (entry_ptr != NULL) && (entry_ptr->opcode != opcode); + entry_ptr= entry_ptr->next) { + } + + if (entry_ptr == NULL) { + sprintf( outbuf, "word\t%08x", instruction ); + } else { + sprintf( outbuf, "%s\t", entry_ptr->mnemonic ); + sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op1), instruction, pc, 1 ); + sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op2), instruction, pc, 0 ); + sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op3), instruction, pc, 0 ); + } + + + return 4; +} + + +/* +* Decode an Operand of an Instruction +* +* Functional Description +* +* This module formats and writes an operand of an instruction to buf +* based on the operand specification. When the first flag is set this +* is the first operand of an instruction. Undefined operand types +* cause a message. +* +* Parameters +* char *buf buffer where the operand may be printed +* OPSPEC *opptr Pointer to an operand specification +* UINT inst Instruction from which operand is extracted +* UINT pc PC of instruction; used for pc-relative disp. +* int first Flag which if nonzero indicates the first +* operand of an instruction +* +* Output +* +* The operand specified is extracted from the instruction and is +* written to buf in the format specified. The operand is preceded +* by a comma if it is not the first operand of an instruction and it +* is not a register indirect form. Registers are preceded by 'r' and +* hex values by '0x'. +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date +*/ + +sprintop( buf, opptr, inst, pc, first ) + + char *buf; + OPSPEC *opptr; + UINT inst; + int pc; + int first; + +{ int extracted_field; + char *cond_mask_sym; + char cond_mask_sym_buf[6]; + + if (opptr->width == 0) + return; + + switch(opptr->type) { + case CRREG: + if (!first) + *buf++= ','; + sprintf( buf, "cr%d", UEXT(inst,opptr->offset,opptr->width)); + break; + + case FCRREG: + if (!first) + *buf++= ','; + sprintf( buf, "fcr%d", UEXT(inst,opptr->offset,opptr->width)); + break; + + case REGSC: + sprintf( buf, "[r%d]", UEXT(inst,opptr->offset,opptr->width)); + break; + + case REG: + if (!first) + *buf++= ','; + sprintf( buf, "r%d", UEXT(inst,opptr->offset,opptr->width)); + break; + + case HEX: + if (!first) + *buf++= ','; + extracted_field= UEXT(inst, opptr->offset, opptr->width); + if (extracted_field == 0) { + sprintf( buf, "0" ); + } else { + sprintf( buf, "0x%02x", extracted_field ); + } + break; + + case CONDMASK: + if (!first) + *buf++= ','; + extracted_field= UEXT(inst, opptr->offset, opptr->width); + switch (extracted_field & 0x0f) { + case 0x1: cond_mask_sym= "gt0"; + break; + case 0x2: cond_mask_sym= "eq0"; + break; + case 0x3: cond_mask_sym= "ge0"; + break; + case 0xc: cond_mask_sym= "lt0"; + break; + case 0xd: cond_mask_sym= "ne0"; + break; + case 0xe: cond_mask_sym= "le0"; + break; + default: cond_mask_sym= cond_mask_sym_buf; + sprintf( cond_mask_sym_buf, + "%x", + extracted_field ); + break; + } + strcpy( buf, cond_mask_sym ); + break; + + case PCREL: + if (!first) + *buf++= ','; + sprint_address( pc + 4*(SEXT(inst,opptr->offset,opptr->width)), + buf ); + break; + + case CONT: + sprintf( buf, + "%d,r%d", + UEXT(inst,opptr->offset,5), + UEXT(inst,(opptr->offset)+5,5) ); + break; + + case BF: + if (!first) + *buf++= ','; + sprintf( buf, + "%d<%d>", + UEXT(inst,(opptr->offset)+5,5), + UEXT(inst,opptr->offset,5)); + break; + + default: + sprintf( buf, "", inst ); + } + +} + +/* +* Initialize the Disassembler Instruction Table +* +* Initialize the hash table and instruction table for the disassembler. +* This should be called once before the first call to disasm(). +* +* Parameters +* +* Output +* +* If the debug option is selected, certain statistics about the hashing +* distribution are written to stdout. +* +* Revision History +* +* Revision 1.0 11/08/85 Creation date +*/ + +init_disasm() +{ + int i,size; + + for (i=0 ; i < HASHVAL ; i++) + hashtable[i] = NULL; + + for (i=0, size = sizeof(instructions) / sizeof(INSTAB) ; i < size ; + install(&instructions[i++])); + +} + +/* +* Insert an instruction into the disassembler table by hashing the +* opcode and inserting it into the linked list for that hash value. +* +* Parameters +* +* INSTAB *instptr Pointer to the entry in the instruction table +* to be installed +* +* Revision 1.0 11/08/85 Creation date +* 05/11/89 R. TRAWICK ADAPTED FROM MOTOROLA +*/ + +install(instptr) + INSTAB *instptr; +{ + UINT i; + + i = (instptr->opcode) % HASHVAL; + instptr->next = hashtable[i]; + hashtable[i] = instptr; +} + + +/* adapted from print_address in printcmd by R. Trawick 5/15/89. The two should + be combined. + */ + +void sprint_address (addr, buffer) + + CORE_ADDR addr; + char *buffer; + +{ + register int i; + struct symbol *fs; + char *name; + int name_location; + + sprintf ( buffer, "0x%x", addr); + + fs = find_pc_function (addr); + + if (!fs) { + i = find_pc_misc_function (addr); + + if (i < 0) return; /* If nothing comes through, don't + print anything symbolic */ + + name = misc_function_vector[i].name; + name_location = misc_function_vector[i].address; + } else { + name = fs->name; + name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs)); + } + + if (addr - name_location) + sprintf (buffer, " <%s+%d>", name, addr - name_location); + else + sprintf (buffer, " <%s>", name); +} diff --git a/gdb/m88k-tdep.c b/gdb/m88k-tdep.c new file mode 100644 index 0000000000..ee78ca1da4 --- /dev/null +++ b/gdb/m88k-tdep.c @@ -0,0 +1,600 @@ +/* Copyright (C) 1988, 1990 Free Software Foundation, Inc. + +This file is part of GDB. + +GDB 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 1, or (at your option) +any later version. + +GDB 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 GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include "defs.h" +#include "param.h" +#include "frame.h" +#include "inferior.h" +#include "value.h" + +#ifdef USG +#include +#endif + +#include +#include +#include +#include "gdbcore.h" +#include +#ifndef USER /* added to support BCS ptrace_user */ + +#define USER ptrace_user +#endif +#include +#include + +#ifdef COFF_ENCAPSULATE +#include "a.out.encap.h" +#else +#include +#endif + +#include +#include + +#include "symtab.h" +#include "setjmp.h" +#include "value.h" + +int stack_error; +jmp_buf stack_jmp; + +void +tdesc_error_function (environment, continuable, message) +dc_word_t environment; +dc_boolean_t continuable; +char *message; +{ + if (stack_error) longjmp (stack_jmp, 1); + if (!continuable) + { + printf("%s\n",message); + abort(); + } +} + + +void +tdesc_read_function (environment, memory, length, buffer) +dc_word_t environment; +dc_word_t memory; +int length; +char *buffer; +{ + int ptrace_code; + errno = 0; + if (memory < 2048) +#if 0 + /* This is a no-op! It sets buffer, but doesn't do anything to + what buffer points to. What does this function do anyway? + And this is wrong for cross-debugging. */ + buffer = ptrace (3, inferior_pid, memory, 0); +#else + return; +#endif + else + read_memory (memory, buffer, length); +} + +/* Map function for tdesc */ +void +tdesc_map_function (map_env, loc, map_info_in, map_info_out) +dc_word_t map_env; +dc_word_t loc; +dc_map_info_in_t map_info_in; +dc_map_info_out_t *map_info_out; +{ +int map_flags = DC_MIO_ENTRY_POINT | DC_MIO_IMPLICIT_PROLOGUE_END; +int entry_point = get_pc_function_start(loc); +map_info_out->flags = map_flags; +map_info_out->entry_point = entry_point; +} + +dc_handle_t tdesc_handle; + +extern int debug_info; + +void +init_tdesc () +{ + tdesc_handle = dc_initiate (debug_info, tdesc_error_function, + 0,tdesc_read_function,0,0,0,0,0,tdesc_map_function,0); +} +dc_dcontext_t current_context; + +/* setup current context, called from wait_for_inferior */ + +dc_dcontext_t +init_dcontext() +{ + dc_word_t reg_info[DC_NUM_REG]; + dc_word_t reg_flags[2] = {0,-1}; + dc_word_t aux_info[DC_NUM_AUX]; + dc_word_t aux_flags[2] = {0,-1}; + dc_exactness_t loc_exact = DC_NO; + dc_word_t psr_info; + dc_boolean_t psr_ind = 0; + dc_word_t psr_flags[2] = {0,-1}; + + bcopy (®isters, reg_info, DC_NUM_REG * 4); + aux_info[DC_AUX_LOC] = read_register(SXIP_REGNUM); + aux_info[DC_AUX_SXIP] = read_register(SXIP_REGNUM); + aux_info[DC_AUX_SNIP] = read_register(SNIP_REGNUM); + aux_info[DC_AUX_SFIP] = read_register(SFIP_REGNUM); + aux_info[DC_AUX_FPSR] = read_register(FPSR_REGNUM); + aux_info[DC_AUX_FPCR] = read_register(FPCR_REGNUM); + + psr_info = read_register(PSR_REGNUM); + + return dc_make_dcontext (tdesc_handle, reg_info, reg_flags, aux_info, + aux_flags, loc_exact, psr_info, psr_ind, psr_flags); +} + + +dc_dcontext_t +get_prev_context (context) + dc_dcontext_t context; +{ + return current_context = dc_previous_dcontext (context); +} + + + + +/* Determine frame base for this file's frames. This will be either + the CFA or the old style FP_REGNUM; the symtab for the current pc's + file has the information */ + +CORE_ADDR +get_frame_base(pc) +CORE_ADDR pc; +{ + struct symtab *this_file = find_pc_symtab(pc); + int coffsem_frame_position; + + /* If this_file is null, there's a good chance the file was compiled + without -g. If that's the case, use CFA (canonical frame addr) + as the default frame pointer. */ + + if (this_file) + { + coffsem_frame_position = this_file->coffsem & 3; + if (coffsem_frame_position == 1) + return (CORE_ADDR) dc_general_register (current_context, FP_REGNUM); + else + /* default is CFA, as well as if coffsem==2 */ + return (CORE_ADDR) dc_frame_address (current_context); + } + + return (CORE_ADDR) dc_frame_address (current_context); +} + +#if TARGET_BYTE_ORDER != HOST_BYTE_ORDER +you lose +#else /* Host and target byte order the same. */ +#define SINGLE_EXP_BITS 8 +#define DOUBLE_EXP_BITS 11 +int +IEEE_isNAN(fp, len) + int *fp, len; + /* fp points to a single precision OR double precision + * floating point value; len is the number of bytes, either 4 or 8. + * Returns 1 iff fp points to a valid IEEE floating point number. + * Returns 0 if fp points to a denormalized number or a NaN + */ +{ + int exponent; + if (len == 4) + { + exponent = *fp; + exponent = exponent << 1 >> (32 - SINGLE_EXP_BITS - 1); + return ((exponent == -1) || (! exponent && *fp)); + } + else if (len == 8) + { + exponent = *(fp+1); + exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1); + return ((exponent == -1) || (! exponent && *fp * *(fp+1))); + } + else return 1; +} +#endif /* Host and target byte order the same. */ + +#define FIRST_PRESERVED_REGNUM 14 +#define LAST_PRESERVED_REGNUM 25 +#define FIRST_PARM_REGNUM 2 +#define LAST_PARM_REGNUM 9 + +#define MAX_REG_PARMS (LAST_PARM_REGNUM - FIRST_PARM_REGNUM + 1) + +void +frame_find_saved_regs (fi, fsr) + struct frame_info *fi; + struct frame_saved_regs *fsr; +{ + register int regnum; + + error ("Feature not implemented for the 88k yet."); + return; + +#if 0 + for (regnum = FIRST_PARM_REGNUM; regnum <= LAST_PARM_REGNUM; regnum++) + fsr->regs[regnum] + = (unsigned) fi->frame - ((regnum - FIRST_PARM_REGNUM) * 4); + + fsr->regs[SP_REGNUM] = 0; /* SP not saved in frames */ + fsr->regs[FP_REGNUM] = fi->frame; + fsr->regs[PC_REGNUM] = fi->frame + 4; +#endif + } + + static int + pushed_size (prev_words, v) + int prev_words; + struct value *v; + { + switch (TYPE_CODE (VALUE_TYPE (v))) + { + case TYPE_CODE_VOID: /* Void type (values zero length) */ + + return 0; /* That was easy! */ + + case TYPE_CODE_PTR: /* Pointer type */ + case TYPE_CODE_ENUM: /* Enumeration type */ + case TYPE_CODE_INT: /* Integer type */ + case TYPE_CODE_REF: /* C++ Reference types */ + case TYPE_CODE_ARRAY: /* Array type, lower bound zero */ + + return 1; + + case TYPE_CODE_FLT: /* Floating type */ + + if (TYPE_LENGTH (VALUE_TYPE (v)) == 4) + return 1; + else + /* Assume that it must be a double. */ + if (prev_words & 1) /* at an odd-word boundary */ + return 3; /* round to 8-byte boundary */ + else + return 2; + + case TYPE_CODE_STRUCT: /* C struct or Pascal record */ + case TYPE_CODE_UNION: /* C union or Pascal variant part */ + + return (((TYPE_LENGTH (VALUE_TYPE (v)) + 3) / 4) * 4); + + case TYPE_CODE_FUNC: /* Function type */ + case TYPE_CODE_SET: /* Pascal sets */ + case TYPE_CODE_RANGE: /* Range (integers within bounds) */ + case TYPE_CODE_PASCAL_ARRAY: /* Array with explicit type of index */ + case TYPE_CODE_MEMBER: /* Member type */ + case TYPE_CODE_METHOD: /* Method type */ + /* Don't know how to pass these yet. */ + + case TYPE_CODE_UNDEF: /* Not used; catches errors */ + default: + abort (); + } + } + + static void + store_parm_word (address, val) + CORE_ADDR address; + int val; + { + write_memory (address, &val, 4); + } + + static int + store_parm (prev_words, left_parm_addr, v) + unsigned int prev_words; + CORE_ADDR left_parm_addr; + struct value *v; + { + CORE_ADDR start = left_parm_addr + (prev_words * 4); + int *val_addr = (int *)VALUE_CONTENTS(v); + + switch (TYPE_CODE (VALUE_TYPE (v))) + { + case TYPE_CODE_VOID: /* Void type (values zero length) */ + + return 0; + + case TYPE_CODE_PTR: /* Pointer type */ + case TYPE_CODE_ENUM: /* Enumeration type */ + case TYPE_CODE_INT: /* Integer type */ + case TYPE_CODE_ARRAY: /* Array type, lower bound zero */ + case TYPE_CODE_REF: /* C++ Reference types */ + + store_parm_word (start, *val_addr); + return 1; + + case TYPE_CODE_FLT: /* Floating type */ + + if (TYPE_LENGTH (VALUE_TYPE (v)) == 4) + { + store_parm_word (start, *val_addr); + return 1; + } + else + { + store_parm_word (start + ((prev_words & 1) * 4), val_addr[0]); + store_parm_word (start + ((prev_words & 1) * 4) + 4, val_addr[1]); + return 2 + (prev_words & 1); + } + + case TYPE_CODE_STRUCT: /* C struct or Pascal record */ + case TYPE_CODE_UNION: /* C union or Pascal variant part */ + + { + unsigned int words = (((TYPE_LENGTH (VALUE_TYPE (v)) + 3) / 4) * 4); + unsigned int word; + + for (word = 0; word < words; word++) + store_parm_word (start + (word * 4), val_addr[word]); + return words; + } + + default: + abort (); + } + } + + /* This routine sets up all of the parameter values needed to make a pseudo + call. The name "push_parameters" is a misnomer on some archs, + because (on the m88k) most parameters generally end up being passed in + registers rather than on the stack. In this routine however, we do + end up storing *all* parameter values onto the stack (even if we will + realize later that some of these stores were unnecessary). */ + +void +push_parameters (return_type, struct_conv, nargs, args) + struct type *return_type; + int struct_conv; + int nargs; + value *args; + { + int parm_num; + unsigned int p_words = 0; + CORE_ADDR left_parm_addr; + + /* Start out by creating a space for the return value (if need be). We + only need to do this if the return value is a struct or union. If we + do make a space for a struct or union return value, then we must also + arrange for the base address of that space to go into r12, which is the + standard place to pass the address of the return value area to the + callee. Note that only structs and unions are returned in this fashion. + Ints, enums, pointers, and floats are returned into r2. Doubles are + returned into the register pair {r2,r3}. Note also that the space + reserved for a struct or union return value only has to be word aligned + (not double-word) but it is double-word aligned here anyway (just in + case that becomes important someday). */ + + switch (TYPE_CODE (return_type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + { + int return_bytes = ((TYPE_LENGTH (return_type) + 7) / 8) * 8; + CORE_ADDR rv_addr; + + rv_addr = read_register (SP_REGNUM) - return_bytes; + + write_register (SP_REGNUM, rv_addr); /* push space onto the stack */ + write_register (SRA_REGNUM, rv_addr);/* set return value register */ + } + } + + /* Here we make a pre-pass on the whole parameter list to figure out exactly + how many words worth of stuff we are going to pass. */ + + for (p_words = 0, parm_num = 0; parm_num < nargs; parm_num++) + p_words += pushed_size (p_words, value_arg_coerce (args[parm_num])); + + /* Now, check to see if we have to round up the number of parameter words + to get up to the next 8-bytes boundary. This may be necessary because + of the software convention to always keep the stack aligned on an 8-byte + boundary. */ + + if (p_words & 1) + p_words++; /* round to 8-byte boundary */ + + /* Now figure out the absolute address of the leftmost parameter, and update + the stack pointer to point at that address. */ + + left_parm_addr = read_register (SP_REGNUM) - (p_words * 4); + write_register (SP_REGNUM, left_parm_addr); + + /* Now we can go through all of the parameters (in left-to-right order) + and write them to their parameter stack slots. Note that we are not + really "pushing" the parameter values. The stack space for these values + was already allocated above. Now we are just filling it up. */ + + for (p_words = 0, parm_num = 0; parm_num < nargs; parm_num++) + p_words += + store_parm (p_words, left_parm_addr, value_arg_coerce (args[parm_num])); + + /* Now that we are all done storing the parameter values into the stack, we + must go back and load up the parameter registers with the values from the + corresponding stack slots. Note that in the two cases of (a) gaps in the + parameter word sequence causes by (otherwise) misaligned doubles, and (b) + slots correcponding to structs or unions, the work we do here in loading + some parameter registers may be unnecessary, but who cares? */ + + for (p_words = 0; p_words < 8; p_words++) + { + write_register (FIRST_PARM_REGNUM + p_words, + read_memory_integer (left_parm_addr + (p_words * 4), 4)); + } +} + +void +pop_frame () +{ + error ("Feature not implemented for the m88k yet."); + return; +} + + void + collect_returned_value (rval, value_type, struct_return, nargs, args) + value *rval; + struct type *value_type; + int struct_return; + int nargs; + value *args; + { + char retbuf[REGISTER_BYTES]; + + bcopy (registers, retbuf, REGISTER_BYTES); + *rval = value_being_returned (value_type, retbuf, struct_return); + return; + } + +#if 0 +/* Now handled in a machine independent way with CALL_DUMMY_LOCATION. */ + /* Stuff a breakpoint instruction onto the stack (or elsewhere if the stack + is not a good place for it). Return the address at which the instruction + got stuffed, or zero if we were unable to stuff it anywhere. */ + + CORE_ADDR + push_breakpoint () + { + static char breakpoint_insn[] = BREAKPOINT; + extern CORE_ADDR text_end; /* of inferior */ + static char readback_buffer[] = BREAKPOINT; + int i; + + /* With a little bit of luck, we can just stash the breakpoint instruction + in the word just beyond the end of normal text space. For systems on + which the hardware will not allow us to execute out of the stack segment, + we have to hope that we *are* at least allowed to effectively extend the + text segment by one word. If the actual end of user's the text segment + happens to fall right at a page boundary this trick may fail. Note that + we check for this by reading after writing, and comparing in order to + be sure that the write worked. */ + + write_memory (text_end, &breakpoint_insn, 4); + + /* Fill the readback buffer with some garbage which is certain to be + unequal to the breakpoint insn. That way we can tell if the + following read doesn't actually succeed. */ + + for (i = 0; i < sizeof (readback_buffer); i++) + readback_buffer[i] = ~ readback_buffer[i]; /* Invert the bits */ + + /* Now check that the breakpoint insn was successfully installed. */ + + read_memory (text_end, readback_buffer, sizeof (readback_buffer)); + for (i = 0; i < sizeof (readback_buffer); i++) + if (readback_buffer[i] != breakpoint_insn[i]) + return 0; /* Failed to install! */ + + return text_end; + } +#endif + +/* Like dc_psr_register but takes an extra int arg. */ +static dc_word_t +psr_register (context, dummy) + dc_dcontext_t context; + int dummy; +{ + return dc_psr_register (context); +} + +/* Same functionality as get_saved_register in findvar.c, but implemented + to use tdesc. */ +void +get_saved_register (raw_buffer, optim, addrp, frame, regnum, lvalp) + char *raw_buffer; + int *optim; + CORE_ADDR *addrp; + FRAME frame; + int regnum; + enum lval_type *lvalp; +{ + struct frame_info *fi = get_frame_info (frame); + + /* Functions to say whether a register is optimized out, and + if not, to get the value. Take as args a context and the + value of get_reg_arg. */ + int (*get_reg_state) (); + dc_word_t (*get_reg) (); + int get_reg_arg; + + /* Because tdesc doesn't tell us whether it got it from a register + or memory, always say we don't have an address for it. */ + if (addrp != NULL) + *addrp = 0; + + if (regnum < DC_NUM_REG) + { + get_reg_state = dc_general_register_state; + get_reg = dc_general_register; + get_reg_arg = regnum; + } + else + { + get_reg_state = dc_auxiliary_register_state; + get_reg = dc_auxiliary_register; + switch (regnum) + { + case SXIP_REGNUM: + get_reg_arg = DC_AUX_SXIP; + break; + case SNIP_REGNUM: + get_reg_arg = DC_AUX_SNIP; + break; + case FPSR_REGNUM: + get_reg_arg = DC_AUX_FPSR; + break; + case FPCR_REGNUM: + get_reg_arg = DC_AUX_FPCR; + break; + case PSR_REGNUM: + get_reg_state = dc_psr_register_bit_state; + get_reg = psr_register; + get_reg_arg = 0; + break; + default: + if (optim != NULL) + *optim = 1; + return; + } + } + + if ((*get_reg_state) (fi->frame_context, get_reg_arg)) + { + if (raw_buffer != NULL) + *(int *)raw_buffer = (*get_reg) (fi->frame_context, get_reg_arg); + if (optim != NULL) + *optim = 0; + return; + } + else + { + if (optim != NULL) + *optim = 1; + return; + } + + /* Well, the caller can't treat it as a register or memory... */ + if (lvalp != NULL) + *lvalp = not_lval; +} diff --git a/gdb/m88k-xdep.c b/gdb/m88k-xdep.c new file mode 100644 index 0000000000..af73489159 --- /dev/null +++ b/gdb/m88k-xdep.c @@ -0,0 +1,340 @@ +/* Copyright (C) 1988, 1990 Free Software Foundation, Inc. + +This file is part of GDB. + +GDB 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 1, or (at your option) +any later version. + +GDB 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 GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include "defs.h" +#include "param.h" +#include "frame.h" +#include "inferior.h" + +#ifdef USG +#include +#endif + +#include +#include +#include +#include "gdbcore.h" +#include +#ifndef USER /* added to support BCS ptrace_user */ + +#define USER ptrace_user +#endif +#include +#include + +#ifdef COFF_ENCAPSULATE +#include "a.out.encap.h" +#else +#include +#endif + +#include +#include + +#include "symtab.h" +#include "setjmp.h" +#include "value.h" + +/* define offsets to the pc instruction offsets in ptrace_user struct */ +#define SXIP_OFFSET (char *)&u.pt_sigframe.dg_sigframe.sc_sxip - \ + (char *)&u + +#define SNIP_OFFSET (char *)&u.pt_sigframe.dg_sigframe.sc_snip - \ + (char *)&u + +#define SFIP_OFFSET (char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u +extern int have_symbol_file_p(); + +extern jmp_buf stack_jmp; + +extern int errno; +extern char registers[REGISTER_BYTES]; + +void +fetch_inferior_registers () +{ + register int regno; + register unsigned int regaddr; + char buf[MAX_REGISTER_RAW_SIZE]; + register int i; + + struct USER u; + unsigned int offset; + + offset = (char *) &u.pt_r0 - (char *) &u; + regaddr = offset; /* byte offset to r0;*/ + +/* offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; */ + for (regno = 0; regno < NUM_REGS; regno++) + { + /*regaddr = register_addr (regno, offset);*/ + /* 88k enhancement */ + + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) + { + *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0); + regaddr += sizeof (int); + } + supply_register (regno, buf); + } + /* now load up registers 36 - 38; special pc registers */ + *(int *) &buf[0] = ptrace (3,inferior_pid,(char *)&u.pt_sigframe.dg_sigframe.sc_sxip - (char *)&u ,0); + supply_register (SXIP_REGNUM, buf); + *(int *) &buf[0] = ptrace (3, inferior_pid, (char *)&u.pt_sigframe.dg_sigframe.sc_snip - (char *)&u ,0); + supply_register (SNIP_REGNUM, buf); + *(int *) &buf[0] = ptrace (3, inferior_pid, (char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u ,0); + supply_register (SFIP_REGNUM, buf); +} + +/* Store our register values back into the inferior. + If REGNO is -1, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ + +store_inferior_registers (regno) + int regno; +{ + register unsigned int regaddr; + char buf[80]; + + struct USER u; + +#if defined(BCS) +#if defined(DGUX) + + unsigned int offset = (char *) &u.pt_r0 - (char *) &u; + +#endif /* defined (DGUX) */ +#else + + unsigned int offset = (char *) &u.pt_r0 - (char *) &u; + +#endif /* defined(BCS) */ +/* offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; */ + regaddr = offset; + + if (regno >= 0) + { +/* regaddr = register_addr (regno, offset); */ + if (regno < PC_REGNUM) + { + regaddr = offset + regno * sizeof (int); + errno = 0; + ptrace (6, inferior_pid, regaddr, read_register (regno)); + if (errno != 0) + { + sprintf (buf, "writing register number %d", regno); + perror_with_name (buf); + } + } + else if (regno == SXIP_REGNUM) + ptrace (6, inferior_pid, SXIP_OFFSET, read_register(regno)); + else if (regno == SNIP_REGNUM) + ptrace (6, inferior_pid, SNIP_OFFSET, read_register(regno)); + else if (regno == SFIP_REGNUM) + ptrace (6, inferior_pid, SFIP_OFFSET, read_register(regno)); + else printf ("Bad register number for store_inferior routine\n"); + } + else { + for (regno = 0; regno < NUM_REGS - 3; regno++) + { + /* regaddr = register_addr (regno, offset); */ + errno = 0; + regaddr = offset + regno * sizeof (int); + ptrace (6, inferior_pid, regaddr, read_register (regno)); + if (errno != 0) + { + sprintf (buf, "writing register number %d", regno); + perror_with_name (buf); + } + } + ptrace (6,inferior_pid,SXIP_OFFSET,read_register(SXIP_REGNUM)); + ptrace (6,inferior_pid,SNIP_OFFSET,read_register(SNIP_REGNUM)); + ptrace (6,inferior_pid,SFIP_OFFSET,read_register(SFIP_REGNUM)); + } + + +} + +#if 0 +/* Core files are now a function of BFD. */ + +void +core_file_command (filename, from_tty) + char *filename; + int from_tty; +{ + int val; + extern char registers[]; + + /* Need symbol file and one with tdesc info for corefiles to work */ + if (!have_symbol_file_p()) + error ("Requires symbol-file and exec-file"); + if (!execfile) + error ("Requires exec-file and symbol-file"); + + /* Discard all vestiges of any previous core file + and mark data and stack spaces as empty. */ + + if (corefile) + free (corefile); + corefile = 0; + + if (corechan >= 0) + close (corechan); + corechan = -1; + + data_start = 0; + data_end = 0; + stack_start = STACK_END_ADDR; + stack_end = STACK_END_ADDR; + + /* Now, if a new core file was specified, open it and digest it. */ + + if (filename) + { + filename = tilde_expand (filename); + make_cleanup (free, filename); + + if (have_inferior_p ()) + error ("To look at a core file, you must kill the inferior with \"kill\"."); + corechan = open (filename, O_RDONLY, 0); + if (corechan < 0) + perror_with_name (filename); + /* 4.2-style (and perhaps also sysV-style) core dump file. */ + { + struct USER u; + + int reg_offset; + + val = myread (corechan, &u, sizeof u); + if (val < 0) + perror_with_name (filename); + data_start = u.pt_o_data_start; + + data_end = data_start + u.pt_dsize; + stack_start = stack_end - u.pt_ssize; + data_offset = u.pt_dataptr; + stack_offset = data_offset + u.pt_dsize; + +#if defined(BCS) +#if defined(DGUX) + + reg_offset = 2048; + + +#endif /* defined (DGUX) */ +#else + + /* original code: */ + reg_offset = (int) u.pt_r0 - KERNEL_U_ADDR; + +#endif /* defined(BCS) */ + + /* I don't know where to find this info. + So, for now, mark it as not available. */ +/* N_SET_MAGIC (core_aouthdr, 0); */ + bzero ((char *) &core_aouthdr, sizeof core_aouthdr); + + /* Read the register values out of the core file and store + them where `read_register' will find them. */ + + { + register int regno; + + for (regno = 0; regno < NUM_REGS; regno++) + { + char buf[MAX_REGISTER_RAW_SIZE]; + + val = lseek (corechan, register_addr (regno, reg_offset), 0); + if (val < 0) + perror_with_name (filename); + + val = myread (corechan, buf, sizeof buf); + if (val < 0) + perror_with_name (filename); + supply_register (regno, buf); + } + } + } + if (filename[0] == '/') + corefile = savestring (filename, strlen (filename)); + else + { + corefile = concat (current_directory, "/", filename); + } + init_tdesc(); + current_context = init_dcontext(); + set_current_frame ( create_new_frame(get_frame_base (read_pc()), + read_pc ())); + select_frame (get_current_frame (), 0); + validate_files (); + } + else if (from_tty) + printf ("No core file now.\n"); +} +#endif + +/* blockend is the address of the end of the user structure */ +m88k_register_u_addr (blockend, regnum) +{ + struct USER u; + int ustart = blockend - sizeof (struct USER); + switch (regnum) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: return (ustart + ((int) &u.pt_r0 - (int) &u) + sizeof(REGISTER_TYPE) * regnum); + case PSR_REGNUM: return (ustart + ((int) &u.pt_psr - (int) &u)); + case FPSR_REGNUM: return (ustart + ((int) &u.pt_fpsr - (int) &u)); + case FPCR_REGNUM: return (ustart + ((int) &u.pt_fpcr - (int) &u)); + case SXIP_REGNUM: return (ustart + SXIP_OFFSET); + case SNIP_REGNUM: return (ustart + SNIP_OFFSET); + case SFIP_REGNUM: return (ustart + SFIP_OFFSET); + default: return (blockend + sizeof (REGISTER_TYPE) * regnum); + } +} diff --git a/gdb/symtab.h b/gdb/symtab.h index 99e370ce80..ac0b8bc2e0 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -555,6 +555,13 @@ struct symtab /* Full name of file as found by searching the source path. 0 if not yet known. */ char *fullname; + + /* Anything extra for this symtab. This is for target machines + with special debugging info of some sort (which cannot just + be represented in a normal symtab). */ +#if defined (EXTRA_SYMTAB_INFO) + EXTRA_SYMTAB_INFO +#endif }; /* Each source file that has not been fully read in is represented by diff --git a/gdb/tm-m88k.h b/gdb/tm-m88k.h index 1890d6ca67..59fde0015f 100644 --- a/gdb/tm-m88k.h +++ b/gdb/tm-m88k.h @@ -22,14 +22,20 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "tdesc.h" +#if !defined (DGUX) +#define DGUX 1 +#endif + #define TARGET_BYTE_ORDER BIG_ENDIAN +#define EXTRA_SYMTAB_INFO int coffsem; + /* This is not a CREATE_INFERIOR_HOOK because it also applies to remote debugging. */ -#define START_INFERIOR_HOOK () \ +#define START_INFERIOR_HOOK() \ { \ extern int safe_to_init_tdesc_context; \ - extern int tdesc_handle; \ + extern dc_handle_t tdesc_handle; \ \ safe_to_init_tdesc_context = 0; \ if (tdesc_handle) \ @@ -39,18 +45,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ } \ } +dc_dcontext_t get_prev_context (); +extern int stack_error; + #define EXTRA_FRAME_INFO dc_dcontext_t frame_context; #define INIT_EXTRA_FRAME_INFO(fci) \ { \ if (fci->next_frame != NULL) \ { \ + extern jmp_buf stack_jmp; \ + struct frame_info *next_frame = fci->next; \ /* The call to get_prev_context */ \ /* will update current_context for us. */ \ - int stack_error = 1; \ - jmp_buf stack_jmp; \ + stack_error = 1; \ if (!setjmp (stack_jmp)) \ { \ - prev->frame_context \ + fci->frame_context \ = get_prev_context (next_frame->frame_context); \ stack_error = 0; \ } \ @@ -60,7 +70,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ next_frame->prev = 0; \ return 0; \ } \ - if (!prev->frame_context) \ + if (!fci->frame_context) \ { \ next_frame->prev = 0; \ return 0; \ @@ -357,7 +367,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ into consecutive registers starting from r2. */ #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ - bcopy (&(((void *)REGBUF)[REGISTER_BYTE(RV_REGNUM)]), (VALBUF), TYPE_LENGTH (TYPE)) + bcopy (&(((char *)REGBUF)[REGISTER_BYTE(RV_REGNUM)]), (VALBUF), TYPE_LENGTH (TYPE)) #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF)) @@ -372,6 +382,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define BELIEVE_PCC_PROMOTION 1 +/* We provide our own get_saved_register in m88k-tdep.c. */ +#define GET_SAVED_REGISTER + /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -448,6 +461,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ frame_find_saved_regs (frame_info, &frame_saved_regs) +/* There is not currently a functioning way to call functions in the + inferior. */ + +/* But if there was this is where we'd put the call dummy. */ +/* #define CALL_DUMMY_LOCATION AFTER_TEXT_END */ + /* When popping a frame on the 88k (say when doing a return command), the calling function only expects to have the "preserved" registers restored. Thus, those are the only ones that we even try to restore here. */ @@ -457,4 +476,6 @@ extern void pop_frame (); #define POP_FRAME pop_frame () /* BCS is a standard for binary compatibility. This machine uses it. */ -#define BCS +#if !defined (BCS) +#define BCS 1 +#endif diff --git a/gdb/utils.c b/gdb/utils.c index b014d3c957..cce338da5e 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -448,9 +448,12 @@ savestring (ptr, size) return p; } +/* The "const" is so it compiles under DGUX (which prototypes strsave + in . FIXME: This should be named "xstrsave", shouldn't it? + Doesn't real strsave return NULL if out of memory? */ char * strsave (ptr) - char *ptr; + const char *ptr; { return savestring (ptr, strlen (ptr)); } diff --git a/gdb/xm-m88k.h b/gdb/xm-m88k.h index 240459bc89..04e5d7af56 100644 --- a/gdb/xm-m88k.h +++ b/gdb/xm-m88k.h @@ -22,7 +22,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HOST_BYTE_ORDER BIG_ENDIAN -#define USG +#if !defined (USG) +#define USG 1 +#endif /* DGUX has bcopy(), etc. */ #define USG_UTILS 0 @@ -37,7 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define bcmp(left,right,count) (memcmp((right),(left),(count))) #ifdef __GNUC__ #define memcpy __builtin_memcpy -#define memset __builtin_memset +/* gcc doesn't have this, at least not gcc 1.92. */ +/* #define memset __builtin_memset */ #define strcmp __builtin_strcmp #endif