Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1814 yogev_ezra 1
/*=====================================================================
2
  Macros.c -> Macros used on the opcode execution.
3
 
4
 This program is free software; you can redistribute it and/or modify
5
 it under the terms of the GNU General Public License as published by
6
 the Free Software Foundation; either version 2 of the License, or
7
 (at your option) any later version.
8
 
9
 This program is distributed in the hope that it will be useful,
10
 but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 GNU General Public License for more details.
13
 
14
 You should have received a copy of the GNU General Public License
15
 along with this program; if not, write to the Free Software
16
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
 
18
 Copyright (c) 2000 Santiago Romero Iglesias.
19
 Email: sromero@escomposlinux.org
20
 ======================================================================*/
21
 
22
/* defines for the registers: faster access to them when coding... */
23
 
24
#define   r_PC    regs->PC.W
25
#define   r_PCl   regs->PC.B.l
26
#define   r_PCh   regs->PC.B.h
27
#define   r_SP    regs->SP.W
28
#define   r_IFF1  regs->IFF1
29
#define   r_IFF2  regs->IFF2
30
#define   r_R     regs->R.W
31
 
32
#define   r_AF    regs->AF.W
33
#define   r_A     regs->AF.B.h
34
#define   r_F     regs->AF.B.l
35
#define   r_BC    regs->BC.W
36
#define   r_B     regs->BC.B.h
37
#define   r_C     regs->BC.B.l
38
#define   r_DE    regs->DE.W
39
#define   r_D     regs->DE.B.h
40
#define   r_E     regs->DE.B.l
41
#define   r_HL    regs->HL.W
42
#define   r_H     regs->HL.B.h
43
#define   r_L     regs->HL.B.l
44
#define   r_IX    regs->IX.W
45
#define   r_IXh   regs->IX.B.h
46
#define   r_IXl   regs->IX.B.l
47
#define   r_IY    regs->IY.W
48
#define   r_IYh   regs->IY.B.h
49
#define   r_IYl   regs->IY.B.l
50
 
51
#define   r_AFs   regs->AFs.W
52
#define   r_As    regs->AFs.B.h
53
#define   r_Fs    regs->AFs.B.l
54
#define   r_BCs   regs->BCs.W
55
#define   r_Bs    regs->BCs.B.h
56
#define   r_Cs    regs->BCs.B.l
57
#define   r_DEs   regs->DEs.W
58
#define   r_Ds    regs->DEs.B.h
59
#define   r_Es    regs->DEs.B.l
60
#define   r_HLs   regs->HLs.W
61
#define   r_Hs    regs->HLs.B.h
62
#define   r_Ls    regs->HLs.B.l
63
#define   r_IXs   regs->IX.W
64
#define   r_IXhs  regs->IX.B.h
65
#define   r_IXls  regs->IX.B.l
66
#define   r_IYs   regs->IY.W
67
#define   r_IYhs  regs->IY.B.h
68
#define   r_IYls  regs->IY.B.l
69
 
70
#define   r_op    ops.W
71
#define   r_oph   ops.B.h
72
#define   r_opl   ops.B.l
73
#define   r_tmp   tmpreg2.W
74
#define   r_tmph  tmpreg2.B.h
75
#define   r_tmpl  tmpreg2.B.l
76
#define   r_mem   mread.W
77
#define   r_memh  mread.B.h
78
#define   r_meml  mread.B.l
79
 
80
#ifndef _DISASM_
81
/*--- Flag tables by Philip Kendall, taken from it's fuse emulator -*/
82
/*--- I was having headache trying to emulate correctly the FLAGS,
83
      so I finished using the FLAG tables used by P. Kendall. ------*/
84
#define FLAG_C  0x01
85
#define FLAG_N  0x02
86
#define FLAG_P  0x04
87
#define FLAG_V  FLAG_P
88
#define FLAG_3  0x08
89
#define FLAG_H  0x10
90
#define FLAG_5  0x20
91
#define FLAG_Z  0x40
92
#define FLAG_S  0x80
93
 
