Implement 386 instruction table, improve 8086/186/286 instruction table
[multi_emu.git] / cpu_6809.h
1 #ifndef _CPU_6809_H
2 #define _CPU_6809_H
3
4 #include <endian.h>
5 #include <stdbool.h>
6 #include <stdint.h>
7
8 // gcc specific
9 #ifndef ALWAYS_INLINE
10 #define ALWAYS_INLINE __attribute__((always_inline))
11 #endif
12
13 #define CPU_6809_IRQ_VECTOR 0xfff8
14 #define CPU_6809_SWI_VECTOR 0xfffa
15 #define CPU_6809_NMI_VECTOR 0xfffc
16 #define CPU_6809_RESET_VECTOR 0xfffe
17
18 // bits within REG_CC
19 #define CPU_6809_REG_CC_BIT_H 5
20 #define CPU_6809_REG_CC_BIT_I 4
21 #define CPU_6809_REG_CC_BIT_N 3
22 #define CPU_6809_REG_CC_BIT_Z 2
23 #define CPU_6809_REG_CC_BIT_V 1
24 #define CPU_6809_REG_CC_BIT_C 0
25
26 // special memory locations (negative address)
27 // m1 and sink are used to implement undefined registers for TFR/EXG
28 #define CPU_6809_EA_PC (-0x12)
29 #define CPU_6809_EA_D (-0x10)
30 #define CPU_6809_EA_A (-0x10)
31 #define CPU_6809_EA_B (-0xf)
32 #define CPU_6809_EA_U (-0xe)
33 #define CPU_6809_EA_S (-0xc)
34 #define CPU_6809_EA_X (-0xa)
35 #define CPU_6809_EA_Y (-8)
36 #define CPU_6809_EA_CC (-6)
37 #define CPU_6809_EA_DP (-5)
38 #define CPU_6809_EA_IFLAGS (-4)
39 #define CPU_6809_EA_M1 (-3)
40 #define CPU_6809_EA_SINK (-2)
41
42 // registers, in same order as special memory locations, but reversed on
43 // little endian hardware where special memory address will be complemented
44 // (this allows special memory to always look like it is big endian)
45 union cpu_6809_regs {
46 #if __BYTE_ORDER == __BIG_ENDIAN
47   struct {
48     uint16_t _fill_pc;
49     uint16_t _fill_d;
50     uint16_t _fill_u;
51     uint16_t _fill_s;
52     uint16_t _fill_x;
53     uint16_t _fill_y;
54     uint8_t ef : 1;
55     uint8_t ff : 1;
56     uint8_t hf : 1;
57     uint8_t _if : 1;
58     uint8_t nf : 1;
59     uint8_t zf : 1;
60     uint8_t vf : 1;
61     uint8_t cf : 1;
62     uint8_t _fill_dp;
63     uint8_t _fill_iflags : 5;
64     uint8_t wai_flag : 1;
65     uint8_t irq_pending : 1;
66     uint8_t nmi_pending : 1;
67     uint8_t _fill_m1;
68     uint8_t _fill_sink;
69     uint8_t _pad;
70   } bit;
71   struct {
72     uint16_t _fill_pc;
73     uint8_t a;
74     uint8_t b;
75     uint16_t _fill_u;
76     uint16_t _fill_s;
77     uint16_t _fill_x;
78     uint16_t _fill_y;
79     uint8_t cc;
80     uint8_t dp;
81     uint8_t iflags;
82     uint8_t m1;
83     uint8_t sink;
84     uint8_t _pad;
85   } byte;
86   struct {
87     uint16_t pc;
88     uint16_t d;
89     uint16_t u;
90     uint16_t s;
91     uint16_t x;
92     uint16_t y;
93     uint8_t _fill_cc;
94     uint8_t _fill_dp;
95     uint8_t _fill_iflags;
96     uint8_t _fill_m1;
97     uint8_t _fill_sink;
98     uint8_t _pad;
99   } word;
100   uint8_t mem_be[0x10];
101 #else
102   struct {
103     uint8_t _pad;
104     uint8_t _fill_sink;
105     uint8_t _fill_m1;
106     uint8_t nmi_pending : 1;
107     uint8_t irq_pending : 1;
108     uint8_t wai_flag : 1;
109     uint8_t _fill_iflags : 5;
110     uint8_t _fill_dp;
111     uint8_t cf : 1;
112     uint8_t vf : 1;
113     uint8_t zf : 1;
114     uint8_t nf : 1;
115     uint8_t _if : 1;
116     uint8_t hf : 1;
117     uint8_t ff : 1;
118     uint8_t ef : 1;
119     uint16_t _fill_y;
120     uint16_t _fill_x;
121     uint16_t _fill_s;
122     uint16_t _fill_u;
123     uint16_t _fill_d;
124     uint16_t _fill_pc;
125   } bit;
126   struct {
127     uint8_t _pad;
128     uint8_t sink;
129     uint8_t m1;
130     uint8_t iflags;
131     uint8_t dp;
132     uint8_t cc;
133     uint16_t _fill_y;
134     uint16_t _fill_x;
135     uint16_t _fill_s;
136     uint16_t _fill_u;
137     uint8_t b;
138     uint8_t a;
139     uint16_t _fill_pc;
140   } byte;
141   struct {
142     uint8_t _pad;
143     uint8_t _fill_sink;
144     uint8_t _fill_m1;
145     uint8_t _fill_iflags;
146     uint8_t _fill_dp;
147     uint8_t _fill_cc;
148     uint16_t y;
149     uint16_t x;
150     uint16_t s;
151     uint16_t u;
152     uint16_t d;
153     uint16_t pc;
154   } word;
155   uint8_t mem_le[0x10];
156 #endif
157 };
158
159 struct cpu_6809 {
160   int cycles;
161   int (*read_byte)(void *context, int addr);
162   void *read_byte_context;
163   void (*write_byte)(void *context, int addr, int data);
164   void *write_byte_context;
165   union cpu_6809_regs regs;
166 };
167
168 // tables
169 extern int cpu_6809_ea_src[0x10][2];
170 extern int cpu_6809_ea_dest[0x10][2];
171  
172 // memory or special memory access
173 static ALWAYS_INLINE int cpu_6809_read_byte(struct cpu_6809 *self, int addr) {
174   if (addr < 0)
175 #if __BYTE_ORDER == __BIG_ENDIAN
176     return self->regs.mem_be[sizeof(union cpu_6809_regs) + addr];
177 #else
178     return self->regs.mem_le[~addr];
179 #endif
180   self->cycles += 1;
181   return self->read_byte(self->read_byte_context, addr & 0xffff);
182 }
183
184 static ALWAYS_INLINE int cpu_6809_read_word(struct cpu_6809 *self, int addr) {
185   int data = cpu_6809_read_byte(self, addr) << 8;
186   return data | cpu_6809_read_byte(self, addr + 1);
187 }
188
189 static ALWAYS_INLINE void cpu_6809_write_byte(struct cpu_6809 *self, int addr, int data) {
190   self->cycles += 1;
191   if (addr < 0)
192 #if __BYTE_ORDER == __BIG_ENDIAN
193     self->regs.mem_be[sizeof(union cpu_6809_regs) + addr] = data;
194 #else
195     self->regs.mem_le[~addr] = data;
196 #endif
197   else
198     self->write_byte(self->write_byte_context, addr, data);
199 }
200
201 static ALWAYS_INLINE void cpu_6809_write_word(struct cpu_6809 *self, int addr, int data) {
202   cpu_6809_write_byte(self, addr, data >> 8);
203   cpu_6809_write_byte(self, addr + 1, data & 0xff);
204 }
205
206 static ALWAYS_INLINE int cpu_6809_fetch_byte(struct cpu_6809 *self) {
207   int data = cpu_6809_read_byte(self, self->regs.word.pc++);
208   return data;
209 }
210
211 static ALWAYS_INLINE int cpu_6809_fetch_word(struct cpu_6809 *self) {
212   int data = cpu_6809_fetch_byte(self) << 8;
213   return data | cpu_6809_fetch_byte(self);
214 }
215
216 static ALWAYS_INLINE void cpu_6809_push_byte(struct cpu_6809 *self, uint16_t *sp, int data) {
217   cpu_6809_write_byte(self, --*sp, data);
218 }
219
220 static ALWAYS_INLINE void cpu_6809_push_word(struct cpu_6809 *self, uint16_t *sp, int data) {
221   cpu_6809_push_byte(self, sp, data & 0xff);
222   cpu_6809_push_byte(self, sp, data >> 8);
223 }
224
225 static ALWAYS_INLINE int cpu_6809_pop_byte(struct cpu_6809 *self, uint16_t *sp) {
226   return cpu_6809_read_byte(self, (*sp)++);
227 }
228
229 static ALWAYS_INLINE int cpu_6809_pop_word(struct cpu_6809 *self, uint16_t *sp) {
230   int data = cpu_6809_pop_byte(self, sp) << 8;
231   return data | cpu_6809_pop_byte(self, sp);
232 }
233
234 // effective address calculation
235 static ALWAYS_INLINE int cpu_6809_ea_extended(struct cpu_6809 *self) {
236   return cpu_6809_fetch_word(self);
237 }
238
239 static ALWAYS_INLINE int cpu_6809_ea_relative(struct cpu_6809 *self) {
240   return (int8_t)cpu_6809_fetch_byte(self);
241 }
242
243 static ALWAYS_INLINE int cpu_6809_ea_long_relative(struct cpu_6809 *self) {
244   return cpu_6809_fetch_word(self);
245 }
246
247 static ALWAYS_INLINE int cpu_6809_ea_direct(struct cpu_6809 *self) {
248   return cpu_6809_fetch_byte(self);
249 }
250
251 // instruction execute
252 static ALWAYS_INLINE void cpu_6809_abx(struct cpu_6809 *self) {
253   self->regs.word.x += self->regs.byte.b;
254 }
255
256 static ALWAYS_INLINE void cpu_6809_adc(struct cpu_6809 *self, int lvalue, int rvalue) {
257   int data = cpu_6809_read_byte(self, lvalue);
258
259   int result0 = (data & 0xf) + (rvalue & 0xf) + self->regs.bit.cf;
260   int result1 = result0 + (data & 0x70) + (rvalue & 0x70);
261   int result2 = result1 + (data & 0x80) + (rvalue & 0x80);
262
263   cpu_6809_write_byte(self, lvalue, result2 & 0xff);
264   self->regs.bit.hf = result0 >> 4;
265   self->regs.bit.nf = (result2 >> 7) & 1;
266   self->regs.bit.zf = (result2 & 0xff) == 0;
267   self->regs.bit.vf = ((result1 >> 7) ^ (result2 >> 8)) & 1;
268   self->regs.bit.cf = result2 >> 8;
269 }
270
271 static ALWAYS_INLINE void cpu_6809_add_byte(struct cpu_6809 *self, int lvalue, int rvalue) {
272   int data = cpu_6809_read_byte(self, lvalue);
273
274   int result0 = (data & 0xf) + (rvalue & 0xf);
275   int result1 = result0 + (data & 0x70) + (rvalue & 0x70);
276   int result2 = result1 + (data & 0x80) + (rvalue & 0x80);
277
278   cpu_6809_write_byte(self, lvalue, result2 & 0xff);
279   self->regs.bit.hf = result0 >> 4;
280   self->regs.bit.nf = (result2 >> 7) & 1;
281   self->regs.bit.zf = (result2 & 0xff) == 0;
282   self->regs.bit.vf = ((result1 >> 7) ^ (result2 >> 8)) & 1;
283   self->regs.bit.cf = result2 >> 8;
284 }
285
286 static ALWAYS_INLINE void cpu_6809_add_word(struct cpu_6809 *self, int lvalue, int rvalue) {
287   int data = cpu_6809_read_word(self, lvalue);
288
289   int result0 = (data & 0x7fff) + (rvalue & 0x7fff);
290   int result1 = result0 + (data & 0x8000) + (rvalue & 0x8000);
291
292   cpu_6809_write_word(self, lvalue, result1 & 0xffff);
293   self->regs.bit.nf = (result1 >> 15) & 1;
294   self->regs.bit.zf = (result1 & 0xffff) == 0;
295   self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
296   self->regs.bit.cf = result1 >> 16;
297 }
298
299 static ALWAYS_INLINE void cpu_6809_and(struct cpu_6809 *self, int lvalue, int rvalue) {
300   int result = cpu_6809_read_byte(self, lvalue) & rvalue;
301
302   cpu_6809_write_byte(self, lvalue, result);
303   self->regs.bit.nf = result >> 7;
304   self->regs.bit.zf = result == 0;
305   self->regs.bit.vf = false;
306 }
307
308 static ALWAYS_INLINE void cpu_6809_andcc(struct cpu_6809 *self, int rvalue) {
309   self->regs.byte.cc &= rvalue;
310 }
311
312 static ALWAYS_INLINE void cpu_6809_asl(struct cpu_6809 *self, int lvalue) {
313   int result = cpu_6809_read_byte(self, lvalue) << 1;
314   ++self->cycles;
315
316   cpu_6809_write_byte(self, lvalue, result & 0xff);
317   self->regs.bit.nf = (result >> 7) & 1;
318   self->regs.bit.zf = (result & 0xff) == 0;
319   self->regs.bit.vf = ((result >> 7) ^ (result >> 8)) & 1;
320   self->regs.bit.cf = result >> 8;
321 }
322
323 static ALWAYS_INLINE void cpu_6809_asr(struct cpu_6809 *self, int lvalue) {
324   int data = cpu_6809_read_byte(self, lvalue);
325
326   int result = data | ((data << 1) & 0x100);
327   ++self->cycles;
328
329   cpu_6809_write_byte(self, lvalue, result >> 1);
330   self->regs.bit.nf = result >> 8;
331   self->regs.bit.zf = (result & 0xfe) == 0;
332   self->regs.bit.cf = result & 1;
333 }
334
335 static ALWAYS_INLINE void cpu_6809_bit(struct cpu_6809 *self, int rvalue0, int rvalue1) {
336   int result = rvalue0 & rvalue1;
337
338   self->regs.bit.nf = result >> 7;
339   self->regs.bit.zf = result == 0;
340   self->regs.bit.vf = false;
341 }
342
343 static ALWAYS_INLINE void cpu_6809_bra(struct cpu_6809 *self, bool pred, int lvalue) {
344   if (pred) {
345     self->cycles += ((self->regs.word.pc & 0xff) + (lvalue & 0xff)) >> 8;
346     self->regs.word.pc += lvalue;
347   }
348 }
349
350 static ALWAYS_INLINE void cpu_6809_bsr(struct cpu_6809 *self, int lvalue) {
351   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
352   self->cycles += ((self->regs.word.pc & 0xff) + (lvalue & 0xff)) >> 8;
353   self->regs.word.pc += lvalue;
354 }
355
356 static ALWAYS_INLINE void cpu_6809_clr(struct cpu_6809 *self, int lvalue) {
357   //cpu_6809_read_byte(self, lvalue); // clr is implemented as RMW like inc/dec
358   cpu_6809_write_byte(self, lvalue, 0);
359
360   self->regs.bit.nf = false;
361   self->regs.bit.zf = true;
362   self->regs.bit.vf = false;
363   self->regs.bit.cf = false;
364 }
365
366 static ALWAYS_INLINE void cpu_6809_cmp_byte(struct cpu_6809 *self, int rvalue0, int rvalue1) {
367   int result0 = (rvalue0 & 0x7f) - (rvalue1 & 0x7f);
368   int result1 = result0 + (rvalue0 & 0x80) - (rvalue1 & 0x80);
369
370   self->regs.bit.nf = (result1 >> 7) & 1;
371   self->regs.bit.zf = (result1 & 0xff) == 0;
372   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
373   self->regs.bit.cf = (result1 >> 8) & 1;
374 }
375
376 static ALWAYS_INLINE void cpu_6809_cmp_word(struct cpu_6809 *self, int rvalue0, int rvalue1) {
377   int result0 = (rvalue0 & 0x7fff) - (rvalue1 & 0x7fff);
378   int result1 = result0 + (rvalue0 & 0x8000) - (rvalue1 & 0x8000);
379
380   self->regs.bit.nf = (result1 >> 15) & 1;
381   self->regs.bit.zf = (result1 & 0xffff) == 0;
382   self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
383   self->regs.bit.cf = (result1 >> 16) & 1;
384 }
385
386 static ALWAYS_INLINE void cpu_6809_com(struct cpu_6809 *self, int lvalue) {
387   int result = cpu_6809_read_byte(self, lvalue) ^ 0xff;
388
389   cpu_6809_write_byte(self, lvalue, result);
390   self->regs.bit.nf = result >> 7;
391   self->regs.bit.zf = result == 0;
392   self->regs.bit.vf = false;
393   self->regs.bit.cf = true;
394 }
395
396 static ALWAYS_INLINE void cpu_6809_cwai(struct cpu_6809 *self, int rvalue) {
397   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
398   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.x);
399   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.a);
400   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.b);
401   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.cc);
402   self->regs.bit.wai_flag = true;
403 }
404
405 static ALWAYS_INLINE void cpu_6809_daa(struct cpu_6809 *self) {
406   int correction = 0;
407   if (self->regs.bit.hf || (self->regs.byte.a & 0xf) >= 0xa)
408     correction = 6;
409   if (self->regs.bit.cf || self->regs.byte.a >= 0x9a) {
410     correction |= 0x60;
411     self->regs.bit.cf = true;
412   }
413
414   int result0 = (self->regs.byte.a & 0x7f) + correction;
415   int result1 = result0 + (self->regs.byte.a & 0x80);
416
417   self->regs.byte.a = result1 & 0xff;
418   self->regs.bit.nf = (result1 >> 7) & 1;
419   self->regs.bit.zf = (result1 & 0xff) == 0;
420   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
421   //self->regs.bit.cf |= result1 >> 8;
422 }
423
424 static ALWAYS_INLINE void cpu_6809_dec_byte(struct cpu_6809 *self, int lvalue) {
425   int data = cpu_6809_read_byte(self, lvalue);
426
427   int result0 = (data & 0x7f) - 1;
428   int result1 = result0 + (data & 0x80);
429   ++self->cycles;
430
431   cpu_6809_write_byte(self, lvalue, result1 & 0xff);
432   self->regs.bit.nf = (result1 >> 7) & 1;
433   self->regs.bit.zf = (result1 & 0xff) == 0;
434   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
435 }
436
437 static ALWAYS_INLINE void cpu_6809_dec_word(struct cpu_6809 *self, int lvalue) {
438   cpu_6809_write_word(
439     self,
440     lvalue,
441     (cpu_6809_read_word(self, lvalue) - 1) & 0xffff
442   );
443   ++self->cycles;
444 }
445
446 static ALWAYS_INLINE void cpu_6809_dec_word_zf(struct cpu_6809 *self, int lvalue) {
447   int result = (cpu_6809_read_word(self, lvalue) - 1) & 0xffff;
448   ++self->cycles;
449
450   self->regs.word.x = result;
451   self->regs.bit.zf = result == 0;
452 }
453
454 static ALWAYS_INLINE void cpu_6809_eor(struct cpu_6809 *self, int lvalue, int rvalue) {
455   int result = cpu_6809_read_byte(self, lvalue) ^ rvalue;
456
457   cpu_6809_write_byte(self, lvalue, result);
458   self->regs.bit.nf = result >> 7;
459   self->regs.bit.zf = result == 0;
460   self->regs.bit.vf = false;
461 }
462
463 static ALWAYS_INLINE void cpu_6809_exg(struct cpu_6809 *self, int postbyte) {
464   int reg0 = postbyte >> 4;
465   int reg1 = postbyte & 0xf;
466
467   int rvalue00 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][0]);
468   int rvalue10 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg1][0]);
469   cpu_6809_write_byte(self, cpu_6809_ea_dest[reg1][0], rvalue00);
470   cpu_6809_write_byte(self, cpu_6809_ea_dest[reg0][0], rvalue10);
471
472   int rvalue01 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][1]);
473   int rvalue11 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg1][1]);
474   cpu_6809_write_byte(self, cpu_6809_ea_dest[reg1][1], rvalue01);
475   cpu_6809_write_byte(self, cpu_6809_ea_dest[reg0][1], rvalue11);
476 }
477
478 static ALWAYS_INLINE void cpu_6809_illegal_opcode(struct cpu_6809 *self) {
479   abort();
480 }
481
482 static ALWAYS_INLINE void cpu_6809_inc_byte(struct cpu_6809 *self, int lvalue) {
483   int data = cpu_6809_read_byte(self, lvalue);
484
485   int result0 = (data & 0x7f) + 1;
486   int result1 = result0 + (data & 0x80);
487   ++self->cycles;
488
489   cpu_6809_write_byte(self, lvalue, result1 & 0xff);
490   self->regs.bit.nf = (result1 >> 7) & 1;
491   self->regs.bit.zf = (result1 & 0xff) == 0;
492   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
493 }
494
495 static ALWAYS_INLINE void cpu_6809_inc_word(struct cpu_6809 *self, int lvalue) {
496   cpu_6809_write_word(
497     self,
498     lvalue,
499     (cpu_6809_read_word(self, lvalue) + 1) & 0xffff
500   );
501   ++self->cycles;
502 }
503
504 static ALWAYS_INLINE void cpu_6809_inc_word_zf(struct cpu_6809 *self, int lvalue) {
505   int result = (cpu_6809_read_word(self, lvalue) + 1) & 0xffff;
506   ++self->cycles;
507
508   self->regs.word.x = result;
509   self->regs.bit.zf = result == 0;
510 }
511
512 static ALWAYS_INLINE void cpu_6809_jmp(struct cpu_6809 *self, int lvalue) {
513   self->regs.word.pc = lvalue;
514 }
515
516 static ALWAYS_INLINE void cpu_6809_jsr(struct cpu_6809 *self, int lvalue) {
517   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
518   self->regs.word.pc = lvalue;
519 }
520
521 static ALWAYS_INLINE void cpu_6809_lbra(struct cpu_6809 *self, bool pred, int lvalue) {
522   if (pred) {
523     self->cycles += ((self->regs.word.pc & 0xff) + (lvalue & 0xff)) >> 8;
524     self->regs.word.pc += lvalue;
525   }
526 }
527
528 static ALWAYS_INLINE void cpu_6809_lbsr(struct cpu_6809 *self, int lvalue) {
529   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
530   self->cycles += ((self->regs.word.pc & 0xff) + (lvalue & 0xff)) >> 8;
531   self->regs.word.pc += lvalue;
532 }
533
534 static ALWAYS_INLINE void cpu_6809_ld_word(struct cpu_6809 *self, int lvalue, int rvalue) {
535   cpu_6809_write_word(self, lvalue, rvalue);
536
537   self->regs.bit.nf = (rvalue >> 15) & 1;
538   self->regs.bit.zf = rvalue == 0;
539   self->regs.bit.vf = false;
540 }
541
542 static ALWAYS_INLINE void cpu_6809_ld_byte(struct cpu_6809 *self, int lvalue, int rvalue) {
543   cpu_6809_write_byte(self, lvalue, rvalue);
544
545   self->regs.bit.nf = (rvalue >> 7) & 1;
546   self->regs.bit.zf = rvalue == 0;
547   self->regs.bit.vf = false;
548 }
549
550 static ALWAYS_INLINE void cpu_6809_lea(struct cpu_6809 *self, int lvalue0, int lvalue1) {
551   cpu_6809_write_word(self, lvalue0, lvalue1);
552 }
553
554 static ALWAYS_INLINE void cpu_6809_lea_zf(struct cpu_6809 *self, int lvalue0, int lvalue1) {
555   cpu_6809_write_word(self, lvalue0, lvalue1);
556
557   self->regs.bit.zf = lvalue1 == 0;
558 }
559
560 static ALWAYS_INLINE void cpu_6809_lsr(struct cpu_6809 *self, int lvalue) {
561   int data = cpu_6809_read_byte(self, lvalue);
562
563   int result = data;
564   ++self->cycles;
565
566   cpu_6809_write_byte(self, lvalue, result >> 1);
567   self->regs.bit.nf = result >> 8;
568   self->regs.bit.zf = (result & 0xfe) == 0;
569   self->regs.bit.cf = result & 1;
570 }
571
572 static ALWAYS_INLINE void cpu_6809_mul(struct cpu_6809 *self) {
573   abort();
574 }
575
576 static ALWAYS_INLINE void cpu_6809_neg(struct cpu_6809 *self, int lvalue) {
577   int data = cpu_6809_read_byte(self, lvalue);
578
579   int result0 = -(data & 0x7f);
580   int result1 = result0 - (data & 0x80);
581
582   cpu_6809_write_byte(self, lvalue, result1 & 0xff);
583   self->regs.bit.nf = (result1 >> 7) & 1;
584   self->regs.bit.zf = (result1 & 0xff) == 0;
585   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
586   self->regs.bit.cf = (result1 >> 8) & 1;
587 }
588
589 static ALWAYS_INLINE void cpu_6809_nop(struct cpu_6809 *self) {
590 }
591
592 static ALWAYS_INLINE void cpu_6809_or(struct cpu_6809 *self, int lvalue, int rvalue) {
593   int result = cpu_6809_read_byte(self, lvalue) | rvalue;
594
595   cpu_6809_write_byte(self, lvalue, result);
596   self->regs.bit.nf = result >> 7;
597   self->regs.bit.zf = result == 0;
598   self->regs.bit.vf = false;
599 }
600
601 static ALWAYS_INLINE void cpu_6809_orcc(struct cpu_6809 *self, int rvalue) {
602   self->regs.byte.cc |= rvalue;
603 }
604
605 static ALWAYS_INLINE void cpu_6809_psh(struct cpu_6809 *self, int lvalue, int postbyte) {
606   uint16_t sp = cpu_6809_read_word(self, lvalue);
607   if (postbyte & 0x80)
608     cpu_6809_push_word(self, &sp, self->regs.word.pc);
609   if (postbyte & 0x40)
610     cpu_6809_push_word(
611       self,
612       &sp,
613       cpu_6809_read_word(self, lvalue ^ (CPU_6809_EA_U ^ CPU_6809_EA_S))
614     );
615   if (postbyte & 0x20)
616     cpu_6809_push_word(self, &sp, self->regs.word.y);
617   if (postbyte & 0x10)
618     cpu_6809_push_word(self, &sp, self->regs.word.x);
619   if (postbyte & 8)
620     cpu_6809_push_byte(self, &sp, self->regs.byte.dp);
621   if (postbyte & 4)
622     cpu_6809_push_byte(self, &sp, self->regs.byte.b);
623   if (postbyte & 2)
624     cpu_6809_push_byte(self, &sp, self->regs.byte.a);
625   if (postbyte & 1)
626     cpu_6809_push_byte(self, &sp, self->regs.byte.cc);
627   cpu_6809_write_word(self, lvalue, sp);
628 }
629
630 static ALWAYS_INLINE void cpu_6809_pul(struct cpu_6809 *self, int lvalue, int postbyte) {
631   uint16_t sp = cpu_6809_read_word(self, lvalue);
632   if (postbyte & 1)
633     self->regs.byte.cc = cpu_6809_pop_byte(self, &sp);
634   if (postbyte & 2)
635     self->regs.byte.a = cpu_6809_pop_byte(self, &sp);
636   if (postbyte & 4)
637     self->regs.byte.b = cpu_6809_pop_byte(self, &sp);
638   if (postbyte & 8)
639     self->regs.byte.dp = cpu_6809_pop_byte(self, &sp);
640   if (postbyte & 0x10)
641     self->regs.word.x = cpu_6809_pop_word(self, &sp);
642   if (postbyte & 0x20)
643     self->regs.word.y = cpu_6809_pop_word(self, &sp);
644   if (postbyte & 0x40)
645     cpu_6809_write_word(
646       self,
647       lvalue ^ (CPU_6809_EA_U ^ CPU_6809_EA_S),
648       cpu_6809_pop_word(self, &sp)
649     );
650   if (postbyte & 0x80)
651     self->regs.word.pc = cpu_6809_pop_word(self, &sp);
652   cpu_6809_write_word(self, lvalue, sp);
653 }
654
655 static ALWAYS_INLINE void cpu_6809_rol(struct cpu_6809 *self, int lvalue) {
656   int result = self->regs.bit.cf | (cpu_6809_read_byte(self, lvalue) << 1);
657   ++self->cycles;
658
659   cpu_6809_write_byte(self, lvalue, result & 0xff);
660   self->regs.bit.nf = (result >> 7) & 1;
661   self->regs.bit.zf = (result & 0xff) == 0;
662   self->regs.bit.vf = ((result >> 7) ^ (result >> 8)) & 1;
663   self->regs.bit.cf = result >> 8;
664 }
665
666 static ALWAYS_INLINE void cpu_6809_ror(struct cpu_6809 *self, int lvalue) {
667   int result = cpu_6809_read_byte(self, lvalue) | (self->regs.bit.cf << 8);
668   ++self->cycles;
669   cpu_6809_write_byte(self, lvalue, result >> 1);
670
671   self->regs.bit.nf = result >> 8;
672   self->regs.bit.zf = (result & 0x1fe) == 0;
673   self->regs.bit.cf = result & 1;
674 }
675
676 static ALWAYS_INLINE void cpu_6809_rti(struct cpu_6809 *self) {
677   self->regs.byte.cc = cpu_6809_pop_byte(self, &self->regs.word.s);
678   self->regs.byte.b = cpu_6809_pop_byte(self, &self->regs.word.s);
679   self->regs.byte.a = cpu_6809_pop_byte(self, &self->regs.word.s);
680   self->regs.word.x = cpu_6809_pop_word(self, &self->regs.word.s);
681   self->regs.word.pc = cpu_6809_pop_word(self, &self->regs.word.s);
682 }
683
684 static ALWAYS_INLINE void cpu_6809_rts(struct cpu_6809 *self) {
685   self->regs.word.pc = cpu_6809_pop_word(self, &self->regs.word.s);
686 }
687
688 static ALWAYS_INLINE void cpu_6809_sbc(struct cpu_6809 *self, int lvalue, int rvalue) {
689   int data = cpu_6809_read_byte(self, lvalue);
690
691   int result0 = (data & 0x7f) - (rvalue & 0x7f) - self->regs.bit.cf;
692   int result1 = result0 + (data & 0x80) - (rvalue & 0x80);
693
694   cpu_6809_write_byte(self, lvalue, result1 & 0xff);
695   self->regs.bit.nf = (result1 >> 7) & 1;
696   self->regs.bit.zf = (result1 & 0xff) == 0;
697   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
698   self->regs.bit.cf = (result1 >> 8) & 1;
699 }
700
701 static ALWAYS_INLINE void cpu_6809_sex(struct cpu_6809 *self) {
702   abort();
703 }
704
705 static ALWAYS_INLINE void cpu_6809_st_word(struct cpu_6809 *self, int rvalue, int lvalue) {
706   cpu_6809_write_word(self, lvalue, rvalue);
707
708   self->regs.bit.nf = (rvalue >> 15) & 1;
709   self->regs.bit.zf = rvalue == 0;
710   self->regs.bit.vf = false;
711 }
712
713 static ALWAYS_INLINE void cpu_6809_st_byte(struct cpu_6809 *self, int rvalue, int lvalue) {
714   cpu_6809_write_byte(self, lvalue, rvalue);
715
716   self->regs.bit.nf = (rvalue >> 7) & 1;
717   self->regs.bit.zf = rvalue == 0;
718   self->regs.bit.vf = false;
719 }
720
721 static ALWAYS_INLINE void cpu_6809_sub_byte(struct cpu_6809 *self, int lvalue, int rvalue) {
722   int data = cpu_6809_read_byte(self, lvalue);
723
724   int result0 = (data & 0x7f) - (rvalue & 0x7f);
725   int result1 = result0 + (data & 0x80) - (rvalue & 0x80);
726
727   cpu_6809_write_byte(self, lvalue, result1 & 0xff);
728   self->regs.bit.nf = (result1 >> 7) & 1;
729   self->regs.bit.zf = (result1 & 0xff) == 0;
730   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
731   self->regs.bit.cf = (result1 >> 8) & 1;
732 }
733
734 static ALWAYS_INLINE void cpu_6809_sub_word(struct cpu_6809 *self, int lvalue, int rvalue) {
735   int data = cpu_6809_read_word(self, lvalue);
736
737   int result0 = (data & 0x7fff) - (rvalue & 0x7fff);
738   int result1 = result0 + (data & 0x8000) - (rvalue & 0x8000);
739
740   cpu_6809_write_word(self, lvalue, result1 & 0xffff);
741   self->regs.bit.nf = (result1 >> 15) & 1;
742   self->regs.bit.zf = (result1 & 0xffff) == 0;
743   self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
744   self->regs.bit.cf = (result1 >> 16) & 1;
745 }
746
747 static ALWAYS_INLINE void cpu_6809_swi(struct cpu_6809 *self) {
748   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
749   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.x);
750   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.a);
751   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.b);
752   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.cc);
753   self->regs.word.pc = cpu_6809_read_word(self, CPU_6809_SWI_VECTOR);
754   self->regs.bit._if = true;
755 }
756
757 static ALWAYS_INLINE void cpu_6809_swi_n(struct cpu_6809 *self, int n) {
758   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
759   cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.x);
760   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.a);
761   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.b);
762   cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.cc);
763   self->regs.word.pc = cpu_6809_read_word(self, CPU_6809_SWI_VECTOR);
764   self->regs.bit._if = true;
765 }
766
767 static ALWAYS_INLINE void cpu_6809_sync(struct cpu_6809 *self) {
768   abort();
769 }
770
771 static ALWAYS_INLINE void cpu_6809_tfr(struct cpu_6809 *self, int postbyte) {
772   int reg0 = postbyte >> 4;
773   int reg1 = postbyte & 0xf;
774
775   cpu_6809_write_byte(
776     self,
777     cpu_6809_ea_dest[reg1][0],
778     cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][0])
779   );
780   cpu_6809_write_byte(
781     self,
782     cpu_6809_ea_dest[reg1][1],
783     cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][1])
784   );
785 }
786
787 static ALWAYS_INLINE void cpu_6809_tst(struct cpu_6809 *self, int rvalue) {
788   self->regs.bit.nf = (rvalue >> 7) & 1;
789   self->regs.bit.zf = rvalue == 0;
790   self->regs.bit.vf = false;
791 }
792
793 // prototypes
794 void cpu_6809_init(
795   struct cpu_6809 *self,
796   int (*read_byte)(void *context, int addr),
797   void *read_byte_context,
798   void (*write_byte)(void *context, int addr, int data),
799   void *write_byte_context
800 );
801 void cpu_6809_reset(struct cpu_6809 *self);
802 int cpu_6809_addressing_mode(struct cpu_6809 *self);
803 void cpu_6809_execute(struct cpu_6809 *self);
804 void cpu_6809_execute_10(struct cpu_6809 *self);
805 void cpu_6809_execute_11(struct cpu_6809 *self);
806  
807 #endif