275 lines
5.6 KiB
C
275 lines
5.6 KiB
C
/* s12z-dis.h -- Header file for s12z-dis.c and s12z-decode.c
|
|
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
|
|
|
This file is part of the GNU opcodes library.
|
|
|
|
This library 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 3, or (at your option)
|
|
any later version.
|
|
|
|
It 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; see the file COPYING3. If not,
|
|
see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef S12Z_OPC_H
|
|
#define S12Z_OPC_H
|
|
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
/* An abstraction used to read machine code from a source. */
|
|
struct mem_read_abstraction_base
|
|
{
|
|
int (*read) (struct mem_read_abstraction_base *, int, size_t, bfd_byte *);
|
|
void (*advance) (struct mem_read_abstraction_base *);
|
|
bfd_vma (*posn) (struct mem_read_abstraction_base *);
|
|
};
|
|
|
|
|
|
/* Machine code operators.
|
|
These *roughly* correspond to opcodes.
|
|
But describe their purpose rather than their form. */
|
|
enum optr
|
|
{
|
|
OP_INVALID = 0,
|
|
|
|
OP_push,
|
|
OP_pull,
|
|
/* Test and branch. */
|
|
OP_tbNE, OP_tbEQ, OP_tbPL, OP_tbMI, OP_tbGT, OP_tbLE,
|
|
/* Decrement and branch. */
|
|
OP_dbNE, OP_dbEQ, OP_dbPL, OP_dbMI, OP_dbGT, OP_dbLE,
|
|
|
|
/* Note: sex and exg are the same opcode.
|
|
They are mnemonic changes according to the operands. */
|
|
OP_sex,
|
|
OP_exg,
|
|
|
|
/* Shifters. */
|
|
OP_lsl, OP_lsr,
|
|
OP_asl, OP_asr,
|
|
OP_rol, OP_ror,
|
|
/* Bit field operations. */
|
|
OP_bfins, OP_bfext,
|
|
OP_trap,
|
|
|
|
OP_ld,
|
|
OP_st,
|
|
OP_cmp,
|
|
|
|
OP_stop,
|
|
OP_wai,
|
|
OP_sys,
|
|
|
|
OP_minu,
|
|
OP_mins,
|
|
OP_maxu,
|
|
OP_maxs,
|
|
|
|
OP_abs,
|
|
OP_adc,
|
|
OP_bit,
|
|
OP_sbc,
|
|
OP_rti,
|
|
OP_clb,
|
|
OP_eor,
|
|
|
|
OP_sat,
|
|
|
|
OP_nop,
|
|
OP_bgnd,
|
|
OP_brclr,
|
|
OP_brset,
|
|
OP_rts,
|
|
OP_lea,
|
|
OP_mov,
|
|
|
|
OP_bra,
|
|
OP_bsr,
|
|
OP_bhi,
|
|
OP_bls,
|
|
OP_bcc,
|
|
OP_bcs,
|
|
OP_bne,
|
|
OP_beq,
|
|
OP_bvc,
|
|
OP_bvs,
|
|
OP_bpl,
|
|
OP_bmi,
|
|
OP_bge,
|
|
OP_blt,
|
|
OP_bgt,
|
|
OP_ble,
|
|
OP_inc,
|
|
OP_clr,
|
|
OP_dec,
|
|
|
|
OP_add,
|
|
OP_sub,
|
|
OP_and,
|
|
OP_or,
|
|
|
|
OP_tfr,
|
|
OP_jmp,
|
|
OP_jsr,
|
|
OP_com,
|
|
OP_andcc,
|
|
OP_neg,
|
|
OP_orcc,
|
|
OP_bclr,
|
|
OP_bset,
|
|
OP_btgl,
|
|
OP_swi,
|
|
|
|
OP_mulu,
|
|
OP_divu,
|
|
OP_modu,
|
|
OP_macu,
|
|
OP_qmulu,
|
|
|
|
OP_muls,
|
|
OP_divs,
|
|
OP_mods,
|
|
OP_macs,
|
|
OP_qmuls,
|
|
|
|
OPBASE_mul = 0x4000,
|
|
OPBASE_div,
|
|
OPBASE_mod,
|
|
OPBASE_mac,
|
|
OPBASE_qmul,
|
|
|
|
n_OPS
|
|
};
|
|
|
|
|
|
/* Used for operands which mutate their index/base registers.
|
|
Eg ld d0, (s+). */
|
|
enum op_reg_mutation
|
|
{
|
|
OPND_RM_NONE,
|
|
OPND_RM_PRE_DEC,
|
|
OPND_RM_PRE_INC,
|
|
OPND_RM_POST_DEC,
|
|
OPND_RM_POST_INC
|
|
};
|
|
|
|
/* The class of an operand. */
|
|
enum opnd_class
|
|
{
|
|
OPND_CL_IMMEDIATE,
|
|
OPND_CL_MEMORY,
|
|
OPND_CL_REGISTER,
|
|
OPND_CL_REGISTER_ALL, /* Used only for psh/pul. */
|
|
OPND_CL_REGISTER_ALL16, /* Used only for psh/pul. */
|
|
OPND_CL_SIMPLE_MEMORY,
|
|
OPND_CL_BIT_FIELD
|
|
};
|
|
|
|
|
|
/* Base structure of all operands. */
|
|
struct operand
|
|
{
|
|
enum opnd_class cl;
|
|
|
|
/* OSIZE determines the size of memory access for
|
|
the operation in which the operand participates.
|
|
It may be -1 which indicates either unknown
|
|
(must be determined by other operands) or if
|
|
it is not applicable for this operation. */
|
|
int osize;
|
|
};
|
|
|
|
/* Immediate operands. Eg: #23 */
|
|
struct immediate_operand
|
|
{
|
|
struct operand parent;
|
|
int value;
|
|
};
|
|
|
|
/* Bitfield operands. Used only in bfext and bfins
|
|
instructions. */
|
|
struct bitfield_operand
|
|
{
|
|
struct operand parent;
|
|
int width;
|
|
int offset;
|
|
};
|
|
|
|
/* Register operands. */
|
|
struct register_operand
|
|
{
|
|
struct operand parent;
|
|
int reg;
|
|
};
|
|
|
|
|
|
/* Simple memory operands. ie, direct memory,
|
|
no index, no pre/post inc/dec. May be either relative or absolute.
|
|
Eg st d0, 0x123456 */
|
|
struct simple_memory_operand
|
|
{
|
|
struct operand parent;
|
|
|
|
bfd_vma addr;
|
|
bfd_vma base;
|
|
bool relative;
|
|
};
|
|
|
|
|
|
/* Memory operands. Should be able to represent all memory
|
|
operands in the S12Z instruction set which are not simple
|
|
memory operands. */
|
|
struct memory_operand
|
|
{
|
|
struct operand parent;
|
|
|
|
/* True for indirect operands: eg [0x123456] */
|
|
bool indirect;
|
|
|
|
/* The value of any offset. eg 45 in (45,d7) */
|
|
int base_offset;
|
|
|
|
/* Does this operand increment or decrement
|
|
its participating registers. Eg (-s) */
|
|
enum op_reg_mutation mutation;
|
|
|
|
/* The number of registers participating in this operand.
|
|
For S12Z this is always in the range [0, 6] (but for most
|
|
instructions it's <= 2). */
|
|
int n_regs;
|
|
|
|
/* The participating registers. */
|
|
int regs[6];
|
|
};
|
|
|
|
|
|
/* Decode a single instruction.
|
|
OPERATOR, OSIZE, N_OPERANDS and OPERANDS are pointers to
|
|
variables which must be provided by the caller.
|
|
N_OPERANDS will be incremented by the number of operands read, so
|
|
you should assign it to something before calling this function.
|
|
OPERANDS must be large enough to contain all operands read
|
|
(which may be up to 6).
|
|
It is the responsibility of the caller to free all operands
|
|
when they are no longer needed.
|
|
Returns the number of bytes read. */
|
|
int decode_s12z (enum optr *myoperator, short *osize,
|
|
int *n_operands, struct operand **operands,
|
|
struct mem_read_abstraction_base *);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* S12Z_OPC_H */
|