94
/* Whether a half carry occured or not can be determined by looking at
95
   the 3rd bit of the two arguments and the result; these are hashed
96
   into this table in the form r12, where r is the 3rd bit of the
97
   result, 1 is the 3rd bit of the 1st argument and 2 is the
98
   third bit of the 2nd argument; the tables differ for add and subtract
99
   operations */
100
 
101
/* Whether a half carry occured or not can be determined by looking at
102
   the 3rd bit of the two arguments and the result; these are hashed
103
   into this table in the form r12, where r is the 3rd bit of the
104
   result, 1 is the 3rd bit of the 1st argument and 2 is the
105
   third bit of the 2nd argument; the tables differ for add and subtract
106
   operations */
107
byte halfcarry_add_table[] = { 0, FLAG_H, FLAG_H, FLAG_H, 0, 0, 0, FLAG_H };
108
byte halfcarry_sub_table[] = { 0, 0, FLAG_H, 0, FLAG_H, 0, FLAG_H, FLAG_H };
109
 
110
/* Similarly, overflow can be determined by looking at the 7th bits; again
111
   the hash into this table is r12 */
112
byte overflow_add_table[] = { 0, 0, 0, FLAG_V, FLAG_V, 0, 0, 0 };
113
byte overflow_sub_table[] = { 0, FLAG_V, 0, 0, 0, 0, FLAG_V, 0 };
114
 
115
/* Some more tables; initialised in z80_init_tables() */
116
byte sz53_table[0x100];   /* The S, Z, 5 and 3 bits of the temp value */
117
byte parity_table[0x100]; /* The parity of the temp value */
118
byte sz53p_table[0x100];  /* OR the above two tables together */
119
/*------------------------------------------------------------------*/
120
 
121
// Contributed by Metalbrain to implement OUTI, etc.
122
byte ioblock_inc1_table[64];
123
byte ioblock_dec1_table[64];
124
byte ioblock_2_table[0x100];
125
 
126
/*--- Memory Write on the A address on no bank machines -------------*/
127
void Z80WriteMem( word where, word A, Z80Regs *regs)
128
{
129
  if( where >= 16384 )
130
     regs->RAM[where] = A;
131
}
132
 
133
#endif
134
 
135
 
136
/*--- Memory Read from the A address on no bank machines -------------*/
137
#define Z80ReadMem(A)   ((regs->RAM[(A)]))
138
 
139
//  return( regs->RAM[A] );
140
 
141
 
142
/* macros to change the ICount register */
143
#define AddCycles(n) regs->ICount-=(n)
144
 
145
#define SubCycles(n) regs->ICount+=(n)
146
 
147
//#define AddR(n) r_R = (r_R+(n))
148
#define AddR(n) r_R = ((r_R & 0x80) | ((r_R+(n)) & 0x7f ))
149
#define SubR(n) r_R = ((r_R & 0x80) | ((r_R-(n)) & 0x7f ))
150
 
151
 
152
/* setting and resetting the flag bits: */
153
#define SET_FLAG(flag)        (r_F |= (flag))
154
 
155
#define RESET_FLAG(flag)      (r_F &= ~(flag))
156
 
157
#define TEST_FLAG(flag)       (r_F & (flag))
158
 
159
 
160
/* store a given register in the stack (hi and lo bytes) */
161
#define PUSH(rreg)                              \
162
  Z80WriteMem( --(r_SP), regs->rreg.B.h, regs); \
163
  Z80WriteMem( --(r_SP), regs->rreg.B.l, regs)
164
 
165
#define POP(rreg)\
166
  regs->rreg.B.l = Z80ReadMem(r_SP); r_SP++;\
167
  regs->rreg.B.h = Z80ReadMem(r_SP); r_SP++
168
 
169
#define PUSH_IXYr() \
170
  Z80WriteMem( --(r_SP), REGH, regs); \
