]>
Commit | Line | Data |
---|---|---|
1 | ; Z80 emulator with CP/M support. The Z80-specific instructions themselves actually aren't | |
2 | ; implemented yet, making this more of an i8080 emulator. | |
3 | ; | |
4 | ; Copyright (C) 2010 Sprite_tm | |
5 | ; | |
6 | ; This program is free software: you can redistribute it and/or modify | |
7 | ; it under the terms of the GNU General Public License as published by | |
8 | ; the Free Software Foundation, either version 3 of the License, or | |
9 | ; (at your option) any later version. | |
10 | ; | |
11 | ; This program is distributed in the hope that it will be useful, | |
12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | ; GNU General Public License for more details. | |
15 | ; | |
16 | ; You should have received a copy of the GNU General Public License | |
17 | ; along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | ||
19 | ;.nolist | |
20 | #if defined atmega8 | |
21 | .include "m8def.inc" | |
22 | #elif defined atmega168 | |
23 | .include "m8def.inc" | |
24 | #else /* default */ | |
25 | .include "m88def.inc" | |
26 | ;FUSE_H=0xDF | |
27 | ;FUSE_L=0xF7 | |
28 | #endif | |
29 | .list | |
30 | ||
31 | ||
32 | #ifndef DRAM_DQ_ORDER /* If this is set to 1, the portbits */ | |
33 | #define DRAM_DQ_ORDER 0 /* for DRAM D1 and WE are swapped. */ | |
34 | #endif | |
35 | ||
36 | ||
37 | #ifndef F_CPU | |
38 | #define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */ | |
39 | #endif | |
40 | #ifndef BAUD | |
41 | #define BAUD 38400 /* console baud rate */ | |
42 | #endif | |
43 | ||
44 | ||
45 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */ | |
46 | ||
47 | #define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */ | |
48 | ||
49 | #define REFR_RATE 64000 /* dram refresh rate in cycles/s. */ | |
50 | /* Most drams need 1/15.6µs. */ | |
51 | #define REFR_PRE 8 /* timer prescale factor */ | |
52 | #define REFR_CS 0x02 /* timer clock select for 1/8 */ | |
53 | #define REFR_CNT F_CPU / REFR_RATE / REFR_PRE | |
54 | ||
55 | ||
56 | #if defined __ATmega8__ | |
57 | .equ refr_vect = OC2addr | |
58 | #else | |
59 | .equ refr_vect = OC2Aaddr | |
60 | #endif | |
61 | ||
62 | ||
63 | #define EM_Z80 0 /* we don't have any z80 instructions yet */ | |
64 | ||
65 | .equ MMC_DEBUG = 0 | |
66 | .equ INS_DEBUG = 0 | |
67 | .equ MEMTEST = 1 | |
68 | .equ BOOTWAIT = 1 | |
69 | .equ PORT_DEBUG = 0 | |
70 | .equ DISK_DEBUG = 0 | |
71 | .equ MEMFILL_CB = 1 | |
72 | .equ STACK_DBG = 0 | |
73 | .equ PRINT_PC = 0 | |
74 | ||
75 | ;Port declarations | |
76 | ||
77 | ; Port D | |
78 | .equ rxd = 0 | |
79 | .equ txd = 1 | |
80 | .equ ram_oe = 2 | |
81 | .equ ram_a8 = 3 | |
82 | .equ mmc_cs = 4 | |
83 | .equ ram_a5 = 5 | |
84 | .equ ram_a6 = 6 | |
85 | .equ ram_a7 = 7 | |
86 | ||
87 | .equ RAM_AH_MASK = 0xE0 ; ram_a[7..5] | |
88 | .equ PD_OUTPUT_MASK = 0xFE | |
89 | ||
90 | ||
91 | ;Port B | |
92 | .equ ram_a4 = 0 | |
93 | .equ ram_a3 = 1 | |
94 | .equ ram_a2 = 2 | |
95 | .equ ram_a1 = 3 | |
96 | .equ mmc_mosi = 3 | |
97 | .equ ram_a0 = 4 | |
98 | .equ mmc_miso = 4 | |
99 | .equ ram_ras = 5 | |
100 | .equ mmc_sck = 5 | |
101 | ||
102 | .equ RAM_AL_MASK = 0x1F ; ram_a[4..0] | |
103 | .equ PB_OUTPUT_MASK = 0x3F | |
104 | ||
105 | ;Port C | |
106 | #if DRAM_DQ_ORDER == 1 | |
107 | .equ ram_d1 = 1 | |
108 | .equ ram_w = 4 | |
109 | #else /* original */ | |
110 | .equ ram_d1 = 4 | |
111 | .equ ram_w = 1 | |
112 | #endif | |
113 | .equ ram_d0 = 0 | |
114 | .equ ram_d2 = 2 | |
115 | .equ ram_d3 = 3 | |
116 | .equ ram_cas= 5 | |
117 | ||
118 | .equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0) | |
119 | .equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w) | |
120 | ||
121 | ||
122 | ;Flag bits in z_flags | |
123 | .equ ZFL_S = 7 | |
124 | .equ ZFL_Z = 6 | |
125 | .equ ZFL_H = 4 | |
126 | .equ ZFL_P = 2 | |
127 | .equ ZFL_N = 1 | |
128 | .equ ZFL_C = 0 | |
129 | ||
130 | ;Register definitions | |
131 | .def z_a = r2 | |
132 | .def z_b = r3 | |
133 | .def z_c = r4 | |
134 | .def z_d = r5 | |
135 | .def z_e = r6 | |
136 | .def z_l = r7 | |
137 | .def z_h = r8 | |
138 | .def z_spl = r9 | |
139 | .def z_sph = r10 | |
140 | ||
141 | .def dsk_trk = r11 | |
142 | .def dsk_sec = r12 | |
143 | .def dsk_dmah = r13 | |
144 | .def dsk_dmal = r14 | |
145 | ||
146 | ;.def parityb = r15 | |
147 | ||
148 | .def temp = R16 ;The temp register | |
149 | .def temp2 = R17 ;Second temp register | |
150 | .def trace = r18 | |
151 | .def opl = r19 | |
152 | .def oph = r20 | |
153 | .def adrl = r21 | |
154 | .def adrh = r22 | |
155 | .def insdecl = r23 | |
156 | .def z_pcl = r24 | |
157 | .def z_pch = r25 | |
158 | .undef xl | |
159 | .undef xh | |
160 | .def insdech = r26 | |
161 | .def z_flags = r27 | |
162 | ||
163 | ||
164 | ; This is the base z80 port address for clock access | |
165 | #define TIMERPORT 0x40 | |
166 | #define TIMER_CTL TIMERPORT | |
167 | #define TIMER_MSECS TIMERPORT+1 | |
168 | #define TIMER_SECS TIMER_MSECS+2 | |
169 | ||
170 | #define starttimercmd 1 | |
171 | #define quitTimerCmd 2 | |
172 | #define printTimerCmd 15 | |
173 | #define uptimeCmd 16 | |
174 | ||
175 | ||
176 | ||
177 | ;SRAM | |
178 | .dseg | |
179 | ||
180 | ;Sector buffer for 512 byte reads/writes from/to SD-card | |
181 | ||
182 | sectbuff: | |
183 | .byte 512 | |
184 | ||
185 | ||
186 | .cseg | |
187 | .org 0 | |
188 | rjmp start ; reset vector | |
189 | .org refr_vect | |
190 | rjmp refrint ; tim2cmpa | |
191 | .org OC1Aaddr ; Timer/Counter1 Compare Match A | |
192 | rjmp sysclockint ; 1ms system timer | |
193 | .org URXCaddr | |
194 | rjmp rxint ; USART receive int. | |
195 | ;.org UDREaddr | |
196 | ; rjmp txint | |
197 | ||
198 | .org INT_VECTORS_SIZE | |
199 | ||
200 | start: | |
201 | ldi temp,low(RAMEND) ; top of memory | |
202 | out SPL,temp ; init stack pointer | |
203 | ldi temp,high(RAMEND) ; top of memory | |
204 | out SPH,temp ; init stack pointer | |
205 | ||
206 | ; - Kill wdt | |
207 | wdr | |
208 | #if defined __ATmega8__ | |
209 | ldi temp,0 | |
210 | out MCUCSR,temp | |
211 | ||
212 | ldi temp,(1<<WDCE) | (1<<WDE) | |
213 | out WDTCSR,temp | |
214 | ldi temp,(1<<WDCE) | |
215 | out WDTCSR,temp | |
216 | #else | |
217 | ldi temp,0 | |
218 | out MCUSR,temp | |
219 | ||
220 | ldi temp,(1<<WDCE) | (1<<WDE) | |
221 | sts WDTCSR,temp | |
222 | ldi temp,(1<<WDCE) | |
223 | sts WDTCSR,temp | |
224 | #endif | |
225 | ||
226 | ; - Setup Ports | |
227 | ldi temp,PB_OUTPUT_MASK | |
228 | out DDRB,temp | |
229 | ldi temp,PD_OUTPUT_MASK | |
230 | out DDRD,temp | |
231 | ldi temp,PC_OUTPUT_MASK | |
232 | out DDRC,temp | |
233 | ||
234 | sbi PORTC,ram_w | |
235 | sbi PORTC,ram_cas | |
236 | sbi PORTB,ram_ras | |
237 | sbi PORTD,ram_oe | |
238 | sbi PORTD,mmc_cs | |
239 | ||
240 | ||
241 | ; - Init serial port | |
242 | ||
243 | ldi temp,0 ; reset receive buffer | |
244 | sts rxcount,temp | |
245 | sts rxidx_r,temp | |
246 | sts rxidx_w,temp | |
247 | ||
248 | ||
249 | #if defined __ATmega8__ | |
250 | ldi temp, (1<<TXEN) | (1<<RXEN) | (1<<RXCIE) | |
251 | out UCSRB,temp | |
252 | ldi temp, (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) | |
253 | out UCSRC,temp | |
254 | ldi temp, HIGH(UBRR_VAL) | |
255 | out UBRRH,temp | |
256 | ldi temp, LOW(UBRR_VAL) | |
257 | out UBRRL,temp | |
258 | #else | |
259 | ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0) | |
260 | sts UCSR0B,temp | |
261 | ldi temp, (1<<UCSZ01) | (1<<UCSZ00) | |
262 | sts UCSR0C,temp | |
263 | ldi temp, HIGH(UBRR_VAL) | |
264 | sts UBRR0H,temp | |
265 | ldi temp, LOW(UBRR_VAL) | |
266 | sts UBRR0L,temp | |
267 | #endif | |
268 | ||
269 | ;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles. | |
270 | ||
271 | #ifdef __ATmega8__ | |
272 | ldi temp,REFR_CNT*2 ; 2 cycles per int | |
273 | out OCR2,temp | |
274 | ldi temp,(1<<WGM21) | REFR_CS ;CTC, clk/REFR_PRE | |
275 | out TCCR2,temp | |
276 | ldi temp, (1<<OCIE2) | |
277 | out TIMSK,temp | |
278 | #else | |
279 | ldi temp,REFR_CNT ;=312 cycles | |
280 | sts OCR2A,temp | |
281 | ldi temp, (1<<WGM21) | |
282 | sts TCCR2A,temp | |
283 | ldi temp, REFR_CS ;clk/REFR_PRE | |
284 | sts TCCR2B,temp | |
285 | ldi temp,(1<<OCIE2A) | |
286 | sts TIMSK2,temp | |
287 | #endif | |
288 | ||
289 | ||
290 | ; Init clock/timer system | |
291 | ||
292 | ldi zl,low(timer_base) | |
293 | ldi zh,high(timer_base) | |
294 | ldi temp,0 | |
295 | ldi temp2,timer_size | |
296 | ti_loop: | |
297 | st z+,temp | |
298 | dec temp2 | |
299 | brne ti_loop | |
300 | ||
301 | ; Init timer 1 as 1 ms system clock tick. | |
302 | ||
303 | #ifdef __ATmega8__ | |
304 | ldi temp,high(F_CPU/1000) | |
305 | out OCR1AH,temp | |
306 | ldi temp,low(F_CPU/1000) | |
307 | out OCR1AL,temp | |
308 | ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1 | |
309 | out TCCR1B,temp | |
310 | in temp,TIMSK | |
311 | ori temp,(1<<OCIE1A) | |
312 | out TIMSK,temp | |
313 | #else | |
314 | ldi temp,high(F_CPU/1000) | |
315 | sts OCR1AH,temp | |
316 | ldi temp,low(F_CPU/1000) | |
317 | sts OCR1AL,temp | |
318 | ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1 | |
319 | sts TCCR1B,temp | |
320 | lds temp,TIMSK1 | |
321 | ori temp,(1<<OCIE1A) | |
322 | sts TIMSK1,temp | |
323 | #endif | |
324 | sei | |
325 | ||
326 | ||
327 | .if BOOTWAIT | |
328 | ldi temp,0 | |
329 | bootwait1: | |
330 | push temp ;2 | |
331 | ldi temp,0 ;1 | |
332 | bootwait2: | |
333 | dec temp ;1 | |
334 | brne bootwait2 ;2 | |
335 | pop temp ;2 | |
336 | dec temp ;1 | |
337 | brne bootwait1 ;2 (3*256 + 5) * 256 = 198K cycles | |
338 | ||
339 | .endif | |
340 | ||
341 | rcall printstr | |
342 | .db "CPM on an AVR, v1.0",13,0,0 | |
343 | ||
344 | ||
345 | rcall printstr | |
346 | .db "Initing mmc...",13,0 | |
347 | rcall mmcInit | |
348 | ||
349 | ||
350 | .if MEMTEST | |
351 | rcall printstr | |
352 | .db "Testing RAM...",13,0 | |
353 | ||
354 | ;Fill RAM | |
355 | ldi adrl,0 | |
356 | ldi adrh,0 | |
357 | ramtestw: | |
358 | mov temp,adrh | |
359 | eor temp,adrl | |
360 | rcall memwritebyte | |
361 | ldi temp,1 | |
362 | ldi temp2,0 | |
363 | add adrl,temp | |
364 | adc adrh,temp2 | |
365 | brcc ramtestw | |
366 | ||
367 | ;re-read RAM | |
368 | ldi adrl,0 | |
369 | ldi adrh,0 | |
370 | ramtestr: | |
371 | rcall memreadbyte | |
372 | mov temp2,adrh | |
373 | eor temp2,adrl | |
374 | cp temp,temp2 | |
375 | breq ramtestrok | |
376 | rcall printhex | |
377 | ldi temp,'<' | |
378 | rcall uartPutc | |
379 | mov temp,adrh | |
380 | eor temp,adrl | |
381 | rcall printhex | |
382 | ldi temp,'@' | |
383 | rcall uartPutc | |
384 | mov temp,adrh | |
385 | rcall printhex | |
386 | mov temp,adrl | |
387 | rcall printhex | |
388 | ldi temp,13 | |
389 | rcall uartPutc | |
390 | ramtestrok: | |
391 | ldi temp,1 | |
392 | ldi temp2,0 | |
393 | add adrl,temp | |
394 | adc adrh,temp2 | |
395 | brcc ramtestr | |
396 | ||
397 | .endif | |
398 | ||
399 | .if MEMFILL_CB | |
400 | ;Fill ram with cbs, which (for now) will trigger an invalid opcode error. | |
401 | ldi adrl,0 | |
402 | ldi adrh,0 | |
403 | ramfillw: | |
404 | ldi temp,0xcb | |
405 | rcall memwritebyte | |
406 | ldi temp,1 | |
407 | ldi temp2,0 | |
408 | add adrl,temp | |
409 | adc adrh,temp2 | |
410 | brcc ramfillw | |
411 | .endif | |
412 | ||
413 | ||
414 | ||
415 | ;Load initial sector from MMC (512 bytes) | |
416 | ldi adrh,0 | |
417 | ldi adrl,0 | |
418 | rcall mmcReadSect | |
419 | ||
420 | ;Save to Z80 RAM (only 128 bytes because that's retro) | |
421 | ldi zl,low(sectbuff) | |
422 | ldi zh,high(sectbuff) | |
423 | ldi adrh,0x20 | |
424 | ldi adrl,0x00 | |
425 | iplwriteloop: | |
426 | ld temp,z+ | |
427 | push zh | |
428 | push zl | |
429 | rcall memWriteByte | |
430 | pop zl | |
431 | pop zh | |
432 | ldi temp,1 | |
433 | ldi temp2,0 | |
434 | add adrl,temp | |
435 | adc adrh,temp2 | |
436 | cpi zl,low(sectbuff+128) | |
437 | brne iplwriteloop | |
438 | cpi zh,high(sectbuff+128) | |
439 | brne iplwriteloop | |
440 | ||
441 | ||
442 | ||
443 | ;Init z80 | |
444 | ldi temp,0x00 | |
445 | mov z_pcl,temp | |
446 | ldi temp,0x20 | |
447 | mov z_pch,temp | |
448 | ||
449 | ldi trace,0 | |
450 | rcall printstr | |
451 | .db 13,"Ok, CPU is live!",13,0,0 | |
452 | ||
453 | main: | |
454 | ldi trace,0 | |
455 | cpi z_pch,1 | |
456 | brlo notraceon | |
457 | cpi z_pch,$dc | |
458 | brsh notraceon | |
459 | ldi trace,1 | |
460 | notraceon: | |
461 | ||
462 | ||
463 | .if PRINT_PC | |
464 | cpi z_pch,1 | |
465 | brlo noprintpc | |
466 | cpi z_pch,0xdc | |
467 | brsh noprintpc | |
468 | ||
469 | rcall printstr | |
470 | .db "PC=",0 | |
471 | mov temp,z_pch | |
472 | rcall printhex | |
473 | mov temp,z_pcl | |
474 | rcall printhex | |
475 | ldi temp,10 | |
476 | rcall uartputc | |
477 | noprintpc: | |
478 | .endif | |
479 | ||
480 | ; *** Stage 1: Fetch next opcode | |
481 | mov adrl,z_pcl | |
482 | mov adrh,z_pch | |
483 | rcall memReadByte | |
484 | adiw z_pcl,1 | |
485 | ||
486 | ||
487 | .if INS_DEBUG | |
488 | cpi trace,0 | |
489 | breq notrace1 | |
490 | rcall printstr | |
491 | .db "PC=",0 | |
492 | push temp | |
493 | mov temp,adrh | |
494 | rcall printhex | |
495 | mov temp,adrl | |
496 | rcall printhex | |
497 | pop temp | |
498 | rcall printstr | |
499 | .db ", opcode=",0 | |
500 | rcall printhex | |
501 | notrace1: | |
502 | .endif | |
503 | ||
504 | ; *** Stage 2: Decode it using the ins_table. | |
505 | ldi temp2,0 | |
506 | ldi zl,low(inst_table*2) | |
507 | ldi zh,high(inst_table*2) | |
508 | add zl,temp | |
509 | adc zh,temp2 | |
510 | add zl,temp | |
511 | adc zh,temp2 | |
512 | lpm insdecl,Z+ | |
513 | lpm insdech,Z | |
514 | ||
515 | .if INS_DEBUG | |
516 | cpi trace,0 | |
517 | breq notrace2 | |
518 | rcall printstr | |
519 | .db ", decoded=",0 | |
520 | mov temp,insdech | |
521 | rcall printhex | |
522 | mov temp,insdecl | |
523 | rcall printhex | |
524 | rcall printstr | |
525 | .db ".",13,0 | |
526 | notrace2: | |
527 | .endif | |
528 | ||
529 | ; *** Stage 3: Fetch operand. Use the fetch jumptable for this. | |
530 | mov temp,insdecl | |
531 | andi temp,0x1F | |
532 | cpi temp,0 | |
533 | breq nofetch | |
534 | ldi temp2,0 | |
535 | lsl temp | |
536 | ldi zl,low(fetchjumps*2) | |
537 | ldi zh,high(fetchjumps*2) | |
538 | add zl,temp | |
539 | adc zh,temp2 | |
540 | lpm temp,Z+ | |
541 | lpm temp2,Z | |
542 | mov zl,temp | |
543 | mov zh,temp2 | |
544 | icall | |
545 | ||
546 | .if INS_DEBUG | |
547 | cpi trace,0 | |
548 | breq notrace3 | |
549 | rcall printstr | |
550 | .db "pre: oph:l=",0 | |
551 | mov temp,oph | |
552 | rcall printhex | |
553 | mov temp,opl | |
554 | rcall printhex | |
555 | rcall printstr | |
556 | .db " -- ",0 | |
557 | notrace3: | |
558 | .endif | |
559 | ||
560 | nofetch: | |
561 | ; *** Stage 4: Execute operation :) Use the op jumptable for this. | |
562 | mov temp,insdech | |
563 | andi temp,0xFC | |
564 | lsr temp | |
565 | cpi temp,0 | |
566 | breq nooper | |
567 | ldi zl,low(opjumps*2) | |
568 | ldi zh,high(opjumps*2) | |
569 | ldi temp2,0 | |
570 | add zl,temp | |
571 | adc zh,temp2 | |
572 | lpm temp,Z+ | |
573 | lpm temp2,Z | |
574 | mov zl,temp | |
575 | mov zh,temp2 | |
576 | icall | |
577 | ||
578 | .if INS_DEBUG | |
579 | cpi trace,0 | |
580 | breq notrace4 | |
581 | rcall printstr | |
582 | .db ",post:oph:l=",0 | |
583 | mov temp,oph | |
584 | rcall printhex | |
585 | mov temp,opl | |
586 | rcall printhex | |
587 | notrace4: | |
588 | .endif | |
589 | ||
590 | nooper: | |
591 | ; *** Stage 5: Store operand. Use the store jumptable for this. | |
592 | swap insdecl | |
593 | swap insdech | |
594 | mov temp,insdecl | |
595 | andi temp,0x0E | |
596 | andi insdech,0x30 | |
597 | or temp,insdech | |
598 | breq nostore | |
599 | ldi zl,low(storejumps*2) | |
600 | ldi zh,high(storejumps*2) | |
601 | ldi temp2,0 | |
602 | add zl,temp | |
603 | adc zh,temp2 | |
604 | lpm temp,Z+ | |
605 | lpm temp2,Z | |
606 | mov zl,temp | |
607 | mov zh,temp2 | |
608 | icall | |
609 | ||
610 | .if INS_DEBUG | |
611 | cpi trace,0 | |
612 | breq notrace5 | |
613 | rcall printstr | |
614 | .db ", stored.",0 | |
615 | notrace5: | |
616 | .endif | |
617 | ||
618 | nostore: | |
619 | ||
620 | .if INS_DEBUG | |
621 | cpi trace,0 | |
622 | breq notrace6 | |
623 | rcall printstr | |
624 | .db 13,0 | |
625 | notrace6: | |
626 | .endif | |
627 | ||
628 | ;All done. Neeeext! | |
629 | rjmp main | |
630 | ||
631 | ||
632 | ; ----------------Virtual peripherial interface ------ | |
633 | ||
634 | ;The hw is modelled to make writing a CPM BIOS easier. | |
635 | ;Ports: | |
636 | ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise. | |
637 | ;1 - Console input, aka UDR. | |
638 | ;2 - Console output | |
639 | ;16 - Track select | |
640 | ;18 - Sector select | |
641 | ;20 - Write addr l | |
642 | ;21 - Write addr h | |
643 | ;22 - Trigger - write 1 to read, 2 to write a sector using the above info. | |
644 | ; This will automatically move track, sector and dma addr to the next sector. | |
645 | ||
646 | ;Called with port in temp2. Should return value in temp. | |
647 | portRead: | |
648 | cpi temp2,0 | |
649 | breq conStatus | |
650 | cpi temp2,1 | |
651 | breq conInp | |
652 | ||
653 | cpi temp2,TIMER_MSECS | |
654 | brlo pr_noclock | |
655 | cpi temp2,TIMER_MSECS+6 | |
656 | brsh pr_noclock | |
657 | rjmp clockget | |
658 | ||
659 | pr_noclock: | |
660 | ldi temp,0xFF | |
661 | ret | |
662 | ||
663 | ;Called with port in temp2 and value in temp. | |
664 | portWrite: | |
665 | cpi temp2,0 | |
666 | breq dbgOut | |
667 | cpi temp2,2 | |
668 | breq conOut | |
669 | cpi temp2,16 | |
670 | breq dskTrackSel | |
671 | cpi temp2,18 | |
672 | breq dskSecSel | |
673 | cpi temp2,20 | |
674 | breq dskDmaL | |
675 | cpi temp2,21 | |
676 | breq dskDmaH | |
677 | cpi temp2,22 | |
678 | breq dskDoIt | |
679 | ||
680 | cpi temp2,TIMERPORT | |
681 | brlo pw_noclock | |
682 | cpi temp2,TIMER_MSECS+6 | |
683 | brsh pw_noclock | |
684 | rjmp clockput | |
685 | ||
686 | pw_noclock: | |
687 | ret | |
688 | ||
689 | ||
690 | conStatus: | |
691 | ||
692 | lds temp,rxcount | |
693 | tst temp | |
694 | breq PC+2 | |
695 | ldi temp,0xff | |
696 | ret | |
697 | ||
698 | conInp: | |
699 | rcall uartGetc | |
700 | ret | |
701 | ||
702 | dbgOut: | |
703 | rcall printstr | |
704 | .db "Debug: ",0 | |
705 | rcall printhex | |
706 | rcall printstr | |
707 | .db 13,0 | |
708 | ret | |
709 | ||
710 | conOut: | |
711 | rcall uartputc | |
712 | ret | |
713 | ||
714 | ||
715 | ||
716 | dskTrackSel: | |
717 | mov dsk_trk,temp | |
718 | ret | |
719 | ||
720 | dskSecSel: | |
721 | mov dsk_sec,temp | |
722 | ret | |
723 | ||
724 | dskDmal: | |
725 | mov dsk_dmal,temp | |
726 | ret | |
727 | ||
728 | dskDmah: | |
729 | mov dsk_dmah,temp | |
730 | ret | |
731 | ||
732 | dskDoIt: | |
733 | .if DISK_DEBUG | |
734 | push temp | |
735 | rcall printstr | |
736 | .db "Disk read: track ",0 | |
737 | mov temp,dsk_trk | |
738 | rcall printhex | |
739 | rcall printstr | |
740 | .db " sector ",0 | |
741 | mov temp,dsk_sec | |
742 | rcall printhex | |
743 | rcall printstr | |
744 | .db " dma-addr ",0 | |
745 | mov temp,dsk_dmah | |
746 | rcall printhex | |
747 | mov temp,dsk_dmal | |
748 | rcall printhex | |
749 | rcall printstr | |
750 | .db ".",13,0 | |
751 | pop temp | |
752 | .endif | |
753 | ||
754 | ;First, convert track/sector to an LBA address (in 128byte blocks) | |
755 | push temp | |
756 | mov adrl,dsk_sec | |
757 | ldi adrh,0 | |
758 | mov temp2,dsk_trk | |
759 | dskXlateLoop: | |
760 | cpi temp2,0 | |
761 | breq dskXlateLoopEnd | |
762 | ldi temp,26 | |
763 | add adrl,temp | |
764 | ldi temp,0 | |
765 | adc adrh,temp | |
766 | dec temp2 | |
767 | rjmp dskXlateLoop | |
768 | dskXlateLoopEnd: | |
769 | pop temp | |
770 | ||
771 | ;Now, see what has to be done. | |
772 | cpi temp,1 | |
773 | breq dskDoItRead | |
774 | cpi temp,2 | |
775 | breq dskDoItWrite | |
776 | ||
777 | dskDoItRead: | |
778 | push adrl | |
779 | ;Convert from 128-byte LBA blocks to 512-byte LBA blocks | |
780 | lsr adrh | |
781 | ror adrl | |
782 | lsr adrh | |
783 | ror adrl | |
784 | ;Read 512-byte sector | |
785 | rcall mmcReadSect | |
786 | pop adrl | |
787 | ||
788 | ;Now, move the correct portion of the sector from AVR ram to Z80 ram | |
789 | ldi zl,low(sectbuff) | |
790 | ldi zh,high(sectbuff) | |
791 | ldi temp,128 | |
792 | ldi temp2,0 | |
793 | sbrc adrl,0 | |
794 | add zl,temp | |
795 | sbrc adrl,0 | |
796 | adc zh,temp2 | |
797 | sbrc adrl,1 | |
798 | inc zh | |
799 | ||
800 | mov adrh,dsk_dmah | |
801 | mov adrl,dsk_dmal | |
802 | ||
803 | ldi temp2,128 | |
804 | dskDoItReadMemLoop: | |
805 | push temp2 | |
806 | ld temp,z+ | |
807 | push zh | |
808 | push zl | |
809 | rcall memWriteByte | |
810 | pop zl | |
811 | pop zh | |
812 | ldi temp,1 | |
813 | ldi temp2,0 | |
814 | add adrl,temp | |
815 | adc adrh,temp2 | |
816 | pop temp2 | |
817 | dec temp2 | |
818 | brne dskDoItReadMemLoop | |
819 | ret | |
820 | ||
821 | dskDoItWrite: | |
822 | ;The write routines is a bit naive: it'll read the 512-byte sector the 128byte CPM-sector | |
823 | ;resides in into memory, will overwrite the needed 128 byte with the Z80s memory buffer | |
824 | ;and will then write it back to disk. In theory, this would mean that every 512 bytes | |
825 | ;written will take 4 write cycles, while theoretically the writes could be deferred so we | |
826 | ;would only have to do one write cycle. | |
827 | ||
828 | .if DISK_DEBUG | |
829 | push temp | |
830 | rcall printstr | |
831 | .db "Disk write: track ",0 | |
832 | mov temp,dsk_trk | |
833 | rcall printhex | |
834 | rcall printstr | |
835 | .db " sector ",0 | |
836 | mov temp,dsk_sec | |
837 | rcall printhex | |
838 | rcall printstr | |
839 | .db " dma-addr ",0 | |
840 | mov temp,dsk_dmah | |
841 | rcall printhex | |
842 | mov temp,dsk_dmal | |
843 | rcall printhex | |
844 | rcall printstr | |
845 | .db ".",13,0 | |
846 | pop temp | |
847 | .endif | |
848 | ||
849 | ||
850 | push adrl | |
851 | push adrh | |
852 | ;Convert from 128-byte LBA blocks to 512-byte LBA blocks | |
853 | lsr adrh | |
854 | ror adrl | |
855 | lsr adrh | |
856 | ror adrl | |
857 | ;Read 512-byte sector | |
858 | rcall mmcReadSect | |
859 | pop adrh | |
860 | pop adrl | |
861 | ||
862 | push adrl | |
863 | push adrh | |
864 | ||
865 | ;Copy the data from the Z80 DMA buffer in external memory to the right place in the | |
866 | ;sector buffer. | |
867 | ;Now, move the correct portion of the sector from AVR ram to Z80 ram | |
868 | ldi zl,low(sectbuff) | |
869 | ldi zh,high(sectbuff) | |
870 | ldi temp,128 | |
871 | ldi temp2,0 | |
872 | sbrc adrl,0 | |
873 | add zl,temp | |
874 | sbrc adrl,0 | |
875 | adc zh,temp2 | |
876 | sbrc adrl,1 | |
877 | inc zh | |
878 | mov adrh,dsk_dmah | |
879 | mov adrl,dsk_dmal | |
880 | ldi temp2,128 | |
881 | dskDoItWriteMemLoop: | |
882 | push temp2 | |
883 | ||
884 | push zh | |
885 | push zl | |
886 | rcall memReadByte | |
887 | pop zl | |
888 | pop zh | |
889 | st z+,temp | |
890 | ldi temp,1 | |
891 | ldi temp2,0 | |
892 | add adrl,temp | |
893 | adc adrh,temp2 | |
894 | ||
895 | pop temp2 | |
896 | dec temp2 | |
897 | brne dskDoItWriteMemLoop | |
898 | ||
899 | pop adrh | |
900 | pop adrl | |
901 | ||
902 | ;Convert from 128-byte LBA blocks to 512-byte LBA blocks | |
903 | lsr adrh | |
904 | ror adrl | |
905 | lsr adrh | |
906 | ror adrl | |
907 | ;Write the sector back. | |
908 | rcall mmcWriteSect | |
909 | ||
910 | ;All done :) | |
911 | ret | |
912 | ||
913 | ||
914 | ; ----------------- MMC/SD routines ------------------ | |
915 | ||
916 | mmcByteNoSend: | |
917 | ldi temp,0xff | |
918 | mmcByte: | |
919 | ||
920 | .if MMC_DEBUG | |
921 | push zl | |
922 | push zh | |
923 | rcall printstr | |
924 | .db "MMC: <--",0 | |
925 | rcall printhex | |
926 | .endif | |
927 | ||
928 | out SPDR,temp | |
929 | mmcWrByteW: | |
930 | in temp,SPSR | |
931 | sbrs temp,7 | |
932 | rjmp mmcWrByteW | |
933 | in temp,SPDR | |
934 | ||
935 | .if MMC_DEBUG | |
936 | push temp | |
937 | rcall printstr | |
938 | .db ", -->",0 | |
939 | rcall printhex | |
940 | rcall printstr | |
941 | .db ".",13,0 | |
942 | pop temp | |
943 | pop zh | |
944 | pop zl | |
945 | .endif | |
946 | ret | |
947 | ||
948 | ||
949 | ;Wait till the mmc answers with the response in temp2, or till a timeout happens. | |
950 | mmcWaitResp: | |
951 | ldi zl,0 | |
952 | ldi zh,0 | |
953 | mmcWaitResploop: | |
954 | rcall mmcByteNoSend | |
955 | cpi temp,0xff | |
956 | brne mmcWaitResploopEnd | |
957 | adiw zl,1 | |
958 | cpi zh,255 | |
959 | breq mmcWaitErr | |
960 | rjmp mmcWaitResploop | |
961 | mmcWaitResploopEnd: | |
962 | ret | |
963 | ||
964 | ||
965 | mmcWaitErr: | |
966 | mov temp,temp2 | |
967 | rcall printhex | |
968 | rcall printstr | |
969 | .db ": Error: MMC resp timeout!",13,0 | |
970 | rjmp resetAVR | |
971 | ||
972 | mmcInit: | |
973 | ldi temp,0x53 | |
974 | out SPCR,temp | |
975 | ||
976 | ;Init start: send 80 clocks with cs disabled | |
977 | sbi PORTD,mmc_cs | |
978 | ||
979 | ldi temp2,20 | |
980 | mmcInitLoop: | |
981 | mov temp,temp2 | |
982 | rcall mmcByte | |
983 | dec temp2 | |
984 | brne mmcInitLoop | |
985 | ||
986 | cbi PORTD,mmc_cs | |
987 | rcall mmcByteNoSend | |
988 | rcall mmcByteNoSend | |
989 | rcall mmcByteNoSend | |
990 | rcall mmcByteNoSend | |
991 | rcall mmcByteNoSend | |
992 | rcall mmcByteNoSend | |
993 | sbi PORTD,mmc_cs | |
994 | rcall mmcByteNoSend | |
995 | rcall mmcByteNoSend | |
996 | rcall mmcByteNoSend | |
997 | rcall mmcByteNoSend | |
998 | ||
999 | ;Send init command | |
1000 | cbi PORTD,mmc_cs | |
1001 | ldi temp,0xff ;dummy | |
1002 | rcall mmcByte | |
1003 | ldi temp,0xff ;dummy | |
1004 | rcall mmcByte | |
1005 | ldi temp,0x40 ;cmd | |
1006 | rcall mmcByte | |
1007 | ldi temp,0 ;pxh | |
1008 | rcall mmcByte | |
1009 | ldi temp,0 ;pxl | |
1010 | rcall mmcByte | |
1011 | ldi temp,0 ;pyh | |
1012 | rcall mmcByte | |
1013 | ldi temp,0 ;pyl | |
1014 | rcall mmcByte | |
1015 | ldi temp,0x95 ;crc | |
1016 | rcall mmcByte | |
1017 | ldi temp,0xff ;return byte | |
1018 | rcall mmcByte | |
1019 | ||
1020 | ldi temp2,0 | |
1021 | rcall mmcWaitResp | |
1022 | ||
1023 | sbi PORTD,mmc_cs | |
1024 | rcall mmcByteNoSend | |
1025 | ||
1026 | ||
1027 | ;Read OCR till card is ready | |
1028 | ldi temp2,150 | |
1029 | mmcInitOcrLoop: | |
1030 | push temp2 | |
1031 | ||
1032 | cbi PORTD,mmc_cs | |
1033 | ldi temp,0xff ;dummy | |
1034 | rcall mmcByte | |
1035 | ldi temp,0x41 ;cmd | |
1036 | rcall mmcByte | |
1037 | ldi temp,0 ;pxh | |
1038 | rcall mmcByte | |
1039 | ldi temp,0 ;pxl | |
1040 | rcall mmcByte | |
1041 | ldi temp,0 ;pyh | |
1042 | rcall mmcByte | |
1043 | ldi temp,0 ;pyl | |
1044 | rcall mmcByte | |
1045 | ldi temp,0x95 ;crc | |
1046 | rcall mmcByte | |
1047 | rcall mmcByteNoSend | |
1048 | ||
1049 | ldi temp2,1 | |
1050 | rcall mmcWaitResp | |
1051 | cpi temp,0 | |
1052 | breq mmcInitOcrLoopDone | |
1053 | ||
1054 | sbi PORTD,mmc_cs | |
1055 | rcall mmcByteNoSend | |
1056 | ||
1057 | pop temp2 | |
1058 | dec temp2 | |
1059 | cpi temp2,0 | |
1060 | brne mmcInitOcrLoop | |
1061 | ||
1062 | ldi temp,4 | |
1063 | rjmp mmcWaitErr | |
1064 | ||
1065 | mmcInitOcrLoopDone: | |
1066 | pop temp2 | |
1067 | sbi PORTD,mmc_cs | |
1068 | rcall mmcByteNoSend | |
1069 | ||
1070 | ldi temp,0 | |
1071 | out SPCR,temp | |
1072 | ret | |
1073 | ||
1074 | ||
1075 | ;Call this with adrh:adrl = sector number | |
1076 | ;16bit lba address means a max reach of 32M. | |
1077 | mmcReadSect: | |
1078 | ldi temp,0x50 | |
1079 | out SPCR,temp | |
1080 | ||
1081 | cbi PORTD,mmc_cs | |
1082 | rcall mmcByteNoSend | |
1083 | ldi temp,0x51 ;cmd (read sector) | |
1084 | rcall mmcByte | |
1085 | ldi temp,0 | |
1086 | lsl adrl | |
1087 | rol adrh | |
1088 | rol temp | |
1089 | rcall mmcByte | |
1090 | mov temp,adrh ;pxl | |
1091 | rcall mmcByte | |
1092 | mov temp,adrl ;pyh | |
1093 | rcall mmcByte | |
1094 | ldi temp,0 ;pyl | |
1095 | rcall mmcByte | |
1096 | ldi temp,0x95 ;crc | |
1097 | rcall mmcByte | |
1098 | ldi temp,0xff ;return byte | |
1099 | rcall mmcByte | |
1100 | ||
1101 | ;resp | |
1102 | ldi temp2,2 | |
1103 | rcall mmcWaitResp | |
1104 | ||
1105 | ;data token | |
1106 | ldi temp2,3 | |
1107 | rcall mmcWaitResp | |
1108 | ||
1109 | ;Read sector to AVR RAM | |
1110 | ldi zl,low(sectbuff) | |
1111 | ldi zh,high(sectbuff) | |
1112 | mmcreadloop: | |
1113 | rcall mmcByteNoSend | |
1114 | st z+,temp | |
1115 | cpi zl,low(sectbuff+512) | |
1116 | brne mmcreadloop | |
1117 | cpi zh,high(sectbuff+512) | |
1118 | brne mmcreadloop | |
1119 | ||
1120 | ;CRC | |
1121 | rcall mmcByteNoSend | |
1122 | rcall mmcByteNoSend | |
1123 | ||
1124 | sbi PORTD,mmc_cs | |
1125 | rcall mmcByteNoSend | |
1126 | ||
1127 | ldi temp,0 | |
1128 | out SPCR,temp | |
1129 | ret | |
1130 | ||
1131 | ||
1132 | ;Call this with adrh:adrl = sector number | |
1133 | ;16bit lba address means a max reach of 32M. | |
1134 | mmcWriteSect: | |
1135 | ldi temp,0x50 | |
1136 | out SPCR,temp | |
1137 | ||
1138 | cbi PORTD,mmc_cs | |
1139 | rcall mmcByteNoSend | |
1140 | ||
1141 | ldi temp,0x58 ;cmd (write sector) | |
1142 | rcall mmcByte | |
1143 | ldi temp,0 | |
1144 | lsl adrl | |
1145 | rol adrh | |
1146 | rol temp | |
1147 | rcall mmcByte | |
1148 | mov temp,adrh ;pxl | |
1149 | rcall mmcByte | |
1150 | mov temp,adrl ;pyh | |
1151 | rcall mmcByte | |
1152 | ldi temp,0 ;pyl | |
1153 | rcall mmcByte | |
1154 | ldi temp,0x95 ;crc | |
1155 | rcall mmcByte | |
1156 | ldi temp,0xff ;return byte | |
1157 | rcall mmcByte | |
1158 | ||
1159 | ;resp | |
1160 | ldi temp2,1 | |
1161 | rcall mmcWaitResp | |
1162 | ||
1163 | ;Send data token | |
1164 | ldi temp,0xfe | |
1165 | rcall mmcByte | |
1166 | ||
1167 | ;Write sector from AVR RAM | |
1168 | ldi zl,low(sectbuff) | |
1169 | ldi zh,high(sectbuff) | |
1170 | mmcwriteloop: | |
1171 | ld temp,z+ | |
1172 | rcall mmcByte | |
1173 | cpi zl,low(sectbuff+512) | |
1174 | brne mmcwriteloop | |
1175 | cpi zh,high(sectbuff+512) | |
1176 | brne mmcwriteloop | |
1177 | ||
1178 | ;CRC | |
1179 | rcall mmcByteNoSend | |
1180 | rcall mmcByteNoSend | |
1181 | ||
1182 | ;Status. Ignored for now. | |
1183 | rcall mmcByteNoSend | |
1184 | ||
1185 | ;Wait till the mmc has written everything | |
1186 | mmcwaitwritten: | |
1187 | rcall mmcByteNoSend | |
1188 | cpi temp,0xff | |
1189 | brne mmcwaitwritten | |
1190 | ||
1191 | sbi PORTD,mmc_cs | |
1192 | rcall mmcByteNoSend | |
1193 | ||
1194 | ldi temp,0 | |
1195 | out SPCR,temp | |
1196 | ret | |
1197 | ||
1198 | ||
1199 | ;Set up wdt to time out after 1 sec. | |
1200 | resetAVR: | |
1201 | cli | |
1202 | #if defined __ATmega8__ | |
1203 | ldi temp,(1<<WDCE) | |
1204 | out WDTCSR,temp | |
1205 | ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0) | |
1206 | out WDTCSR,temp | |
1207 | #else | |
1208 | ldi temp,(1<<WDCE) | |
1209 | sts WDTCSR,temp | |
1210 | ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0) | |
1211 | sts WDTCSR,temp | |
1212 | #endif | |
1213 | resetwait: | |
1214 | rjmp resetwait | |
1215 | ||
1216 | ||
1217 | ; ------------------ DRAM routines ------------- | |
1218 | ||
1219 | ; TODO: | |
1220 | ||
1221 | #if DRAM_DQ_ORDER == 1 | |
1222 | #define CLASSIC_DRAM 0 | |
1223 | #else | |
1224 | #define CLASSIC_DRAM 1 /* Change manualy, if you want new hw w/ old sw */ | |
1225 | #endif | |
1226 | ||
1227 | ||
1228 | #if DRAM_DQ_ORDER == 0 | |
1229 | #if CLASSIC_DRAM == 1 | |
1230 | #error "Old harware can not work with new software!" | |
1231 | #endif | |
1232 | #endif | |
1233 | ||
1234 | ; **************************************************************************** | |
1235 | ||
1236 | #if CLASSIC_DRAM | |
1237 | ||
1238 | ; ********************** DRAM routines from Sprite_tm ************************ | |
1239 | ||
1240 | ;Sends the address in zh:zl to the ram | |
1241 | dram_setaddr: | |
1242 | push temp | |
1243 | in temp,portd | |
1244 | andi temp,0x17 | |
1245 | out portd,temp | |
1246 | in temp,portb | |
1247 | andi temp,0xE0 | |
1248 | out portb,temp | |
1249 | sbrc zl,0 | |
1250 | sbi portb,ram_a0 | |
1251 | sbrc zl,1 | |
1252 | sbi portb,ram_a1 | |
1253 | sbrc zl,2 | |
1254 | sbi portb,ram_a2 | |
1255 | sbrc zl,3 | |
1256 | sbi portb,ram_a3 | |
1257 | sbrc zl,4 | |
1258 | sbi portb,ram_a4 | |
1259 | sbrc zl,5 | |
1260 | sbi portd,ram_a5 | |
1261 | sbrc zl,6 | |
1262 | sbi portd,ram_a6 | |
1263 | sbrc zl,7 | |
1264 | sbi portd,ram_a7 | |
1265 | sbrc zh,0 | |
1266 | sbi portd,ram_a8 | |
1267 | pop temp | |
1268 | ret | |
1269 | ||
1270 | dram_getnibble: | |
1271 | andi temp,0xf0 | |
1272 | sbic pinc,ram_d0 | |
1273 | ori temp,0x1 | |
1274 | sbic pinc,ram_d1 | |
1275 | ori temp,0x2 | |
1276 | sbic pinc,ram_d2 | |
1277 | ori temp,0x4 | |
1278 | sbic pinc,ram_d3 | |
1279 | ori temp,0x8 | |
1280 | ret | |
1281 | ||
1282 | dram_sendnibble: | |
1283 | push temp2 | |
1284 | in temp2,portc | |
1285 | andi temp2,~RAM_DQ_MASK | |
1286 | ||
1287 | sbrc temp,0 | |
1288 | ori temp2,(1<<ram_d0) | |
1289 | sbrc temp,1 | |
1290 | ori temp2,(1<<ram_d1) | |
1291 | sbrc temp,2 | |
1292 | ori temp2,(1<<ram_d2) | |
1293 | sbrc temp,3 | |
1294 | ori temp2,(1<<ram_d3) | |
1295 | ||
1296 | out portc,temp2 | |
1297 | pop temp2 | |
1298 | ret | |
1299 | ||
1300 | ||
1301 | ;Loads the byte on address adrh:adrl into temp. | |
1302 | dram_read: | |
1303 | cli | |
1304 | mov zl,adrh | |
1305 | ldi zh,0 | |
1306 | mov temp2,adrl | |
1307 | lsl temp2 | |
1308 | rol zl | |
1309 | rol zh | |
1310 | ;z=addr[15-7] | |
1311 | rcall dram_setaddr | |
1312 | cbi portb,ram_ras | |
1313 | ||
1314 | ldi zh,0 | |
1315 | mov zl,adrl | |
1316 | andi zl,0x7F | |
1317 | rcall dram_setaddr | |
1318 | nop | |
1319 | cbi portc,ram_cas | |
1320 | nop | |
1321 | nop | |
1322 | cbi portd,ram_oe | |
1323 | nop | |
1324 | rcall dram_getnibble | |
1325 | sbi portd,ram_oe | |
1326 | swap temp | |
1327 | sbi portc,ram_cas | |
1328 | ||
1329 | ldi zh,0 | |
1330 | mov zl,adrl | |
1331 | ori zl,0x80 | |
1332 | rcall dram_setaddr | |
1333 | nop | |
1334 | cbi portc,ram_cas | |
1335 | nop | |
1336 | cbi portd,ram_oe | |
1337 | nop | |
1338 | nop | |
1339 | rcall dram_getnibble | |
1340 | ||
1341 | sbi portd,ram_oe | |
1342 | sbi portc,ram_cas | |
1343 | sbi portb,ram_ras | |
1344 | sei | |
1345 | ret | |
1346 | ||
1347 | ;Writes the byte in temp to adrh:adrl | |
1348 | dram_write: | |
1349 | cli | |
1350 | ||
1351 | in temp2,ddrc | |
1352 | ori temp2,RAM_DQ_MASK | |
1353 | out ddrc,temp2 | |
1354 | ||
1355 | rcall dram_sendnibble | |
1356 | ||
1357 | mov zl,adrh | |
1358 | ldi zh,0 | |
1359 | mov temp2,adrl | |
1360 | lsl temp2 | |
1361 | rol zl | |
1362 | rol zh | |
1363 | ;z=addr[15-7] | |
1364 | rcall dram_setaddr | |
1365 | nop | |
1366 | nop | |
1367 | cbi portb,ram_ras | |
1368 | ||
1369 | ldi zh,0 | |
1370 | mov zl,adrl | |
1371 | ori zl,0x80 | |
1372 | rcall dram_setaddr | |
1373 | nop | |
1374 | nop | |
1375 | cbi portc,ram_cas | |
1376 | nop | |
1377 | nop | |
1378 | cbi portc,ram_w | |
1379 | nop | |
1380 | nop | |
1381 | nop | |
1382 | sbi portc,ram_w | |
1383 | sbi portc,ram_cas | |
1384 | ||
1385 | ||
1386 | ldi zh,0 | |
1387 | mov zl,adrl | |
1388 | andi zl,0x7F | |
1389 | rcall dram_setaddr | |
1390 | swap temp | |
1391 | rcall dram_sendnibble | |
1392 | cbi portc,ram_cas | |
1393 | nop | |
1394 | nop | |
1395 | cbi portc,ram_w | |
1396 | nop | |
1397 | nop | |
1398 | sbi portc,ram_w | |
1399 | nop | |
1400 | nop | |
1401 | sbi portc,ram_cas | |
1402 | sbi portb,ram_ras | |
1403 | ||
1404 | in temp,ddrc | |
1405 | andi temp,~RAM_DQ_MASK | |
1406 | out ddrc,temp | |
1407 | in temp,portc | |
1408 | andi temp,~RAM_DQ_MASK | |
1409 | out portc,temp | |
1410 | sei | |
1411 | ret | |
1412 | #endif /* CLASSIC_DRAM == 1 */ | |
1413 | ||
1414 | ; **************************************************************************** | |
1415 | ||
1416 | #if ! CLASSIC_DRAM | |
1417 | ||
1418 | ; ***************************** New DRAM routines **************************** | |
1419 | ||
1420 | ; Defines how the dram nibbles are arganized. | |
1421 | ; RAMORG == 0 : A7 == 0: low nibble, A7 == 1: high nibble (Original Sprite_tm design) | |
1422 | ; RAMORG == 1 : A8 == 0: low nibble, A8 == 1: high nibble (faster) | |
1423 | ; | |
1424 | #define RAMORG 1 | |
1425 | ||
1426 | #if RAMORG == 0 | |
1427 | ;Sends the address in zh:zl to the ram | |
1428 | dram_setaddr: | |
1429 | push temp | |
1430 | in temp,PORTB | |
1431 | andi temp,~RAM_AL_MASK | |
1432 | sbrc zl,0 | |
1433 | ori temp,(1<<ram_a0) | |
1434 | sbrc zl,1 | |
1435 | ori temp,(1<<ram_a1) | |
1436 | sbrc zl,2 | |
1437 | ori temp,(1<<ram_a2) | |
1438 | sbrc zl,3 | |
1439 | ori temp,(1<<ram_a3) | |
1440 | sbrc zl,4 | |
1441 | ori temp,(1<<ram_a4) | |
1442 | out PORTB,temp | |
1443 | ||
1444 | in temp,PORTD | |
1445 | andi temp,~RAM_AH_MASK | |
1446 | sbrc zl,5 | |
1447 | ori temp,(1<<ram_a5) | |
1448 | sbrc zl,6 | |
1449 | ori temp,(1<<ram_a6) | |
1450 | sbrc zl,7 | |
1451 | ori temp,(1<<ram_a7) | |
1452 | sbrc zh,0 | |
1453 | ori temp,(1<<ram_a8) | |
1454 | out PORTD,temp | |
1455 | pop temp | |
1456 | #else /* RAMORG == 1 */ | |
1457 | .macro DRAM_SETADDR | |
1458 | push temp | |
1459 | in temp,PORTB | |
1460 | andi temp,~RAM_AL_MASK | |
1461 | sbrc @0,0 | |
1462 | ori temp,(1<<ram_a0) | |
1463 | sbrc @0,1 | |
1464 | ori temp,(1<<ram_a1) | |
1465 | sbrc @0,2 | |
1466 | ori temp,(1<<ram_a2) | |
1467 | sbrc @0,3 | |
1468 | ori temp,(1<<ram_a3) | |
1469 | sbrc @0,4 | |
1470 | ori temp,(1<<ram_a4) | |
1471 | out PORTB,temp | |
1472 | ||
1473 | in temp,PORTD | |
1474 | andi temp,~RAM_AH_MASK | |
1475 | sbrc @0,5 | |
1476 | ori temp,(1<<ram_a5) | |
1477 | sbrc @0,6 | |
1478 | ori temp,(1<<ram_a6) | |
1479 | sbrc @0,7 | |
1480 | ori temp,(1<<ram_a7) | |
1481 | out PORTD,temp | |
1482 | pop temp | |
1483 | .endm | |
1484 | ret | |
1485 | #endif /* RAMORG */ | |
1486 | ||
1487 | .macro DRAM_SENDNIBBLE | |
1488 | in temp2,PORTC | |
1489 | andi temp2,~RAM_DQ_MASK | |
1490 | andi temp,RAM_DQ_MASK | |
1491 | or temp2,temp | |
1492 | out PORTC,temp2 | |
1493 | .endm | |
1494 | ||
1495 | ||
1496 | ;Loads the byte on address adrh:adrl into temp. | |
1497 | ;must not alter adrh:adrl | |
1498 | ||
1499 | dram_read: | |
1500 | cli | |
1501 | #if RAMORG == 0 | |
1502 | mov zl,adrh | |
1503 | ldi zh,0 | |
1504 | mov temp2,adrl | |
1505 | lsl temp2 | |
1506 | rol zl | |
1507 | rol zh | |
1508 | ;z=addr[15-7] | |
1509 | rcall dram_setaddr | |
1510 | cbi PORTB,ram_ras | |
1511 | ||
1512 | ldi zh,0 | |
1513 | mov zl,adrl | |
1514 | andi zl,0x7F | |
1515 | rcall dram_setaddr | |
1516 | cbi PORTC,ram_cas | |
1517 | cbi PORTD,ram_oe | |
1518 | ldi zh,0 | |
1519 | in temp,PINC | |
1520 | andi temp,0x0f | |
1521 | swap temp | |
1522 | sbi PORTC,ram_cas | |
1523 | ||
1524 | mov zl,adrl | |
1525 | ori zl,0x80 | |
1526 | rcall dram_setaddr | |
1527 | cbi PORTC,ram_cas | |
1528 | nop | |
1529 | in temp2,PINC | |
1530 | andi temp2,0x0f | |
1531 | or temp,temp2 | |
1532 | ||
1533 | sbi PORTD,ram_oe | |
1534 | sbi PORTC,ram_cas | |
1535 | sbi PORTB,ram_ras | |
1536 | #else | |
1537 | cbi PORTD,ram_a8 | |
1538 | DRAM_SETADDR adrh | |
1539 | cbi PORTB,ram_ras | |
1540 | ||
1541 | DRAM_SETADDR adrl | |
1542 | cbi PORTC,ram_cas | |
1543 | cbi PORTD,ram_oe | |
1544 | nop | |
1545 | in temp,PINC | |
1546 | andi temp,0x0f | |
1547 | swap temp | |
1548 | sbi PORTC,ram_cas | |
1549 | ||
1550 | sbi PORTD,ram_a8 | |
1551 | cbi PORTC,ram_cas | |
1552 | nop | |
1553 | in temp2,PINC | |
1554 | andi temp2,0x0f | |
1555 | or temp,temp2 | |
1556 | swap temp | |
1557 | ||
1558 | sbi PORTD,ram_oe | |
1559 | sbi PORTC,ram_cas | |
1560 | sbi PORTB,ram_ras | |
1561 | #endif | |
1562 | sei | |
1563 | ret | |
1564 | ||
1565 | ||
1566 | ;Writes the byte in temp to adrh:adrl | |
1567 | ;must not alter adrh:adrl | |
1568 | ||
1569 | dram_write: | |
1570 | cli | |
1571 | #if RAMORG == 0 | |
1572 | in temp2,DDRC ;DRAM data ports as outputs | |
1573 | ori temp2,RAM_DQ_MASK | |
1574 | out DDRC,temp2 | |
1575 | ||
1576 | push temp | |
1577 | DRAM_SENDNIBBLE | |
1578 | pop temp | |
1579 | ||
1580 | mov zl,adrh | |
1581 | ldi zh,0 | |
1582 | mov temp2,adrl | |
1583 | lsl temp2 | |
1584 | rol zl | |
1585 | rol zh | |
1586 | ;z=addr[15-7] | |
1587 | rcall dram_setaddr | |
1588 | cbi PORTB,ram_ras | |
1589 | ||
1590 | ldi zh,0 | |
1591 | mov zl,adrl | |
1592 | ori zl,0x80 | |
1593 | cbi PORTC,ram_w ;early write | |
1594 | rcall dram_setaddr | |
1595 | cbi PORTC,ram_cas | |
1596 | sbi PORTC,ram_cas | |
1597 | ||
1598 | ldi zh,0 | |
1599 | mov zl,adrl | |
1600 | andi zl,0x7F | |
1601 | rcall dram_setaddr | |
1602 | swap temp | |
1603 | ||
1604 | DRAM_SENDNIBBLE | |
1605 | ||
1606 | cbi PORTC,ram_cas | |
1607 | sbi PORTC,ram_cas | |
1608 | sbi PORTC,ram_w | |
1609 | sbi PORTB,ram_ras | |
1610 | ||
1611 | in temp,DDRC | |
1612 | andi temp,~RAM_DQ_MASK | |
1613 | out DDRC,temp | |
1614 | in temp,PORTC | |
1615 | andi temp,~RAM_DQ_MASK | |
1616 | out PORTC,temp | |
1617 | #else /* RAMORG == 1 */ | |
1618 | in temp2,DDRC ;DRAM data ports as outputs | |
1619 | ori temp2,RAM_DQ_MASK | |
1620 | out DDRC,temp2 | |
1621 | ||
1622 | push temp | |
1623 | DRAM_SENDNIBBLE | |
1624 | pop temp | |
1625 | ||
1626 | cbi PORTD,ram_a8 | |
1627 | DRAM_SETADDR adrh | |
1628 | cbi PORTB,ram_ras | |
1629 | ||
1630 | cbi PORTC,ram_w ;early write | |
1631 | DRAM_SETADDR adrl | |
1632 | cbi PORTC,ram_cas | |
1633 | sbi PORTC,ram_cas | |
1634 | ||
1635 | sbi PORTD,ram_a8 | |
1636 | swap temp | |
1637 | ||
1638 | DRAM_SENDNIBBLE | |
1639 | ||
1640 | cbi PORTC,ram_cas | |
1641 | nop | |
1642 | sbi PORTC,ram_cas | |
1643 | sbi PORTC,ram_w | |
1644 | sbi PORTB,ram_ras | |
1645 | ||
1646 | in temp,DDRC | |
1647 | andi temp,~RAM_DQ_MASK | |
1648 | out DDRC,temp | |
1649 | in temp,PORTC | |
1650 | andi temp,~RAM_DQ_MASK | |
1651 | out PORTC,temp | |
1652 | #endif /* RAMORG */ | |
1653 | sei | |
1654 | ret | |
1655 | ||
1656 | #endif /* CLASSIC_DRAM == 0 */ | |
1657 | ||
1658 | ; **************************************************************************** | |
1659 | ||
1660 | ; refresh interupt; exec 2 cbr cycles | |
1661 | refrint: | |
1662 | cbi PORTC,ram_cas | |
1663 | cbi PORTB,ram_ras | |
1664 | nop | |
1665 | sbi PORTB,ram_ras | |
1666 | cbi PORTB,ram_ras | |
1667 | sbi PORTC,ram_cas | |
1668 | sbi PORTB,ram_ras | |
1669 | reti | |
1670 | ||
1671 | ; **************************************************************************** | |
1672 | ||
1673 | ; ------------- system timer 10ms --------------- | |
1674 | .dseg | |
1675 | ||
1676 | timer_base: | |
1677 | timer_ms: | |
1678 | .byte 2 | |
1679 | timer_s: | |
1680 | .byte 4 | |
1681 | ; don't change order here, clock put/get depends on it. | |
1682 | cntms_out: ; register for ms | |
1683 | .byte 2 | |
1684 | utime_io: ; register for uptime. | |
1685 | .byte 4 | |
1686 | cnt_1ms: | |
1687 | .byte 2 | |
1688 | uptime: | |
1689 | .byte 4 | |
1690 | timer_top: | |
1691 | .equ timer_size = timer_top - timer_base | |
1692 | ||
1693 | .equ clkofs = cnt_1ms-cntms_out | |
1694 | .equ timerofs = cnt_1ms-timer_ms | |
1695 | ||
1696 | .cseg | |
1697 | sysclockint: | |
1698 | push zl | |
1699 | in zl,SREG | |
1700 | push zl | |
1701 | push zh | |
1702 | ||
1703 | lds zl,cnt_1ms | |
1704 | lds zh,cnt_1ms+1 | |
1705 | adiw z,1 | |
1706 | ||
1707 | sts cnt_1ms,zl | |
1708 | sts cnt_1ms+1,zh | |
1709 | cpi zl,low(1000) | |
1710 | ldi zl,high(1000) ;doesn't change flags | |
1711 | cpc zh,zl | |
1712 | brlo syscl_end | |
1713 | ||
1714 | ldi zl,0 | |
1715 | sts cnt_1ms,zl | |
1716 | sts cnt_1ms+1,zl | |
1717 | ||
1718 | lds zl,uptime+0 | |
1719 | inc zl | |
1720 | sts uptime+0,zl | |
1721 | brne syscl_end | |
1722 | lds zl,uptime+1 | |
1723 | inc zl | |
1724 | sts uptime+1,zl | |
1725 | brne syscl_end | |
1726 | lds zl,uptime+2 | |
1727 | inc zl | |
1728 | sts uptime+2,zl | |
1729 | brne syscl_end | |
1730 | lds zl,uptime+3 | |
1731 | inc zl | |
1732 | sts uptime+3,zl | |
1733 | ||
1734 | syscl_end: | |
1735 | pop zh | |
1736 | pop zl | |
1737 | out SREG,zl | |
1738 | pop zl | |
1739 | reti | |
1740 | ||
1741 | ||
1742 | clockget: | |
1743 | ldi temp,0xFF | |
1744 | subi temp2,TIMER_MSECS | |
1745 | brcs clkget_end ;Port number in range? | |
1746 | ldi zl,low(cntms_out) | |
1747 | ldi zh,high(cntms_out) | |
1748 | breq clkget_copy ;lowest byte requestet, latch clock | |
1749 | cpi temp2,6 | |
1750 | brsh clkget_end ;Port number to high? | |
1751 | ||
1752 | add zl,temp2 | |
1753 | brcc PC+2 | |
1754 | inc zh | |
1755 | ld temp,z | |
1756 | clkget_end: | |
1757 | ret | |
1758 | ||
1759 | ||
1760 | ||
1761 | clkget_copy: | |
1762 | ldi temp2,6 | |
1763 | cli | |
1764 | clkget_l: | |
1765 | ldd temp,z+clkofs | |
1766 | st z+,temp | |
1767 | dec temp2 | |
1768 | brne clkget_l | |
1769 | sei | |
1770 | lds temp,cntms_out | |
1771 | ;req. byte in temp | |
1772 | ret | |
1773 | ||
1774 | clockput: | |
1775 | subi temp2,TIMERPORT | |
1776 | brcs clkput_end ;Port number in range? | |
1777 | brne clkput_1 | |
1778 | ||
1779 | ; clock control | |
1780 | ||
1781 | cpi temp,starttimercmd | |
1782 | breq timer_start | |
1783 | cpi temp,quitTimerCmd | |
1784 | breq timer_quit | |
1785 | cpi temp,printTimerCmd | |
1786 | breq timer_print | |
1787 | cpi temp,uptimeCmd | |
1788 | brne cp_ex | |
1789 | rjmp uptime_print | |
1790 | cp_ex: | |
1791 | ret | |
1792 | ||
1793 | timer_quit: | |
1794 | rcall timer_print | |
1795 | rjmp timer_start | |
1796 | ||
1797 | clkput_1: | |
1798 | dec temp2 | |
1799 | ldi zl,low(cntms_out) | |
1800 | ldi zh,high(cntms_out) | |
1801 | breq clkput_copy ;lowest byte requestet, latch clock | |
1802 | cpi temp2,6 | |
1803 | brsh clkput_end ;Port number to high? | |
1804 | ||
1805 | add zl,temp2 | |
1806 | brcc PC+2 | |
1807 | inc zh | |
1808 | st z,temp | |
1809 | clkput_end: | |
1810 | ret | |
1811 | ||
1812 | clkput_copy: | |
1813 | st z,temp | |
1814 | adiw z,5 | |
1815 | ldi temp2,6 | |
1816 | cli | |
1817 | clkput_l: | |
1818 | ldd temp,z+clkofs | |
1819 | st z+,temp | |
1820 | dec temp2 | |
1821 | brne clkput_l | |
1822 | sei | |
1823 | ret | |
1824 | ||
1825 | ; start/reset timer | |
1826 | ; | |
1827 | timer_start: | |
1828 | ldi zl,low(timer_ms) | |
1829 | ldi zh,high(timer_ms) | |
1830 | ldi temp2,6 | |
1831 | cli | |
1832 | ts_loop: | |
1833 | ldd temp,z+timerofs | |
1834 | st z+,temp | |
1835 | dec temp2 | |
1836 | brne ts_loop | |
1837 | sei | |
1838 | ret | |
1839 | ||
1840 | ||
1841 | ; print timer | |
1842 | ; | |
1843 | ||
1844 | timer_print: | |
1845 | push adrh | |
1846 | push adrl | |
1847 | push oph | |
1848 | push opl | |
1849 | ldi zl,low(timer_ms) | |
1850 | ldi zh,high(timer_ms) | |
1851 | ||
1852 | ; put ms on stack (16 bit) | |
1853 | ||
1854 | cli | |
1855 | ldd adrl,z+timerofs | |
1856 | ld temp2,z+ | |
1857 | sub adrl,temp2 | |
1858 | ldd adrh,z+timerofs | |
1859 | ld temp2,z+ | |
1860 | sbc adrh,temp2 | |
1861 | brsh tp_s | |
1862 | ||
1863 | subi adrl,low(-1000) | |
1864 | sbci adrh,high(-1000) | |
1865 | sec | |
1866 | tp_s: | |
1867 | push adrh | |
1868 | push adrl | |
1869 | ||
1870 | ; | |
1871 | ||
1872 | ldd temp,z+timerofs | |
1873 | ld adrl,z+ | |
1874 | sbc temp,adrl | |
1875 | ||
1876 | ldd temp2,z+timerofs | |
1877 | ld adrh,z+ | |
1878 | sbc temp2,adrh | |
1879 | ||
1880 | ldd opl,z+timerofs | |
1881 | ld adrl,z+ | |
1882 | sbc opl,adrl | |
1883 | ||
1884 | sei | |
1885 | ldd oph,z+timerofs | |
1886 | ld adrh,z+ | |
1887 | sbc oph,adrh | |
1888 | ||
1889 | rcall printstr | |
1890 | .db 13,"Timer running. Elapsed: ",0 | |
1891 | rcall print_ultoa | |
1892 | ||
1893 | rcall printstr | |
1894 | .db ",",0 | |
1895 | ldi opl,0 | |
1896 | ldi oph,0 | |
1897 | pop temp | |
1898 | pop temp2 | |
1899 | rcall print_ultoa | |
1900 | rcall printstr | |
1901 | .db "s. ",0,0 | |
1902 | ||
1903 | pop opl | |
1904 | pop oph | |
1905 | pop adrl | |
1906 | pop adrh | |
1907 | ret | |
1908 | ||
1909 | uptime_print: | |
1910 | ||
1911 | push oph | |
1912 | push opl | |
1913 | ldi zl,low(cnt_1ms) | |
1914 | ldi zh,high(cnt_1ms) | |
1915 | ||
1916 | cli | |
1917 | ld temp,z+ | |
1918 | push temp | |
1919 | ld temp,z+ | |
1920 | push temp | |
1921 | ||
1922 | ld temp,z+ | |
1923 | ld temp2,z+ | |
1924 | ld opl,z+ | |
1925 | sei | |
1926 | ld oph,z+ | |
1927 | ||
1928 | rcall printstr | |
1929 | .db 13,"Uptime: ",0 | |
1930 | ||
1931 | rcall print_ultoa | |
1932 | rcall printstr | |
1933 | .db ",",0 | |
1934 | ||
1935 | ldi opl,0 | |
1936 | ldi oph,0 | |
1937 | pop temp2 | |
1938 | pop temp | |
1939 | rcall print_ultoa | |
1940 | rcall printstr | |
1941 | .db "s.",0,0 | |
1942 | ||
1943 | pop opl | |
1944 | pop oph | |
1945 | ret | |
1946 | ||
1947 | ||
1948 | ||
1949 | ; --------------- Debugging stuff --------------- | |
1950 | ||
1951 | ;Print a unsigned lonng value to the uart | |
1952 | ; oph:opl:temp2:temp = value | |
1953 | ||
1954 | print_ultoa: | |
1955 | push adrh | |
1956 | push adrl | |
1957 | push yl | |
1958 | ||
1959 | clr adrl ;adrl = stack level | |
1960 | ||
1961 | ultoa1: ldi yl, 32 ;adrh = oph:temp % 10 | |
1962 | clr adrh ;oph:temp /= 10 | |
1963 | ultoa2: lsl temp | |
1964 | rol temp2 | |
1965 | rol opl | |
1966 | rol oph | |
1967 | rol adrh | |
1968 | cpi adrh,10 | |
1969 | brcs ultoa3 | |
1970 | subi adrh,10 | |
1971 | inc temp | |
1972 | ultoa3: dec yl | |
1973 | brne ultoa2 | |
1974 | cpi adrh, 10 ;adrh is a numeral digit '0'-'9' | |
1975 | subi adrh, -'0' | |
1976 | push adrh ;Stack it | |
1977 | inc adrl | |
1978 | ldi yl,0 | |
1979 | cp temp,yl ;Repeat until oph:temp gets zero | |
1980 | cpc temp2,yl | |
1981 | cpc opl,yl | |
1982 | cpc oph,yl | |
1983 | brne ultoa1 | |
1984 | ||
1985 | ultoa6: pop temp ;Flush stacked digits | |
1986 | rcall uartputc | |
1987 | dec adrl | |
1988 | brne ultoa6 | |
1989 | ||
1990 | pop yl | |
1991 | pop adrl | |
1992 | pop adrh | |
1993 | ret | |
1994 | ||
1995 | ||
1996 | ;Prints the lower nibble of temp in hex to the uart | |
1997 | printhexn: | |
1998 | push temp | |
1999 | andi temp,0xf | |
2000 | cpi temp,0xA | |
2001 | brlo printhexn_isno | |
2002 | subi temp,-('A'-10) | |
2003 | rcall uartputc | |
2004 | pop temp | |
2005 | ret | |
2006 | printhexn_isno: | |
2007 | subi temp,-'0' | |
2008 | rcall uartputc | |
2009 | pop temp | |
2010 | ret | |
2011 | ||
2012 | ;Prints temp in hex to the uart | |
2013 | printhex: | |
2014 | swap temp | |
2015 | rcall printhexn | |
2016 | swap temp | |
2017 | rcall printhexn | |
2018 | ret | |
2019 | ||
2020 | ;Prints the zero-terminated string following the call statement. WARNING: Destroys temp. | |
2021 | printstr: | |
2022 | pop zh | |
2023 | pop zl | |
2024 | push temp | |
2025 | ||
2026 | lsl zl | |
2027 | rol zh | |
2028 | ||
2029 | printstr_loop: | |
2030 | lpm temp,z+ | |
2031 | cpi temp,0 | |
2032 | breq printstr_end | |
2033 | rcall uartputc | |
2034 | cpi temp,13 | |
2035 | brne printstr_loop | |
2036 | ldi temp,10 | |
2037 | rcall uartputc | |
2038 | rjmp printstr_loop | |
2039 | ||
2040 | printstr_end: | |
2041 | adiw zl,1 | |
2042 | lsr zh | |
2043 | ror zl | |
2044 | ||
2045 | pop temp | |
2046 | push zl | |
2047 | push zh | |
2048 | ret | |
2049 | ||
2050 | ||
2051 | ; --------------- AVR HW <-> Z80 periph stuff ------------------ | |
2052 | ||
2053 | .equ memReadByte = dram_read | |
2054 | .equ memWriteByte = dram_write | |
2055 | ||
2056 | ; -------------------------------------------------------------- | |
2057 | ||
2058 | .dseg | |
2059 | ||
2060 | #define RXBUFMASK RXBUFSIZE-1 | |
2061 | ||
2062 | rxcount: | |
2063 | .byte 1 | |
2064 | rxidx_w: | |
2065 | .byte 1 | |
2066 | rxidx_r: | |
2067 | .byte 1 | |
2068 | rxfifo: | |
2069 | .byte RXBUFSIZE | |
2070 | .byte 0 | |
2071 | ||
2072 | .cseg | |
2073 | ||
2074 | ; Save received character in a circular buffer. Do nothing if buffer overflows. | |
2075 | ||
2076 | rxint: | |
2077 | push temp | |
2078 | in temp,sreg | |
2079 | push temp | |
2080 | push zh | |
2081 | push zl | |
2082 | #ifdef __ATmega8__ | |
2083 | in temp,UDR | |
2084 | #else | |
2085 | lds temp,UDR0 | |
2086 | #endif | |
2087 | lds zh,rxcount | |
2088 | cpi zh,RXBUFSIZE | |
2089 | brsh rxi_ov | |
2090 | inc zh | |
2091 | sts rxcount,zh | |
2092 | ||
2093 | ldi zl,low(rxfifo) | |
2094 | lds zh,rxidx_w | |
2095 | add zl,zh | |
2096 | inc zh | |
2097 | andi zh,RXBUFMASK | |
2098 | sts rxidx_w,zh | |
2099 | ldi zh,high(rxfifo) | |
2100 | brcc PC+2 | |
2101 | inc zh | |
2102 | st z,temp | |
2103 | rxi_ov: | |
2104 | pop zl | |
2105 | pop zh | |
2106 | pop temp | |
2107 | out sreg,temp | |
2108 | pop temp | |
2109 | reti | |
2110 | ||
2111 | ||
2112 | ;Fetches a char from the buffer to temp. If none available, waits till one is. | |
2113 | ||
2114 | uartgetc: | |
2115 | lds temp,rxcount ; Number of characters in buffer | |
2116 | tst temp | |
2117 | breq uartgetc | |
2118 | ||
2119 | push zh | |
2120 | push zl | |
2121 | ldi zl,low(rxfifo) | |
2122 | ldi zh,high(rxfifo) | |
2123 | lds temp,rxidx_r | |
2124 | add zl,temp | |
2125 | brcc PC+2 | |
2126 | inc zh | |
2127 | inc temp | |
2128 | andi temp,RXBUFMASK | |
2129 | sts rxidx_r,temp | |
2130 | cli | |
2131 | lds temp,rxcount | |
2132 | dec temp | |
2133 | sts rxcount,temp | |
2134 | sei | |
2135 | ld temp,z ;don't forget to get the char | |
2136 | pop zl | |
2137 | pop zh | |
2138 | ret | |
2139 | ||
2140 | ||
2141 | ||
2142 | ;Sends a char from temp to the uart. | |
2143 | uartputc: | |
2144 | #if defined __ATmega8__ | |
2145 | uartputc_l: | |
2146 | sbis UCSRA,UDRE | |
2147 | rjmp uartputc_l | |
2148 | out UDR,temp | |
2149 | #else | |
2150 | push temp | |
2151 | uartputc_l: | |
2152 | lds temp,UCSR0A | |
2153 | sbrs temp,UDRE0 | |
2154 | rjmp uartputc_l | |
2155 | pop temp | |
2156 | sts UDR0,temp | |
2157 | #endif | |
2158 | ret | |
2159 | ||
2160 | ; ------------ Fetch phase stuff ----------------- | |
2161 | ||
2162 | .equ FETCH_NOP = (0<<0) | |
2163 | .equ FETCH_A = (1<<0) | |
2164 | .equ FETCH_B = (2<<0) | |
2165 | .equ FETCH_C = (3<<0) | |
2166 | .equ FETCH_D = (4<<0) | |
2167 | .equ FETCH_E = (5<<0) | |
2168 | .equ FETCH_H = (6<<0) | |
2169 | .equ FETCH_L = (7<<0) | |
2170 | .equ FETCH_AF = (8<<0) | |
2171 | .equ FETCH_BC = (9<<0) | |
2172 | .equ FETCH_DE = (10<<0) | |
2173 | .equ FETCH_HL = (11<<0) | |
2174 | .equ FETCH_SP = (12<<0) | |
2175 | .equ FETCH_MBC = (13<<0) | |
2176 | .equ FETCH_MDE = (14<<0) | |
2177 | .equ FETCH_MHL = (15<<0) | |
2178 | .equ FETCH_MSP = (16<<0) | |
2179 | .equ FETCH_DIR8 = (17<<0) | |
2180 | .equ FETCH_DIR16= (18<<0) | |
2181 | .equ FETCH_RST = (19<<0) | |
2182 | ||
2183 | ||
2184 | ;Jump table for fetch routines. Make sure to keep this in sync with the .equs! | |
2185 | fetchjumps: | |
2186 | .dw do_fetch_nop | |
2187 | .dw do_fetch_a | |
2188 | .dw do_fetch_b | |
2189 | .dw do_fetch_c | |
2190 | .dw do_fetch_d | |
2191 | .dw do_fetch_e | |
2192 | .dw do_fetch_h | |
2193 | .dw do_fetch_l | |
2194 | .dw do_fetch_af | |
2195 | .dw do_fetch_bc | |
2196 | .dw do_fetch_de | |
2197 | .dw do_fetch_hl | |
2198 | .dw do_fetch_sp | |
2199 | .dw do_fetch_mbc | |
2200 | .dw do_fetch_mde | |
2201 | .dw do_fetch_mhl | |
2202 | .dw do_fetch_msp | |
2203 | .dw do_fetch_dir8 | |
2204 | .dw do_fetch_dir16 | |
2205 | .dw do_fetch_rst | |
2206 | ||
2207 | do_fetch_nop: | |
2208 | ret | |
2209 | ||
2210 | do_fetch_a: | |
2211 | mov opl,z_a | |
2212 | ret | |
2213 | ||
2214 | do_fetch_b: | |
2215 | mov opl,z_b | |
2216 | ret | |
2217 | ||
2218 | do_fetch_c: | |
2219 | mov opl,z_c | |
2220 | ret | |
2221 | ||
2222 | do_fetch_d: | |
2223 | mov opl,z_d | |
2224 | ret | |
2225 | ||
2226 | do_fetch_e: | |
2227 | mov opl,z_e | |
2228 | ret | |
2229 | ||
2230 | do_fetch_h: | |
2231 | mov opl,z_h | |
2232 | ret | |
2233 | ||
2234 | do_fetch_l: | |
2235 | mov opl,z_l | |
2236 | ret | |
2237 | ||
2238 | do_fetch_af: | |
2239 | mov opl,z_flags | |
2240 | mov oph,z_a | |
2241 | ret | |
2242 | ||
2243 | do_fetch_bc: | |
2244 | mov opl,z_c | |
2245 | mov oph,z_b | |
2246 | ret | |
2247 | ||
2248 | do_fetch_de: | |
2249 | mov opl,z_e | |
2250 | mov oph,z_d | |
2251 | ret | |
2252 | ||
2253 | do_fetch_hl: | |
2254 | mov opl,z_l | |
2255 | mov oph,z_h | |
2256 | ret | |
2257 | ||
2258 | do_fetch_sp: | |
2259 | mov opl,z_spl | |
2260 | mov oph,z_sph | |
2261 | ret | |
2262 | ||
2263 | do_fetch_mbc: | |
2264 | mov adrh,z_b | |
2265 | mov adrl,z_c | |
2266 | rcall memReadByte | |
2267 | mov opl,temp | |
2268 | ret | |
2269 | ||
2270 | do_fetch_mde: | |
2271 | mov adrh,z_d | |
2272 | mov adrl,z_e | |
2273 | rcall memReadByte | |
2274 | mov opl,temp | |
2275 | ret | |
2276 | ||
2277 | do_fetch_mhl: | |
2278 | mov adrh,z_h | |
2279 | mov adrl,z_l | |
2280 | rcall memReadByte | |
2281 | mov opl,temp | |
2282 | ret | |
2283 | ||
2284 | do_fetch_msp: | |
2285 | mov adrh,z_sph | |
2286 | mov adrl,z_spl | |
2287 | rcall memReadByte | |
2288 | mov opl,temp | |
2289 | ||
2290 | ldi temp,1 | |
2291 | ldi temp2,0 | |
2292 | add adrl,temp | |
2293 | adc adrh,temp2 | |
2294 | rcall memReadByte | |
2295 | mov oph,temp | |
2296 | ret | |
2297 | ||
2298 | do_fetch_dir8: | |
2299 | mov adrl,z_pcl | |
2300 | mov adrh,z_pch | |
2301 | rcall memReadByte | |
2302 | adiw z_pcl,1 | |
2303 | mov opl,temp | |
2304 | ret | |
2305 | ||
2306 | do_fetch_dir16: | |
2307 | mov adrl,z_pcl | |
2308 | mov adrh,z_pch | |
2309 | rcall memReadByte | |
2310 | mov opl,temp | |
2311 | adiw z_pcl,1 | |
2312 | mov adrl,z_pcl | |
2313 | mov adrh,z_pch | |
2314 | rcall memReadByte | |
2315 | adiw z_pcl,1 | |
2316 | mov oph,temp | |
2317 | ret | |
2318 | ||
2319 | do_fetch_rst: | |
2320 | mov adrl,z_pcl | |
2321 | mov adrh,z_pch | |
2322 | subi adrl,1 | |
2323 | sbci adrh,0 | |
2324 | rcall memReadByte | |
2325 | andi temp,0x38 | |
2326 | ldi oph,0 | |
2327 | mov opl,temp | |
2328 | ret | |
2329 | ||
2330 | ||
2331 | ||
2332 | ; ------------ Store phase stuff ----------------- | |
2333 | ||
2334 | .equ STORE_NOP = (0<<5) | |
2335 | .equ STORE_A = (1<<5) | |
2336 | .equ STORE_B = (2<<5) | |
2337 | .equ STORE_C = (3<<5) | |
2338 | .equ STORE_D = (4<<5) | |
2339 | .equ STORE_E = (5<<5) | |
2340 | .equ STORE_H = (6<<5) | |
2341 | .equ STORE_L = (7<<5) | |
2342 | .equ STORE_AF = (8<<5) | |
2343 | .equ STORE_BC = (9<<5) | |
2344 | .equ STORE_DE = (10<<5) | |
2345 | .equ STORE_HL = (11<<5) | |
2346 | .equ STORE_SP = (12<<5) | |
2347 | .equ STORE_PC = (13<<5) | |
2348 | .equ STORE_MBC = (14<<5) | |
2349 | .equ STORE_MDE = (15<<5) | |
2350 | .equ STORE_MHL = (16<<5) | |
2351 | .equ STORE_MSP = (17<<5) | |
2352 | .equ STORE_RET = (18<<5) | |
2353 | .equ STORE_CALL = (19<<5) | |
2354 | .equ STORE_AM = (20<<5) | |
2355 | ||
2356 | ;Jump table for store routines. Make sure to keep this in sync with the .equs! | |
2357 | storejumps: | |
2358 | .dw do_store_nop | |
2359 | .dw do_store_a | |
2360 | .dw do_store_b | |
2361 | .dw do_store_c | |
2362 | .dw do_store_d | |
2363 | .dw do_store_e | |
2364 | .dw do_store_h | |
2365 | .dw do_store_l | |
2366 | .dw do_store_af | |
2367 | .dw do_store_bc | |
2368 | .dw do_store_de | |
2369 | .dw do_store_hl | |
2370 | .dw do_store_sp | |
2371 | .dw do_store_pc | |
2372 | .dw do_store_mbc | |
2373 | .dw do_store_mde | |
2374 | .dw do_store_mhl | |
2375 | .dw do_store_msp | |
2376 | .dw do_store_ret | |
2377 | .dw do_store_call | |
2378 | .dw do_store_am | |
2379 | ||
2380 | ||
2381 | do_store_nop: | |
2382 | ret | |
2383 | ||
2384 | do_store_a: | |
2385 | mov z_a,opl | |
2386 | ret | |
2387 | ||
2388 | do_store_b: | |
2389 | mov z_b,opl | |
2390 | ret | |
2391 | ||
2392 | do_store_c: | |
2393 | mov z_c,opl | |
2394 | ret | |
2395 | ||
2396 | do_store_d: | |
2397 | mov z_d,opl | |
2398 | ret | |
2399 | ||
2400 | do_store_e: | |
2401 | mov z_e,opl | |
2402 | ret | |
2403 | ||
2404 | do_store_h: | |
2405 | mov z_h,opl | |
2406 | ret | |
2407 | ||
2408 | do_store_l: | |
2409 | mov z_l,opl | |
2410 | ret | |
2411 | ||
2412 | do_store_af: | |
2413 | mov z_a,oph | |
2414 | mov z_flags,opl | |
2415 | ret | |
2416 | ||
2417 | do_store_bc: | |
2418 | mov z_b,oph | |
2419 | mov z_c,opl | |
2420 | ret | |
2421 | ||
2422 | do_store_de: | |
2423 | mov z_d,oph | |
2424 | mov z_e,opl | |
2425 | ret | |
2426 | ||
2427 | do_store_hl: | |
2428 | mov z_h,oph | |
2429 | mov z_l,opl | |
2430 | ret | |
2431 | ||
2432 | do_store_mbc: | |
2433 | mov adrh,z_b | |
2434 | mov adrl,z_c | |
2435 | mov temp,opl | |
2436 | rcall memWriteByte | |
2437 | ret | |
2438 | ||
2439 | do_store_mde: | |
2440 | mov adrh,z_d | |
2441 | mov adrl,z_e | |
2442 | mov temp,opl | |
2443 | rcall memWriteByte | |
2444 | ret | |
2445 | ||
2446 | do_store_mhl: | |
2447 | mov adrh,z_h | |
2448 | mov adrl,z_l | |
2449 | mov temp,opl | |
2450 | rcall memWriteByte | |
2451 | ret | |
2452 | ||
2453 | do_store_msp: | |
2454 | mov adrh,z_sph | |
2455 | mov adrl,z_spl | |
2456 | mov temp,opl | |
2457 | rcall memWriteByte | |
2458 | ||
2459 | ldi temp,1 | |
2460 | ldi temp2,0 | |
2461 | add adrl,temp | |
2462 | adc adrh,temp2 | |
2463 | mov temp,oph | |
2464 | rcall memWriteByte | |
2465 | ||
2466 | ret | |
2467 | ||
2468 | do_store_sp: | |
2469 | mov z_sph,oph | |
2470 | mov z_spl,opl | |
2471 | ret | |
2472 | ||
2473 | do_store_pc: | |
2474 | mov z_pch,oph | |
2475 | mov z_pcl,opl | |
2476 | ret | |
2477 | ||
2478 | do_store_ret: | |
2479 | rcall do_op_pop16 | |
2480 | mov z_pcl,opl | |
2481 | mov z_pch,oph | |
2482 | ret | |
2483 | ||
2484 | do_store_call: | |
2485 | push opl | |
2486 | push oph | |
2487 | mov opl,z_pcl | |
2488 | mov oph,z_pch | |
2489 | rcall do_op_push16 | |
2490 | pop z_pch | |
2491 | pop z_pcl | |
2492 | ret | |
2493 | ||
2494 | do_store_am: | |
2495 | mov adrh,oph | |
2496 | mov adrl,opl | |
2497 | mov temp,z_a | |
2498 | rcall memWriteByte | |
2499 | ret | |
2500 | ||
2501 | ||
2502 | ; ------------ Operation phase stuff ----------------- | |
2503 | ||
2504 | ||
2505 | .equ OP_NOP = (0<<10) | |
2506 | .equ OP_INC = (1<<10) | |
2507 | .equ OP_DEC = (2<<10) | |
2508 | .equ OP_INC16 = (3<<10) | |
2509 | .equ OP_DEC16 = (4<<10) | |
2510 | .equ OP_RLC = (5<<10) | |
2511 | .equ OP_RRC = (6<<10) | |
2512 | .equ OP_RR = (7<<10) | |
2513 | .equ OP_RL = (8<<10) | |
2514 | .equ OP_ADDA = (9<<10) | |
2515 | .equ OP_ADCA = (10<<10) | |
2516 | .equ OP_SUBFA = (11<<10) | |
2517 | .equ OP_SBCFA = (12<<10) | |
2518 | .equ OP_ANDA = (13<<10) | |
2519 | .equ OP_ORA = (14<<10) | |
2520 | .equ OP_XORA = (15<<10) | |
2521 | .equ OP_ADDHL = (16<<10) | |
2522 | .equ OP_STHL = (17<<10) ;store HL in fetched address | |
2523 | .equ OP_RMEM16 = (18<<10) ;read mem at fetched address | |
2524 | .equ OP_RMEM8 = (19<<10) ;read mem at fetched address | |
2525 | .equ OP_DA = (20<<10) | |
2526 | .equ OP_SCF = (21<<10) | |
2527 | .equ OP_CPL = (22<<10) | |
2528 | .equ OP_CCF = (23<<10) | |
2529 | .equ OP_POP16 = (24<<10) | |
2530 | .equ OP_PUSH16 = (25<<10) | |
2531 | .equ OP_IFNZ = (26<<10) | |
2532 | .equ OP_IFZ = (27<<10) | |
2533 | .equ OP_IFNC = (28<<10) | |
2534 | .equ OP_IFC = (29<<10) | |
2535 | .equ OP_IFPO = (30<<10) | |
2536 | .equ OP_IFPE = (31<<10) | |
2537 | .equ OP_IFP = (32<<10) | |
2538 | .equ OP_IFM = (33<<10) | |
2539 | .equ OP_OUTA = (34<<10) | |
2540 | .equ OP_IN = (35<<10) | |
2541 | .equ OP_EXHL = (36<<10) | |
2542 | .equ OP_DI = (37<<10) | |
2543 | .equ OP_EI = (38<<10) | |
2544 | .equ OP_INV = (39<<10) | |
2545 | ||
2546 | opjumps: | |
2547 | .dw do_op_nop | |
2548 | .dw do_op_inc | |
2549 | .dw do_op_dec | |
2550 | .dw do_op_inc16 | |
2551 | .dw do_op_dec16 | |
2552 | .dw do_op_rlc | |
2553 | .dw do_op_rrc | |
2554 | .dw do_op_rr | |
2555 | .dw do_op_rl | |
2556 | .dw do_op_adda | |
2557 | .dw do_op_adca | |
2558 | .dw do_op_subfa | |
2559 | .dw do_op_sbcfa | |
2560 | .dw do_op_anda | |
2561 | .dw do_op_ora | |
2562 | .dw do_op_xora | |
2563 | .dw do_op_addhl | |
2564 | .dw do_op_sthl | |
2565 | .dw do_op_rmem16 | |
2566 | .dw do_op_rmem8 | |
2567 | .dw do_op_da | |
2568 | .dw do_op_scf | |
2569 | .dw do_op_cpl | |
2570 | .dw do_op_ccf | |
2571 | .dw do_op_pop16 | |
2572 | .dw do_op_push16 | |
2573 | .dw do_op_ifnz | |
2574 | .dw do_op_ifz | |
2575 | .dw do_op_ifnc | |
2576 | .dw do_op_ifc | |
2577 | .dw do_op_ifpo | |
2578 | .dw do_op_ifpe | |
2579 | .dw do_op_ifp | |
2580 | .dw do_op_ifm | |
2581 | .dw do_op_outa | |
2582 | .dw do_op_in | |
2583 | .dw do_op_exhl | |
2584 | .dw do_op_di | |
2585 | .dw do_op_ei | |
2586 | .dw do_op_inv | |
2587 | ||
2588 | ||
2589 | ;How the flags are supposed to work: | |
2590 | ;7 ZFL_S - Sign flag (=MSBit of result) | |
2591 | ;6 ZFL_Z - Zero flag. Is 1 when the result is 0 | |
2592 | ;4 ZFL_H - Half-carry (carry from bit 3 to 4) | |
2593 | ;2 ZFL_P - Parity/2-complement Overflow | |
2594 | ;1 ZFL_N - Subtract - set if last op was a subtract | |
2595 | ;0 ZFL_C - Carry | |
2596 | ; | |
2597 | ;I sure hope I got the mapping between flags and instructions correct... | |
2598 | ||
2599 | ;---------------------------------------------------------------- | |
2600 | ;| | | |
2601 | ;| Zilog | | |
2602 | ;| | | |
2603 | ;| ZZZZZZZ 88888 000 | | |
2604 | ;| Z 8 8 0 0 | | |
2605 | ;| Z 8 8 0 0 0 | | |
2606 | ;| Z 88888 0 0 0 | | |
2607 | ;| Z 8 8 0 0 0 | | |
2608 | ;| Z 8 8 0 0 | | |
2609 | ;| ZZZZZZZ 88888 000 | | |
2610 | ;| | | |
2611 | ;| Z80 MICROPROCESSOR Instruction Set Summary | | |
2612 | ;| | | |
2613 | ;---------------------------------------------------------------- | |
2614 | ;---------------------------------------------------------------- | |
2615 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2616 | ;|----------+------+---------------------+----------------------| | |
2617 | ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY | | |
2618 | ;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY | | |
2619 | ;|ADD A,s |***V0*|Add |A=A+s | | |
2620 | ;|ADD HL,ss |--?-0*|Add |HL=HL+ss | | |
2621 | ;|ADD IX,pp |--?-0*|Add |IX=IX+pp | | |
2622 | ;|ADD IY,rr |--?-0*|Add |IY=IY+rr | | |
2623 | ;|AND s |**1P00|Logical AND |A=A&s | | |
2624 | ;|BIT b,m |?*1?0-|Test Bit |m&{2^b} | | |
2625 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
2626 | ;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn | | |
2627 | ;|CCF |--?-0*|Complement Carry Flag|CY=~CY | | |
2628 | ;|CP s |***V1*|Compare |A-s | | |
2629 | ;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1| | |
2630 | ;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0| | |
2631 | ;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1| | |
2632 | ;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0| | |
2633 | ;|CPL |--1-1-|Complement |A=~A | | |
2634 | ;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format | | |
2635 | ;|DEC s |***V1-|Decrement |s=s-1 | | |
2636 | ;|DEC xx |------|Decrement |xx=xx-1 | | |
2637 | ;|DEC ss |------|Decrement |ss=ss-1 | | |
2638 | ;|DI |------|Disable Interrupts | | | |
2639 | ;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 | | |
2640 | ;|EI |------|Enable Interrupts | | | |
2641 | ;|EX [SP],HL|------|Exchange |[SP]<->HL | | |
2642 | ;|EX [SP],xx|------|Exchange |[SP]<->xx | | |
2643 | ;|EX AF,AF' |------|Exchange |AF<->AF' | | |
2644 | ;|EX DE,HL |------|Exchange |DE<->HL | | |
2645 | ;|EXX |------|Exchange |qq<->qq' (except AF)| | |
2646 | ;|HALT |------|Halt | | | |
2647 | ;|IM n |------|Interrupt Mode | (n=0,1,2)| | |
2648 | ;|IN A,[n] |------|Input |A=[n] | | |
2649 | ;|IN r,[C] |***P0-|Input |r=[C] | | |
2650 | ;|INC r |***V0-|Increment |r=r+1 | | |
2651 | ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 | | |
2652 | ;|INC xx |------|Increment |xx=xx+1 | | |
2653 | ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 | | |
2654 | ;|INC ss |------|Increment |ss=ss+1 | | |
2655 | ;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1| | |
2656 | ;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 | | |
2657 | ;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1| | |
2658 | ;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 | | |
2659 | ;|JP [HL] |------|Unconditional Jump |PC=[HL] | | |
2660 | ;|JP [xx] |------|Unconditional Jump |PC=[xx] | | |
2661 | ;|JP nn |------|Unconditional Jump |PC=nn | | |
2662 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
2663 | ;|JR e |------|Unconditional Jump |PC=PC+e | | |
2664 | ;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)| | |
2665 | ;|LD dst,src|------|Load |dst=src | | |
2666 | ;|LD A,i |**0*0-|Load |A=i (i=I,R)| | |
2667 | ;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# | | |
2668 | ;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 | | |
2669 | ;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# | | |
2670 | ;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 | | |
2671 | ;|NEG |***V1*|Negate |A=-A | | |
2672 | ;|NOP |------|No Operation | | | |
2673 | ;|OR s |**0P00|Logical inclusive OR |A=Avs | | |
2674 | ;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 | | |
2675 | ;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 | | |
2676 | ;|OUT [C],r |------|Output |[C]=r | | |
2677 | ;|OUT [n],A |------|Output |[n]=A | | |
2678 | ;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1| | |
2679 | ;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1| | |
2680 | ;|POP xx |------|Pop |xx=[SP]+ | | |
2681 | ;|POP qq |------|Pop |qq=[SP]+ | | |
2682 | ;|PUSH xx |------|Push |-[SP]=xx | | |
2683 | ;|PUSH qq |------|Push |-[SP]=qq | | |
2684 | ;|RES b,m |------|Reset bit |m=m&{~2^b} | | |
2685 | ;|RET |------|Return |PC=[SP]+ | | |
2686 | ;|RET cc |------|Conditional Return |If cc RET | | |
2687 | ;|RETI |------|Return from Interrupt|PC=[SP]+ | | |
2688 | ;|RETN |------|Return from NMI |PC=[SP]+ | | |
2689 | ;|RL m |**0P0*|Rotate Left |m={CY,m}<- | | |
2690 | ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- | | |
2691 | ;|RLC m |**0P0*|Rotate Left Circular |m=m<- | | |
2692 | ;|RLCA |--0-0*|Rotate Left Circular |A=A<- | | |
2693 | ;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##| | |
2694 | ;|RR m |**0P0*|Rotate Right |m=->{CY,m} | | |
2695 | ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} | | |
2696 | ;|RRC m |**0P0*|Rotate Right Circular|m=->m | | |
2697 | ;|RRCA |--0-0*|Rotate Right Circular|A=->A | | |
2698 | ;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##| | |
2699 | ;|RST p |------|Restart | (p=0H,8H,10H,...,38H)| | |
2700 | ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY | | |
2701 | ;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY | | |
2702 | ;|SCF |--0-01|Set Carry Flag |CY=1 | | |
2703 | ;|SET b,m |------|Set bit |m=mv{2^b} | | |
2704 | ;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 | | |
2705 | ;|SRA m |**0P0*|Shift Right Arith. |m=m/2 | | |
2706 | ;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} | | |
2707 | ;|SUB s |***V1*|Subtract |A=A-s | | |
2708 | ;|XOR s |**0P00|Logical Exclusive OR |A=Axs | | |
2709 | ;|----------+------+--------------------------------------------| | |
2710 | ||
2711 | ||
2712 | .equ AVR_T = 6 | |
2713 | .equ AVR_H = 5 | |
2714 | .equ AVR_S = 4 | |
2715 | .equ AVR_V = 3 | |
2716 | .equ AVR_N = 2 | |
2717 | .equ AVR_Z = 1 | |
2718 | .equ AVR_C = 0 | |
2719 | ||
2720 | ;------------------------------------------------; | |
2721 | ; Move single bit between two registers | |
2722 | ; | |
2723 | ; bmov dstreg,dstbit,srcreg.srcbit | |
2724 | ||
2725 | .macro bmov | |
2726 | bst @2,@3 | |
2727 | bld @0,@1 | |
2728 | .endm | |
2729 | ||
2730 | ||
2731 | ;------------------------------------------------; | |
2732 | ; Load table value from flash indexed by source reg. | |
2733 | ; | |
2734 | ; ldpmx dstreg,tablebase,indexreg | |
2735 | ; | |
2736 | ; (6 words, 8 cycles) | |
2737 | ||
2738 | .macro ldpmx | |
2739 | ldi zl,low (@1*2) | |
2740 | ldi zh,high(@1*2) | |
2741 | add zl,@2 | |
2742 | brcc PC+2 | |
2743 | inc zh | |
2744 | lpm @0,z | |
2745 | .endm | |
2746 | ||
2747 | .macro do_z80_flags_HP | |
2748 | #if EM_Z80 | |
2749 | bmov z_flags, ZFL_P, temp, AVR_V | |
2750 | bmov z_flags, ZFL_H, temp, AVR_H | |
2751 | #endif | |
2752 | .endm | |
2753 | ||
2754 | .macro do_z80_flags_set_N | |
2755 | #if EM_Z80 | |
2756 | ori z_flags, (1<<ZFL_N) ; Negation auf 1 | |
2757 | #endif | |
2758 | .endm | |
2759 | ||
2760 | .macro do_z80_flags_set_HN | |
2761 | #if EM_Z80 | |
2762 | ori z_flags,(1<<ZFL_N)|(1<<ZFL_H) | |
2763 | #endif | |
2764 | .endm | |
2765 | ||
2766 | .macro do_z80_flags_clear_N | |
2767 | #if EM_Z80 | |
2768 | andi z_flags,~(1<<ZFL_N) | |
2769 | #endif | |
2770 | .endm | |
2771 | ||
2772 | .macro do_z80_flags_op_rotate | |
2773 | ; must not change avr carry flag! | |
2774 | #if EM_Z80 | |
2775 | andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) ) | |
2776 | #else | |
2777 | andi z_flags, ~( (1<<ZFL_C) ) | |
2778 | #endif | |
2779 | .endm | |
2780 | ||
2781 | .macro do_z80_flags_op_and | |
2782 | #if EM_Z80 | |
2783 | ori z_flags,(1<<ZFL_H) | |
2784 | #else | |
2785 | ori z_flags,(1<<ZFL_H) | |
2786 | #endif | |
2787 | .endm | |
2788 | ||
2789 | .macro do_z80_flags_op_or | |
2790 | #if EM_Z80 | |
2791 | #endif | |
2792 | .endm | |
2793 | ||
2794 | ||
2795 | do_op_nop: | |
2796 | ret | |
2797 | ||
2798 | ;---------------------------------------------------------------- | |
2799 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2800 | ;---------------------------------------------------------------- | |
2801 | ;|INC r |***V0-|Increment |r=r+1 | | |
2802 | ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 | | |
2803 | ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 | | |
2804 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2805 | ;|INC r |**-P0-|Increment |r=r+1 | | |
2806 | ;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 | | |
2807 | ; | |
2808 | ; | |
2809 | do_op_inc: | |
2810 | ldi temp,1 | |
2811 | add opl,temp | |
2812 | in temp, sreg | |
2813 | andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag | |
2814 | ldpmx temp2, sz53p_tab, opl | |
2815 | or z_flags,temp2 ; | |
2816 | do_z80_flags_HP | |
2817 | ret | |
2818 | ||
2819 | ;---------------------------------------------------------------- | |
2820 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2821 | ;---------------------------------------------------------------- | |
2822 | ;|DEC r |***V1-|Decrement |s=s-1 | | |
2823 | ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 | | |
2824 | ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 | | |
2825 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2826 | ;|DEC r |**-P -|Increment |r=r+1 | | |
2827 | ;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 | | |
2828 | ; | |
2829 | ; | |
2830 | do_op_dec: | |
2831 | subi opl,1 | |
2832 | in temp, sreg | |
2833 | andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag | |
2834 | ldpmx temp2, sz53p_tab, opl | |
2835 | or z_flags,temp2 ; | |
2836 | do_z80_flags_HP | |
2837 | do_z80_flags_set_N | |
2838 | ret | |
2839 | ||
2840 | ||
2841 | ;---------------------------------------------------------------- | |
2842 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2843 | ;---------------------------------------------------------------- | |
2844 | ;|INC xx |------|Increment |xx=xx+1 | | |
2845 | ;|INC ss |------|Increment |ss=ss+1 | | |
2846 | ; | |
2847 | ; | |
2848 | do_op_inc16: | |
2849 | inc opl | |
2850 | brne op_i16x | |
2851 | inc oph | |
2852 | op_i16x: | |
2853 | ret | |
2854 | ||
2855 | ;---------------------------------------------------------------- | |
2856 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2857 | ;---------------------------------------------------------------- | |
2858 | ;|DEC xx |------|Decrement |xx=xx-1 | | |
2859 | ;|DEC ss |------|Decrement |ss=ss-1 | | |
2860 | ; | |
2861 | ; | |
2862 | do_op_dec16: | |
2863 | subi opl, 1 | |
2864 | sbci oph, 0 | |
2865 | ret | |
2866 | ||
2867 | ;---------------------------------------------------------------- | |
2868 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2869 | ;---------------------------------------------------------------- | |
2870 | ;|RLCA |--0-0*|Rotate Left Circular |A=A<- | | |
2871 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2872 | ;|RLCA |---- *|Rotate Left Circular |A=A<- | | |
2873 | ; | |
2874 | ; | |
2875 | do_op_rlc: | |
2876 | ;Rotate Left Cyclical. All bits move 1 to the | |
2877 | ;left, the msb becomes c and lsb. | |
2878 | do_z80_flags_op_rotate | |
2879 | lsl opl | |
2880 | brcc do_op_rlc_noc | |
2881 | ori opl, 1 | |
2882 | ori z_flags, (1<<ZFL_C) | |
2883 | do_op_rlc_noc: | |
2884 | ret | |
2885 | ||
2886 | ;---------------------------------------------------------------- | |
2887 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2888 | ;---------------------------------------------------------------- | |
2889 | ;|RRCA |--0-0*|Rotate Right Circular|A=->A | | |
2890 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2891 | ;|RRCA |---- *|Rotate Right Circular|A=->A | | |
2892 | ; | |
2893 | ; | |
2894 | do_op_rrc: | |
2895 | ;Rotate Right Cyclical. All bits move 1 to the | |
2896 | ;right, the lsb becomes c and msb. | |
2897 | do_z80_flags_op_rotate | |
2898 | lsr opl | |
2899 | brcc do_op_rrc_noc | |
2900 | ori opl, 0x80 | |
2901 | ori z_flags, (1<<ZFL_C) | |
2902 | do_op_rrc_noc: | |
2903 | ret | |
2904 | ||
2905 | ;---------------------------------------------------------------- | |
2906 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2907 | ;---------------------------------------------------------------- | |
2908 | ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} | | |
2909 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2910 | ;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} | | |
2911 | ; | |
2912 | ; | |
2913 | do_op_rr: | |
2914 | ;Rotate Right. All bits move 1 to the right, the lsb | |
2915 | ;becomes c, c becomes msb. | |
2916 | clc ; get z80 carry to avr carry | |
2917 | sbrc z_flags,ZFL_C | |
2918 | sec | |
2919 | do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C) | |
2920 | bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY | |
2921 | ror opl | |
2922 | ret | |
2923 | ||
2924 | ;---------------------------------------------------------------- | |
2925 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2926 | ;---------------------------------------------------------------- | |
2927 | ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- | | |
2928 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2929 | ;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- | | |
2930 | ; | |
2931 | ; | |
2932 | do_op_rl: | |
2933 | ;Rotate Left. All bits move 1 to the left, the msb | |
2934 | ;becomes c, c becomes lsb. | |
2935 | clc | |
2936 | sbrc z_flags,ZFL_C | |
2937 | sec | |
2938 | do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C) | |
2939 | bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY | |
2940 | rol opl | |
2941 | ret | |
2942 | ||
2943 | ;---------------------------------------------------------------- | |
2944 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2945 | ;---------------------------------------------------------------- | |
2946 | ;|ADD A,s |***V0*|Add |A=A+s | | |
2947 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2948 | ;|ADD A,s |***P *|Add |A=A+s | | |
2949 | ; | |
2950 | ; | |
2951 | do_op_adda: | |
2952 | add opl,z_a | |
2953 | in temp,sreg | |
2954 | ldpmx z_flags,sz53p_tab,opl ;S,Z,P flag | |
2955 | bmov z_flags,ZFL_C, temp,AVR_C | |
2956 | do_z80_flags_HP | |
2957 | ret | |
2958 | ||
2959 | ;---------------------------------------------------------------- | |
2960 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2961 | ;---------------------------------------------------------------- | |
2962 | ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY | | |
2963 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2964 | ;|ADC A,s |***P *|Add with Carry |A=A+s+CY | | |
2965 | ; | |
2966 | ; | |
2967 | do_op_adca: | |
2968 | clc | |
2969 | sbrc z_flags,ZFL_C | |
2970 | sec | |
2971 | adc opl,z_a | |
2972 | in temp,sreg | |
2973 | ldpmx z_flags,sz53p_tab,opl ;S,Z,P | |
2974 | bmov z_flags,ZFL_C, temp,AVR_C | |
2975 | do_z80_flags_HP | |
2976 | ret | |
2977 | ||
2978 | ;---------------------------------------------------------------- | |
2979 | ;|Mnemonic |SZHPNC|Description |Notes | | |
2980 | ;---------------------------------------------------------------- | |
2981 | ;|SUB s |***V1*|Subtract |A=A-s | | |
2982 | ;|CP s |***V1*|Compare |A-s | | |
2983 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
2984 | ;|SUB s |***P *|Subtract |A=A-s | | |
2985 | ;|CP s |***P *|Compare |A-s | | |
2986 | ||
2987 | ; | |
2988 | do_op_subfa: | |
2989 | mov temp,z_a | |
2990 | sub temp,opl | |
2991 | mov opl,temp | |
2992 | in temp,sreg | |
2993 | ldpmx z_flags,sz53p_tab,opl ;S,Z,P | |
2994 | bmov z_flags,ZFL_C, temp,AVR_C | |
2995 | do_z80_flags_HP | |
2996 | do_z80_flags_set_N | |
2997 | ret | |
2998 | ||
2999 | ;---------------------------------------------------------------- | |
3000 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3001 | ;---------------------------------------------------------------- | |
3002 | ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY | | |
3003 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3004 | ;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY | | |
3005 | ; | |
3006 | ; | |
3007 | do_op_sbcfa: | |
3008 | mov temp,z_a | |
3009 | clc | |
3010 | sbrc z_flags,ZFL_C | |
3011 | sec | |
3012 | sbc temp,opl | |
3013 | mov opl,temp | |
3014 | in temp,sreg | |
3015 | ldpmx z_flags,sz53p_tab,opl ;S,Z,P | |
3016 | bmov z_flags,ZFL_C, temp,AVR_C | |
3017 | do_z80_flags_HP | |
3018 | do_z80_flags_set_N | |
3019 | ret | |
3020 | ||
3021 | ;---------------------------------------------------------------- | |
3022 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3023 | ;---------------------------------------------------------------- | |
3024 | ;|AND s |**1P00|Logical AND |A=A&s | | |
3025 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3026 | ;|AND s |**-P 0|Logical AND |A=A&s | | |
3027 | ; | |
3028 | ; TODO H-Flag | |
3029 | do_op_anda: | |
3030 | and opl,z_a ; | |
3031 | ldpmx z_flags,sz53p_tab,opl ;S,Z,P,N,C | |
3032 | do_z80_flags_op_and | |
3033 | ret | |
3034 | ||
3035 | ||
3036 | ;---------------------------------------------------------------- | |
3037 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3038 | ;---------------------------------------------------------------- | |
3039 | ;|OR s |**0P00|Logical inclusive OR |A=Avs | | |
3040 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3041 | ;|OR s |**-P00|Logical inclusive OR |A=Avs | | |
3042 | ; | |
3043 | ; TODO: H-Flag | |
3044 | do_op_ora: | |
3045 | or opl,z_a | |
3046 | ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C | |
3047 | do_z80_flags_op_or | |
3048 | ret | |
3049 | ||
3050 | ;---------------------------------------------------------------- | |
3051 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3052 | ;---------------------------------------------------------------- | |
3053 | ;|XOR s |**0P00|Logical Exclusive OR |A=Axs | | |
3054 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3055 | ;|XOR s |**-P 0|Logical Exclusive OR |A=Axs | | |
3056 | ; | |
3057 | ; TODO: H-Flag | |
3058 | do_op_xora: | |
3059 | eor opl,z_a | |
3060 | ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C | |
3061 | do_z80_flags_op_or | |
3062 | ret | |
3063 | ||
3064 | ;---------------------------------------------------------------- | |
3065 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3066 | ;---------------------------------------------------------------- | |
3067 | ;|ADD HL,ss |--?-0*|Add |HL=HL+ss | | |
3068 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3069 | ;|ADD HL,ss |---- *|Add |HL=HL+ss | | |
3070 | ; | |
3071 | ; | |
3072 | do_op_addhl: | |
3073 | add opl,z_l | |
3074 | adc oph,z_h | |
3075 | in temp,sreg | |
3076 | bmov z_flags,ZFL_H, temp,AVR_H | |
3077 | bmov z_flags,ZFL_C, temp,AVR_C | |
3078 | do_z80_flags_clear_N | |
3079 | ret | |
3080 | ||
3081 | ;---------------------------------------------------------------- | |
3082 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3083 | ;---------------------------------------------------------------- | |
3084 | ;|LD dst,src|------|Load |dst=src | | |
3085 | ; | |
3086 | ; | |
3087 | do_op_sthl: ;store hl to mem loc in opl:h | |
3088 | mov adrl,opl | |
3089 | mov adrh,oph | |
3090 | mov temp,z_l | |
3091 | rcall memWriteByte | |
3092 | ||
3093 | inc opl | |
3094 | brne op_sthlx | |
3095 | inc oph | |
3096 | op_sthlx: | |
3097 | mov adrl,opl | |
3098 | mov adrh,oph | |
3099 | mov temp,z_h | |
3100 | rcall memWriteByte | |
3101 | ||
3102 | ret | |
3103 | ||
3104 | ;---------------------------------------------------------------- | |
3105 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3106 | ;---------------------------------------------------------------- | |
3107 | ;|LD dst,src|------|Load |dst=src | | |
3108 | ; | |
3109 | ; | |
3110 | do_op_rmem16: | |
3111 | mov adrl,opl | |
3112 | mov adrh,oph | |
3113 | rcall memReadByte | |
3114 | mov opl,temp | |
3115 | ldi temp,1 | |
3116 | add adrl,temp | |
3117 | ldi temp,0 | |
3118 | adc adrh,temp | |
3119 | rcall memReadByte | |
3120 | mov oph,temp | |
3121 | ret | |
3122 | ||
3123 | ;---------------------------------------------------------------- | |
3124 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3125 | ;---------------------------------------------------------------- | |
3126 | ;|LD dst,src|------|Load |dst=src | | |
3127 | ; | |
3128 | ; | |
3129 | do_op_rmem8: | |
3130 | mov adrl,opl | |
3131 | mov adrh,oph | |
3132 | rcall memReadByte | |
3133 | mov opl,temp | |
3134 | ret | |
3135 | ||
3136 | ;---------------------------------------------------------------- | |
3137 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3138 | ;---------------------------------------------------------------- | |
3139 | ;|DAA |***P-*|Decimal Adjust Acc. | | | |
3140 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3141 | ; | |
3142 | ; Not yet checked | |
3143 | ||
3144 | ; Description (http://www.z80.info/z80syntx.htm#DAA): | |
3145 | ; This instruction conditionally adjusts the accumulator for BCD addition | |
3146 | ; and subtraction operations. For addition (ADD, ADC, INC) or subtraction | |
3147 | ; (SUB, SBC, DEC, NEC), the following table indicates the operation performed: | |
3148 | ; | |
3149 | ; ------------------------------------------------------------------------------- | |
3150 | ; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag| | |
3151 | ; | Operation| Before | upper digit | Before | lower digit | added | After | | |
3152 | ; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA | | |
3153 | ; |-----------------------------------------------------------------------------| | |
3154 | ; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 | | |
3155 | ; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 | | |
3156 | ; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 | | |
3157 | ; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 | | |
3158 | ; | | 0 | 9-F | 0 | A-F | 66 | 1 | | |
3159 | ; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 | | |
3160 | ; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 | | |
3161 | ; | | 1 | 0-2 | 0 | A-F | 66 | 1 | | |
3162 | ; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 | | |
3163 | ; |-----------------------------------------------------------------------------| | |
3164 | ; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 | | |
3165 | ; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 | | |
3166 | ; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 | | |
3167 | ; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 | | |
3168 | ; |-----------------------------------------------------------------------------| | |
3169 | ; | |
3170 | ; Flags: | |
3171 | ; C: See instruction. | |
3172 | ; N: Unaffected. | |
3173 | ; P/V: Set if Acc. is even parity after operation, reset otherwise. | |
3174 | ; H: See instruction. | |
3175 | ; Z: Set if Acc. is Zero after operation, reset otherwise. | |
3176 | ; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise. | |
3177 | ||
3178 | ||
3179 | ||
3180 | #if 1 | |
3181 | do_op_da: | |
3182 | ldi oph,0 ; what to add | |
3183 | sbrc z_flags,ZFL_H ; if H-Flag | |
3184 | rjmp op_da_06 | |
3185 | mov temp,opl | |
3186 | andi temp,0x0f ; ... or lower digit > 9 | |
3187 | cpi temp,0x0a | |
3188 | brlo op_da_06n | |
3189 | op_da_06: | |
3190 | ori oph,0x06 | |
3191 | op_da_06n: | |
3192 | sbrc z_flags,(1<<ZFL_C) | |
3193 | rjmp op_da_60 | |
3194 | cpi opl,0xa0 | |
3195 | brlo op_da_60n | |
3196 | op_da_60: | |
3197 | ori oph,0x60 | |
3198 | op_da_60n: | |
3199 | cpi opl,0x9a | |
3200 | brlo op_da_99n | |
3201 | ori z_flags,(1<<ZFL_C); set C | |
3202 | op_da_99n: | |
3203 | sbrs z_flags,ZFL_N ; if sub-op | |
3204 | rjmp op_da_add ; then | |
3205 | sub opl,oph | |
3206 | rjmp op_da_ex | |
3207 | op_da_add: ; else add-op | |
3208 | cpi opl,0x91 | |
3209 | brlo op_da_60n2 | |
3210 | mov temp,opl | |
3211 | andi temp,0x0f | |
3212 | cpi temp,0x0a | |
3213 | brlo op_da_60n2 | |
3214 | ori oph,0x60 | |
3215 | op_da_60n2: | |
3216 | add opl,oph | |
3217 | op_da_ex: | |
3218 | in temp,SREG | |
3219 | sbrc temp,AVR_H | |
3220 | ori z_flags,(1<<ZFL_C) | |
3221 | andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N | |
3222 | ldpmx temp2, sz53p_tab, opl ; get S,Z,P | |
3223 | or z_flags,temp2 | |
3224 | bmov z_flags,ZFL_H, temp,AVR_H ; H (?) | |
3225 | ret | |
3226 | #else | |
3227 | ||
3228 | do_op_da: | |
3229 | sbrc z_flags,ZFL_N ; if add-op | |
3230 | rjmp do_op_da_sub ; then | |
3231 | ldi temp2,0 ; | |
3232 | mov temp,opl ; | |
3233 | andi temp,0x0f ; | |
3234 | cpi temp,0x0a ; if lower digit > 9 | |
3235 | brlo do_op_da_h ; | |
3236 | ori temp2,0x06 ; add 6 to lower digit | |
3237 | do_op_da_h: ; | |
3238 | sbrc z_flags,ZFL_H ; ... or H-Flag | |
3239 | ori temp2,0x06 ; | |
3240 | add opl,temp2 ; | |
3241 | ||
3242 | ldi temp2,0 ; | |
3243 | mov temp,opl ; | |
3244 | andi temp,0xf0 ; | |
3245 | cpi temp,0xa0 ; | |
3246 | brlo do_op_da_c ; | |
3247 | ori temp2,0x60 ; | |
3248 | do_op_da_c: ; else sub-op | |
3249 | sbrc z_flags,ZFL_C ; | |
3250 | ori temp2,0x60 ; | |
3251 | andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) ) | |
3252 | add opl,temp2 ; | |
3253 | in temp,SREG ; | |
3254 | bst temp,AVR_Z ;Z-Flag | |
3255 | bld z_flags,ZFL_Z ; | |
3256 | bst temp,AVR_N ;S-Flag | |
3257 | bst z_flags,ZFL_S ; | |
3258 | sbrc temp2,5 ;C-Flag, set if 0x06 added | |
3259 | ori z_flags,(1<<ZFL_C) ; | |
3260 | ;H-Flag? | |
3261 | ret | |
3262 | ||
3263 | do_op_da_sub: ;TODO: | |
3264 | rcall do_op_inv | |
3265 | ret | |
3266 | #endif | |
3267 | ||
3268 | ;---------------------------------------------------------------- | |
3269 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3270 | ;---------------------------------------------------------------- | |
3271 | ;|SCF |--0-01|Set Carry Flag |CY=1 | | |
3272 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3273 | ; | |
3274 | ; | |
3275 | do_op_scf: | |
3276 | andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N)) | |
3277 | ori z_flags,(1<<ZFL_C) | |
3278 | ret | |
3279 | ||
3280 | ;---------------------------------------------------------------- | |
3281 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3282 | ;---------------------------------------------------------------- | |
3283 | ;|CCF |--?-0*|Complement Carry Flag|CY=~CY | | |
3284 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3285 | ;|SCF |---- 1|Set Carry Flag |CY=1 | | |
3286 | ; | |
3287 | ;TODO: H-Flag | |
3288 | do_op_ccf: | |
3289 | do_z80_flags_clear_N | |
3290 | ldi temp,(1<<ZFL_C) | |
3291 | eor z_flags,temp | |
3292 | ret | |
3293 | ||
3294 | ;---------------------------------------------------------------- | |
3295 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3296 | ;---------------------------------------------------------------- | |
3297 | ;|CPL |--1-1-|Complement |A=~A | | |
3298 | ;|----------|SZHP C|---------- 8080 ----------------------------| | |
3299 | ;|CPL |---- -|Complement |A=~A | | |
3300 | ; | |
3301 | ; | |
3302 | do_op_cpl: | |
3303 | com opl | |
3304 | do_z80_flags_set_HN | |
3305 | ret | |
3306 | ||
3307 | ||
3308 | ;---------------------------------------------------------------- | |
3309 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3310 | ;---------------------------------------------------------------- | |
3311 | ;|PUSH xx |------|Push |-[SP]=xx | | |
3312 | ;|PUSH qq |------|Push |-[SP]=qq | | |
3313 | ; | |
3314 | ; | |
3315 | do_op_push16: | |
3316 | #if 1 | |
3317 | ldi temp,1 | |
3318 | ldi temp2,0 | |
3319 | sub z_spl,temp | |
3320 | sbc z_sph,temp2 | |
3321 | ||
3322 | mov adrl,z_spl | |
3323 | mov adrh,z_sph | |
3324 | mov temp,oph | |
3325 | rcall memWriteByte | |
3326 | ||
3327 | ldi temp,1 | |
3328 | ldi temp2,0 | |
3329 | sub z_spl,temp | |
3330 | sbc z_sph,temp2 | |
3331 | ||
3332 | mov adrl,z_spl | |
3333 | mov adrh,z_sph | |
3334 | mov temp,opl | |
3335 | rcall memWriteByte | |
3336 | #else | |
3337 | subi z_spl,1 | |
3338 | sbci z_sph,0 | |
3339 | ||
3340 | mov adrl,z_spl | |
3341 | mov adrh,z_sph | |
3342 | mov temp,oph | |
3343 | rcall memWriteByte | |
3344 | ||
3345 | subi z_spl,1 | |
3346 | sbci z_sph,0 | |
3347 | ||
3348 | mov adrl,z_spl | |
3349 | mov adrh,z_sph | |
3350 | mov temp,opl | |
3351 | rcall memWriteByte | |
3352 | #endif | |
3353 | ||
3354 | .if STACK_DBG | |
3355 | rcall printstr | |
3356 | .db "Stack push ",0 | |
3357 | mov temp,oph | |
3358 | rcall printhex | |
3359 | mov temp,opl | |
3360 | rcall printhex | |
3361 | rcall printstr | |
3362 | .db ", SP is now ",0 | |
3363 | mov temp,z_sph | |
3364 | rcall printhex | |
3365 | mov temp,z_spl | |
3366 | rcall printhex | |
3367 | rcall printstr | |
3368 | .db ".",13,0 | |
3369 | .endif | |
3370 | ||
3371 | ret | |
3372 | ||
3373 | ;---------------------------------------------------------------- | |
3374 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3375 | ;---------------------------------------------------------------- | |
3376 | ;|POP xx |------|Pop |xx=[SP]+ | | |
3377 | ;|POP qq |------|Pop |qq=[SP]+ | | |
3378 | ; | |
3379 | ; | |
3380 | do_op_pop16: | |
3381 | mov adrl,z_spl | |
3382 | mov adrh,z_sph | |
3383 | rcall memReadByte | |
3384 | mov opl,temp | |
3385 | ||
3386 | ldi temp,1 | |
3387 | ldi temp2,0 | |
3388 | add z_spl,temp | |
3389 | adc z_sph,temp2 | |
3390 | ||
3391 | mov adrl,z_spl | |
3392 | mov adrh,z_sph | |
3393 | rcall memReadByte | |
3394 | mov oph,temp | |
3395 | ||
3396 | ldi temp,1 | |
3397 | ldi temp2,0 | |
3398 | add z_spl,temp | |
3399 | adc z_sph,temp2 | |
3400 | ||
3401 | .if STACK_DBG | |
3402 | rcall printstr | |
3403 | .db "Stack pop: val ",0 | |
3404 | mov temp,oph | |
3405 | rcall printhex | |
3406 | mov temp,opl | |
3407 | rcall printhex | |
3408 | rcall printstr | |
3409 | .db ", SP is now",0 | |
3410 | mov temp,z_sph | |
3411 | rcall printhex | |
3412 | mov temp,z_spl | |
3413 | rcall printhex | |
3414 | rcall printstr | |
3415 | .db ".",13,0 | |
3416 | .endif | |
3417 | ret | |
3418 | ||
3419 | ;---------------------------------------------------------------- | |
3420 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3421 | ;---------------------------------------------------------------- | |
3422 | ;|EX [SP],HL|------|Exchange |[SP]<->HL | | |
3423 | ;|EX DE,HL |------|Exchange |DE<->HL | | |
3424 | ; | |
3425 | ; | |
3426 | do_op_exhl: | |
3427 | mov temp,z_h | |
3428 | mov z_h,oph | |
3429 | mov oph,temp | |
3430 | mov temp,z_l | |
3431 | mov z_l,opl | |
3432 | mov opl,temp | |
3433 | ret | |
3434 | ||
3435 | ;---------------------------------------------------------------- | |
3436 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3437 | ;---------------------------------------------------------------- | |
3438 | ; | |
3439 | ; TODO: Implement IFF1, IFF2 | |
3440 | do_op_di: | |
3441 | ret | |
3442 | ||
3443 | ;---------------------------------------------------------------- | |
3444 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3445 | ;---------------------------------------------------------------- | |
3446 | ; | |
3447 | ; TODO: Implement IFF1, IFF2 | |
3448 | do_op_ei: | |
3449 | ret | |
3450 | ||
3451 | ;---------------------------------------------------------------- | |
3452 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3453 | ;---------------------------------------------------------------- | |
3454 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3455 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3456 | ;|RET cc |------|Conditional Return |If cc RET | | |
3457 | ; | |
3458 | ; | |
3459 | do_op_ifnz: | |
3460 | sbrs z_flags, ZFL_Z | |
3461 | ret | |
3462 | ldi insdech, 0 | |
3463 | ldi insdecl, 0 | |
3464 | ret | |
3465 | ||
3466 | ;---------------------------------------------------------------- | |
3467 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3468 | ;---------------------------------------------------------------- | |
3469 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3470 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3471 | ;|RET cc |------|Conditional Return |If cc RET | | |
3472 | ; | |
3473 | ; | |
3474 | do_op_ifz: | |
3475 | sbrc z_flags, ZFL_Z | |
3476 | ret | |
3477 | ldi insdech, 0 | |
3478 | ldi insdecl, 0 | |
3479 | ret | |
3480 | ||
3481 | ;---------------------------------------------------------------- | |
3482 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3483 | ;---------------------------------------------------------------- | |
3484 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3485 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3486 | ;|RET cc |------|Conditional Return |If cc RET | | |
3487 | ; | |
3488 | ; | |
3489 | do_op_ifnc: | |
3490 | sbrs z_flags, ZFL_C | |
3491 | ret | |
3492 | ldi insdech, 0 | |
3493 | ldi insdecl, 0 | |
3494 | ret | |
3495 | ||
3496 | ;---------------------------------------------------------------- | |
3497 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3498 | ;---------------------------------------------------------------- | |
3499 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3500 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3501 | ;|RET cc |------|Conditional Return |If cc RET | | |
3502 | ; | |
3503 | ; | |
3504 | do_op_ifc: | |
3505 | sbrc z_flags, ZFL_C | |
3506 | ret | |
3507 | ldi insdech, 0 | |
3508 | ldi insdecl, 0 | |
3509 | ret | |
3510 | ||
3511 | ;---------------------------------------------------------------- | |
3512 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3513 | ;---------------------------------------------------------------- | |
3514 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3515 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3516 | ;|RET cc |------|Conditional Return |If cc RET | | |
3517 | ; | |
3518 | ; | |
3519 | do_op_ifpo: | |
3520 | sbrs z_flags, ZFL_P | |
3521 | ret | |
3522 | ldi insdech, 0 | |
3523 | ldi insdecl, 0 | |
3524 | ret | |
3525 | ||
3526 | ;---------------------------------------------------------------- | |
3527 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3528 | ;---------------------------------------------------------------- | |
3529 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3530 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3531 | ;|RET cc |------|Conditional Return |If cc RET | | |
3532 | ; | |
3533 | ; | |
3534 | do_op_ifpe: | |
3535 | sbrc z_flags, ZFL_P | |
3536 | ret | |
3537 | ldi insdech, 0 | |
3538 | ldi insdecl, 0 | |
3539 | ret | |
3540 | ||
3541 | ;---------------------------------------------------------------- | |
3542 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3543 | ;---------------------------------------------------------------- | |
3544 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3545 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3546 | ;|RET cc |------|Conditional Return |If cc RET | | |
3547 | ; | |
3548 | ; | |
3549 | do_op_ifp: ;sign positive, aka s=0 | |
3550 | sbrs z_flags, ZFL_S | |
3551 | ret | |
3552 | ldi insdech,0 | |
3553 | ldi insdecl,0 | |
3554 | ret | |
3555 | ||
3556 | ;---------------------------------------------------------------- | |
3557 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3558 | ;---------------------------------------------------------------- | |
3559 | ;|CALL cc,nn|------|Conditional Call |If cc CALL | | |
3560 | ;|JP cc,nn |------|Conditional Jump |If cc JP | | |
3561 | ;|RET cc |------|Conditional Return |If cc RET | | |
3562 | ; | |
3563 | ; | |
3564 | do_op_ifm: ;sign negative, aka s=1 | |
3565 | sbrc z_flags, ZFL_S | |
3566 | ret | |
3567 | ldi insdech, 0 | |
3568 | ldi insdecl, 0 | |
3569 | ret | |
3570 | ||
3571 | ;---------------------------------------------------------------- | |
3572 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3573 | ;---------------------------------------------------------------- | |
3574 | ;|OUT [n],A |------|Output |[n]=A | | |
3575 | ; | |
3576 | ; | |
3577 | ;Interface with peripherials goes here :) | |
3578 | do_op_outa: ; out (opl),a | |
3579 | .if PORT_DEBUG | |
3580 | rcall printstr | |
3581 | .db 13,"Port write: ",0 | |
3582 | mov temp,z_a | |
3583 | rcall printhex | |
3584 | rcall printstr | |
3585 | .db " -> (",0 | |
3586 | mov temp,opl | |
3587 | rcall printhex | |
3588 | rcall printstr | |
3589 | .db ")",13,0 | |
3590 | .endif | |
3591 | mov temp,z_a | |
3592 | mov temp2,opl | |
3593 | rcall portWrite | |
3594 | ret | |
3595 | ||
3596 | ;---------------------------------------------------------------- | |
3597 | ;|Mnemonic |SZHPNC|Description |Notes | | |
3598 | ;---------------------------------------------------------------- | |
3599 | ;|IN A,[n] |------|Input |A=[n] | | |
3600 | ; | |
3601 | ; | |
3602 | do_op_in: ; in a,(opl) | |
3603 | .if PORT_DEBUG | |
3604 | rcall printstr | |
3605 | .db 13,"Port read: (",0 | |
3606 | mov temp,opl | |
3607 | rcall printhex | |
3608 | rcall printstr | |
3609 | .db ") -> ",0 | |
3610 | .endif | |
3611 | ||
3612 | mov temp2,opl | |
3613 | rcall portRead | |
3614 | mov opl,temp | |
3615 | ||
3616 | .if PORT_DEBUG | |
3617 | rcall printhex | |
3618 | rcall printstr | |
3619 | .db 13,0 | |
3620 | .endif | |
3621 | ret | |
3622 | ||
3623 | ;---------------------------------------------------------------- | |
3624 | ||
3625 | #if 0 | |
3626 | do_op_calcparity: | |
3627 | ldi temp2,1 | |
3628 | sbrc parityb,0 | |
3629 | inc temp2 | |
3630 | sbrc parityb,1 | |
3631 | inc temp2 | |
3632 | sbrc parityb,2 | |
3633 | inc temp2 | |
3634 | sbrc parityb,3 | |
3635 | inc temp2 | |
3636 | sbrc parityb,4 | |
3637 | inc temp2 | |
3638 | sbrc parityb,5 | |
3639 | inc temp2 | |
3640 | sbrc parityb,6 | |
3641 | inc temp2 | |
3642 | sbrc parityb,7 | |
3643 | inc temp2 | |
3644 | andi temp2,1 | |
3645 | ret | |
3646 | #endif | |
3647 | ||
3648 | ;---------------------------------------------------------------- | |
3649 | do_op_inv: | |
3650 | rcall printstr | |
3651 | .db "Invalid opcode @ PC=",0,0 | |
3652 | mov temp,z_pch | |
3653 | rcall printhex | |
3654 | mov temp,z_pcl | |
3655 | rcall printhex | |
3656 | ||
3657 | ;---------------------------------------------------------------- | |
3658 | haltinv: | |
3659 | rjmp haltinv | |
3660 | ||
3661 | ;---------------------------------------------------------------- | |
3662 | ; Lookup table, stolen from z80ex, Z80 emulation library. | |
3663 | ; http://z80ex.sourceforge.net/ | |
3664 | ||
3665 | ; The S, Z, 5 and 3 bits and the parity of the lookup value | |
3666 | sz53p_tab: | |
3667 | .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 | |
3668 | .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c | |
3669 | .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 | |
3670 | .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 | |
3671 | .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 | |
3672 | .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 | |
3673 | .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 | |
3674 | .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c | |
3675 | .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 | |
3676 | .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 | |
3677 | .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 | |
3678 | .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c | |
3679 | .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 | |
3680 | .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c | |
3681 | .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 | |
3682 | .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 | |
3683 | .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 | |
3684 | .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 | |
3685 | .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 | |
3686 | .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c | |
3687 | .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 | |
3688 | .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac | |
3689 | .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 | |
3690 | .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 | |
3691 | .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 | |
3692 | .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c | |
3693 | .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 | |
3694 | .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 | |
3695 | .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 | |
3696 | .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 | |
3697 | .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 | |
3698 | .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac | |
3699 | ||
3700 | ||
3701 | ; ----------------------- Opcode decoding ------------------------- | |
3702 | ||
3703 | ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three | |
3704 | ; operations: fetch, do something, store. | |
3705 | ; The table is made of 256 words. These 16-bit words consist of | |
3706 | ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store | |
3707 | ; operation (bit 5-9). | |
3708 | ||
3709 | inst_table: | |
3710 | .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP | |
3711 | .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn | |
3712 | .dw (FETCH_A | OP_NOP | STORE_MBC ) ; 02 LD (BC),A | |
3713 | .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC | |
3714 | .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B | |
3715 | .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B | |
3716 | .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n | |
3717 | .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA | |
3718 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80) | |
3719 | .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC | |
3720 | .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC) | |
3721 | .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC | |
3722 | .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C | |
3723 | .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C | |
3724 | .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n | |
3725 | .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA | |
3726 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80) | |
3727 | .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn | |
3728 | .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A | |
3729 | .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE | |
3730 | .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D | |
3731 | .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D | |
3732 | .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n | |
3733 | .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA | |
3734 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80) | |
3735 | .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE | |
3736 | .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE) | |
3737 | .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE | |
3738 | .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E | |
3739 | .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E | |
3740 | .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n | |
3741 | .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA | |
3742 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80) | |
3743 | .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn | |
3744 | .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL | |
3745 | .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL | |
3746 | .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H | |
3747 | .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H | |
3748 | .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n | |
3749 | .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA | |
3750 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80) | |
3751 | .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL | |
3752 | .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn) | |
3753 | .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL | |
3754 | .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L | |
3755 | .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L | |
3756 | .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n | |
3757 | .dw (FETCH_A | OP_CPL | STORE_A ) ; 2F CPL | |
3758 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80) | |
3759 | .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn | |
3760 | .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A | |
3761 | .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP | |
3762 | .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL) | |
3763 | .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL) | |
3764 | .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n | |
3765 | .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF | |
3766 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80) | |
3767 | .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP | |
3768 | .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn) | |
3769 | .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP | |
3770 | .dw (FETCH_A | OP_INC | STORE_A ) ; 3C INC A | |
3771 | .dw (FETCH_A | OP_DEC | STORE_A ) ; 3D DEC A | |
3772 | .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n | |
3773 | .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd) | |
3774 | .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r | |
3775 | .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r | |
3776 | .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r | |
3777 | .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r | |
3778 | .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r | |
3779 | .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r | |
3780 | .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r | |
3781 | .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r | |
3782 | .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r | |
3783 | .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r | |
3784 | .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r | |
3785 | .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r | |
3786 | .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r | |
3787 | .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r | |
3788 | .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r | |
3789 | .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r | |
3790 | .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r | |
3791 | .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r | |
3792 | .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r | |
3793 | .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r | |
3794 | .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r | |
3795 | .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r | |
3796 | .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r | |
3797 | .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r | |
3798 | .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r | |
3799 | .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r | |
3800 | .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r | |
3801 | .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r | |
3802 | .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r | |
3803 | .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r | |
3804 | .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r | |
3805 | .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r | |
3806 | .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r | |
3807 | .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r | |
3808 | .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r | |
3809 | .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r | |
3810 | .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r | |
3811 | .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r | |
3812 | .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r | |
3813 | .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r | |
3814 | .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r | |
3815 | .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r | |
3816 | .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r | |
3817 | .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r | |
3818 | .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r | |
3819 | .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r | |
3820 | .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r | |
3821 | .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r | |
3822 | .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r | |
3823 | .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r | |
3824 | .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r | |
3825 | .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r | |
3826 | .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r | |
3827 | .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r | |
3828 | .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT | |
3829 | .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r | |
3830 | .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r | |
3831 | .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r | |
3832 | .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r | |
3833 | .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r | |
3834 | .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r | |
3835 | .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r | |
3836 | .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r | |
3837 | .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r | |
3838 | .dw (FETCH_B | OP_ADDA | STORE_A ) ; 80 ADD A,r | |
3839 | .dw (FETCH_C | OP_ADDA | STORE_A ) ; 81 ADD A,r | |
3840 | .dw (FETCH_D | OP_ADDA | STORE_A ) ; 82 ADD A,r | |
3841 | .dw (FETCH_E | OP_ADDA | STORE_A ) ; 83 ADD A,r | |
3842 | .dw (FETCH_H | OP_ADDA | STORE_A ) ; 84 ADD A,r | |
3843 | .dw (FETCH_L | OP_ADDA | STORE_A ) ; 85 ADD A,r | |
3844 | .dw (FETCH_MHL | OP_ADDA | STORE_A ) ; 86 ADD A,r | |
3845 | .dw (FETCH_A | OP_ADDA | STORE_A ) ; 87 ADD A,r | |
3846 | .dw (FETCH_B | OP_ADCA | STORE_A ) ; 88 ADC A,r | |
3847 | .dw (FETCH_C | OP_ADCA | STORE_A ) ; 89 ADC A,r | |
3848 | .dw (FETCH_D | OP_ADCA | STORE_A ) ; 8A ADC A,r | |
3849 | .dw (FETCH_E | OP_ADCA | STORE_A ) ; 8B ADC A,r | |
3850 | .dw (FETCH_H | OP_ADCA | STORE_A ) ; 8C ADC A,r | |
3851 | .dw (FETCH_L | OP_ADCA | STORE_A ) ; 8D ADC A,r | |
3852 | .dw (FETCH_MHL | OP_ADCA | STORE_A ) ; 8E ADC A,r | |
3853 | .dw (FETCH_A | OP_ADCA | STORE_A ) ; 8F ADC A,r | |
3854 | .dw (FETCH_B | OP_SUBFA | STORE_A ) ; 90 SUB A,r | |
3855 | .dw (FETCH_C | OP_SUBFA | STORE_A ) ; 91 SUB A,r | |
3856 | .dw (FETCH_D | OP_SUBFA | STORE_A ) ; 92 SUB A,r | |
3857 | .dw (FETCH_E | OP_SUBFA | STORE_A ) ; 93 SUB A,r | |
3858 | .dw (FETCH_H | OP_SUBFA | STORE_A ) ; 94 SUB A,r | |
3859 | .dw (FETCH_L | OP_SUBFA | STORE_A ) ; 95 SUB A,r | |
3860 | .dw (FETCH_MHL | OP_SUBFA | STORE_A ) ; 96 SUB A,r | |
3861 | .dw (FETCH_A | OP_SUBFA | STORE_A ) ; 97 SUB A,r | |
3862 | .dw (FETCH_B | OP_SBCFA | STORE_A ) ; 98 SBC A,r | |
3863 | .dw (FETCH_C | OP_SBCFA | STORE_A ) ; 99 SBC A,r | |
3864 | .dw (FETCH_D | OP_SBCFA | STORE_A ) ; 9A SBC A,r | |
3865 | .dw (FETCH_E | OP_SBCFA | STORE_A ) ; 9B SBC A,r | |
3866 | .dw (FETCH_H | OP_SBCFA | STORE_A ) ; 9C SBC A,r | |
3867 | .dw (FETCH_L | OP_SBCFA | STORE_A ) ; 9D SBC A,r | |
3868 | .dw (FETCH_MHL | OP_SBCFA | STORE_A ) ; 9E SBC A,r | |
3869 | .dw (FETCH_A | OP_SBCFA | STORE_A ) ; 9F SBC A,r | |
3870 | .dw (FETCH_B | OP_ANDA | STORE_A ) ; A0 AND A,r | |
3871 | .dw (FETCH_C | OP_ANDA | STORE_A ) ; A1 AND A,r | |
3872 | .dw (FETCH_D | OP_ANDA | STORE_A ) ; A2 AND A,r | |
3873 | .dw (FETCH_E | OP_ANDA | STORE_A ) ; A3 AND A,r | |
3874 | .dw (FETCH_H | OP_ANDA | STORE_A ) ; A4 AND A,r | |
3875 | .dw (FETCH_L | OP_ANDA | STORE_A ) ; A5 AND A,r | |
3876 | .dw (FETCH_MHL | OP_ANDA | STORE_A ) ; A6 AND A,r | |
3877 | .dw (FETCH_A | OP_ANDA | STORE_A ) ; A7 AND A,r | |
3878 | .dw (FETCH_B | OP_XORA | STORE_A ) ; A8 XOR A,r | |
3879 | .dw (FETCH_C | OP_XORA | STORE_A ) ; A9 XOR A,r | |
3880 | .dw (FETCH_D | OP_XORA | STORE_A ) ; AA XOR A,r | |
3881 | .dw (FETCH_E | OP_XORA | STORE_A ) ; AB XOR A,r | |
3882 | .dw (FETCH_H | OP_XORA | STORE_A ) ; AC XOR A,r | |
3883 | .dw (FETCH_L | OP_XORA | STORE_A ) ; AD XOR A,r | |
3884 | .dw (FETCH_MHL | OP_XORA | STORE_A ) ; AE XOR A,r | |
3885 | .dw (FETCH_A | OP_XORA | STORE_A ) ; AF XOR A,r | |
3886 | .dw (FETCH_B | OP_ORA | STORE_A ) ; B0 OR A,r | |
3887 | .dw (FETCH_C | OP_ORA | STORE_A ) ; B1 OR A,r | |
3888 | .dw (FETCH_D | OP_ORA | STORE_A ) ; B2 OR A,r | |
3889 | .dw (FETCH_E | OP_ORA | STORE_A ) ; B3 OR A,r | |
3890 | .dw (FETCH_H | OP_ORA | STORE_A ) ; B4 OR A,r | |
3891 | .dw (FETCH_L | OP_ORA | STORE_A ) ; B5 OR A,r | |
3892 | .dw (FETCH_MHL | OP_ORA | STORE_A ) ; B6 OR A,r | |
3893 | .dw (FETCH_A | OP_ORA | STORE_A ) ; B7 OR A,r | |
3894 | .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; B8 CP A,r | |
3895 | .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; B9 CP A,r | |
3896 | .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; BA CP A,r | |
3897 | .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; BB CP A,r | |
3898 | .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; BC CP A,r | |
3899 | .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; BD CP A,r | |
3900 | .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; BE CP A,r | |
3901 | .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; BF CP A,r | |
3902 | .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ | |
3903 | .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC | |
3904 | .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn | |
3905 | .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn | |
3906 | .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn | |
3907 | .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC | |
3908 | .dw (FETCH_DIR8 | OP_ADDA | STORE_A ) ; C6 nn ADD A,n | |
3909 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0 | |
3910 | .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z | |
3911 | .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET | |
3912 | .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn | |
3913 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific) | |
3914 | .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn | |
3915 | .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn | |
3916 | .dw (FETCH_DIR8 | OP_ADCA | STORE_A ) ; CE nn ADC A,n | |
3917 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H | |
3918 | .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC | |
3919 | .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE | |
3920 | .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn | |
3921 | .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A | |
3922 | .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn | |
3923 | .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE | |
3924 | .dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n | |
3925 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H | |
3926 | .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C | |
3927 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80) | |
3928 | .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn | |
3929 | .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n) | |
3930 | .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn | |
3931 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80) | |
3932 | .dw (FETCH_DIR8 | OP_SBCFA | STORE_A ) ; DE nn SBC A,n | |
3933 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H | |
3934 | .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO | |
3935 | .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL | |
3936 | .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn | |
3937 | .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL | |
3938 | .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn | |
3939 | .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL | |
3940 | .dw (FETCH_DIR8 | OP_ANDA | STORE_A ) ; E6 nn AND n | |
3941 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H | |
3942 | .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE | |
3943 | .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL) | |
3944 | .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn | |
3945 | .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL | |
3946 | .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn | |
3947 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific) | |
3948 | .dw (FETCH_DIR8 | OP_XORA | STORE_A ) ; EE nn XOR n | |
3949 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H | |
3950 | .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P | |
3951 | .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF | |
3952 | .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn | |
3953 | .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI | |
3954 | .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn | |
3955 | .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF | |
3956 | .dw (FETCH_DIR8 | OP_ORA | STORE_A ) ; F6 nn OR n | |
3957 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H | |
3958 | .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M | |
3959 | .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL | |
3960 | .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn | |
3961 | .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI | |
3962 | .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn | |
3963 | .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific) | |
3964 | .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n | |
3965 | .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H | |
3966 | ||
3967 | ; vim:set ts=8 noet nowrap | |
3968 |