diff options
Diffstat (limited to 'opcodes/s12z-opc.h')
-rw-r--r-- | opcodes/s12z-opc.h | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/opcodes/s12z-opc.h b/opcodes/s12z-opc.h new file mode 100644 index 00000000000..186a7f29c3f --- /dev/null +++ b/opcodes/s12z-opc.h @@ -0,0 +1,267 @@ +/* s12z-dis.h -- Header file for s12z-dis.c and s12z-decode.c + Copyright (C) 2019 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> + +/* 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 operator + { + 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 operator *myoperator, short *osize, + int *n_operands, struct operand **operands, + struct mem_read_abstraction_base *); + + +#endif /* S12Z_OPC_H */ |