/* Print Convex instructions for GDB, the GNU debugger.
Copyright (C) 1989 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)
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. */
/* reg (fmt_field, inst_field) --
the {first,second,third} operand of instruction as fmt_field = [ijk]
gets the value of the field from the [ijk] position of the instruction */
#define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b]
/* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */
#define lit(i) op[fmt->i]
/* aj[j] -- name for A register j */
#define aj ((char (*)[3])(op[A]))
int mask
; /* opcode mask */
int shift
; /* opcode align */
struct formstr
*formstr
[3]; /* ST, E0, E1 */
unsigned lop
:8, rop
:5; /* opcode */
unsigned fmt
:5; /* inst format */
unsigned i
:5, j
:5, k
:2; /* operand formats */
#include "convex-opcode.h"
unsigned char formdecode
[] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
struct opform opdecode
[] = {
0x7e00, 9, format0
, e0_format0
, e1_format0
,
0x3f00, 8, format1
, e0_format1
, e1_format1
,
0x1fc0, 6, format2
, e0_format2
, e1_format2
,
0x0fc0, 6, format3
, e0_format3
, e1_format3
,
0x0700, 8, format4
, e0_format4
, e1_format4
,
0x03c0, 6, format5
, e0_format5
, e1_format5
,
0x01f8, 3, format6
, e0_format6
, e1_format6
,
0x00f8, 3, format7
, e0_format7
, e1_format7
,
0x0000, 0, formatx
, formatx
, formatx
,
0x0f80, 7, formatx
, formatx
, formatx
,
0x0f80, 7, formatx
, formatx
, formatx
,
/* Print the instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
print_insn (memaddr
, stream
)
register int format
, op1
, pfx
;
read_memory (memaddr
, &inst
, sizeof inst
);
/* Remove and note prefix, if present */
if ((pfx
& 0xfff0) == 0x7ef0)
pfx
= ((pfx
>> 3) & 1) + 1;
*(long long *) &inst
= *(long long *) &inst
.half
[1];
/* Split opcode into format.op1 and look up in appropriate table */
format
= formdecode
[inst
.byte
[0]];
op1
= (inst
.half
[0] & opdecode
[format
].mask
) >> opdecode
[format
].shift
;
fmt
= &opdecode
[format
].formstr
[pfx
][op1
];
fprintf (stream
, "0x%04x", pfx
? pfx
: inst
.half
[0]);
fprintf (stream
, "%s%s%s", lop
[fmt
->lop
], rop
[fmt
->rop
],
&" "[strlen(lop
[fmt
->lop
]) + strlen(rop
[fmt
->rop
])]);
case rrr
: /* three register */
fprintf (stream
, "%s,%s,%s", reg(i
,i
), reg(j
,j
), reg(k
,k
));
case rr
: /* two register */
fprintf (stream
, "%s,%s", reg(i
,j
), reg(j
,k
));
case rxr
: /* two register, reversed i and j fields */
fprintf (stream
, "%s,%s", reg(i
,k
), reg(j
,j
));
case r
: /* one register */
fprintf (stream
, "%s", reg(i
,k
));
case nops
: /* no operands */
case nr
: /* short immediate, one register */
fprintf (stream
, "#%d,%s", inst
.f0
.j
, reg(i
,k
));
case pcrel
: /* pc relative */
print_address (memaddr
+ 2 * inst
.signed_byte
[1], stream
);
case lr
: /* literal, one register */
fprintf (stream
, "%s,%s", lit(i
), reg(j
,k
));
case rxl
: /* one register, literal */
fprintf (stream
, "%s,%s", reg(i
,k
), lit(j
));
case rlr
: /* register, literal, register */
fprintf (stream
, "%s,%s,%s", reg(i
,j
), lit(j
), reg(k
,k
));
case rrl
: /* register, register, literal */
fprintf (stream
, "%s,%s,%s", reg(i
,j
), reg(j
,k
), lit(k
));
case iml
: /* immediate, literal */
fprintf (stream
, "#%#x,%s",
(inst
.signed_half
[1] << 16) + inst
.half
[2], lit(i
));
fprintf (stream
, "#%d,%s", inst
.signed_half
[1], lit(i
));
case imr
: /* immediate, register */
fprintf (stream
, "#%#x,%s",
(inst
.signed_half
[1] << 16) + inst
.half
[2], reg(i
,k
));
fprintf (stream
, "#%d,%s", inst
.signed_half
[1], reg(i
,k
));
case a1r
: /* memory, register */
l
= print_effa (inst
, stream
);
fprintf (stream
, ",%s", reg(i
,k
));
case a1l
: /* memory, literal */
l
= print_effa (inst
, stream
);
fprintf (stream
, ",%s", lit(i
));
case a2r
: /* register, memory */
fprintf (stream
, "%s,", reg(i
,k
));
return pfx
+ print_effa (inst
, stream
);
case a2l
: /* literal, memory */
fprintf (stream
, "%s,", lit(i
));
return pfx
+ print_effa (inst
, stream
);
return pfx
+ print_effa (inst
, stream
);
case a4
: /* system call */
unsigned int m
= (inst
.signed_half
[1] << 16) + inst
.half
[2];
fprintf (stream
, "#%d,#%d", m
>> l
, m
& (-1 >> (32-l
)));
unsigned int m
= inst
.signed_half
[1];
fprintf (stream
, "#%d,#%d", m
>> l
, m
& (-1 >> (32-l
)));
/* print effective address @nnn(aj), return instruction length */
int print_effa (inst
, stream
)
n
= (inst
.signed_half
[1] << 16) + inst
.half
[2];
print_address (n
, stream
);
fprintf (stream
, (n
& 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)",