summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/z8000/z8000cpu.h
blob: 20c9e4b93ff546ae494e026d01918a7fe11589df (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// license:BSD-3-Clause
// copyright-holders:Juergen Buchmueller,Ernesto Corvi
/*****************************************************************************
 *
 *   z8000cpu.h
 *   Portable Z8000(2) emulator
 *   Macros and types used in z8000.c / z8000ops.inc / z8000tbl.inc
 *
 *****************************************************************************/

/**************************************************************************
 * This is the register file layout:
 *
 * BYTE        WORD         LONG           QUAD
 * msb   lsb       bits           bits           bits
 * RH0 - RL0   R 0 15- 0    RR 0  31-16    RQ 0  63-48
 * RH1 - RL1   R 1 15- 0          15- 0          47-32
 * RH2 - RL2   R 2 15- 0    RR 2  31-16          31-16
 * RH3 - RL3   R 3 15- 0          15- 0          15- 0
 * RH4 - RL4   R 4 15- 0    RR 4  31-16    RQ 4  63-48
 * RH5 - RL5   R 5 15- 0          15- 0          47-32
 * RH6 - RL6   R 6 15- 0    RR 6  31-16          31-16
 * RH7 - RL7   R 7 15- 0          15- 0          15- 0
 *             R 8 15- 0    RR 8  31-16    RQ 8  63-48
 *             R 9 15- 0          15- 0          47-32
 *             R10 15- 0    RR10  31-16          31-16
 *             R11 15- 0          15- 0          15- 0
 *             R12 15- 0    RR12  31-16    RQ12  63-48
 *             R13 15- 0          15- 0          47-32
 *             R14 15- 0    RR14  31-16          31-16
 *             R15 15- 0          15- 0          15- 0
 *
 * Note that for LSB_FIRST machines we have the case that the RR registers
 * use the lower numbered R registers in the higher bit positions.
 * And also the RQ registers use the lower numbered RR registers in the
 * higher bit positions.
 * That's the reason for the ordering in the following pointer table.
 **************************************************************************/
#define RB(n)   m_regs.B[BYTE8_XOR_BE((((n) & 7) << 1) | (((n) & 8) >> 3))]
#define RW(n)   m_regs.W[BYTE4_XOR_BE(n)]
#define RL(n)   m_regs.L[BYTE_XOR_BE((n) >> 1)]
#define RQ(n)   m_regs.Q[(n) >> 2]

/* the register used as stack pointer */
#define SP      (get_segmented_mode() ? 14 : 15)

/* these vectors are based on m_psap */
#define RST     (PSA_ADDR() + 0)  /* start up m_fcw and m_pc */
#define EPU     (PSA_ADDR() + m_vector_mult * 0x0004)  /* extension processor unit? trap */
#define TRAP    (PSA_ADDR() + m_vector_mult * 0x0008)  /* privilege violation trap */
#define SYSCALL (PSA_ADDR() + m_vector_mult * 0x000c)  /* system call SC */
#define SEGTRAP (PSA_ADDR() + m_vector_mult * 0x0010)  /* segment trap */
#define NMI     (PSA_ADDR() + m_vector_mult * 0x0014)  /* non maskable interrupt */
#define NVI     (PSA_ADDR() + m_vector_mult * 0x0018)  /* non vectored interrupt */
#define VI      (PSA_ADDR() + m_vector_mult * 0x001c)  /* vectored interrupt */
#define VEC00   (PSA_ADDR() + m_vector_mult * 0x001e)  /* vector n m_pc value */

/* bits of the m_fcw */
#define F_SEG   0x8000              /* segmented mode (Z8001 only) */
#define F_S_N   0x4000              /* system / normal mode */
#define F_EPU   0x2000              /* extension processor unit? */
#define F_VIE   0x1000              /* vectored interrupt enable */
#define F_NVIE  0x0800              /* non vectored interrupt enable */
#define F_10    0x0400              /* unused */
#define F_9     0x0200              /* unused */
#define F_8     0x0100              /* unused */
#define F_C     0x0080              /* carry flag */
#define F_Z     0x0040              /* zero flag */
#define F_S     0x0020              /* sign flag */
#define F_PV    0x0010              /* parity/overflow flag */
#define F_DA    0x0008              /* decimal adjust flag (0 add/adc, 1 sub/sbc) */
#define F_H     0x0004              /* half carry flag (byte arithmetic only) */
#define F_1     0x0002              /* unused */
#define F_0     0x0001              /* unused */

/* opcode word numbers in m_op[] array */
#define OP0     0
#define OP1     1
#define OP2     2

/* nibble shift factors for an opcode word */
/* left to right: 0x1340 -> NIB0=1, NIB1=3, NIB2=4, NIB3=0 */
#define NIB0    12
#define NIB1    8
#define NIB2    4
#define NIB3    0

/* sign bit masks for byte, word and long */
#define S08 0x80
#define S16 0x8000
#define S32 0x80000000

/* get a single flag bit 0/1 */
#define GET_C       ((m_fcw >> 7) & 1)
#define GET_Z       ((m_fcw >> 6) & 1)
#define GET_S       ((m_fcw >> 5) & 1)
#define GET_PV      ((m_fcw >> 4) & 1)
#define GET_DA      ((m_fcw >> 3) & 1)
#define GET_H       ((m_fcw >> 2) & 1)

/* clear a single flag bit */
#define CLR_C       m_fcw &= ~F_C
#define CLR_Z       m_fcw &= ~F_Z
#define CLR_S       m_fcw &= ~F_S
#define CLR_P       m_fcw &= ~F_PV
#define CLR_V       m_fcw &= ~F_PV
#define CLR_DA      m_fcw &= ~F_DA
#define CLR_H       m_fcw &= ~F_H

/* clear a flag bit combination */
#define CLR_CZS     m_fcw &= ~(F_C|F_Z|F_S)
#define CLR_CZSP    m_fcw &= ~(F_C|F_Z|F_S|F_PV)
#define CLR_CZSV    m_fcw &= ~(F_C|F_Z|F_S|F_PV)
#define CLR_CZSVH   m_fcw &= ~(F_C|F_Z|F_S|F_PV|F_H)
#define CLR_ZS      m_fcw &= ~(F_Z|F_S)
#define CLR_ZSV     m_fcw &= ~(F_Z|F_S|F_PV)
#define CLR_ZSP     m_fcw &= ~(F_Z|F_S|F_PV)

/* set a single flag bit */
#define SET_C       m_fcw |= F_C
#define SET_Z       m_fcw |= F_Z
#define SET_S       m_fcw |= F_S
#define SET_P       m_fcw |= F_PV
#define SET_V       m_fcw |= F_PV
#define SET_DA      m_fcw |= F_DA
#define SET_H       m_fcw |= F_H

/* set a flag bit combination */
#define SET_SC      m_fcw |= F_C | F_S

/* check condition codes */
#define CC0 (0)                         /* always false */
#define CC1 (GET_PV^GET_S)              /* less than */
#define CC2 (GET_Z|(GET_PV^GET_S))      /* less than or equal */
#define CC3 (GET_Z|GET_C)               /* unsigned less than or equal */
#define CC4 GET_PV                      /* parity even / overflow */
#define CC5 GET_S                       /* minus (signed) */
#define CC6 GET_Z                       /* zero / equal */
#define CC7 GET_C                       /* carry / unsigned less than */

#define CC8 (1)                         /* always true */
#define CC9 !(GET_PV^GET_S)             /* greater than or equal */
#define CCA !(GET_Z|(GET_PV^GET_S))     /* greater than */
#define CCB !(GET_Z|GET_C)              /* unsigned greater than */
#define CCC !GET_PV                     /* parity odd / no overflow */
#define CCD !GET_S                      /* plus (not signed) */
#define CCE !GET_Z                      /* not zero / not equal */
#define CCF !GET_C                      /* not carry / unsigned greater than */

/* get data from the opcode words */
/* o is the opcode word offset    */
/* s is a nibble shift factor     */
#define GET_BIT(o)      uint16_t bit = 1 << (get_operand(o) & 15)
#define GET_CCC(o,s)    uint8_t cc = (get_operand(o) >> (s)) & 15

#define GET_DST(o,s)    uint8_t dst = (get_operand(o) >> (s)) & 15
#define GET_SRC(o,s)    uint8_t src = (get_operand(o) >> (s)) & 15
#define GET_IDX(o,s)    uint8_t idx = (get_operand(o) >> (s)) & 15
#define GET_CNT(o,s)    int8_t cnt = (get_operand(o) >> (s)) & 15
#define GET_IMM4(o,s)   uint8_t imm4 = (get_operand(o) >> (s)) & 15

#define GET_I4M1(o,s)   uint8_t i4p1 = ((get_operand(o) >> (s)) & 15) + 1
#define GET_IMM1(o,s)   uint8_t imm1 = (get_operand(o) >> (s)) & 2
#define GET_IMM2(o,s)   uint8_t imm2 = (get_operand(o) >> (s)) & 3
#define GET_IMM3(o,s)   uint8_t imm3 = (get_operand(o) >> (s)) & 7

#define GET_IMM8(o)     uint8_t imm8 = (uint8_t)get_operand(o)

// Be very careful with order of operations since get_operand has side effects
#define GET_IMM16(o)    uint16_t imm16 = get_operand(o)
#define GET_IDX16(o)    uint32_t idx16 = get_operand(o)
#define GET_IMM32       uint32_t imm32 = get_operand(1); imm32 = (imm32 << 16) + get_operand(2)
#define GET_DSP7        uint8_t dsp7 = get_operand(0) & 127
#define GET_DSP8        int8_t dsp8 = (int8_t)get_operand(0)
#define GET_DSP16       uint16_t tmp16 = get_operand(1); uint32_t dsp16 = addr_add(m_pc, (int16_t)tmp16)
#define GET_ADDR(o)     uint32_t addr = (uint32_t)get_addr_operand(o)
#define GET_ADDR_RAW(o)     uint32_t addr = (uint32_t)get_raw_addr_operand(o)