171
  Z80WriteMem( --(r_SP), REGL, regs)
172
 
173
#define POP_IXYr()\
174
  REGL = Z80ReadMem(r_SP); r_SP++; \
175
  REGH = Z80ReadMem(r_SP); r_SP++
176
 
177
#define RST(rstval)  PUSH(PC); r_PC=(rstval)
178
 
179
 
180
/*--- Move data to mem or regs --------------------------------------*/
181
#define LD_r_r(dreg, sreg)  (dreg) = (sreg)
182
 
183
#define STORE_r(daddreg, sreg)  Z80WriteMem((daddreg), (sreg), regs)
184
 
185
#define STORE_nn_rr(dreg) \
186
                        r_opl = Z80ReadMem(r_PC); r_PC++;\
187
                        r_oph = Z80ReadMem(r_PC); r_PC++; \
188
                        r_tmp = dreg; \
189
                        Z80WriteMem((r_op),r_tmpl, regs); \
190
                        Z80WriteMem((r_op+1),r_tmph, regs)
191
 
192
#define STORE_nn_r(sreg) \
193
                        r_opl = Z80ReadMem(r_PC); r_PC++; \
194
                        r_oph = Z80ReadMem(r_PC); r_PC++; \
195
                        Z80WriteMem((r_op),(sreg), regs)
196
 
197
#define LOAD_r(dreg, saddreg)   (dreg)=Z80ReadMem((saddreg))
198
 
199
#define LOAD_rr_nn(dreg)   r_opl = Z80ReadMem(r_PC); r_PC++; \
200
                           r_oph = Z80ReadMem(r_PC); r_PC++; \
201
                           r_tmpl = Z80ReadMem(r_op); \
202
                           r_tmph = Z80ReadMem((r_op)+1); \
203
                           dreg=r_tmp
204
 
205
 
206
#define LOAD_r_nn(dreg)    r_opl = Z80ReadMem(r_PC); r_PC++; \
207
                           r_oph = Z80ReadMem(r_PC); r_PC++; \
208
                           dreg = Z80ReadMem(r_op)
209
 
210
#define LD_r_n(reg) (reg) = Z80ReadMem(r_PC++)
211
 
212
#define LD_rr_nn(reg)   r_opl = Z80ReadMem(r_PC); r_PC++; \
213
                        r_oph = Z80ReadMem(r_PC); r_PC++; \
214
                        reg = r_op
215
 
216
#define EX(reg1,reg2)        r_opl=(reg1); (reg1)=(reg2); (reg2)=r_opl
217
 
218
#define EX_WORD(reg1,reg2)   r_op=(reg1); (reg1)=(reg2); (reg2)=r_op
219
 
220
/*--- Increments/Decrements -----------------------------------------*/
221
#define INC(reg)            (reg)++;                        \
222
   r_F = ( r_F & FLAG_C ) | ( (reg)==0x80 ? FLAG_V : 0 ) |  \
223
  ( (reg)&0x0f ? 0 : FLAG_H ) | ( (reg) ? 0 : FLAG_Z ) |    \
224
   sz53_table[(reg)]
225
 
