summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/powerpc/ppc_dasm.h
blob: 5fab7dfe0747d6c404b531a90bb353cfb944e80f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/*
 * disasm.c
 *
 * PowerPC 603e disassembler.
 *
 * When possible, invalid forms of instructions are checked for. To the best
 * of my knowledge, all appropriate load/store instructions are checked. I'm
 * not sure whether any other kinds of instructions need checking.
 */

/* Originally written by Bart Trzynadlowski for Supermodel project
 *
 * PowerPC 403 opcodes and MAME conversion by Ville Linde
 */

#ifndef MAME_CPU_POWERPC_PPC_DASM_H
#define MAME_CPU_POWERPC_PPC_DASM_H

#pragma once

class powerpc_disassembler : public util::disasm_interface
{
public:
	powerpc_disassembler() = default;
	virtual ~powerpc_disassembler() = default;

	virtual u32 opcode_alignment() const override;
	virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
	static offs_t dasm_one(std::ostream &stream, uint32_t pc, uint32_t op);

private:
	/*
	 * Operand Formats
	 *
	 * These convey information on what operand fields are present and how they
	 * ought to be printed.
	 *
	 * I'm fairly certain all of these are used, but that is not guaranteed.
	 */

	enum
	{
		F_NONE,         // <no operands>
		F_LI,           // LI*4+PC if AA=0 else LI*4
		F_BCx,          // BO, BI, target_addr  used only by BCx
		F_RT_RA_0_SIMM, // rT, rA|0, SIMM       rA|0 means if rA == 0, print 0
		F_ADDIS,        // rT, rA, SIMM (printed as unsigned)   only used by ADDIS
		F_RT_RA_SIMM,   // rT, rA, SIMM
		F_RA_RT_UIMM,   // rA, rT, UIMM
		F_CMP_SIMM,     // crfD, L, A, SIMM
		F_CMP_UIMM,     // crfD, L, A, UIMM
		F_RT_RA_0_RB,   // rT, rA|0, rB
		F_RT_RA_RB,     // rT, rA, rB
		F_RT_D_RA_0,    // rT, d(rA|0)
		F_RT_D_RA,      // rT, d(rA)
		F_RA_RT_RB,     // rA, rT, rB
		F_FRT_D_RA_0,   // frT, d(RA|0)
		F_FRT_D_RA,     // frT, d(RA)
		F_FRT_RA_0_RB,  // frT, rA|0, rB
		F_FRT_RA_RB,    // frT, rA, rB
		F_TWI,          // TO, rA, SIMM         only used by TWI instruction
		F_CMP,          // crfD, L, rA, rB
		F_RA_RT,        // rA, rT
		F_RA_0_RB,      // rA|0, rB
		F_FRT_FRB,      // frT, frB
		F_FCMP,         // crfD, frA, frB
		F_CRFD_CRFS,    // crfD, crfS
		F_MCRXR,        // crfD                 only used by MCRXR
		F_RT,           // rT
		F_MFSR,         // rT, SR               only used by MFSR
		F_MTSR,         // SR, rT               only used by MTSR
		F_MFFSx,        // frT                  only used by MFFSx
		F_FCRBD,        // crbD                 FPSCR[crbD]
		F_MTFSFIx,      // crfD, IMM            only used by MTFSFIx
		F_RB,           // rB
		F_TW,           // TO, rA, rB           only used by TW
		F_RT_RA_0_NB,   // rT, rA|0, NB         print 32 if NB == 0
		F_SRAWIx,       // rA, rT, SH           only used by SRAWIx
		F_BO_BI,        // BO, BI
		F_CRBD_CRBA_CRBB,   // crbD, crbA, crbB
		F_RT_SPR,       // rT, SPR              and TBR
		F_MTSPR,        // SPR, rT              only used by MTSPR
		F_MTCRF,        // CRM, rT              only used by MTCRF
		F_MTFSFx,       // FM, frB              only used by MTFSFx
		F_RT_DCR,       // rT, DCR
		F_MTDCR,        // DCR, rT
		F_RT_RA,        // rT, rA
		F_FRT_FRA_FRC_FRB,  // frT, frA, frC, frB
		F_FRT_FRA_FRB,  // frT, frA, frB
		F_FRT_FRA_FRC,  // frT, frA, frC
		F_RA_RT_SH_MB_ME,   // rA, rT, SH, MB, ME
		F_RLWNMx,       // rT, rA, rB, MB, ME   only used by RLWNMx
		F_RT_RB         // rT, rB
	};

	/*
	 * Flags
	 */

	enum
	{
		FL_OE           = 1 << 0,    // if there is an OE field
		FL_RC           = 1 << 1,    // if there is an RC field
		FL_LK           = 1 << 2,    // if there is an LK field
		FL_AA           = 1 << 3,    // if there is an AA field
		FL_CHECK_RA_RT  = 1 << 4,    // assert rA!=0 and rA!=rT
		FL_CHECK_RA     = 1 << 5,    // assert rA!=0
		FL_CHECK_LSWI   = 1 << 6,    // specific check for LSWI validity
		FL_CHECK_LSWX   = 1 << 7,    // specific check for LSWX validity
		FL_SO           = 1 << 8     // use STEP_OUT
	};

	/*
	 * Instruction Descriptor
	 *
	 * Describes the layout of an instruction.
	 */

	struct IDESCR
	{
		char    mnem[32];   // mnemonic
		uint32_t  match;      // bit pattern of instruction after it has been masked
		uint32_t  mask;       // mask of variable fields (AND with ~mask to compare w/
						// bit pattern to determine a match)
		int format;         // operand format
		int flags;          // flags
	};

	static const IDESCR itab[];
	static const char *const crbit[4];
	static const char *const crnbit[4];

	static std::string SPR(int spr_field);
	static std::string DCR(int dcr_field);
	static std::string DecodeSigned16(uint32_t op, int do_unsigned);
	static uint32_t Mask(int mb, int me);
	static bool Simplified(uint32_t op, uint32_t vpc, std::string &signed16, std::string &mnem, std::string &oprs);
};

#endif