226
#define DEC(reg)                                                  \
227
   r_F = ( r_F & FLAG_C ) | ( (reg)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
228
   (reg)--;                                                       \
229
   r_F |= ( (reg)==0x7f ? FLAG_V : 0 ) | sz53_table[(reg)]
230
 
231
// it was:
232
//   r_F |= ( (reg)==0x79 ? FLAG_V : 0 ) | sz53_table[(reg)]
233
// But Kak pointed my was not 0x79 -> 0x7F, changed 7-3-2001
234
 
235
 
236
/*--- Bit operations ------------------------------------------------*/
237
#define BIT_RES(b,reg) reg &= ~(0x1<
238
 
239
#define BIT_SET(b,reg) reg |= (0x1<
240
 
241
#define BIT_mem_RES(b,addr) r_opl = Z80ReadMem(addr); \
242
                            r_opl &= ~(0x1<
243
                            Z80WriteMem(addr, r_opl, regs)
244
 
245
#define BIT_mem_SET(b,addr) r_opl = Z80ReadMem(addr); \
246
                            r_opl |= (0x1<
247
                            Z80WriteMem(addr, r_opl, regs)
248
 
249
#define BIT_RES_mem(b,addr,reg)  reg &= ~(0x1<
250
                                 Z80WriteMem((addr), (reg), regs)
251
 
252
#define BIT_SET_mem(b,addr,reg) reg |= (0x1<
253
                                Z80WriteMem((addr), (reg), regs)
254
 
255
#define BIT_BIT(b,reg)     r_F = ( r_F & FLAG_C ) | \
256
                           ( (reg) & ( FLAG_3 | FLAG_5 ) ) |\
257
                           (((reg) & ( 0x01 << b ) ) ? FLAG_H : \
258
                           (FLAG_P|FLAG_H|FLAG_Z ) )
259
 
260
#define BIT_mem_BIT(b,reg)  r_opl = Z80ReadMem(reg); \
261
                            r_F = ( r_F & FLAG_C ) | \
262
                            ( (r_opl) & ( FLAG_3 | FLAG_5 ) ) |\
263
                            (((r_opl) & ( 0x01 << b ) ) ? FLAG_H : \
264
                            (FLAG_P|FLAG_H|FLAG_Z ) )
265
 
266
#define BIT_BIT7(reg)        r_F = ( r_F & FLAG_C ) | ( (reg) & \
267
                         ( FLAG_3 | FLAG_5 ) ) |\
268
                         (((reg) & 0x80 ) ? ( FLAG_H | FLAG_S ) :\
269
                         ( FLAG_P | FLAG_H | FLAG_Z ) )
270
 
271
#define BIT_mem_BIT7(reg)    r_opl = Z80ReadMem(reg); \
272
                         r_F = ( r_F & FLAG_C ) | ( (r_opl) & \
273
                         ( FLAG_3 | FLAG_5 ) ) |\
274
                         (((r_opl) & 0x80 ) ? ( FLAG_H | FLAG_S ) :\
275
                         ( FLAG_P | FLAG_H | FLAG_Z ) )
276
 
277
 
278
#define RLC(reg)  (reg) = ( (reg)<<1 ) | ( (reg)>>7 );          \
279
                  r_F = ( (reg) & FLAG_C ) | sz53p_table[(reg)]
280
 
281
#define RRC(reg)  r_F = (reg) & FLAG_C;               \
282
                  (reg) = ( (reg)>>1 ) | ( (reg)<<7 );\
283
                   r_F |= sz53p_table[(reg)]
284
 
285
#define RL(reg)   r_opl = (reg);                         \
286
                 (reg) = ( (reg)<<1 ) | ( r_F & FLAG_C );  \
287
                  r_F = ( r_opl >> 7 ) | sz53p_table[(reg)]
288
 
289
#define RR(reg)   r_opl = (reg);                          \
290
                  (reg) = ( (reg)>>1 ) | ( r_F << 7 );\
291
                  r_F = ( r_opl & FLAG_C ) | sz53p_table[(reg)]
292
 
293
#define SLA(reg)  r_F = (reg) >> 7;\
294
                  (reg) <<= 1;\
295
                   r_F |= sz53p_table[(reg)]
296
 
297
#define SRA(reg)  r_F = (reg) & FLAG_C; \
298
                 (reg) = ( (reg) & 0x80 ) | ( (reg) >> 1 );\
299
                  r_F |= sz53p_table[(reg)]
300
 
301
#define SLL(reg)  r_F = (reg) >> 7;\
302
                  (reg) = ( (reg) << 1 ) | 0x01;\
303
                   r_F |= sz53p_table[(reg)]
304
 
305
#define SRL(reg)  r_F = (reg) & FLAG_C;\
306
                  (reg) >>= 1;\
307
                  r_F |= sz53p_table[(reg)]
308
 
309
 
310
 
311
/*--- JP operations -------------------------------------------------*/
312
#define JP_nn()  r_opl = Z80ReadMem(r_PC); \
313
                 r_PC++;                   \
314
                 r_oph = Z80ReadMem(r_PC);  \
315
                 r_PC = r_op
316
 
317
#define JR_n()   r_PC += (offset) (Z80ReadMem(r_PC)); r_PC++
318
 
319
#define RET_nn()   r_PCl = Z80ReadMem (r_SP); r_SP++; \
320
                   r_PCh = Z80ReadMem (r_SP);  r_SP++;
321
 
322
#define CALL_nn()  r_opl = Z80ReadMem (r_PC); r_PC++; \
323
                   r_oph = Z80ReadMem (r_PC); r_PC++; \
324
                   Z80WriteMem( --(r_SP), r_PCh, regs ); \
325
                   Z80WriteMem( --(r_SP), r_PCl, regs ); \
326
                   r_PC = r_op
327
 
328
 
329
/*--- ALU operations ------------------------------------------------*/
330
#define AND(reg)     r_A &= (reg); \
331
                     r_F = FLAG_H | sz53p_table[r_A]
332
 
333
#define OR(reg)      r_A |= (reg); \
334
                     r_F = sz53p_table[r_A]
335
 
336
#define XOR(reg)     r_A ^= (reg); \
337
                     r_F = sz53p_table[r_A]
338
 
339
#define AND_mem(raddress)     r_opl = Z80ReadMem(raddress); \
340
                              r_A &= (r_opl);              \
341
                              r_F = FLAG_H | sz53p_table[r_A]
342
 
343
#define OR_mem(raddress)      r_opl = Z80ReadMem(raddress); \
344
                              r_A |= (r_opl);               \
345
                              r_F = sz53p_table[r_A]
346
 
347
#define XOR_mem(raddress)     r_opl = Z80ReadMem(raddress); \
348
                              r_A ^= (r_opl);               \
349
                              r_F = sz53p_table[r_A]
350
 
351
#define ADD(val)   tempword = r_A + (val);                    \
352
                   r_oph = ((r_A&0x88)>>3)|(((val)&0x88)>>2) | \
353
                   ( (tempword & 0x88) >> 1 );                \
354
                   r_A = tempword;                            \
355
                   r_F = ( tempword & 0x100 ? FLAG_C : 0 ) |  \
356
                   halfcarry_add_table[ r_oph & 0x07] |        \
357
                   overflow_add_table[ r_oph >> 4] |           \
358
                   sz53_table[r_A]
359
 
360
#define ADD_WORD(value1,value2)                                   \
361
                   tempdword = (value1) + (value2);               \
362
                   r_oph = ( ( (value1) & 0x0800 ) >> 11 ) |     \
363
                   ( ( (value2) & 0x0800 ) >> 10 ) |              \
364
                   ( ( tempdword & 0x0800 ) >> 9 );               \
365
                   (value1) = tempdword;                            \
366
                   r_F = ( r_F & ( FLAG_V | FLAG_Z | FLAG_S ) ) | \
367
                   ( tempdword & 0x10000 ? FLAG_C : 0 ) |         \
368
                   (( tempdword >> 8 ) & ( FLAG_3 | FLAG_5 ) ) | \
369
                   halfcarry_add_table[r_oph]
370
 
371
#define ADC(value)                                                 \
372
                   tempword = r_A + (value) + ( r_F & FLAG_C );      \
373
            r_oph = ( (r_A & 0x88) >> 3 ) | ( ( (value) & 0x88 ) >> 2 ) |\
374
                   ( (tempword & 0x88) >> 1 );                       \
375
                    r_A = tempword;                                  \
376
                    r_F = ( tempword & 0x100 ? FLAG_C : 0 ) |        \
377
                   halfcarry_add_table[r_oph & 0x07] |            \
378
                   overflow_add_table[r_oph >> 4] |               \
379
                   sz53_table[r_A]
380
 
381
#define ADC_WORD(value)                                            \
382
              tempdword= r_HL + (value) + ( r_F & FLAG_C );            \
383
              r_oph = ( ( r_HL & 0x8800 ) >> 11 ) |               \
384
              ( ( (value) & 0x8800 ) >> 10 ) |                     \
385
              ( ( tempdword & 0x8800 ) >> 9 );                         \
386
              r_HL = tempdword;                                        \
387
              r_F = ( tempdword & 0x10000 ? FLAG_C : 0 )|              \
388
              overflow_add_table[r_oph >> 4] |                    \
389
              ( r_H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |             \
390
              halfcarry_add_table[ r_oph & 0x0f ]|                \
391
              ( r_HL ? 0 : FLAG_Z )
392
 
393
#define SUB(value)                                                 \
394
              tempword = r_A - (value);\
395
              r_opl = ( (r_A & 0x88) >> 3 ) |                     \
396
              ( ( (value) & 0x88 ) >> 2 ) |                        \
397
              ( (tempword & 0x88) >> 1 );                             \
398
              r_A = tempword;                                         \
399
              r_F = ( tempword & 0x100 ? FLAG_C : 0 ) | FLAG_N |      \
400
              halfcarry_sub_table[r_opl & 0x07] |                 \
401
              overflow_sub_table[r_opl >> 4] |                    \
402
              sz53_table[r_A]
403
 
404
#define SBC(value)                                                 \
405
              tempword = r_A - (value) - ( r_F & FLAG_C );            \
406
              r_opl = ( (r_A & 0x88) >> 3 ) |                     \
407
              ( ( (value) & 0x88 ) >> 2 ) |                        \
408
              ( (tempword & 0x88) >> 1 );                             \
409
              r_A = tempword;                                         \
410
              r_F = ( tempword & 0x100 ? FLAG_C : 0 ) | FLAG_N |      \
411
              halfcarry_sub_table[r_opl & 0x07] |                 \
412
              overflow_sub_table[r_opl >> 4] |                    \
413
              sz53_table[r_A]
414
 
415
 
416
#define SBC_WORD(Rg)      \
417
  tempword=r_F & C_FLAG; r_op=(r_HL-Rg-tempword)&0xFFFF;           \
418
  r_F=                                                   \
419
    N_FLAG|                                                    \
420
    (((long)r_HL-(long)Rg-(long)tempword)&0x10000? C_FLAG:0)| \
421
    ((r_HL^Rg)&(r_HL^r_op)&0x8000? O_FLAG:0)|        \
422
    ((r_HL^Rg^r_op)&0x1000? H_FLAG:0)|                  \
423
    (r_op? 0:Z_FLAG)|(r_oph&S_FLAG);                            \
424
     r_HL=r_op
425
 
426
#define CP(value)                                                       \
427
  tempword = r_A - (value);\
428
  r_opl = ( (r_A & 0x88) >> 3 ) | ( ( (value) & 0x88 ) >> 2 ) |        \
429
       ( (tempword & 0x88) >> 1 );                                        \
430
  r_F = ( tempword & 0x100 ? FLAG_C : ( tempword ? 0 : FLAG_Z ) ) | FLAG_N |\
431
  halfcarry_sub_table[r_opl & 0x07] |                                  \
432
  overflow_sub_table[r_opl >> 4] |                                     \
433
  ( value & ( FLAG_3 | FLAG_5 ) ) |                                     \
434
  ( tempword & FLAG_S )
435
 
436
#define NEG_A()  r_opl = r_A; r_A=0; SUB(r_opl)
437
 
438
/*--- MISC operations -----------------------------------------------*/
439
#define IN(reg,port)    (reg)=Z80InPort((port));                  \
440
                         r_F = ( r_F & FLAG_C) | sz53p_table[(reg)]
441
 
442
 
443
 
444
 
445
 
446
 
447