some work on PSP CLUT
[picodrive.git] / cpu / a68k / make68kd.c
CommitLineData
cc68a136 1/*---------------------------------------------------------------\r
2 * Motorola 68000 32 Bit emulator\r
3 *\r
4 * Copyright 1998-2001 Mike Coates, All rights reserved\r
5 * Darren Olafson\r
6 *---------------------------------------------------------------\r
7 *\r
8 * Thanks to ...\r
9 *\r
10 * Neil Bradley (lots of optimisation help & ideas)\r
11 *\r
12 *---------------------------------------------------------------\r
13 * History (so we know what bugs have been fixed)\r
14 *\r
15 * 02.11.98 MJC - CMPM bug, overwriting first value\r
16 * 04.11.98 MJC - Debug timing - same as C core\r
17 * save PC on calls to C memory routines\r
18 * 05.11.98 NS - Re-insert changes to make work on OS/2\r
19 * 06.11.98 MJC - Flags saved on ADDA commands\r
20 * X set on ADD commands\r
21 * 23.11.98 MJC - Alternate Memory Read/Write for non DOS ports\r
22 * 24.11.98 CK - Add WIN32 specific stuff\r
23 * 25.11.98 DEO - ABCD Size not initialised\r
24 * 21.12.98 MJC - Change register saving on Memory Banking\r
25 * 13.01.99 M/D - Change to new C core disassembler\r
26 * 19.01.99 MJC - Proper? support for new Interrupt System\r
27 * 17.02.99 MJC - TRACE68K define added\r
28 * ABCD,SBCD not keeping Z flag\r
29 * JMP, JSR for some EA combo's damaging flags\r
30 * DIVU - Overflow not being set correctly\r
31 * ASL/ASR - Flag Handling now correct\r
32 * some minor optimisations\r
33 * 13.03.99 DEO - Added new cycle timing\r
34 * 24.03.99 MJC - TRACE68K define removed\r
35 * NEW INTERRUPT SYSTEM only\r
36 * interrupt check sped up (when not taken)\r
37 * STOP checks for interrupt\r
38 * 01.04.99 MJC - OS2 specifics added\r
39 * MOVEM reference point moved\r
40 * Data and Address register mode combined for :-\r
41 * movecodes\r
42 * dumpx\r
43 * 04.05.99 MJC - Add Previous PC support to MOVE.B #X,XXXXXX.L (F1 Dream)\r
44 * ABCD/SBCD could corrupt zero flag\r
45 * DIVS/DIVU overflow should not update register\r
46 * 22.05.99 MJC - Complete support of Previous PC on C calls\r
47 * Some optional bits now selected by DEFINES\r
48 * 27.05.99 MJC - Interrupt system changed\r
49 * 28.05.99 MJC - Use DEFINES in more places\r
50 * Interrupt check running one opcode when taken\r
51 * 16.07.99 MJC - Reset - Preload next opcode / external call\r
52 * 68010 commands almost complete\r
53 * more compression on jump table (16k smaller)\r
54 * Some optimising\r
55 * shl reg,1 -> add reg,reg\r
56 * or ecx,ecx:jz -> jecxz\r
57 * 22.08.99 DEO - SBCD/ABCD sets N flag same as carry\r
58 * 19.10.99 MJC - Change DOS memory routines\r
59 * Change DOS Clobber flags (ESI no longer safe)\r
60 * Save EAX around memory write where needed\r
61 * bit commands optimised\r
62 * 25.10.99 MJC - Was keeping masked register on read/write\r
63 * if register was preserved over call\r
64 * ESI assumed 'safe' again\r
65 * 25.10.99 MJC - Bank ID moved to CPU context\r
66 * 03.11.99 KENJO - VC++6.0 seems not to preserve EDI. Fixed "ABCD -(A0), -(A0)" crash / "roxr (A0)"-type shift crash\r
67 * 13.11.99 KENJO - Fixed "NABC"\r
68 * Now Win32 uses FASTCALL type call for interrupt callback\r
69 * 09.02.00 MJC - Check CPU type before allowing 68010/68020 instructions\r
70 * remove routines for 5 non existant opcodes\r
71 * 05.03.00 MJC - not command decrement A7 by 1 for bytes\r
72 * 10.03.00 MJC - as did btst,cmpm and nbcd\r
73 * 22.03.00 MJC - Divide by zero should not decrement PC by 2 before push\r
74 * Move memory banking into exception routine\r
75 * 14.04.00 Dave - BTST missing Opcode\r
76 * ASL.L > 31 shift\r
77 * 20.04.00 MJC - TST.B Also missing A7 specific routine\r
78 * - Extra Define A7ROUTINE to switch between having seperate\r
79 * routines for +-(A7) address modes.\r
80 * 24.06.00 MJC - ADDX/SUBX +-(A7) routines added.\r
81 * TAS should not touch X flag\r
82 * LSL/LSR EA not clearing V flag\r
83 * CHK not all opcodes in jump table\r
84 * Add define to mask status register\r
85 * 04.07.00 MJC - Keep high byte of Program Counter on Bxx and Jxx\r
86 * Fix flag handling on NEGX\r
87 * Really fix ADDX/SUBX +-(A7)\r
88 * PC could be set wrong after CHK.W instruction\r
89 * DIVS/DIVU always clear C flag\r
90 * ABCD/SBCD missing +-(A7) Routine\r
91 * TAS missing +-(A7) Routine\r
92 * Bitwise Static missing +-(A7) Routine\r
93 * CMPM missing +-(A7) Routine\r
94 * 30.09.00 DEO - added mull, divl, bfextu\r
95 * added '020 addressing modes\r
96 * fixed $6xff branching\r
97 * 23.01.01 MJC - Spits out seperate code for 68000 & 68020\r
98 * allows seperate optimising!\r
99 * 17.02.01 MJC - Support for encrypted PC relative fetch calls\r
100 * 11.03.01 GUTI - change some cmp reg,0 and or reg,reg with test\r
101 * 13.03.01 MJC - Single Icount for Asm & C cores\r
102 * 16.05.01 ASG - use push/pop around mem calls instead of store to safe_REG\r
103 * optimized a bit the 020 extension word decoder\r
104 * removed lots of unnecessary code in branches\r
105 *---------------------------------------------------------------\r
106 * Known Problems / Bugs\r
107 *\r
108 * 68000\r
109 * None - Let us know if you find any!\r
110 *\r
111 * 68010\r
112 * Instructions that are supervisor only as per 68000 spec.\r
113 * move address space not implemented.\r
114 *\r
115 * 68020\r
116 * only long Bcc instruction implemented.\r
117 *---------------------------------------------------------------\r
118 * Notes\r
119 *\r
120 * STALLCHECK should be defined for Pentium Class\r
121 * undefined for P2/Celerons\r
122 *\r
123 * ALIGNMENT is normally 4, but seems faster on my P2 as 0 !\r
124 *\r
125 *---------------------------------------------------------------\r
126 *\r
127 * Future Changes\r
128 *\r
129 * 68020 instructions to be completed\r
130 * assembler memory routines +\r
131 *\r
132 * and anything else that takes our fancy!\r
133 *---------------------------------------------------------------*/\r
134\r
135/* Specials - Switch what program allows/disallows */\r
136\r
137#undef STALLCHECK /* Affects fetching of Opcode */\r
138#undef SAVEPPC /* Save Previous PC */ // dave \r
139#define ENCRYPTED /* PC relative = decrypted */\r
140#define ASMBANK /* Memory banking algorithm to use */ // dave\r
141#define A7ROUTINE /* Define to use separate routines for -(a7)/(a7)+ */\r
142#define ALIGNMENT 4 /* Alignment to use for branches */\r
143#undef MASKCCR /* Mask the status register to filter out unused bits */\r
144#define KEEPHIGHPC /* Keep or Ignore bits 24-31 */\r
145#define QUICKZERO /* selects XOR r,r or MOV r,0 */\r
146\r
147#include <stdio.h>\r
148#include <stdlib.h>\r
149#include <string.h>\r
150#include <assert.h>\r
151\r
152/* New Disassembler */\r
153\r
154char * codebuf;\r
155int DisOp;\r
156\r
157#define cpu_readmem24bew(addr) (0)\r
158#define cpu_readmem24bew_word(addr) (DisOp)\r
159\r
160#define MEMORY_H /* so memory.h will not be included... */\r
161/*\r
162#include "d68k.c"\r
163*/\r
164#undef MEMORY_H\r
165\r
166#undef cpu_readmem24bew\r
167#undef cpu_readmem24bew_word\r
168\r
169#include "cpuintrf.h"\r
170\r
171/*\r
172 * Defines used by Program\r
173 *\r
174 */\r
175\r
176#define VERSION "0.30"\r
177\r
178#define TRUE -1\r
179#define FALSE 0\r
180\r
181#define EAX 0\r
182#define EBX 1\r
183#define ECX 2\r
184#define EDX 3\r
185#define ESI 4\r
186#define PC ESI\r
187#define EDI 5\r
188#define EBP 6\r
189\r
190\r
191#define NORMAL 0\r
192#define PCREL 1\r
193\r
194/* Register Location Offsets */\r
195\r
196#define ICOUNT "_m68k_ICount"\r
197\r
198#define REG_DAT "R_D0"\r
199#define REG_DAT_EBX "[R_D0+ebx*4]"\r
200#define REG_ADD "R_A0"\r
201#define REG_A7 "R_A7"\r
202#define REG_USP "R_USP"\r
203#define REG_ISP "R_ISP"\r
204#define REG_SRH "R_SR_H"\r
205#define REG_CCR "R_CCR"\r
206#define REG_X "R_XC"\r
207#define REG_PC "R_PC"\r
208#define REG_IRQ "R_IRQ"\r
209#define REG_S "R_SR"\r
210#define REG_IRQ_CALLBACK "R_IRQ_CALLBACK"\r
211#define REG_RESET_CALLBACK "R_RESET_CALLBACK"\r
212\r
213\r
214/* 68010 Regs */\r
215\r
216#define REG_VBR "R_VBR"\r
217#define REG_SFC "R_SFC"\r
218#define REG_DFC "R_DFC"\r
219\r
220#define FASTCALL_FIRST_REG "ecx"\r
221#define FASTCALL_SECOND_REG "edx"\r
222\r
223\r
224\r
225/*\r
226 * Global Variables\r
227 *\r
228 */\r
229\r
230FILE *fp = NULL;\r
231\r
232char *comptab = NULL;\r
233char *CPUtype = NULL;\r
234\r
235int CPU = 0;\r
236int FlagProcess = 0;\r
237int CheckInterrupt = 0;\r
238int ExternalIO = 0;\r
239int Opcount = 0;\r
240int TimingCycles = 0;\r
241int AddEACycles = 0;\r
242int AccessType = NORMAL;\r
243int ppro = 0;\r
244\r
245\r
246\r
247/* External register preservation */\r
248\r
249#ifdef DOS\r
250\r
251/* Registers normally saved around C routines anyway */\r
252/* GCC 2.9.1 (dos) seems to preserve EBX,EDI and EBP */\r
253static char SavedRegs[] = "-B--SDB";\r
254\r
255#elif defined(WIN32)\r
256\r
257/* visual C++, win32, says it preserves ebx, edi, esi, and ebp */\r
258/* ---------- VC++ deosn't preserve EDI? (Kenjo, 110399) ---------- */\r
259static char SavedRegs[] = "-B--S-B";\r
260\r
261#else\r
262\r
263/* Assume nothing preserved */\r
264static char SavedRegs[] = "-------";\r
265\r
266#endif\r
267\r
268\r
269\r
270/* Jump Table */\r
271\r
272int OpcodeArray[65536];\r
273\r
274/* Lookup Arrays */\r
275\r
276static char* regnameslong[] =\r
277{ "EAX","EBX","ECX","EDX","ESI","EDI","EBP"};\r
278\r
279static char* regnamesword[] =\r
280{ "AX","BX","CX","DX", "SI", "DI", "BP"};\r
281\r
282static char* regnamesshort[] =\r
283{ "AL","BL","CL","DL"};\r
284\r
285\r
286\r
287/*********************************/\r
288/* Conversion / Utility Routines */\r
289/*********************************/\r
290\r
291/* Convert EA to Address Mode Number\r
292 *\r
293 * 0 Dn\r
294 * 1 An\r
295 * 2 (An)\r
296 * 3 (An)+\r
297 * 4 -(An)\r
298 * 5 x(An)\r
299 * 6 x(An,xr.s)\r
300 * 7 x.w\r
301 * 8 x.l\r
302 * 9 x(PC)\r
303 * 10 x(PC,xr.s)\r
304 * 11 #x,SR,CCR Read = Immediate, Write = SR or CCR\r
305 * in order to read SR to AX, use READCCR\r
306 * 12-15 INVALID\r
307 *\r
308 * 19 (A7)+\r
309 * 20 -(A7)\r
310 *\r
311 */\r
312\r
313int EAtoAMN(int EA, int Way)\r
314{\r
315 int Work;\r
316\r
317 if (Way)\r
318 {\r
319 Work = (EA & 0x7);\r
320\r
321 if (Work == 7) Work += ((EA & 0x38) >> 3);\r
322\r
323 if (((Work == 3) || (Work == 4)) && (((EA & 0x38) >> 3) == 7))\r
324 {\r
325 Work += 16;\r
326 }\r
327 }\r
328 else\r
329 {\r
330 Work = (EA & 0x38) >> 3;\r
331\r
332 if (Work == 7) Work += (EA & 7);\r
333\r
334 if (((Work == 3) || (Work == 4)) && ((EA & 7) == 7))\r
335 {\r
336 Work += 16;\r
337 }\r
338 }\r
339\r
340 return Work;\r
341}\r
342\r
343/*\r
344 * Generate Main or Sub label\r
345 */\r
346\r
347char *GenerateLabel(int ID,int Type)\r
348{\r
349 static int LabID,LabNum;\r
350/*\r
351 static char disasm[80];\r
352 char *dis = disasm;\r
353*/\r
354 if (Type == 0)\r
355 {\r
356 CheckInterrupt=0; /* No need to check for Interrupts */\r
357 ExternalIO=0; /* Not left Assembler Yet */\r
358 TimingCycles=0; /* No timing info for this command */\r
359 AddEACycles=1; /* default to add in EA timing */\r
360 Opcount++; /* for screen display */\r
361\r
362 DisOp = ID;\r
363/*\r
364 m68k_disassemble(dis,0);\r
365 sprintf(codebuf, "OP%d_%4.4x:\t\t\t\t; %s", CPU,ID, dis);\r
366*/\r
367 sprintf(codebuf, "OP%d_%4.4x:\t\t\t\t;", CPU,ID);\r
368\r
369 LabID = ID;\r
370 LabNum = 0;\r
371 }\r
372 else\r
373 {\r
374 LabNum++;\r
375 sprintf(codebuf, "OP%d_%4.4x_%1x", CPU,LabID, LabNum);\r
376 }\r
377\r
378 return codebuf;\r
379}\r
380\r
381/*\r
382 * Generate Alignment Line\r
383 */\r
384\r
385void Align(void)\r
386{\r
387 fprintf(fp, "\t\t ALIGN %d\n\n",ALIGNMENT);\r
388}\r
389\r
390/*\r
391 * Copy X into Carry\r
392 *\r
393 * There are several ways this could be done, this allows\r
394 * us to easily change the way we are doing it!\r
395 */\r
396\r
397void CopyX(void)\r
398{\r
399 /* Copy bit 0 from X flag store into Carry */\r
400\r
401 fprintf(fp, "\t\t bt dword [%s],0\n",REG_X);\r
402}\r
403\r
404/*\r
405 * Immediate 3 bit data\r
406 *\r
407 * 0=8, anything else is itself\r
408 *\r
409 * Again, several ways to achieve this\r
410 *\r
411 * ECX contains data as 3 lowest bits\r
412 *\r
413 */\r
414\r
415void ClearRegister(int regno)\r
416{\r
417#ifdef QUICKZERO\r
418 fprintf(fp, "\t\t mov %s,0\n",regnameslong[regno]);\r
419#else\r
420 fprintf(fp, "\t\t xor %s,%s\n",regnameslong[regno],regnameslong[regno]);\r
421#endif\r
422}\r
423\r
424void Immediate8(void)\r
425{\r
426 /* This takes 3 cycles, 5 bytes, no memory reads */\r
427\r
428 fprintf(fp, "\t\t dec ecx ; Move range down\n");\r
429 fprintf(fp, "\t\t and ecx,byte 7 ; Mask out lower bits\n");\r
430 fprintf(fp, "\t\t inc ecx ; correct range\n");\r
431\r
432\r
433 /* This takes 2 cycles, 10 bytes but has a memory read */\r
434 /* I don't know timing for the mov command - assumed 1 */\r
435\r
436#if 0\r
437 fprintf(fp, "\t\t and ecx,byte 7\n");\r
438 fprintf(fp, "\t\t mov ecx,[ImmTable+ECX*4]\n");\r
439#endif\r
440}\r
441\r
442/*\r
443 * This will check for bank changes before\r
444 * resorting to calling the C bank select code\r
445 *\r
446 * Most of the time it does not change!\r
447 *\r
448 */\r
449\r
450/* forward used by MemoryBanking */\r
451void Exception(int Number, int BaseCode) ;\r
452\r
453void MemoryBanking(int BaseCode)\r
454{\r
455 /* check for odd address */\r
456 fprintf(fp, "\t\t test esi, dword 1\n");\r
457 fprintf(fp, "\t\t jz near OP%d_%5.5x\n",CPU,BaseCode);\r
458\r
459 /* trying to run at an odd address */\r
460 Exception(3,BaseCode);\r
461\r
462 /* Keep Whole PC */\r
463\r
464 fprintf(fp, "OP%d_%5.5x:\n",CPU,BaseCode);\r
465\r
466/* ASG - always call to the changepc subroutine now, since the number of */\r
467/* bits varies based on the memory model */\r
468#ifdef KEEPHIGHPC\r
469 fprintf(fp, "\t\t mov [FullPC],ESI\n");\r
470#endif\r
471\r
472 /* Mask to n bits */\r
473 fprintf(fp, "\t\t and esi,[_mem_amask]\n");\r
474\r
475#if 0\r
476#ifdef KEEPHIGHPC\r
477 fprintf(fp, "\t\t mov [FullPC],ESI\n");\r
478#endif\r
479\r
480 /* Mask to 24 bits */\r
481// fprintf(fp, "\t\t and esi,0ffffffh\n");\r
482\r
483#ifdef ASMBANK\r
484 /* Assembler bank switch - 64k granularity */\r
485\r
486 fprintf(fp, "\t\t mov eax,esi\n");\r
487 fprintf(fp, "\t\t shr eax,16\n");\r
488 fprintf(fp, "\t\t cmp [asmbank],eax\n");\r
489 fprintf(fp, "\t\t je OP%d_%5.5x_Bank\n",CPU,BaseCode);\r
490\r
491 fprintf(fp, "\t\t mov [asmbank],eax\n");\r
492#else\r
493 /* This code is same as macro used by C core */\r
494\r
495 fprintf(fp, "\t\t mov ecx,esi\n");\r
496 fprintf(fp, "\t\t mov ebx,[_cur_mrhard]\n");\r
497 fprintf(fp, "\t\t shr ecx,9\n");\r
498 fprintf(fp, "\t\t mov al,byte [_opcode_entry]\n");\r
499 fprintf(fp, "\t\t cmp al,[ecx+ebx]\n");\r
500 fprintf(fp, "\t\t je OP%d_%5.5x_Bank\n",CPU,BaseCode);\r
501#endif\r
502#endif\r
503\r
504 /* Call Banking Routine */\r
505\r
506 if (SavedRegs[ESI] == '-')\r
507 {\r
508 fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC);\r
509 }\r
510\r
511 if (SavedRegs[EDX] == '-')\r
512 {\r
513 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
514 }\r
515\r
516#ifdef FASTCALL\r
517 fprintf(fp, "\t\t mov %s,esi\n",FASTCALL_FIRST_REG);\r
518#else\r
519 fprintf(fp, "\t\t push esi\n");\r
520#endif\r
521\r
522 fprintf(fp, "\t\t call [_a68k_memory_intf+28]\n");\r
523\r
524#ifndef FASTCALL\r
525 fprintf(fp, "\t\t lea esp,[esp+4]\n");\r
526#endif\r
527\r
528 if (SavedRegs[EDX] == '-')\r
529 {\r
530 fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR);\r
531 }\r
532\r
533 if (SavedRegs[ESI] == '-')\r
534 {\r
535 fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC);\r
536 }\r
537\r
538 /* Update our copy */\r
539\r
540 fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n");\r
541\r
542 fprintf(fp, "OP%d_%5.5x_Bank:\n",CPU,BaseCode);\r
543}\r
544\r
545/*\r
546 * Update Previous PC value\r
547 *\r
548 */\r
549\r
550void SavePreviousPC(void)\r
551{\r
552#ifdef SAVEPPC\r
553 fprintf(fp, "\t\t mov [R_PPC],esi\t\t\t ; Keep Previous PC\n");\r
554#endif\r
555}\r
556\r
557/*\r
558 * Complete Opcode handling\r
559 *\r
560 * Any tidying up, end code\r
561 *\r
562 */\r
563\r
564void Completed(void)\r
565{\r
566\r
567 /* Flag Processing to be finished off ? */\r
568\r
569 AccessType = NORMAL;\r
570\r
571 /* Use assembler timing routines */\r
572\r
573 if (TimingCycles != 0)\r
574 {\r
575 if (TimingCycles > 127)\r
576 fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,TimingCycles);\r
577 else\r
578 {\r
579 if (TimingCycles != -1)\r
580 fprintf(fp, "\t\t sub dword [%s],byte %d\n",ICOUNT,TimingCycles);\r
581 }\r
582 \r
583 if (FlagProcess > 0)\r
584 fprintf(fp, "\t\t pop EDX\n");\r
585 if (FlagProcess == 2)\r
586 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
587\r
588 fprintf(fp, "\t\t js near MainExit\n\n");\r
589 }\r
590 else\r
591 {\r
592 fprintf(fp, "\t\t test dword [%s],0xffffffff\n",ICOUNT);\r
593 \r
594 if (FlagProcess > 0)\r
595 fprintf(fp, "\t\t pop EDX\n");\r
596 if (FlagProcess == 2)\r
597 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
598\r
599 fprintf(fp, "\t\t jle near MainExit\n\n");\r
600 }\r
601 FlagProcess = 0;\r
602\r
603#ifdef MAME_DEBUG\r
604\r
605 /* Check for Debug Active */\r
606\r
607 fprintf(fp, "\n\t\t test byte [_mame_debug],byte 0xff\n");\r
608 fprintf(fp, "\t\t jnz near MainExit\n\n");\r
609\r
610#endif\r
611\r
612 if (CheckInterrupt)\r
613 {\r
614 fprintf(fp,"; Check for Interrupt waiting\n\n");\r
615 fprintf(fp,"\t\t test byte [%s],07H\n",REG_IRQ);\r
616 fprintf(fp,"\t\t jne near interrupt\n\n");\r
617 }\r
618\r
619 if(CPU==2)\r
620 {\r
621 /* 32 bit memory version */\r
622 fprintf(fp, "\t\t mov eax,2\n"); /* ASG */\r
623 fprintf(fp, "\t\t xor eax,esi\n"); /* ASG */\r
624\r
625#ifdef STALLCHECK\r
626 ClearRegister(ECX);\r
627 fprintf(fp, "\t\t mov cx,[eax+ebp]\n");\r
628#else\r
629 fprintf(fp, "\t\t movzx ecx,word [eax+ebp]\n");\r
630#endif\r
631 }\r
632 else\r
633 {\r
634 /* 16 bit memory */\r
635#ifdef STALLCHECK\r
636 ClearRegister(ECX);\r
637 fprintf(fp, "\t\t mov cx,[esi+ebp]\n");\r
638#else\r
639 fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n");\r
640#endif\r
641 }\r
642\r
643 fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n\n", CPUtype);\r
644}\r
645\r
646/*\r
647 * Flag Routines\r
648 *\r
649 * Size = B,W or L\r
650 * Sreg = Register to Test\r
651 * TestReg = Need to test register (false if flags already set up)\r
652 * SetX = if C needs to be copied across to X register\r
653 * Delayed = Delays final processing to end of routine (Completed())\r
654 *\r
655 */\r
656\r
657void TestFlags(char Size,int Sreg)\r
658{\r
659 char* Regname="";\r
660\r
661 switch (Size)\r
662 {\r
663 case 66:\r
664 Regname = regnamesshort[Sreg];\r
665 break;\r
666\r
667 case 87:\r
668 Regname = regnamesword[Sreg];\r
669 break;\r
670\r
671 case 76:\r
672 Regname = regnameslong[Sreg];\r
673 break;\r
674 }\r
675\r
676 /* Test does not update register */\r
677 /* so cannot generate partial stall */\r
678\r
679 fprintf(fp, "\t\t test %s,%s\n",Regname,Regname);\r
680}\r
681\r
682void SetFlags(char Size,int Sreg,int Testreg,int SetX,int Delayed)\r
683{\r
684 if (Testreg) TestFlags(Size,Sreg);\r
685\r
686 fprintf(fp, "\t\t pushfd\n");\r
687\r
688 if (Delayed)\r
689 {\r
690 /* Rest of code done by Completed routine */\r
691\r
692 if (SetX) FlagProcess = 2;\r
693 else FlagProcess = 1;\r
694 }\r
695 else\r
696 {\r
697 fprintf(fp, "\t\t pop EDX\n");\r
698\r
699 if (SetX) fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
700 }\r
701}\r
702\r
703/******************/\r
704/* Check CPU Type */\r
705/******************/\r
706\r
707void CheckCPUtype(int Minimum)\r
708{\r
709 if(CPU==2)\r
710 {\r
711 /* Only check for > 020 */\r
712\r
713 if(Minimum>2)\r
714 {\r
715 fprintf(fp, "\t\t mov eax,[CPUversion]\n");\r
716\r
717 fprintf(fp, "\t\t cmp al,%d\n",Minimum);\r
718 fprintf(fp, "\t\t jb near ILLEGAL\n\n");\r
719 }\r
720 }\r
721 else\r
722 {\r
723 fprintf(fp, "\t\t mov eax,[CPUversion]\n");\r
724\r
725 if (Minimum == 1)\r
726 {\r
727 fprintf(fp, "\t\t test eax,eax\n");\r
728 fprintf(fp, "\t\t jz near ILLEGAL\n\n");\r
729 }\r
730 else\r
731 {\r
732 fprintf(fp, "\t\t cmp al,%d\n",Minimum);\r
733 fprintf(fp, "\t\t jb near ILLEGAL\n\n");\r
734 }\r
735 }\r
736}\r
737\r
738/************************************/\r
739/* Pre-increment and Post-Decrement */\r
740/************************************/\r
741\r
742void IncrementEDI(int Size,int Rreg)\r
743{\r
744 switch (Size)\r
745 {\r
746 case 66:\r
747\r
748#ifdef A7ROUTINE\r
749\r
750 /* Always does Byte Increment - A7 uses special routine */\r
751\r
752 fprintf(fp, "\t\t inc dword [%s+%s*4]\n",REG_ADD,regnameslong[Rreg]);\r
753\r
754#else\r
755\r
756 /* A7 uses same routines, so inc by 2 if A7 */\r
757\r
758 fprintf(fp, "\t\t cmp %s,7\n",regnamesshort[Rreg]);\r
759 fprintf(fp, "\t\t cmc\n");\r
760 fprintf(fp, "\t\t adc dword [%s+%s*4],byte 1\n",REG_ADD,regnameslong[Rreg]);\r
761\r
762#endif\r
763 break;\r
764\r
765 case 87:\r
766\r
767 fprintf(fp, "\t\t add dword [%s+%s*4],byte 2\n",REG_ADD,regnameslong[Rreg]);\r
768 break;\r
769\r
770 case 76:\r
771\r
772 fprintf(fp, "\t\t add dword [%s+%s*4],byte 4\n",REG_ADD,regnameslong[Rreg]);\r
773 break;\r
774 }\r
775}\r
776\r
777void DecrementEDI(int Size,int Rreg)\r
778{\r
779 switch (Size)\r
780 {\r
781 case 66:\r
782\r
783#ifdef A7ROUTINE\r
784\r
785 /* Always does Byte Increment - A7 uses special routine */\r
786\r
787 fprintf(fp, "\t\t dec EDI\n");\r
788\r
789#else\r
790\r
791 /* A7 uses same routines, so dec by 2 if A7 */\r
792\r
793 fprintf(fp, "\t\t cmp %s,7\n",regnamesshort[Rreg]);\r
794 fprintf(fp, "\t\t cmc\n");\r
795 fprintf(fp, "\t\t sbb dword edi,byte 1\n");\r
796\r
797#endif\r
798 break;\r
799\r
800 case 87:\r
801\r
802 fprintf(fp, "\t\t sub EDI,byte 2\n");\r
803 break;\r
804\r
805 case 76:\r
806 fprintf(fp, "\t\t sub EDI,byte 4\n");\r
807 break;\r
808 }\r
809}\r
810\r
811/*\r
812 * Generate an exception\r
813 *\r
814 * if Number = -1 then assume value in AL already\r
815 * code must continue running afterwards\r
816 *\r
817 */\r
818\r
819void Exception(int Number, int BaseCode)\r
820{\r
821 if (Number > -1)\r
822 {\r
823 fprintf(fp, "\t\t sub esi,byte 2\n");\r
824 fprintf(fp, "\t\t mov al,%d\n",Number);\r
825 }\r
826\r
827 fprintf(fp, "\t\t call Exception\n\n");\r
828\r
829 if (Number > -1)\r
830 Completed();\r
831}\r
832\r
833\r
834/********************/\r
835/* Address Routines */\r
836/********************/\r
837\r
838/*\r
839 * Decode Intel flags into AX as SR register\r
840 *\r
841 * Wreg = spare register to use (must not be EAX or EDX)\r
842 */\r
843\r
844void ReadCCR(char Size, int Wreg)\r
845{\r
846 fprintf(fp, "\t\t mov eax,edx\n");\r
847 fprintf(fp, "\t\t mov ah,byte [%s]\n",REG_X);\r
848\r
849 /* Partial stall so .. switch to new bit of processing */\r
850\r
851 fprintf(fp, "\t\t mov %s,edx\n",regnameslong[Wreg]);\r
852 fprintf(fp, "\t\t and %s,byte 1\n",regnameslong[Wreg]);\r
853\r
854 /* Finish what we started */\r
855\r
856 fprintf(fp, "\t\t shr eax,4\n");\r
857 fprintf(fp, "\t\t and eax,byte 01Ch \t\t; X, N & Z\n\n");\r
858\r
859 /* and complete second task */\r
860\r
861 fprintf(fp, "\t\t or eax,%s \t\t\t\t; C\n\n",regnameslong[Wreg]);\r
862\r
863 /* and Finally */\r
864\r
865 fprintf(fp, "\t\t mov %s,edx\n",regnameslong[Wreg]);\r
866 fprintf(fp, "\t\t shr %s,10\n",regnameslong[Wreg]);\r
867 fprintf(fp, "\t\t and %s,byte 2\n",regnameslong[Wreg]);\r
868 fprintf(fp, "\t\t or eax,%s\t\t\t\t; O\n\n",regnameslong[Wreg]);\r
869\r
870 if (Size == 'W')\r
871 {\r
872 fprintf(fp, "\t\t mov ah,byte [%s] \t; T, S & I\n\n",REG_SRH);\r
873\r
874#ifdef MASKCCR\r
875 fprintf(fp, "\t\t and ax,0A71Fh\t; Mask unused bits\n");\r
876#endif\r
877 }\r
878}\r
879\r
880/*\r
881 * Convert SR into Intel flags\r
882 *\r
883 * Also handles change of mode from Supervisor to User\r
884 *\r
885 * n.b. This is also called by EffectiveAddressWrite\r
886 */\r
887\r
888void WriteCCR(char Size)\r
889{\r
890 if (Size == 'W')\r
891 {\r
892 /* Did we change from Supervisor to User mode ? */\r
893\r
894 char *Label = GenerateLabel(0,1);\r
895\r
896 fprintf(fp, "\t\t test ah,20h \t\t\t; User Mode ?\n");\r
897 fprintf(fp, "\t\t jne short %s\n\n",Label);\r
898\r
899 /* Mode Switch - Update A7 */\r
900\r
901 fprintf(fp, "\t\t mov edx,[%s]\n",REG_A7);\r
902 fprintf(fp, "\t\t mov [%s],edx\n",REG_ISP);\r
903 fprintf(fp, "\t\t mov edx,[%s]\n",REG_USP);\r
904 fprintf(fp, "\t\t mov [%s],edx\n",REG_A7);\r
905\r
906 fprintf(fp, "%s:\n",Label);\r
907 fprintf(fp, "\t\t mov byte [%s],ah \t;T, S & I\n",REG_SRH);\r
908\r
909 /* Mask may now allow Interrupt */\r
910\r
911 CheckInterrupt += 1;\r
912 }\r
913\r
914 /* Flags */\r
915\r
916 fprintf(fp, "\t\t and eax,byte 1Fh\n");\r
917 fprintf(fp, "\t\t mov edx,[IntelFlag+eax*4]\n");\r
918 fprintf(fp, "\t\t mov [%s],dh\n",REG_X);\r
919 fprintf(fp, "\t\t and edx,0EFFh\n");\r
920}\r
921\r
922\r
923/*\r
924 * Interface to Mame memory commands\r
925 *\r
926 * Flags = "ABCDSDB" - set to '-' if not required to preserve\r
927 * (order EAX,EBX,ECX,EDX,ESI,EDI,EBP)\r
928 *\r
929 * AReg = Register containing Address\r
930 *\r
931 * Mask 0 : No Masking\r
932 * 1 : Mask top byte, but preserve register\r
933 * 2 : Mask top byte, preserve masked register\r
934 */\r
935\r
936void Memory_Read(char Size,int AReg,char *Flags,int Mask)\r
937{\r
938 ExternalIO = 1;\r
939\r
940 /* Save PC */\r
941\r
942 fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC);\r
943\r
944 /* Check for special mask condition */\r
945\r
946 /* ASG - no longer need to mask addresses here */\r
947/* if (Mask == 2)\r
948 fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/\r
949\r
950 /* Check to see if registers need saving */\r
951\r
952 if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-'))\r
953 {\r
954 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
955 }\r
956\r
957 if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-'))\r
958 {\r
959 fprintf(fp, "\t\t push EBX\n");\r
960 }\r
961\r
962 if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-'))\r
963 {\r
964 fprintf(fp, "\t\t push ECX\n");\r
965 }\r
966\r
967 if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-'))\r
968 {\r
969 fprintf(fp, "\t\t push EDI\n");\r
970 }\r
971\r
972 /* Sort Address out */\r
973\r
974#ifdef FASTCALL\r
975\r
976 fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_FIRST_REG,regnameslong[AReg]);\r
977\r
978 /* ASG - no longer need to mask addresses here */\r
979/* if (Mask == 1)\r
980 fprintf(fp, "\t\t and %s,0FFFFFFh\n",FASTCALL_FIRST_REG);*/\r
981\r
982#else\r
983\r
984 if (Mask == 1)\r
985 {\r
986 if ((Flags[AReg] != '-') && (SavedRegs[AReg] != '-'))\r
987 {\r
988 /* Don't trash a wanted safe register */\r
989\r
990 fprintf(fp, "\t\t mov EAX,%s\n",regnameslong[AReg]);\r
991 /* ASG - no longer need to mask addresses here */\r
992/* fprintf(fp, "\t\t and EAX,0FFFFFFh\n");*/\r
993 fprintf(fp, "\t\t push EAX\n");\r
994 }\r
995 else\r
996 {\r
997 /* ASG - no longer need to mask addresses here */\r
998/* fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/\r
999 fprintf(fp, "\t\t push %s\n",regnameslong[AReg]);\r
1000 }\r
1001 }\r
1002 else\r
1003 fprintf(fp, "\t\t push %s\n",regnameslong[AReg]);\r
1004\r
1005#endif\r
1006\r
1007\r
1008\r
1009 /* Call Mame memory routine */\r
1010\r
1011 /* ASG - changed these to call through the function pointers */\r
1012\r
1013#ifdef ENCRYPTED\r
1014 switch (AccessType)\r
1015 {\r
1016 case NORMAL :\r
1017 switch (Size)\r
1018 {\r
1019 case 66 :\r
1020 fprintf(fp, "\t\t call [_a68k_memory_intf+4]\n");\r
1021 break;\r
1022\r
1023 case 87 :\r
1024 fprintf(fp, "\t\t call [_a68k_memory_intf+8]\n");\r
1025 break;\r
1026\r
1027 case 76 :\r
1028 fprintf(fp, "\t\t call [_a68k_memory_intf+12]\n");\r
1029 break;\r
1030 }\r
1031 break;\r
1032\r
1033 case PCREL :\r
1034\r
1035 switch (Size)\r
1036 {\r
1037 case 66 :\r
1038 fprintf(fp, "\t\t call [_a68k_memory_intf+32]\n");\r
1039 break;\r
1040\r
1041 case 87 :\r
1042 fprintf(fp, "\t\t call [_a68k_memory_intf+36]\n");\r
1043 break;\r
1044\r
1045 case 76 :\r
1046 fprintf(fp, "\t\t call [_a68k_memory_intf+40]\n");\r
1047 break;\r
1048 }\r
1049 break;\r
1050 }\r
1051\r
1052// AccessType = NORMAL;\r
1053\r
1054#else\r
1055\r
1056 switch (Size)\r
1057 {\r
1058 case 66 :\r
1059 fprintf(fp, "\t\t call [_a68k_memory_intf+4]\n");\r
1060 break;\r
1061\r
1062 case 87 :\r
1063 fprintf(fp, "\t\t call [_a68k_memory_intf+8]\n");\r
1064 break;\r
1065\r
1066 case 76 :\r
1067 fprintf(fp, "\t\t call [_a68k_memory_intf+12]\n");\r
1068 break;\r
1069 }\r
1070#endif\r
1071\r
1072 /* Correct Stack */\r
1073\r
1074#ifndef FASTCALL\r
1075 fprintf(fp, "\t\t lea esp,[esp+4]\n");\r
1076#endif\r
1077\r
1078\r
1079\r
1080 /* Restore registers */\r
1081\r
1082 /* Check to see if registers need restoring */\r
1083\r
1084 if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-'))\r
1085 {\r
1086 fprintf(fp, "\t\t pop EDI\n");\r
1087 }\r
1088\r
1089 if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-'))\r
1090 {\r
1091 fprintf(fp, "\t\t pop ECX\n");\r
1092 }\r
1093\r
1094 if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-'))\r
1095 {\r
1096 fprintf(fp, "\t\t pop EBX\n");\r
1097 }\r
1098\r
1099 if ((Flags[ESI] != '-') && (SavedRegs[ESI] == '-'))\r
1100 {\r
1101 fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC);\r
1102 }\r
1103\r
1104 if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-'))\r
1105 {\r
1106 fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR);\r
1107 }\r
1108\r
1109 if ((Flags[EBP] != '-') && (SavedRegs[EBP] == '-'))\r
1110 {\r
1111 fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n");\r
1112 }\r
1113}\r
1114\r
1115void Memory_Write(char Size,int AReg,int DReg,char *Flags,int Mask)\r
1116{\r
1117 ExternalIO = 1;\r
1118\r
1119 /* Save PC */\r
1120\r
1121 fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC);\r
1122\r
1123 /* Check for special mask condition */\r
1124\r
1125 /* ASG - no longer need to mask addresses here */\r
1126/* if (Mask == 2)\r
1127 fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/\r
1128\r
1129 /* Check to see if registers need saving */\r
1130\r
1131 if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-'))\r
1132 {\r
1133 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
1134 }\r
1135\r
1136 if ((Flags[EAX] != '-') && (SavedRegs[EAX] == '-'))\r
1137 {\r
1138 fprintf(fp, "\t\t push EAX\n");\r
1139 }\r
1140\r
1141 if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-'))\r
1142 {\r
1143 fprintf(fp, "\t\t push EBX\n");\r
1144 }\r
1145\r
1146 if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-'))\r
1147 {\r
1148 fprintf(fp, "\t\t push ECX\n");\r
1149 }\r
1150\r
1151 if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-'))\r
1152 {\r
1153 fprintf(fp, "\t\t push EDI\n");\r
1154 }\r
1155\r
1156#ifdef FASTCALL\r
1157\r
1158 fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_SECOND_REG,regnameslong[DReg]);\r
1159 fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_FIRST_REG,regnameslong[AReg]);\r
1160\r
1161 /* ASG - no longer need to mask addresses here */\r
1162/* if (Mask == 1)\r
1163 fprintf(fp, "\t\t and %s,0FFFFFFh\n",FASTCALL_FIRST_REG);*/\r
1164\r
1165#else\r
1166\r
1167 fprintf(fp, "\t\t push %s\n",regnameslong[DReg]);\r
1168\r
1169 if (Mask == 1)\r
1170 {\r
1171 if ((Flags[AReg] != '-') && (SavedRegs[AReg] != '-'))\r
1172 {\r
1173 /* Don't trash a wanted safe register */\r
1174\r
1175 fprintf(fp, "\t\t mov EAX,%s\n",regnameslong[AReg]);\r
1176 /* ASG - no longer need to mask addresses here */\r
1177/* fprintf(fp, "\t\t and EAX,0FFFFFFh\n");*/\r
1178 fprintf(fp, "\t\t push EAX\n");\r
1179 }\r
1180 else\r
1181 {\r
1182 /* ASG - no longer need to mask addresses here */\r
1183/* fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/\r
1184 fprintf(fp, "\t\t push %s\n",regnameslong[AReg]);\r
1185 }\r
1186 }\r
1187 else\r
1188 fprintf(fp, "\t\t push %s\n",regnameslong[AReg]);\r
1189\r
1190#endif\r
1191\r
1192\r
1193\r
1194 /* Call Mame Routine */\r
1195\r
1196 /* ASG - changed these to call through the function pointers */\r
1197 switch (Size)\r
1198 {\r
1199 case 66 :\r
1200 fprintf(fp, "\t\t call [_a68k_memory_intf+16]\n");\r
1201 break;\r
1202\r
1203 case 87 :\r
1204 fprintf(fp, "\t\t call [_a68k_memory_intf+20]\n");\r
1205 break;\r
1206\r
1207 case 76 :\r
1208 fprintf(fp, "\t\t call [_a68k_memory_intf+24]\n");\r
1209 break;\r
1210 }\r
1211\r
1212 /* Correct Stack */\r
1213\r
1214#ifndef FASTCALL\r
1215 fprintf(fp, "\t\t lea esp,[esp+8]\n");\r
1216#endif\r
1217\r
1218\r
1219\r
1220 /* Restore registers */\r
1221\r
1222 /* Check to see if registers need restoring */\r
1223\r
1224 if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-'))\r
1225 {\r
1226 fprintf(fp, "\t\t pop EDI\n");\r
1227 }\r
1228\r
1229 if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-'))\r
1230 {\r
1231 fprintf(fp, "\t\t pop ECX\n");\r
1232 }\r
1233\r
1234 if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-'))\r
1235 {\r
1236 fprintf(fp, "\t\t pop EBX\n");\r
1237 }\r
1238\r
1239 if ((Flags[EAX] != '-') && (SavedRegs[EAX] == '-'))\r
1240 {\r
1241 fprintf(fp, "\t\t pop EAX\n");\r
1242 }\r
1243\r
1244 if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-'))\r
1245 {\r
1246 fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR);\r
1247 }\r
1248\r
1249 if ((Flags[ESI] != '-') && (SavedRegs[ESI] == '-'))\r
1250 {\r
1251 fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC);\r
1252 }\r
1253\r
1254 if ((Flags[EBP] != '-') && (SavedRegs[EBP] == '-'))\r
1255 {\r
1256 fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n");\r
1257 }\r
1258}\r
1259\r
1260\r
1261/*\r
1262 * Fetch data from Code area\r
1263 *\r
1264 * Dreg = Destination Register\r
1265 * Extend = Sign Extend Word to Long\r
1266 *\r
1267 */\r
1268\r
1269void Memory_Fetch(char Size,int Dreg,int Extend)\r
1270{\r
1271 static int loopcount=0;\r
1272\r
1273 /* Always goes via OP_ROM */\r
1274\r
1275 if(CPU!=2)\r
1276 {\r
1277 /* 16 Bit version */\r
1278\r
1279 if ((Extend == TRUE) & (Size == 'W'))\r
1280 fprintf(fp, "\t\t movsx %s,word [esi+ebp]\n",regnameslong[Dreg]);\r
1281 else if (Size == 'W')\r
1282 fprintf(fp, "\t\t movzx %s,word [esi+ebp]\n",regnameslong[Dreg]);\r
1283 else\r
1284 fprintf(fp, "\t\t mov %s,dword [esi+ebp]\n",regnameslong[Dreg]);\r
1285\r
1286 if (Size == 'L')\r
1287 fprintf(fp, "\t\t rol %s,16\n",regnameslong[Dreg]);\r
1288 }\r
1289 else\r
1290 {\r
1291 /* 32 Bit version */\r
1292\r
1293 if (Size == 'W')\r
1294 {\r
1295 fprintf(fp, "\t\t mov %s,esi\n",regnameslong[Dreg]);\r
1296 fprintf(fp, "\t\t xor %s,byte 2\n",regnameslong[Dreg]);\r
1297\r
1298 if (Extend == TRUE)\r
1299 fprintf(fp, "\t\t movsx %s,word [%s+ebp]\n",regnameslong[Dreg],regnameslong[Dreg]);\r
1300 else\r
1301 fprintf(fp, "\t\t movzx %s,word [%s+ebp]\n",regnameslong[Dreg],regnameslong[Dreg]);\r
1302 }\r
1303 else\r
1304 {\r
1305 // if address is exact multiple of 4, long read will work\r
1306 // otherwise we need to get words address-2 and address+4\r
1307\r
1308 // Always read long\r
1309 fprintf(fp, "\t\t test esi,2\n");\r
1310#if (!ppro)\r
1311 fprintf(fp, "\t\t mov %s,dword [esi+ebp]\n",regnameslong[Dreg]);\r
1312\r
1313 // OK ?\r
1314 fprintf(fp, "\t\t jz short FL%3.3d\n",loopcount+1);\r
1315\r
1316 // no, so get high word\r
1317 fprintf(fp, "\t\t mov %s,dword [esi+ebp-4]\n",regnameslong[Dreg]);\r
1318 // and get low word\r
1319 fprintf(fp, "\t\t mov %s,word [esi+ebp+4]\n",regnamesword[Dreg]);\r
1320\r
1321 fprintf(fp, "FL%3.3d:\n",++loopcount);\r
1322#else\r
1323 fprintf(fp, "\t\t cmovnz %s,dword [esi+ebp-4]\n",regnameslong[Dreg]);\r
1324 fprintf(fp, "\t\t cmovz %s,dword [esi+ebp]\n",regnameslong[Dreg]);\r
1325 fprintf(fp, "\t\t cmovnz %s,word [esi+ebp+4]\n",regnamesword[Dreg]);\r
1326#endif\r
1327 }\r
1328 }\r
1329}\r
1330\r
1331/**********************/\r
1332/* Push PC onto Stack */\r
1333/**********************/\r
1334\r
1335void PushPC(int Wreg,int Wreg2,char *Flags, int Mask)\r
1336{\r
1337\r
1338 /* Wreg2 is only used when high byte is kept */\r
1339 /* If it is EBP then the register is restored */\r
1340\r
1341 fprintf(fp, "\t\t mov %s,[%s]\t ; Push onto Stack\n",regnameslong[Wreg],REG_A7);\r
1342 fprintf(fp, "\t\t sub %s,byte 4\n",regnameslong[Wreg]);\r
1343 fprintf(fp, "\t\t mov [%s],%s\n",REG_A7,regnameslong[Wreg]);\r
1344\r
1345#ifndef KEEPHIGHPC\r
1346\r
1347 Memory_Write('L',Wreg,ESI,Flags,Mask);\r
1348\r
1349#else\r
1350\r
1351 fprintf(fp, "\t\t mov %s,[FullPC]\n",regnameslong[Wreg2]);\r
1352 fprintf(fp, "\t\t and %s,0xff000000\n",regnameslong[Wreg2]);\r
1353 fprintf(fp, "\t\t or %s,ESI\n",regnameslong[Wreg2]);\r
1354\r
1355 Memory_Write('L',Wreg,Wreg2,Flags,Mask);\r
1356\r
1357 if (Wreg2 == EBP)\r
1358 {\r
1359 fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n");\r
1360 }\r
1361\r
1362#endif\r
1363}\r
1364\r
1365void ExtensionDecode(int SaveEDX)\r
1366{\r
1367 char *Label = GenerateLabel(0,1);\r
1368\r
1369 if (SaveEDX)\r
1370 fprintf(fp, "\t\t push edx\n");\r
1371\r
1372 Memory_Fetch('W',EAX,FALSE);\r
1373 fprintf(fp, "\t\t add esi,byte 2\n");\r
1374\r
1375 if(CPU!=2)\r
1376 {\r
1377 /* 68000 Extension */\r
1378\r
1379 fprintf(fp, "\t\t mov edx,eax\n");\r
1380 fprintf(fp, "\t\t shr eax,12\n");\r
1381 fprintf(fp, "\t\t test edx,0x0800\n");\r
1382 fprintf(fp, "\t\t mov eax,[%s+eax*4]\n",REG_DAT);\r
1383 fprintf(fp, "\t\t jnz short %s\n",Label);\r
1384 fprintf(fp, "\t\t cwde\n");\r
1385 fprintf(fp, "%s:\n",Label);\r
1386 fprintf(fp, "\t\t lea edi,[edi+eax]\n");\r
1387 fprintf(fp, "\t\t movsx edx,dl\n");\r
1388 fprintf(fp, "\t\t lea edi,[edi+edx]\n");\r
1389 }\r
1390 else\r
1391 {\r
1392 /* 68020 Extension */\r
1393\r
1394 // eax holds scaled index\r
1395\r
1396 // might be faster just to push all regs\r
1397 fprintf(fp, "\t\t push ebx\n");\r
1398 fprintf(fp, "\t\t push ecx\n");\r
1399\r
1400 // copies for later use\r
1401 fprintf(fp, "\t\t mov ecx,eax\n");\r
1402 fprintf(fp, "\t\t mov edx,eax\n");\r
1403\r
1404 // check E bit to see if displacement or full format\r
1405 fprintf(fp, "\t\t test edx,0x0100\n");\r
1406 fprintf(fp, "\t\t jz short %s_a\n",Label);\r
1407 // full mode so check IS (index supress)\r
1408 fprintf(fp, "\t\t test edx,0x0040\n");\r
1409 fprintf(fp, "\t\t jz short %s_b\n",Label);\r
1410 // set index to 0, it's not added\r
1411 ClearRegister(EAX);\r
1412 fprintf(fp, "\t\t jmp short %s_d\n",Label); // near\r
1413\r
1414 // add displacement\r
1415 fprintf(fp, "%s_a:\n",Label);\r
1416 fprintf(fp, "\t\t movsx eax,al\n");\r
1417 fprintf(fp, "\t\t lea edi,[edi+eax]\n");\r
1418\r
1419 fprintf(fp, "%s_b:\n",Label);\r
1420 // calc index always scale (68k will scale by 1)\r
1421 fprintf(fp, "\t\t mov eax,edx\n");\r
1422 fprintf(fp, "\t\t shr eax,12\n");\r
1423 fprintf(fp, "\t\t test edx,0x0800\n");\r
1424 fprintf(fp, "\t\t mov eax,[%s+eax*4]\n",REG_DAT);\r
1425 fprintf(fp, "\t\t jnz short %s_c\n",Label);\r
1426 fprintf(fp, "\t\t cwde\n");\r
1427\r
1428 fprintf(fp, "%s_c:\n",Label);\r
1429 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
1430 fprintf(fp, "\t\t and ecx,byte 3\n");\r
1431 fprintf(fp, "\t\t shl eax,cl\n");\r
1432\r
1433 // if brief mode we can add index and exit\r
1434 fprintf(fp, "\t\t test edx,0x0100\n");\r
1435 fprintf(fp, "\t\t jz near %s_i2\n",Label);\r
1436\r
1437 fprintf(fp, "%s_d:\n",Label);\r
1438 // check BS (base supress)\r
1439 // if BS is 1 then set edi to 0\r
1440 fprintf(fp, "\t\t test edx,0x0080\n");\r
1441 fprintf(fp, "\t\t jz short %s_4a\n",Label);\r
1442 ClearRegister(EDI);\r
1443 // if null displacement skip over\r
1444 fprintf(fp, "%s_4a:\n",Label);\r
1445 fprintf(fp, "\t\t test edx,0x0020\n");\r
1446 fprintf(fp, "\t\t jz short %s_f\n",Label);\r
1447\r
1448 // **** calc base displacement ****\r
1449 // is it long\r
1450 fprintf(fp, "\t\t test edx,0x0010\n");\r
1451 fprintf(fp, "\t\t jz short %s_e\n",Label);\r
1452 // fetch long base\r
1453 Memory_Fetch('L',EBX,FALSE);\r
1454 fprintf(fp, "\t\t lea edi,[edi+ebx]\n");\r
1455 fprintf(fp, "\t\t add esi,byte 4\n");\r
1456 fprintf(fp, "\t\t jmp short %s_f\n",Label);\r
1457\r
1458 // fetch word base\r
1459 fprintf(fp, "%s_e:\n",Label);\r
1460 Memory_Fetch('W',EBX,TRUE);\r
1461 fprintf(fp, "\t\t lea edi,[edi+ebx]\n");\r
1462 fprintf(fp, "\t\t add esi,byte 2\n");\r
1463\r
1464 // **** indirect? ****\r
1465 fprintf(fp, "%s_f:\n",Label);\r
1466 fprintf(fp, "\t\t test edx,0x0003\n");\r
1467 fprintf(fp, "\t\t jz near %s_7a\n",Label);\r
1468 // pre or post indirect\r
1469 fprintf(fp, "\t\t test edx,0x0004\n");\r
1470 fprintf(fp, "\t\t jnz short %s_g\n",Label);\r
1471 // do pre\r
1472 fprintf(fp, "\t\t lea edi,[edi+eax]\n");\r
1473 Memory_Read('L',EDI,"ABCDSDB",2);\r
1474 fprintf(fp, "\t\t mov edi,eax\n");\r
1475 fprintf(fp, "\t\t jmp short %s_h\n",Label);\r
1476\r
1477 // do post\r
1478 fprintf(fp, "%s_g:\n",Label);\r
1479 fprintf(fp, "\t\t push eax\n");\r
1480 Memory_Read('L',EDI,"-B-DS-B",2);\r
1481 fprintf(fp, "\t\t pop edi\n");\r
1482\r
1483 fprintf(fp, "%s_7a:\n",Label);\r
1484 fprintf(fp, "\t\t lea edi,[edi+eax]\n");\r
1485\r
1486 // **** outer displacement ****\r
1487 // if null displacement skip over\r
1488 fprintf(fp, "%s_h:\n",Label);\r
1489 fprintf(fp, "\t\t test edx,0x0002\n");\r
1490 fprintf(fp, "\t\t jz short %s_j\n",Label);\r
1491 // word or long?\r
1492 fprintf(fp, "\t\t test edx,0x0001\n");\r
1493 fprintf(fp, "\t\t jz short %s_i\n",Label);\r
1494 // fetch long\r
1495 Memory_Fetch('L',EAX,FALSE);\r
1496 fprintf(fp, "\t\t add esi,byte 4\n");\r
1497 fprintf(fp, "\t\t jmp short %s_i2\n",Label);\r
1498 // fetch word\r
1499 fprintf(fp, "%s_i:\n",Label);\r
1500 Memory_Fetch('W',EAX,TRUE);\r
1501 fprintf(fp, "\t\t add esi,byte 2\n");\r
1502 fprintf(fp, "%s_i2:\n",Label);\r
1503 fprintf(fp, "\t\t lea edi,[edi+eax]\n");\r
1504\r
1505 // **** exit ****\r
1506 fprintf(fp, "%s_j:\n",Label);\r
1507 fprintf(fp, "\t\t pop ecx\n");\r
1508 fprintf(fp, "\t\t pop ebx\n");\r
1509 }\r
1510\r
1511 if (SaveEDX)\r
1512 fprintf(fp, "\t\t pop edx\n");\r
1513}\r
1514\r
1515/* Calculate Effective Address - Return address in EDI\r
1516 *\r
1517 * mode = Effective Address from Instruction\r
1518 * Size = Byte,Word or Long\r
1519 * Rreg = Register with Register Number in\r
1520 *\r
1521 * Only for modes 2 - 10 (5-10 clobber EAX)\r
1522 */\r
1523\r
1524void EffectiveAddressCalculate(int mode,char Size,int Rreg,int SaveEDX)\r
1525{\r
1526 /* timing */\r
1527\r
1528 if ((TimingCycles > 0) && (AddEACycles!=0))\r
1529 {\r
1530 switch (mode)\r
1531 {\r
1532 case 2: /* (An) */\r
1533 case 3: /* (An)+ */\r
1534 case 11: /* #x,SR,CCR */\r
1535 case 19: /* (A7)+ */\r
1536 TimingCycles += 4 ;\r
1537 break ;\r
1538\r
1539 case 4: /* -(An) */\r
1540 case 20: /* -(A7) */\r
1541 TimingCycles += (CPU==2) ? 5 : 6 ;\r
1542 break ;\r
1543\r
1544 case 5: /* x(An) */\r
1545 case 9: /* x(PC) */\r
1546 TimingCycles += (CPU==2) ? 5 : 8 ;\r
1547 break ;\r
1548\r
1549 case 7: /* x.w */\r
1550 TimingCycles += (CPU==2) ? 4 : 8 ;\r
1551 break ;\r
1552\r
1553 case 6: /* x(An,xr.s) */\r
1554 case 10: /* x(PC,xr.s) */\r
1555 TimingCycles += (CPU==2) ? 7 : 10 ;\r
1556 break ;\r
1557\r
1558 case 8: /* x.l */\r
1559 TimingCycles += (CPU==2) ? 4 : 12 ;\r
1560 break ;\r
1561 }\r
1562\r
1563 /* long w/r adds 4 cycles */\r
1564\r
1565 if ((mode>1) && (Size == 'L') && (CPU != 2))\r
1566 TimingCycles += 4 ;\r
1567 }\r
1568\r
1569 AccessType = NORMAL;\r
1570\r
1571 switch (mode)\r
1572 {\r
1573\r
1574 case 2:\r
1575 fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]);\r
1576 break;\r
1577\r
1578 case 3:\r
1579 fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]);\r
1580 IncrementEDI(Size,Rreg);\r
1581 break;\r
1582\r
1583 case 4:\r
1584 fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]);\r
1585 DecrementEDI(Size,Rreg);\r
1586 fprintf(fp, "\t\t mov [%s+%s*4],EDI\n",REG_ADD,regnameslong[Rreg]);\r
1587 break;\r
1588\r
1589 case 5:\r
1590 Memory_Fetch('W',EAX,TRUE);\r
1591 fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]);\r
1592 fprintf(fp, "\t\t add esi,byte 2\n");\r
1593 fprintf(fp, "\t\t add edi,eax\n");\r
1594 break;\r
1595\r
1596 case 6:\r
1597\r
1598 /* Get Address register Value */\r
1599\r
1600 fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]);\r
1601\r
1602 /* Add Extension Details */\r
1603\r
1604 ExtensionDecode(SaveEDX);\r
1605 break;\r
1606\r
1607 case 7:\r
1608\r
1609 /* Get Word */\r
1610\r
1611 Memory_Fetch('W',EDI,TRUE);\r
1612// fprintf(fp, "\t\t movsx edi,di\n");\r
1613 fprintf(fp, "\t\t add esi,byte 2\n");\r
1614 break;\r
1615\r
1616 case 8:\r
1617\r
1618 /* Get Long */\r
1619\r
1620 Memory_Fetch('L',EDI,FALSE);\r
1621 fprintf(fp, "\t\t add esi,byte 4\n");\r
1622 break;\r
1623\r
1624 case 9:\r
1625\r
1626 AccessType = PCREL;\r
1627\r
1628 Memory_Fetch('W',EAX,TRUE);\r
1629// fprintf(fp, "\t\t movsx eax,ax\n");\r
1630 fprintf(fp, "\t\t mov EDI,ESI ; Get PC\n");\r
1631 fprintf(fp, "\t\t add esi,byte 2\n");\r
1632 fprintf(fp, "\t\t add edi,eax ; Add Offset to PC\n");\r
1633 break;\r
1634\r
1635 case 10:\r
1636\r
1637 AccessType = PCREL;\r
1638\r
1639 /* Get PC */\r
1640\r
1641 fprintf(fp, "\t\t mov edi,esi ; Get PC\n");\r
1642\r
1643 /* Add Extension Details */\r
1644\r
1645 ExtensionDecode(SaveEDX);\r
1646\r
1647 break;\r
1648\r
1649 case 19:\r
1650\r
1651 /* (A7)+ */\r
1652\r
1653 fprintf(fp, "\t\t mov edi,[%s] ; Get A7\n",REG_A7);\r
1654 fprintf(fp, "\t\t add dword [%s],byte 2\n",REG_A7);\r
1655 break;\r
1656\r
1657 case 20:\r
1658\r
1659 /* -(A7) */\r
1660\r
1661 fprintf(fp, "\t\t mov edi,[%s] ; Get A7\n",REG_A7);\r
1662 fprintf(fp, "\t\t sub edi,byte 2\n");\r
1663 fprintf(fp, "\t\t mov [%s],edi\n",REG_A7);\r
1664 break;\r
1665\r
1666 }\r
1667}\r
1668\r
1669/* Read from Effective Address\r
1670 *\r
1671 * mode = Effective Address from Instruction\r
1672 * Size = Byte,Word or Long\r
1673 * Rreg = Register with Register Number in\r
1674 * Flag = Registers to preserve (EDX is handled by SaveEDX)\r
1675 *\r
1676 * Return\r
1677 * Dreg = Register to return result in (EAX is usually most efficient)\r
1678 * (modes 5 to 10) EDI = Address of data read (masked with FFFFFF)\r
1679 */\r
1680\r
1681void EffectiveAddressRead(int mode,char Size,int Rreg,int Dreg,const char *flags,int SaveEDX)\r
1682{\r
1683 char* Regname="";\r
1684 int MaskMode;\r
1685 char Flags[8];\r
1686\r
1687 AccessType = NORMAL;\r
1688\r
1689 strcpy(Flags,flags);\r
1690\r
1691 /* Which Masking to Use */\r
1692\r
1693 if (Flags[5] != '-')\r
1694 MaskMode = 2;\r
1695 else\r
1696 MaskMode = 1;\r
1697\r
1698 if (SaveEDX)\r
1699 Flags[3] = 'D';\r
1700 else\r
1701 Flags[3] = '-';\r
1702\r
1703 switch (Size)\r
1704 {\r
1705 case 66:\r
1706 Regname = regnamesshort[Dreg];\r
1707 break;\r
1708\r
1709 case 87:\r
1710 Regname = regnamesword[Dreg];\r
1711 break;\r
1712\r
1713 case 76:\r
1714 Regname = regnameslong[Dreg];\r
1715 break;\r
1716 }\r
1717\r
1718 switch (mode & 15)\r
1719 {\r
1720\r
1721 case 0:\r
1722\r
1723 /* Read 32 bits - No prefix */\r
1724\r
1725 fprintf(fp, "\t\t mov %s,[%s+%s*4]\n",regnameslong[Dreg],REG_DAT,regnameslong[Rreg]);\r
1726 break;\r
1727\r
1728 case 1:\r
1729\r
1730 /* Read 32 bits - No prefix */\r
1731\r
1732 fprintf(fp, "\t\t mov %s,[%s+%s*4]\n",regnameslong[Dreg],REG_ADD,regnameslong[Rreg]);\r
1733 break;\r
1734\r
1735 case 2:\r
1736 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1737\r
1738 Memory_Read(Size,EDI,Flags,MaskMode);\r
1739\r
1740 if (Dreg != EAX)\r
1741 {\r
1742 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1743 }\r
1744 break;\r
1745\r
1746 case 3:\r
1747 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1748\r
1749 Memory_Read(Size,EDI,Flags,MaskMode);\r
1750\r
1751 if (Dreg != EAX)\r
1752 {\r
1753 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1754 }\r
1755 break;\r
1756\r
1757 case 4:\r
1758 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1759\r
1760 Memory_Read(Size,EDI,Flags,MaskMode);\r
1761\r
1762 if (Dreg != EAX)\r
1763 {\r
1764 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1765 }\r
1766 break;\r
1767\r
1768\r
1769 case 5:\r
1770 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1771\r
1772 Memory_Read(Size,EDI,Flags,MaskMode);\r
1773\r
1774 if (Dreg != EAX)\r
1775 {\r
1776 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1777 }\r
1778 break;\r
1779\r
1780 case 6:\r
1781 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1782\r
1783 Memory_Read(Size,EDI,Flags,MaskMode);\r
1784\r
1785 if (Dreg != EAX)\r
1786 {\r
1787 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1788 }\r
1789 break;\r
1790\r
1791 case 7:\r
1792 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1793\r
1794 Memory_Read(Size,EDI,Flags,MaskMode);\r
1795\r
1796 if (Dreg != EAX)\r
1797 {\r
1798 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1799 }\r
1800 break;\r
1801\r
1802 case 8:\r
1803 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1804\r
1805 Memory_Read(Size,EDI,Flags,MaskMode);\r
1806\r
1807 if (Dreg != EAX)\r
1808 {\r
1809 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1810 }\r
1811 break;\r
1812\r
1813 case 9:\r
1814 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1815\r
1816 Memory_Read(Size,EDI,Flags,MaskMode);\r
1817\r
1818 if (Dreg != EAX)\r
1819 {\r
1820 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1821 }\r
1822 break;\r
1823\r
1824 case 10:\r
1825 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1826\r
1827 Memory_Read(Size,EDI,Flags,MaskMode);\r
1828\r
1829 if (Dreg != EAX)\r
1830 {\r
1831 fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]);\r
1832 }\r
1833 break;\r
1834\r
1835 case 11:\r
1836\r
1837 /* Immediate - for SR or CCR see ReadCCR() */\r
1838\r
1839 if (Size == 'L')\r
1840 {\r
1841 Memory_Fetch('L',Dreg,FALSE);\r
1842 fprintf(fp, "\t\t add esi,byte 4\n");\r
1843 }\r
1844 else\r
1845 {\r
1846 Memory_Fetch('W',Dreg,FALSE);\r
1847 fprintf(fp, "\t\t add esi,byte 2\n");\r
1848 };\r
1849 break;\r
1850 }\r
1851}\r
1852\r
1853/*\r
1854 * EA = Effective Address from Instruction\r
1855 * Size = Byte,Word or Long\r
1856 * Rreg = Register with Register Number in\r
1857 *\r
1858 * Writes from EAX\r
1859 */\r
1860\r
1861void EffectiveAddressWrite(int mode,char Size,int Rreg,int CalcAddress,const char *flags,int SaveEDX)\r
1862{\r
1863 int MaskMode;\r
1864 char* Regname="";\r
1865 char Flags[8];\r
1866\r
1867\r
1868 strcpy(Flags,flags);\r
1869\r
1870 /* Which Masking to Use ? */\r
1871\r
1872 if (CalcAddress)\r
1873 {\r
1874 if (Flags[5] != '-')\r
1875 MaskMode = 2;\r
1876 else\r
1877 MaskMode = 1;\r
1878 }\r
1879 else\r
1880 MaskMode = 0;\r
1881\r
1882 if (SaveEDX)\r
1883 Flags[3] = 'D';\r
1884 else\r
1885 Flags[3] = '-';\r
1886\r
1887 switch (Size)\r
1888 {\r
1889 case 66:\r
1890 Regname = regnamesshort[0];\r
1891 break;\r
1892\r
1893 case 87:\r
1894 Regname = regnamesword[0];\r
1895 break;\r
1896\r
1897 case 76:\r
1898 Regname = regnameslong[0];\r
1899 break;\r
1900 }\r
1901\r
1902 switch (mode & 15)\r
1903 {\r
1904\r
1905 case 0:\r
1906 fprintf(fp, "\t\t mov [%s+%s*4],%s\n",REG_DAT,regnameslong[Rreg],Regname);\r
1907 break;\r
1908\r
1909 case 1:\r
1910 if (Size == 66)\r
1911 {\r
1912 /* Not Allowed */\r
1913\r
1914 fprintf(fp, "DUFF CODE!\n");\r
1915 }\r
1916 else\r
1917 {\r
1918 if (Size == 87)\r
1919 {\r
1920 fprintf(fp, "\t\t cwde\n");\r
1921 }\r
1922\r
1923 fprintf(fp, "\t\t mov [%s+%s*4],%s\n",REG_ADD,regnameslong[Rreg],regnameslong[0]);\r
1924 }\r
1925 break;\r
1926\r
1927 case 2:\r
1928 if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1929 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1930 break;\r
1931\r
1932 case 3:\r
1933 if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1934 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1935 break;\r
1936\r
1937 case 4:\r
1938 if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1939 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1940 break;\r
1941\r
1942 case 5:\r
1943 if (CalcAddress)\r
1944 {\r
1945 fprintf(fp, "\t\t push EAX\n");\r
1946 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1947 fprintf(fp, "\t\t pop EAX\n");\r
1948 }\r
1949 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1950 break;\r
1951\r
1952 case 6:\r
1953 if (CalcAddress)\r
1954 {\r
1955 fprintf(fp, "\t\t push EAX\n");\r
1956 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1957 fprintf(fp, "\t\t pop EAX\n");\r
1958 }\r
1959 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1960 break;\r
1961\r
1962 case 7:\r
1963 if (CalcAddress)\r
1964 {\r
1965 fprintf(fp, "\t\t push EAX\n");\r
1966 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1967 fprintf(fp, "\t\t pop EAX\n");\r
1968 }\r
1969 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1970 break;\r
1971\r
1972 case 8:\r
1973 if (CalcAddress)\r
1974 {\r
1975 fprintf(fp, "\t\t push EAX\n");\r
1976 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1977 fprintf(fp, "\t\t pop EAX\n");\r
1978 }\r
1979 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1980 break;\r
1981\r
1982 case 9:\r
1983 if (CalcAddress)\r
1984 {\r
1985 fprintf(fp, "\t\t push EAX\n");\r
1986 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1987 fprintf(fp, "\t\t pop EAX\n");\r
1988 }\r
1989 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
1990 break;\r
1991\r
1992 case 10:\r
1993 if (CalcAddress)\r
1994 {\r
1995 fprintf(fp, "\t\t push EAX\n");\r
1996 EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX);\r
1997 fprintf(fp, "\t\t pop EAX\n");\r
1998 }\r
1999 Memory_Write(Size,EDI,EAX,Flags,MaskMode);\r
2000 break;\r
2001\r
2002 case 11:\r
2003\r
2004 /* SR, CCR - Chain to correct routine */\r
2005\r
2006 WriteCCR(Size);\r
2007 }\r
2008}\r
2009\r
2010/* Condition Decode Routines */\r
2011\r
2012/*\r
2013 * mode = condition to check for\r
2014 *\r
2015 * Returns LABEL that is jumped to if condition is Condition\r
2016 *\r
2017 * Some conditions clobber AH\r
2018 */\r
2019\r
2020char *ConditionDecode(int mode, int Condition)\r
2021{\r
2022 char *Label = GenerateLabel(0,1);\r
2023\r
2024 switch (mode)\r
2025 {\r
2026\r
2027 case 0: /* A - Always */\r
2028 if (Condition)\r
2029 {\r
2030 fprintf(fp, "\t\t jmp %s ;dave removed near\n",Label);\r
2031 }\r
2032 break;\r
2033\r
2034 case 1: /* F - Never */\r
2035 if (!Condition)\r
2036 {\r
2037 fprintf(fp, "\t\t jmp near %s\n",Label);\r
2038 }\r
2039 break;\r
2040\r
2041 case 2: /* Hi */\r
2042 fprintf(fp, "\t\t mov ah,dl\n");\r
2043 fprintf(fp, "\t\t sahf\n");\r
2044\r
2045 if (Condition)\r
2046 {\r
2047 fprintf(fp, "\t\t ja near %s\n",Label);\r
2048 }\r
2049 else\r
2050 {\r
2051 fprintf(fp, "\t\t jbe near %s\n",Label);\r
2052 }\r
2053 break;\r
2054\r
2055 case 3: /* Ls */\r
2056 fprintf(fp, "\t\t mov ah,dl\n");\r
2057 fprintf(fp, "\t\t sahf\n");\r
2058\r
2059 if (Condition)\r
2060 {\r
2061 fprintf(fp, "\t\t jbe near %s\n",Label);\r
2062 }\r
2063 else\r
2064 {\r
2065 fprintf(fp, "\t\t ja near %s\n",Label);\r
2066 }\r
2067 break;\r
2068\r
2069 case 4: /* CC */\r
2070 fprintf(fp, "\t\t test dl,1H\t\t;check carry\n");\r
2071\r
2072 if (Condition)\r
2073 {\r
2074 fprintf(fp, "\t\t jz near %s\n",Label);\r
2075 }\r
2076 else\r
2077 {\r
2078 fprintf(fp, "\t\t jnz near %s\n",Label);\r
2079 }\r
2080 break;\r
2081\r
2082 case 5: /* CS */\r
2083 fprintf(fp, "\t\t test dl,1H\t\t;check carry\n");\r
2084 if (Condition)\r
2085 {\r
2086 fprintf(fp, "\t\t jnz near %s\n",Label);\r
2087 }\r
2088 else\r
2089 {\r
2090 fprintf(fp, "\t\t jz near %s\n",Label);\r
2091 }\r
2092 break;\r
2093\r
2094 case 6: /* NE */\r
2095 fprintf(fp, "\t\t test dl,40H\t\t;Check zero\n");\r
2096 if (Condition)\r
2097 {\r
2098 fprintf(fp, "\t\t jz near %s\n",Label);\r
2099 }\r
2100 else\r
2101 {\r
2102 fprintf(fp, "\t\t jnz near %s\n",Label);\r
2103 }\r
2104 break;\r
2105\r
2106 case 7: /* EQ */\r
2107 fprintf(fp, "\t\t test dl,40H\t\t;Check zero\n");\r
2108 if (Condition)\r
2109 {\r
2110 fprintf(fp, "\t\t jnz near %s\n",Label);\r
2111 }\r
2112 else\r
2113 {\r
2114 fprintf(fp, "\t\t jz near %s\n",Label);\r
2115 }\r
2116 break;\r
2117\r
2118 case 8: /* VC */\r
2119 fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n");\r
2120 if (Condition)\r
2121 {\r
2122 fprintf(fp, "\t\t jz near %s\n", Label);\r
2123 }\r
2124 else\r
2125 {\r
2126 fprintf(fp, "\t\t jnz near %s\n", Label);\r
2127 }\r
2128 break;\r
2129\r
2130 case 9: /* VS */\r
2131 fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n");\r
2132 if (Condition)\r
2133 {\r
2134 fprintf(fp, "\t\t jnz near %s\n", Label);\r
2135 }\r
2136 else\r
2137 {\r
2138 fprintf(fp, "\t\t jz near %s\n", Label);\r
2139 }\r
2140 break;\r
2141\r
2142 case 10: /* PL */\r
2143 fprintf(fp,"\t\t test dl,80H\t\t;Check Sign\n");\r
2144 if (Condition)\r
2145 {\r
2146 fprintf(fp, "\t\t jz near %s\n", Label);\r
2147 }\r
2148 else\r
2149 {\r
2150 fprintf(fp, "\t\t jnz near %s\n", Label);\r
2151 }\r
2152 break;\r
2153\r
2154 case 11: /* MI */\r
2155 fprintf(fp,"\t\t test dl,80H\t\t;Check Sign\n");\r
2156 if (Condition)\r
2157 {\r
2158 fprintf(fp, "\t\t jnz near %s\n", Label);\r
2159 }\r
2160 else\r
2161 {\r
2162 fprintf(fp, "\t\t jz near %s\n", Label);\r
2163 }\r
2164 break;\r
2165\r
2166 case 12: /* GE */\r
2167 fprintf(fp, "\t\t or edx,200h\n");\r
2168 fprintf(fp, "\t\t push edx\n");\r
2169 fprintf(fp, "\t\t popf\n");\r
2170 if (Condition)\r
2171 {\r
2172 fprintf(fp, "\t\t jge near %s\n",Label);\r
2173 }\r
2174 else\r
2175 {\r
2176 fprintf(fp, "\t\t jl near %s\n",Label);\r
2177 }\r
2178 break;\r
2179\r
2180 case 13: /* LT */\r
2181 fprintf(fp, "\t\t or edx,200h\n");\r
2182 fprintf(fp, "\t\t push edx\n");\r
2183 fprintf(fp, "\t\t popf\n");\r
2184 if (Condition)\r
2185 {\r
2186 fprintf(fp, "\t\t jl near %s\n",Label);\r
2187 }\r
2188 else\r
2189 {\r
2190 fprintf(fp, "\t\t jge near %s\n",Label);\r
2191 }\r
2192 break;\r
2193\r
2194 case 14: /* GT */\r
2195 fprintf(fp, "\t\t or edx,200h\n");\r
2196 fprintf(fp, "\t\t push edx\n");\r
2197 fprintf(fp, "\t\t popf\n");\r
2198 if (Condition)\r
2199 {\r
2200 fprintf(fp, "\t\t jg near %s\n",Label);\r
2201 }\r
2202 else\r
2203 {\r
2204 fprintf(fp, "\t\t jle near %s\n",Label);\r
2205 }\r
2206 break;\r
2207\r
2208 case 15: /* LE */\r
2209 fprintf(fp, "\t\t or edx,200h\n");\r
2210 fprintf(fp, "\t\t push edx\n");\r
2211 fprintf(fp, "\t\t popf\n");\r
2212 if (Condition)\r
2213 {\r
2214 fprintf(fp, "\t\t jle near %s\n",Label);\r
2215 }\r
2216 else\r
2217 {\r
2218 fprintf(fp, "\t\t jg near %s\n",Label);\r
2219 }\r
2220 break;\r
2221 }\r
2222\r
2223 return Label;\r
2224}\r
2225\r
2226/*\r
2227 * mode = condition to check for\r
2228 * SetWhat = text for assembler command (usually AL or address descriptor)\r
2229 *\r
2230 * Some conditions clobber AH\r
2231 */\r
2232\r
2233void ConditionCheck(int mode, char *SetWhat)\r
2234{\r
2235 switch (mode)\r
2236 {\r
2237\r
2238 case 0: /* A - Always */\r
2239 fprintf(fp, "\t\t mov %s,byte 0ffh\n",SetWhat);\r
2240 break;\r
2241\r
2242 case 1: /* F - Never */\r
2243 if (SetWhat[1] == 'L')\r
2244 {\r
2245 ClearRegister(EAX);\r
2246 }\r
2247 else\r
2248 {\r
2249 fprintf(fp, "\t\t mov %s,byte 0h\n",SetWhat);\r
2250 }\r
2251 break;\r
2252\r
2253 case 2: /* Hi */\r
2254 fprintf(fp, "\t\t mov ah,dl\n");\r
2255 fprintf(fp, "\t\t sahf\n");\r
2256 fprintf(fp, "\t\t seta %s\n",SetWhat);\r
2257 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2258 break;\r
2259\r
2260 case 3: /* Ls */\r
2261 fprintf(fp, "\t\t mov ah,dl\n");\r
2262 fprintf(fp, "\t\t sahf\n");\r
2263 fprintf(fp, "\t\t setbe %s\n",SetWhat);\r
2264 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2265 break;\r
2266\r
2267 case 4: /* CC */\r
2268 fprintf(fp, "\t\t test dl,1\t\t;Check Carry\n");\r
2269 fprintf(fp, "\t\t setz %s\n",SetWhat);\r
2270 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2271 break;\r
2272\r
2273 case 5: /* CS */\r
2274 fprintf(fp, "\t\t test dl,1\t\t;Check Carry\n");\r
2275 fprintf(fp, "\t\t setnz %s\n",SetWhat);\r
2276 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2277 break;\r
2278\r
2279 case 6: /* NE */\r
2280 fprintf(fp, "\t\t test dl,40H\t\t;Check Zero\n");\r
2281 fprintf(fp, "\t\t setz %s\n",SetWhat);\r
2282 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2283 break;\r
2284\r
2285 case 7: /* EQ */\r
2286 fprintf(fp, "\t\t test dl,40H\t\t;Check Zero\n");\r
2287 fprintf(fp, "\t\t setnz %s\n",SetWhat);\r
2288 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2289 break;\r
2290\r
2291 case 8: /* VC */\r
2292 fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n");\r
2293 fprintf(fp, "\t\t setz %s\n",SetWhat);\r
2294 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2295 break;\r
2296\r
2297 case 9: /* VS */\r
2298 fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n");\r
2299 fprintf(fp, "\t\t setnz %s\n",SetWhat);\r
2300 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2301 break;\r
2302\r
2303 case 10: /* PL */\r
2304 fprintf(fp, "\t\t test dl,80H\t\t;Check Sign\n");\r
2305 fprintf(fp, "\t\t setz %s\n",SetWhat);\r
2306 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2307 break;\r
2308\r
2309 case 11: /* MI */\r
2310 fprintf(fp, "\t\t test dl,80H\t\t;Check Sign\n");\r
2311 fprintf(fp, "\t\t setnz %s\n",SetWhat);\r
2312 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2313 break;\r
2314\r
2315 case 12: /* GE */\r
2316 fprintf(fp, "\t\t or edx,200h\n");\r
2317 fprintf(fp, "\t\t push edx\n");\r
2318 fprintf(fp, "\t\t popf\n");\r
2319 fprintf(fp, "\t\t setge %s\n",SetWhat);\r
2320 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2321 break;\r
2322\r
2323 case 13: /* LT */\r
2324 fprintf(fp, "\t\t or edx,200h\n");\r
2325 fprintf(fp, "\t\t push edx\n");\r
2326 fprintf(fp, "\t\t popf\n");\r
2327 fprintf(fp, "\t\t setl %s\n",SetWhat);\r
2328 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2329 break;\r
2330\r
2331 case 14: /* GT */\r
2332 fprintf(fp, "\t\t or edx,200h\n");\r
2333 fprintf(fp, "\t\t push edx\n");\r
2334 fprintf(fp, "\t\t popf\n");\r
2335 fprintf(fp, "\t\t setg %s\n",SetWhat);\r
2336 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2337 break;\r
2338\r
2339 case 15: /* LE */\r
2340 fprintf(fp, "\t\t or edx,200h\n");\r
2341 fprintf(fp, "\t\t push edx\n");\r
2342 fprintf(fp, "\t\t popf\n");\r
2343 fprintf(fp, "\t\t setle %s\n",SetWhat);\r
2344 fprintf(fp, "\t\t neg byte %s\n",SetWhat);\r
2345 break;\r
2346 }\r
2347}\r
2348\r
2349\r
2350/**********************************************************************/\r
2351/* Instructions - Each routine generates a range of instruction codes */\r
2352/**********************************************************************/\r
2353\r
2354/*\r
2355 * Immediate Commands\r
2356 *\r
2357 * ORI 00xx\r
2358 * ANDI 02xx\r
2359 * SUBI 04xx\r
2360 * ADDI 06xx\r
2361 * EORI 0axx\r
2362 * CMPI 0cxx\r
2363 *\r
2364 */\r
2365\r
2366void dump_imm( int type, int leng, int mode, int sreg )\r
2367{\r
2368 int Opcode,BaseCode ;\r
2369 char Size=' ' ;\r
2370 char * RegnameEBX="" ;\r
2371 char * Regname="" ;\r
2372 char * OpcodeName[16] = {"or ", "and", "sub", "add",0,"xor","cmp",0} ;\r
2373 int allow[] = {1,0,1,1, 1,1,1,1, 1,0,0,0, 0,0,0,0, 0,0,0,1, 1} ;\r
2374\r
2375 Opcode = (type << 9) | ( leng << 6 ) | ( mode << 3 ) | sreg;\r
2376\r
2377 BaseCode = Opcode & 0xfff8;\r
2378\r
2379 if (mode == 7) BaseCode |= sreg ;\r
2380\r
2381#ifdef A7ROUTINE\r
2382 if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5))\r
2383 {\r
2384 BaseCode |= sreg ;\r
2385 }\r
2386#endif\r
2387\r
2388 if (type != 4) /* Not Valid (for this routine) */\r
2389 {\r
2390 int Dest = EAtoAMN(Opcode, FALSE);\r
2391 int SetX;\r
2392\r
2393 /* ADDI & SUBI also set X flag */\r
2394\r
2395 SetX = ((type == 2) || (type == 3));\r
2396\r
2397 switch (leng)\r
2398 {\r
2399 case 0:\r
2400 Size = 'B';\r
2401 Regname = regnamesshort[0];\r
2402 RegnameEBX = regnamesshort[EBX];\r
2403 break;\r
2404 case 1:\r
2405 Size = 'W';\r
2406 Regname = regnamesword[0];\r
2407 RegnameEBX = regnamesword[EBX];\r
2408 break;\r
2409 case 2:\r
2410 Size = 'L';\r
2411 Regname = regnameslong[0];\r
2412 RegnameEBX = regnameslong[EBX];\r
2413 break;\r
2414 }\r
2415\r
2416 if (allow[Dest])\r
2417 {\r
2418 if (OpcodeArray[BaseCode] == -2)\r
2419 {\r
2420 Align();\r
2421 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
2422\r
2423 /* Save Previous PC if Memory Access */\r
2424\r
2425 if ((Dest >= 2) && (Dest <=10))\r
2426 SavePreviousPC();\r
2427\r
2428 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
2429\r
2430 if (mode < 2)\r
2431 {\r
2432 if (Size != 'L')\r
2433 TimingCycles += (CPU==2) ? 4 : 8;\r
2434 else\r
2435 {\r
2436 TimingCycles += (CPU==2) ? 8 : 14;\r
2437 if ((type != 1) && (type!=6))\r
2438 TimingCycles += 2 ;\r
2439 }\r
2440 }\r
2441 else\r
2442 {\r
2443 if (type != 6)\r
2444 {\r
2445 if (Size != 'L')\r
2446 TimingCycles += (CPU==2) ? 4 : 12 ;\r
2447 else\r
2448 TimingCycles += (CPU==2) ? 4 : 20 ;\r
2449 }\r
2450 else\r
2451 {\r
2452 if (Size != 'L')\r
2453 TimingCycles += (CPU==2) ? 4 : 8 ;\r
2454 else\r
2455 TimingCycles += (CPU==2) ? 4 : 12 ;\r
2456 }\r
2457 }\r
2458\r
2459 fprintf(fp, "\t\t and ecx,byte 7\n");\r
2460\r
2461 /* Immediate Mode Data */\r
2462 EffectiveAddressRead(11,Size,EBX,EBX,"--C-S-B",FALSE);\r
2463\r
2464 /* Source Data */\r
2465 EffectiveAddressRead(Dest,Size,ECX,EAX,"-BC-SDB",FALSE);\r
2466\r
2467 /* The actual work */\r
2468 fprintf(fp, "\t\t %s %s,%s\n", OpcodeName[type], Regname, RegnameEBX );\r
2469\r
2470 SetFlags(Size,EAX,FALSE,SetX,TRUE);\r
2471\r
2472 if (type != 6) /* CMP no update */\r
2473 EffectiveAddressWrite(Dest,Size,ECX,EAX,"---DS-B",FALSE);\r
2474\r
2475 Completed();\r
2476 }\r
2477 }\r
2478 else\r
2479 {\r
2480 /* Logicals are allowed to alter SR/CCR */\r
2481\r
2482 if ((!SetX) && (Dest == 11) && (Size != 'L') && (type != 6))\r
2483 {\r
2484 Align();\r
2485\r
2486 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
2487 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
2488 TimingCycles += 20 ;\r
2489\r
2490 if (Size=='W')\r
2491 {\r
2492 /* If SR then must be in Supervisor Mode */\r
2493\r
2494 char *Label = GenerateLabel(0,1);\r
2495\r
2496 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
2497 fprintf(fp, "\t\t jne near %s\n\n",Label);\r
2498\r
2499 /* User Mode - Exception */\r
2500\r
2501 Exception(8,BaseCode);\r
2502\r
2503 fprintf(fp, "%s:\n",Label);\r
2504 }\r
2505\r
2506 /* Immediate Mode Data */\r
2507 EffectiveAddressRead(11,Size,EBX,EBX,"---DS-B",TRUE);\r
2508\r
2509 ReadCCR(Size,ECX);\r
2510\r
2511 fprintf(fp, "\t\t %s %s,%s\n", OpcodeName[type], Regname, RegnameEBX );\r
2512\r
2513 WriteCCR(Size);\r
2514\r
2515 Completed();\r
2516 }\r
2517 else\r
2518 {\r
2519\r
2520 /* Illegal Opcode */\r
2521\r
2522 OpcodeArray[BaseCode] = -1;\r
2523 BaseCode = -1;\r
2524 }\r
2525 }\r
2526 }\r
2527 else\r
2528 {\r
2529 BaseCode = -2;\r
2530 }\r
2531\r
2532 OpcodeArray[Opcode] = BaseCode;\r
2533}\r
2534\r
2535void immediate(void)\r
2536{\r
2537 int type, size, mode, sreg ;\r
2538\r
2539 for (type = 0 ; type < 0x7; type++)\r
2540 for (size = 0 ; size < 3 ; size++)\r
2541 for (mode = 0 ; mode < 8 ; mode++)\r
2542 for (sreg = 0 ; sreg < 8 ; sreg++)\r
2543 dump_imm( type, size, mode, sreg ) ;\r
2544}\r
2545\r
2546\r
2547/*\r
2548 * Bitwise Codes\r
2549 *\r
2550 */\r
2551\r
2552void dump_bit_dynamic( int sreg, int type, int mode, int dreg )\r
2553{\r
2554 int Opcode, BaseCode ;\r
2555 char Size ;\r
2556 char *EAXReg,*ECXReg, *Label ;\r
2557 char allow[] = "0-2345678-------" ;\r
2558 int Dest ;\r
2559\r
2560 /* BTST allows x(PC) and x(PC,xr.s) - others do not */\r
2561\r
2562 if (type == 0)\r
2563 {\r
2564 allow[9] = '9';\r
2565 allow[10] = 'a';\r
2566 allow[11] = 'b'; // dave fix to nhl\r
2567 }\r
2568\r
2569 Opcode = 0x0100 | (sreg << 9) | (type<<6) | (mode<<3) | dreg ;\r
2570\r
2571 BaseCode = Opcode & 0x01f8 ;\r
2572 if (mode == 7) BaseCode |= dreg ;\r
2573\r
2574\r
2575 // A7+, A7-\r
2576\r
2577#ifdef A7ROUTINE\r
2578 if ((mode > 2) && (mode < 5))\r
2579 {\r
2580 if (dreg == 7) BaseCode |= dreg;\r
2581 }\r
2582#endif\r
2583\r
2584 Dest = EAtoAMN(Opcode, FALSE);\r
2585\r
2586 if (allow[Dest&0xf] != '-')\r
2587 {\r
2588 if (mode == 0) /* long*/\r
2589 {\r
2590 /* Modify register memory directly */\r
2591\r
2592 Size = 'L' ;\r
2593 EAXReg = REG_DAT_EBX;\r
2594 ECXReg = regnameslong[ECX];\r
2595 }\r
2596 else\r
2597 {\r
2598 Size = 'B' ;\r
2599 EAXReg = regnamesshort[EAX];\r
2600 ECXReg = regnamesshort[ECX];\r
2601 }\r
2602\r
2603 if (OpcodeArray[BaseCode] == -2)\r
2604 {\r
2605 Align();\r
2606 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
2607\r
2608 /* Save Previous PC if Memory Access */\r
2609\r
2610 if ((Dest >= 2) && (Dest <=10))\r
2611 SavePreviousPC();\r
2612\r
2613 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
2614\r
2615 if (mode<2)\r
2616 {\r
2617 switch (type)\r
2618 {\r
2619 case 0:\r
2620 TimingCycles += 6 ;\r
2621 break;\r
2622 case 1:\r
2623 case 3:\r
2624 TimingCycles += 8 ;\r
2625 break;\r
2626 case 2:\r
2627 TimingCycles += 10;\r
2628 break;\r
2629 }\r
2630 }\r
2631 else\r
2632 {\r
2633 if (type==0)\r
2634 TimingCycles += 4;\r
2635 else\r
2636 TimingCycles += 8;\r
2637 }\r
2638\r
2639 /* Only need this sorted out if a register is involved */\r
2640\r
2641 if (Dest < 7)\r
2642 {\r
2643 fprintf(fp, "\t\t mov ebx,ecx\n");\r
2644 fprintf(fp, "\t\t and ebx,byte 7\n");\r
2645 }\r
2646\r
2647 /* Get bit number and create mask in ECX */\r
2648\r
2649 fprintf(fp, "\t\t shr ecx, byte 9\n");\r
2650 fprintf(fp, "\t\t and ecx, byte 7\n");\r
2651 fprintf(fp, "\t\t mov ecx, [%s+ECX*4]\n",REG_DAT);\r
2652\r
2653 if (Size == 'L')\r
2654 fprintf(fp, "\t\t and ecx, byte 31\n");\r
2655 else\r
2656 fprintf(fp, "\t\t and ecx, byte 7\n");\r
2657\r
2658 #ifdef QUICKZERO\r
2659 fprintf(fp,"\t\t mov eax,1\n");\r
2660 #else\r
2661 fprintf(fp,"\t\t xor eax,eax\n");\r
2662 fprintf(fp,"\t\t inc eax\n");\r
2663 #endif\r
2664\r
2665 fprintf(fp,"\t\t shl eax,cl\n");\r
2666 fprintf(fp,"\t\t mov ecx,eax\n");\r
2667\r
2668 if (mode != 0)\r
2669 EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",TRUE);\r
2670\r
2671\r
2672 /* All commands copy existing bit to Zero Flag */\r
2673\r
2674 Label = GenerateLabel(0,1);\r
2675\r
2676 fprintf(fp,"\t\t or edx,byte 40h\t; Set Zero Flag\n");\r
2677 fprintf(fp,"\t\t test %s,%s\n",EAXReg,ECXReg);\r
2678 fprintf(fp,"\t\t jz short %s\n",Label);\r
2679 fprintf(fp,"\t\t xor edx,byte 40h\t; Clear Zero Flag\n");\r
2680 fprintf(fp,"%s:\n",Label);\r
2681\r
2682 /* Some then modify the data */\r
2683\r
2684 switch (type)\r
2685 {\r
2686 case 0: /* btst*/\r
2687 break;\r
2688\r
2689 case 1: /* bchg*/\r
2690 fprintf(fp,"\t\t xor %s,%s\n",EAXReg,ECXReg);\r
2691 break;\r
2692\r
2693 case 2: /* bclr*/\r
2694 fprintf(fp,"\t\t not ecx\n");\r
2695 fprintf(fp,"\t\t and %s,%s\n",EAXReg,ECXReg);\r
2696 break;\r
2697\r
2698 case 3: /* bset*/\r
2699 fprintf(fp,"\t\t or %s,%s\n",EAXReg,ECXReg);\r
2700 break;\r
2701 }\r
2702\r
2703 if ((mode !=0) && (type != 0))\r
2704 EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",TRUE);\r
2705\r
2706 Completed();\r
2707 }\r
2708\r
2709 OpcodeArray[Opcode] = BaseCode ;\r
2710 }\r
2711}\r
2712\r
2713void bitdynamic(void) /* dynamic non-immediate bit operations*/\r
2714{\r
2715 int type, sreg, mode, dreg ;\r
2716\r
2717 for (sreg = 0 ; sreg < 8 ; sreg++)\r
2718 for (type = 0 ; type < 4 ; type++)\r
2719 for (mode = 0 ; mode < 8 ;mode++)\r
2720 for (dreg = 0 ; dreg < 8 ;dreg++)\r
2721 dump_bit_dynamic( sreg, type, mode, dreg ) ;\r
2722}\r
2723\r
2724void dump_bit_static(int type, int mode, int dreg )\r
2725{\r
2726 int Opcode, BaseCode ;\r
2727 char Size ;\r
2728 char *EAXReg,*ECXReg, *Label ;\r
2729 char allow[] = "0-2345678-------" ;\r
2730 int Dest ;\r
2731\r
2732 /* BTST allows x(PC) and x(PC,xr.s) - others do not */\r
2733\r
2734 if (type == 0)\r
2735 {\r
2736 allow[9] = '9';\r
2737 allow[10] = 'a';\r
2738 }\r
2739\r
2740 Opcode = 0x0800 | (type<<6) | (mode<<3) | dreg ;\r
2741 BaseCode = Opcode & 0x08f8 ;\r
2742 if (mode == 7) BaseCode |= dreg ;\r
2743\r
2744 // A7+, A7-\r
2745\r
2746#ifdef A7ROUTINE\r
2747 if ((mode > 2) && (mode < 5))\r
2748 {\r
2749 if (dreg == 7) BaseCode |= dreg;\r
2750 }\r
2751#endif\r
2752\r
2753 Dest = EAtoAMN(Opcode, FALSE);\r
2754\r
2755 if (allow[Dest&0xf] != '-')\r
2756 {\r
2757 if (mode == 0) /* long*/\r
2758 {\r
2759 /* Modify register memory directly */\r
2760\r
2761 Size = 'L' ;\r
2762 EAXReg = REG_DAT_EBX;\r
2763 ECXReg = regnameslong[ECX];\r
2764 }\r
2765 else\r
2766 {\r
2767 Size = 'B' ;\r
2768 EAXReg = regnamesshort[EAX];\r
2769 ECXReg = regnamesshort[ECX];\r
2770 }\r
2771\r
2772 if (OpcodeArray[BaseCode] == -2)\r
2773 {\r
2774 Align();\r
2775 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
2776\r
2777 /* Save Previous PC if Memory Access */\r
2778\r
2779 if ((Dest >= 2) && (Dest <=10))\r
2780 SavePreviousPC();\r
2781\r
2782 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
2783\r
2784 if (mode<2)\r
2785 {\r
2786 switch (type)\r
2787 {\r
2788 case 0:\r
2789 TimingCycles += 10 ;\r
2790 break ;\r
2791 case 1:\r
2792 case 3:\r
2793 TimingCycles += 12 ;\r
2794 break ;\r
2795 case 2:\r
2796 TimingCycles += 14 ;\r
2797 break ;\r
2798 }\r
2799 }\r
2800 else\r
2801 {\r
2802 if (type != 0)\r
2803 TimingCycles += 12 ;\r
2804 else\r
2805 TimingCycles += 8 ;\r
2806 }\r
2807\r
2808 /* Only need this sorted out if a register is involved */\r
2809\r
2810 if (Dest < 7)\r
2811 {\r
2812 fprintf(fp, "\t\t mov ebx,ecx\n");\r
2813 fprintf(fp, "\t\t and ebx, byte 7\n");\r
2814 }\r
2815\r
2816 /* Get bit number and create mask in ECX */\r
2817\r
2818 Memory_Fetch('W',ECX,FALSE);\r
2819 fprintf(fp, "\t\t add esi,byte 2\n");\r
2820\r
2821 if (Size == 'L')\r
2822 fprintf(fp, "\t\t and ecx, byte 31\n");\r
2823 else\r
2824 fprintf(fp, "\t\t and ecx, byte 7\n");\r
2825\r
2826 #ifdef QUICKZERO\r
2827 fprintf(fp,"\t\t mov eax,1\n");\r
2828 #else\r
2829 fprintf(fp,"\t\t xor eax,eax\n");\r
2830 fprintf(fp,"\t\t inc eax\n");\r
2831 #endif\r
2832\r
2833 fprintf(fp,"\t\t shl eax,cl\n");\r
2834 fprintf(fp,"\t\t mov ecx,eax\n");\r
2835\r
2836 if (mode != 0)\r
2837 EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",TRUE);\r
2838\r
2839 /* All commands copy existing bit to Zero Flag */\r
2840\r
2841 Label = GenerateLabel(0,1);\r
2842\r
2843 fprintf(fp,"\t\t or edx,byte 40h\t; Set Zero Flag\n");\r
2844 fprintf(fp,"\t\t test %s,%s\n",EAXReg,ECXReg);\r
2845 fprintf(fp,"\t\t jz short %s\n",Label);\r
2846 fprintf(fp,"\t\t xor edx,byte 40h\t; Clear Zero Flag\n");\r
2847 fprintf(fp,"%s:\n",Label);\r
2848\r
2849 /* Some then modify the data */\r
2850\r
2851 switch (type)\r
2852 {\r
2853 case 0: /* btst*/\r
2854 break;\r
2855\r
2856 case 1: /* bchg*/\r
2857 fprintf(fp,"\t\t xor %s,%s\n",EAXReg,ECXReg);\r
2858 break;\r
2859\r
2860 case 2: /* bclr*/\r
2861 fprintf(fp,"\t\t not ecx\n");\r
2862 fprintf(fp,"\t\t and %s,%s\n",EAXReg,ECXReg);\r
2863 break;\r
2864\r
2865 case 3: /* bset*/\r
2866 fprintf(fp,"\t\t or %s,%s\n",EAXReg,ECXReg);\r
2867 break;\r
2868 }\r
2869\r
2870 if ((mode !=0) && (type != 0))\r
2871 EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",TRUE);\r
2872\r
2873 Completed();\r
2874 }\r
2875\r
2876 OpcodeArray[Opcode] = BaseCode ;\r
2877 }\r
2878}\r
2879\r
2880\r
2881void bitstatic(void) /* static non-immediate bit operations*/\r
2882{\r
2883 int type, mode, dreg ;\r
2884\r
2885 for (type = 0 ; type < 4 ; type++)\r
2886 for (mode = 0 ; mode < 8 ;mode++)\r
2887 for (dreg = 0 ; dreg < 8 ;dreg++)\r
2888 dump_bit_static( type, mode, dreg ) ;\r
2889}\r
2890\r
2891/*\r
2892 * Move Peripheral\r
2893 *\r
2894 */\r
2895\r
2896void movep(void)\r
2897{\r
2898 int sreg,dir,leng,dreg ;\r
2899 int Opcode, BaseCode ;\r
2900\r
2901 for (sreg = 0 ; sreg < 8 ; sreg++)\r
2902 {\r
2903 for (dir = 0 ; dir < 2 ; dir++)\r
2904 {\r
2905 for (leng = 0 ; leng < 2 ; leng++)\r
2906 {\r
2907 for (dreg = 0 ; dreg < 8 ; dreg++)\r
2908 {\r
2909 Opcode = 0x0108 | (sreg<<9) | (dir<<7) | (leng<<6) | dreg;\r
2910 BaseCode = Opcode & 0x01c8 ;\r
2911 if (OpcodeArray[BaseCode] == -2)\r
2912 {\r
2913 Align();\r
2914 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
2915 SavePreviousPC();\r
2916 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
2917\r
2918 if (leng == 0) /* word */\r
2919 TimingCycles += 16 ;\r
2920 else\r
2921 TimingCycles += 24 ;\r
2922\r
2923 /* Save Flags Register (so we only do it once) */\r
2924\r
2925 fprintf(fp, "\t\t push edx\n");\r
2926\r
2927 fprintf(fp, "\t\t mov ebx,ecx\n");\r
2928 fprintf(fp, "\t\t and ebx,byte 7\n");\r
2929\r
2930 /* Get Address to Read/Write in EDI */\r
2931\r
2932 EffectiveAddressCalculate(5,'L',EBX,FALSE);\r
2933\r
2934 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
2935 fprintf(fp, "\t\t and ecx,byte 7\n");\r
2936\r
2937\r
2938 if (dir == 0) /* from memory to register*/\r
2939 {\r
2940 Memory_Read('B',EDI,"-BC-SDB",2); /* mask first call */\r
2941 fprintf(fp,"\t\t mov bh,al\n");\r
2942 fprintf(fp,"\t\t add edi,byte 2\n");\r
2943 Memory_Read('B',EDI,"-BC-SDB",0); /* not needed then */\r
2944 fprintf(fp,"\t\t mov bl,al\n");\r
2945\r
2946 if (leng == 0) /* word d(Ax) into Dx.W*/\r
2947 {\r
2948 fprintf(fp,"\t\t mov [%s+ecx*4],bx\n",REG_DAT);\r
2949 }\r
2950 else /* long d(Ax) into Dx.L*/\r
2951 {\r
2952 fprintf(fp,"\t\t add edi,byte 2\n");\r
2953 fprintf(fp,"\t\t shl ebx,16\n");\r
2954 Memory_Read('B',EDI,"-BC-SDB",0);\r
2955 fprintf(fp,"\t\t mov bh,al\n");\r
2956 fprintf(fp,"\t\t add edi,byte 2\n");\r
2957 Memory_Read('B',EDI,"-BC-S-B",0);\r
2958 fprintf(fp,"\t\t mov bl,al\n");\r
2959 fprintf(fp,"\t\t mov [%s+ecx*4],ebx\n",REG_DAT);\r
2960 }\r
2961 }\r
2962 else /* Register to Memory*/\r
2963 {\r
2964 fprintf(fp,"\t\t mov eax,[%s+ecx*4]\n",REG_DAT);\r
2965\r
2966 /* Move bytes into Line */\r
2967\r
2968 if (leng == 1)\r
2969 fprintf(fp,"\t\t rol eax,byte 8\n");\r
2970 else\r
2971 fprintf(fp,"\t\t rol eax,byte 24\n");\r
2972\r
2973 Memory_Write('B',EDI,EAX,"A---SDB",2); /* Mask First */\r
2974 fprintf(fp,"\t\t add edi,byte 2\n");\r
2975 fprintf(fp,"\t\t rol eax,byte 8\n");\r
2976\r
2977 if (leng == 1) /* long*/\r
2978 {\r
2979 Memory_Write('B',EDI,EAX,"A---SDB",0);\r
2980 fprintf(fp,"\t\t add edi,byte 2\n");\r
2981 fprintf(fp,"\t\t rol eax,byte 8\n");\r
2982 Memory_Write('B',EDI,EAX,"A---SDB",0);\r
2983 fprintf(fp,"\t\t add edi,byte 2\n");\r
2984 fprintf(fp,"\t\t rol eax,byte 8\n");\r
2985 }\r
2986 Memory_Write('B',EDI,EAX,"A---S-B",0);\r
2987 }\r
2988\r
2989 fprintf(fp, "\t\t pop edx\n");\r
2990 Completed();\r
2991 }\r
2992\r
2993 OpcodeArray[Opcode] = BaseCode ;\r
2994 }\r
2995 }\r
2996 }\r
2997 }\r
2998}\r
2999\r
3000void movecodes(int allowfrom[],int allowto[],int Start,char Size) /* MJC */\r
3001{\r
3002 int Opcode;\r
3003 int Src,Dest;\r
3004 int SaveEDX;\r
3005 int BaseCode;\r
3006\r
3007 for (Opcode=Start;Opcode<Start+0x1000;Opcode++)\r
3008 {\r
3009 /* Mask our Registers */\r
3010\r
3011 BaseCode = Opcode & (Start + 0x1f8);\r
3012\r
3013 /* Unless Mode = 7 */\r
3014\r
3015 if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7);\r
3016 if ((BaseCode & 0x1c0) == 0x1c0) BaseCode |= (Opcode & 0xE00);\r
3017\r
3018 /* If mode = 3 or 4 and Size = byte and register = A7 */\r
3019 /* then make it a separate code */\r
3020\r
3021#ifdef A7ROUTINE\r
3022 if (Size == 'B')\r
3023 {\r
3024 if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27))\r
3025 {\r
3026 BaseCode |= 0x07;\r
3027 }\r
3028\r
3029 if (((Opcode & 0xFC0) == 0xEC0) || ((Opcode & 0xFC0) == 0xF00))\r
3030 {\r
3031 BaseCode |= 0x0E00;\r
3032 }\r
3033 }\r
3034#endif\r
3035\r
3036 /* If Source = Data or Address register - combine into same routine */\r
3037\r
3038 if (((Opcode & 0x38) == 0x08) && (allowfrom[1]))\r
3039 {\r
3040 BaseCode &= 0xfff7;\r
3041 }\r
3042\r
3043 if (OpcodeArray[BaseCode] == -2)\r
3044 {\r
3045 Src = EAtoAMN(Opcode, FALSE);\r
3046 Dest = EAtoAMN(Opcode >> 6, TRUE);\r
3047\r
3048 if ((allowfrom[(Src & 15)]) && (allowto[(Dest & 15)]))\r
3049 {\r
3050 /* If we are not going to calculate the flags */\r
3051 /* we need to preserve the existing ones */\r
3052\r
3053 SaveEDX = (Dest == 1);\r
3054\r
3055 Align();\r
3056 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3057\r
3058 if (((Src >= 2) && (Src <= 10)) || ((Dest >= 2) && (Dest <=10)))\r
3059 SavePreviousPC();\r
3060\r
3061 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3062\r
3063\r
3064 TimingCycles += 4 ;\r
3065\r
3066 if (Src < 7)\r
3067 {\r
3068 if (Dest < 7)\r
3069 {\r
3070 fprintf(fp, "\t\t mov ebx,ecx\n");\r
3071\r
3072 if ((Src == 0) && allowfrom[1])\r
3073 fprintf(fp, "\t\t and ebx,byte 15\n");\r
3074 else\r
3075 fprintf(fp, "\t\t and ebx,byte 7\n");\r
3076\r
3077 EffectiveAddressRead(Src,Size,EBX,EAX,"--CDS-B",SaveEDX);\r
3078 }\r
3079 else\r
3080 {\r
3081 if ((Src == 0) && allowfrom[1])\r
3082 fprintf(fp, "\t\t and ecx,byte 15\n");\r
3083 else\r
3084 fprintf(fp, "\t\t and ecx,byte 7\n");\r
3085\r
3086 EffectiveAddressRead(Src,Size,ECX,EAX,"---DS-B",SaveEDX);\r
3087 }\r
3088 }\r
3089 else\r
3090 {\r
3091 if (Dest < 7)\r
3092 EffectiveAddressRead(Src,Size,EBX,EAX,"--CDS-B",SaveEDX);\r
3093 else\r
3094 EffectiveAddressRead(Src,Size,EBX,EAX,"---DS-B",SaveEDX);\r
3095 }\r
3096\r
3097 /* No flags if Destination Ax */\r
3098\r
3099 if (!SaveEDX)\r
3100 {\r
3101 SetFlags(Size,EAX,TRUE,FALSE,TRUE);\r
3102 }\r
3103\r
3104 if (Dest < 7)\r
3105 {\r
3106 fprintf(fp, "\t\t shr ecx,9\n");\r
3107 fprintf(fp, "\t\t and ecx,byte 7\n");\r
3108 }\r
3109\r
3110 EffectiveAddressWrite(Dest,Size,ECX,TRUE,"---DS-B",SaveEDX);\r
3111\r
3112 Completed();\r
3113 }\r
3114 else\r
3115 {\r
3116 BaseCode = -1; /* Invalid Code */\r
3117 }\r
3118 }\r
3119 else\r
3120 {\r
3121 BaseCode = OpcodeArray[BaseCode];\r
3122 }\r
3123\r
3124 if (OpcodeArray[Opcode] < 0)\r
3125 OpcodeArray[Opcode] = BaseCode;\r
3126 }\r
3127}\r
3128\r
3129void moveinstructions(void)\r
3130{\r
3131 int allowfrom[] = {1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0};\r
3132 int allowto[] = {1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0};\r
3133\r
3134 /* For Byte */\r
3135\r
3136 movecodes(allowfrom,allowto,0x1000,'B');\r
3137\r
3138 /* For Word & Long */\r
3139\r
3140 allowto[1] = 1;\r
3141 movecodes(allowfrom,allowto,0x2000,'L');\r
3142 movecodes(allowfrom,allowto,0x3000,'W');\r
3143}\r
3144\r
3145/*\r
3146 *\r
3147 * Opcodes 5###\r
3148 *\r
3149 * ADDQ,SUBQ,Scc and DBcc\r
3150 *\r
3151 */\r
3152\r
3153void opcode5(void)\r
3154{\r
3155 /* ADDQ,SUBQ,Scc and DBcc */\r
3156\r
3157 int allowtoScc[] = {1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0};\r
3158 int allowtoADDQ[] = {1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0};\r
3159 int Opcode,BaseCode;\r
3160 char Label[32];\r
3161 char Label2[32];\r
3162 char Size=' ';\r
3163 char* Regname="";\r
3164 char* RegnameECX="";\r
3165\r
3166 for (Opcode = 0x5000;Opcode < 0x6000;Opcode++)\r
3167 {\r
3168 if ((Opcode & 0xc0) == 0xc0)\r
3169 {\r
3170 /* Scc or DBcc */\r
3171\r
3172 BaseCode = Opcode & 0x5FF8;\r
3173 if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7);\r
3174\r
3175 /* If mode = 3 or 4 and register = A7 */\r
3176 /* then make it a separate code */\r
3177\r
3178#ifdef A7ROUTINE\r
3179 if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27))\r
3180 {\r
3181 BaseCode |= 0x07;\r
3182 }\r
3183#endif\r
3184\r
3185 if (OpcodeArray[BaseCode] == -2)\r
3186 {\r
3187 OpcodeArray[BaseCode] = BaseCode;\r
3188\r
3189 if ((BaseCode & 0x38) == 0x8)\r
3190 {\r
3191 /* DBcc */\r
3192\r
3193 Align();\r
3194 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3195\r
3196 TimingCycles += 10 ;\r
3197\r
3198\r
3199 strcpy(Label,GenerateLabel(BaseCode,1)) ;\r
3200 strcpy(Label2,ConditionDecode((Opcode >> 8) & 0x0F,TRUE));\r
3201\r
3202 /* False - Decrement Counter - Loop if not -1 */\r
3203\r
3204 fprintf(fp, "\t\t and ecx,byte 7\n");\r
3205 fprintf(fp, "\t\t mov ax,[%s+ecx*4]\n",REG_DAT);\r
3206 fprintf(fp, "\t\t dec ax\n");\r
3207 fprintf(fp, "\t\t mov [%s+ecx*4],ax\n",REG_DAT);\r
3208 fprintf(fp, "\t\t inc ax\t\t; Is it -1\n");\r
3209 fprintf(fp, "\t\t jz short %s\n",Label);\r
3210\r
3211 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3212 Memory_Fetch('W',EAX,TRUE);\r
3213 fprintf(fp, "\t\t add esi,eax\n");\r
3214 Completed();\r
3215\r
3216 /* True - Exit Loop */\r
3217 fprintf(fp, "%s:\n",Label);\r
3218\r
3219 fprintf(fp, "%s:\n",Label2);\r
3220 fprintf(fp, "\t\t add esi,byte 4\n");\r
3221 TimingCycles += 2 ;\r
3222\r
3223 Completed();\r
3224 }\r
3225 else\r
3226 {\r
3227 /* Scc */\r
3228\r
3229 int Dest = EAtoAMN(Opcode, FALSE);\r
3230\r
3231 if (allowtoScc[(Dest & 15)])\r
3232 {\r
3233 Align();\r
3234 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3235\r
3236 if ((Dest >= 2) && (Dest <=10))\r
3237 SavePreviousPC();\r
3238\r
3239 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3240\r
3241 if (Dest > 1)\r
3242 TimingCycles += 8 ;\r
3243 else\r
3244 TimingCycles += 4 ;\r
3245\r
3246 if (Dest < 7)\r
3247 {\r
3248 fprintf(fp, "\t\t and ecx,byte 7\n");\r
3249 }\r
3250\r
3251 if (Dest > 1)\r
3252 {\r
3253 EffectiveAddressCalculate(Dest,'B',ECX,TRUE);\r
3254 /* ASG - no longer need to mask addresses here */\r
3255/* fprintf(fp,"\t\t and edi,0FFFFFFh\n");*/\r
3256 }\r
3257\r
3258 ConditionCheck((Opcode >> 8) & 0x0F,"AL");\r
3259\r
3260 EffectiveAddressWrite(Dest,'B',ECX,FALSE,"---DS-B",TRUE);\r
3261\r
3262 /* take advantage of AL being 0 for false, 0xff for true */\r
3263 /* need to add 2 cycles if register and condition is true */\r
3264\r
3265 if (Dest == 0)\r
3266 {\r
3267 fprintf(fp, "\t\t and eax,byte 2\n");\r
3268 fprintf(fp, "\t\t add eax,byte %d\n",TimingCycles);\r
3269 fprintf(fp, "\t\t sub dword [%s],eax\n",ICOUNT);\r
3270\r
3271 TimingCycles = -1;\r
3272 }\r
3273 Completed();\r
3274 }\r
3275 else\r
3276 {\r
3277 OpcodeArray[BaseCode] = -1;\r
3278 BaseCode = -1;\r
3279 }\r
3280 }\r
3281 }\r
3282 else\r
3283 {\r
3284 BaseCode = OpcodeArray[BaseCode];\r
3285 }\r
3286\r
3287 OpcodeArray[Opcode] = BaseCode;\r
3288 }\r
3289 else\r
3290 {\r
3291 /* ADDQ or SUBQ */\r
3292\r
3293 BaseCode = Opcode & 0x51F8;\r
3294 if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7);\r
3295\r
3296 /* Special for Address Register Direct - Force LONG */\r
3297\r
3298 if ((Opcode & 0x38) == 0x8) BaseCode = ((BaseCode & 0xFF3F) | 0x80);\r
3299\r
3300\r
3301 /* If mode = 3 or 4 and Size = byte and register = A7 */\r
3302 /* then make it a separate code */\r
3303\r
3304#ifdef A7ROUTINE\r
3305 if ((Opcode & 0xC0) == 0)\r
3306 {\r
3307 if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27))\r
3308 {\r
3309 BaseCode |= 0x07;\r
3310 }\r
3311 }\r
3312#endif\r
3313\r
3314 if (OpcodeArray[BaseCode] == -2)\r
3315 {\r
3316 char *Operation;\r
3317 int Dest = EAtoAMN(Opcode, FALSE);\r
3318 int SaveEDX = (Dest == 1);\r
3319\r
3320 if (allowtoADDQ[(Dest & 15)])\r
3321 {\r
3322 switch (BaseCode & 0xC0)\r
3323 {\r
3324 case 0:\r
3325 Size = 'B';\r
3326 Regname = regnamesshort[0];\r
3327 RegnameECX = regnamesshort[ECX];\r
3328 break;\r
3329\r
3330 case 0x40:\r
3331 Size = 'W';\r
3332 Regname = regnamesword[0];\r
3333 RegnameECX = regnamesword[ECX];\r
3334 break;\r
3335\r
3336 case 0x80:\r
3337 Size = 'L';\r
3338 Regname = regnameslong[0];\r
3339 RegnameECX = regnameslong[ECX];\r
3340 break;\r
3341 }\r
3342\r
3343 OpcodeArray[BaseCode] = BaseCode;\r
3344\r
3345 Align();\r
3346 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3347\r
3348 if ((Dest >= 2) && (Dest <=10))\r
3349 SavePreviousPC();\r
3350\r
3351 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3352\r
3353 if (Dest == 0) /* write to Dx */\r
3354 {\r
3355 if (Size != 'L')\r
3356 TimingCycles += 4 ;\r
3357 else\r
3358 TimingCycles += 8 ;\r
3359 }\r
3360\r
3361 if (Dest == 1)\r
3362 {\r
3363 if ((Size == 'L') || (Opcode & 0x100)) /* if long or SUBQ */\r
3364 TimingCycles += 8 ;\r
3365 else\r
3366 TimingCycles += 4 ;\r
3367 }\r
3368\r
3369 if (Dest > 1) /* write to mem */\r
3370 {\r
3371 if (Size != 'L')\r
3372 TimingCycles += 8 ;\r
3373 else\r
3374 TimingCycles += 12 ;\r
3375 }\r
3376\r
3377 if (Dest < 7)\r
3378 {\r
3379 fprintf(fp, "\t\t mov ebx,ecx\n");\r
3380 fprintf(fp, "\t\t and ebx,byte 7\n");\r
3381 }\r
3382\r
3383 if (Dest > 1)\r
3384 {\r
3385 EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",SaveEDX);\r
3386 }\r
3387\r
3388 /* Sub Immediate from Opcode */\r
3389\r
3390 fprintf(fp, "\t\t shr ecx,9\n");\r
3391\r
3392 Immediate8();\r
3393\r
3394 if (Opcode & 0x100)\r
3395 {\r
3396 /* SUBQ */\r
3397 Operation = "sub";\r
3398 }\r
3399 else\r
3400 {\r
3401 /* ADDQ */\r
3402 Operation = "add";\r
3403 }\r
3404\r
3405 /* For Data or Address register, operate directly */\r
3406 /* on the memory location. Don't load into EAX */\r
3407\r
3408 if (Dest < 2)\r
3409 {\r
3410 if (Dest == 0)\r
3411 {\r
3412 fprintf(fp, "\t\t %s [%s+ebx*4],%s\n",Operation,REG_DAT,RegnameECX);\r
3413 }\r
3414 else\r
3415 {\r
3416 fprintf(fp, "\t\t %s [%s+ebx*4],%s\n",Operation,REG_ADD,RegnameECX);\r
3417 }\r
3418 }\r
3419 else\r
3420 {\r
3421 fprintf(fp, "\t\t %s %s,%s\n",Operation,Regname,RegnameECX);\r
3422 }\r
3423\r
3424 /* No Flags for Address Direct */\r
3425\r
3426 if (!SaveEDX)\r
3427 {\r
3428 /* Directly after ADD or SUB, so test not needed */\r
3429\r
3430 SetFlags(Size,EAX,FALSE,TRUE,TRUE);\r
3431 }\r
3432\r
3433 if (Dest > 1)\r
3434 {\r
3435 EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",FALSE);\r
3436 }\r
3437\r
3438 Completed();\r
3439 }\r
3440 else\r
3441 {\r
3442 OpcodeArray[BaseCode] = -1;\r
3443 BaseCode = -1;\r
3444 }\r
3445 }\r
3446 else\r
3447 {\r
3448 BaseCode = OpcodeArray[BaseCode];\r
3449 }\r
3450\r
3451 OpcodeArray[Opcode] = BaseCode;\r
3452 }\r
3453 }\r
3454}\r
3455\r
3456/*\r
3457 * Branch Instructions\r
3458 *\r
3459 * BSR, Bcc\r
3460 *\r
3461 */\r
3462\r
3463void branchinstructions(void)\r
3464{\r
3465 int Opcode,BaseCode;\r
3466 int Counter;\r
3467 char *Label;\r
3468 char jmpLabel[40] ;\r
3469\r
3470 for (Opcode = 0x60;Opcode < 0x70;Opcode++)\r
3471 {\r
3472 /* Displacement = 0 -> 16 Bit displacement */\r
3473\r
3474 BaseCode = Opcode * 0x100;\r
3475 OpcodeArray[BaseCode] = BaseCode;\r
3476\r
3477 Align();\r
3478 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3479 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3480\r
3481 TimingCycles += 10 ;\r
3482\r
3483 if (Opcode == 0x60)\r
3484 {\r
3485 Memory_Fetch('W',EAX,TRUE);\r
3486 fprintf(fp, "\t\t add esi,eax\n");\r
3487 MemoryBanking(BaseCode);\r
3488 Completed();\r
3489 }\r
3490 else\r
3491 {\r
3492 if (Opcode != 0x61)\r
3493 {\r
3494 Label = ConditionDecode(Opcode & 0x0F,TRUE);\r
3495\r
3496 /* Code for Failed branch */\r
3497\r
3498 fprintf(fp, "\t\t add esi,byte 2\n");\r
3499\r
3500 /* 2 less cycles for Failure */\r
3501\r
3502 TimingCycles -= 2;\r
3503 Completed();\r
3504 TimingCycles += 2;\r
3505\r
3506 /* Successful Branch */\r
3507\r
3508 Align();\r
3509 fprintf(fp, "%s:\n",Label);\r
3510\r
3511 Memory_Fetch('W',EAX,TRUE);\r
3512 fprintf(fp, "\t\t add esi,eax\n");\r
3513 MemoryBanking(BaseCode+2);\r
3514 Completed();\r
3515\r
3516 }\r
3517 else\r
3518 {\r
3519 /* BSR - Special Case */\r
3520\r
3521 TimingCycles += 8 ;\r
3522\r
3523 Memory_Fetch('W',EBX,TRUE);\r
3524 fprintf(fp, "\t\t add ebx,esi\n");\r
3525\r
3526 fprintf(fp, "\t\t add esi,byte 2\n");\r
3527 PushPC(ECX,EAX,"-B-DS-B",1);\r
3528\r
3529 fprintf(fp, "\t\t mov esi,ebx\n");\r
3530 MemoryBanking(BaseCode+3);\r
3531 Completed();\r
3532 }\r
3533 }\r
3534\r
3535 /* 8 Bit Displacement */\r
3536\r
3537 Align();\r
3538 fprintf(fp, "%s:\n",GenerateLabel(BaseCode+1,0));\r
3539 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3540\r
3541 TimingCycles += 10 ;\r
3542\r
3543 if (Opcode > 0x60)\r
3544 {\r
3545 if (Opcode != 0x61)\r
3546 {\r
3547 Label = ConditionDecode(Opcode & 0x0F,TRUE);\r
3548\r
3549 /* Code for Failed branch */\r
3550\r
3551 TimingCycles -= 2;\r
3552 Completed();\r
3553 TimingCycles += 2;\r
3554\r
3555 /* Successful Branch */\r
3556\r
3557 Align();\r
3558 fprintf(fp, "%s:\n",Label);\r
3559 }\r
3560 else\r
3561 {\r
3562 /* BSR - Special Case */\r
3563\r
3564 TimingCycles += 8 ;\r
3565\r
3566 PushPC(EDI,EBX,"--CDS-B",1);\r
3567 }\r
3568 }\r
3569\r
3570 /* Common Ending */\r
3571\r
3572 fprintf(fp, "\t\t movsx eax,cl ; Sign Extend displacement\n");\r
3573 fprintf(fp, "\t\t add esi,eax\n");\r
3574 MemoryBanking(BaseCode+5);\r
3575 Completed();\r
3576\r
3577 /* Fill up Opcode Array */\r
3578\r
3579 for (Counter=1;Counter<0x100;Counter++)\r
3580 OpcodeArray[BaseCode+Counter] = BaseCode+1;\r
3581\r
3582 if(CPU==2)\r
3583 {\r
3584\r
3585 /* 8 bit 0xff & 68020 instruction - 32 bit displacement */\r
3586\r
3587 Align();\r
3588 fprintf(fp, "%s:\n",GenerateLabel(BaseCode+0xff,0));\r
3589 sprintf( jmpLabel, GenerateLabel(BaseCode+0xff,1) ) ;\r
3590 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3591\r
3592 TimingCycles += 10 ;\r
3593\r
3594 if (Opcode == 0x60)\r
3595 {\r
3596 /* bra - always branch */\r
3597 Memory_Fetch('L',EAX,FALSE);\r
3598 fprintf(fp, "\t\t add esi,eax\n");\r
3599 MemoryBanking(BaseCode+6);\r
3600 Completed();\r
3601 }\r
3602 else\r
3603 {\r
3604 if (Opcode != 0x61)\r
3605 {\r
3606 Label = ConditionDecode(Opcode & 0x0F,TRUE);\r
3607\r
3608 /* Code for Failed branch */\r
3609 fprintf(fp, "\t\t add esi,byte 4\n");\r
3610\r
3611 TimingCycles -= 2;\r
3612 Completed();\r
3613 TimingCycles += 2;\r
3614\r
3615 /* Successful Branch */\r
3616 Align();\r
3617 fprintf(fp, "%s:\n",Label);\r
3618\r
3619 Memory_Fetch('L',EAX,FALSE);\r
3620 fprintf(fp, "\t\t add esi,eax\n");\r
3621 MemoryBanking(BaseCode+8);\r
3622 Completed();\r
3623 }\r
3624 else\r
3625 {\r
3626 /* BSR - Special Case */\r
3627\r
3628 TimingCycles += 8 ;\r
3629\r
3630 Memory_Fetch('L',EBX,TRUE);\r
3631 fprintf(fp, "\t\t add ebx,esi\n");\r
3632\r
3633 fprintf(fp, "\t\t add esi,byte 4\n");\r
3634 PushPC(ECX,EAX,"-B-DS-B",1);\r
3635\r
3636 fprintf(fp, "\t\t mov esi,ebx\n");\r
3637 MemoryBanking(BaseCode+9);\r
3638 Completed();\r
3639 }\r
3640 }\r
3641\r
3642 OpcodeArray[BaseCode+0xff] = BaseCode+0xff;\r
3643 }\r
3644 }\r
3645}\r
3646\r
3647/*\r
3648 * Move Quick Commands\r
3649 *\r
3650 * Fairly simple, as only allowed to Data Registers\r
3651 *\r
3652 */\r
3653\r
3654void moveq(void)\r
3655{\r
3656 int Count;\r
3657\r
3658 /* The Code */\r
3659\r
3660 Align();\r
3661 fprintf(fp, "%s:\n",GenerateLabel(0x7000,0));\r
3662 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3663\r
3664 TimingCycles += 4 ;\r
3665\r
3666 fprintf(fp, "\t\t movsx eax,cl\n");\r
3667 fprintf(fp, "\t\t shr ecx,9\n");\r
3668 fprintf(fp, "\t\t and ecx,byte 7\n");\r
3669 SetFlags('L',EAX,TRUE,FALSE,FALSE);\r
3670 EffectiveAddressWrite(0,'L',ECX,TRUE,"---DS-B",FALSE);\r
3671 Completed();\r
3672\r
3673 /* Set OpcodeArray (Not strictly correct, since some are illegal!) */\r
3674\r
3675 for (Count=0x7000;Count<0x8000;Count++)\r
3676 {\r
3677 OpcodeArray[Count] = 0x7000;\r
3678 }\r
3679}\r
3680\r
3681/*\r
3682 * Extended version of Add & Sub commands\r
3683 *\r
3684 */\r
3685\r
3686void addx_subx(void)\r
3687{\r
3688 int Opcode, BaseCode ;\r
3689 int regx,type,leng,rm,regy,mode ;\r
3690 int ModeModX;\r
3691 int ModeModY;\r
3692 char Size=' ' ;\r
3693 char * Regname="" ;\r
3694 char * RegnameEBX="" ;\r
3695 char * Operand="";\r
3696 char * Label;\r
3697\r
3698 for (type = 0 ; type < 2 ; type ++) /* 0=subx, 1=addx */\r
3699 for (regx = 0 ; regx < 8 ; regx++)\r
3700 for (leng = 0 ; leng < 3 ; leng++)\r
3701 for (rm = 0 ; rm < 2 ; rm++)\r
3702 for (regy = 0 ; regy < 8 ; regy++)\r
3703 {\r
3704 Opcode = 0x9100 | (type<<14) | (regx<<9) | (leng<<6) | (rm<<3) | regy ;\r
3705\r
3706 BaseCode = Opcode & 0xd1c8 ;\r
3707\r
3708 ModeModX = 0;\r
3709 ModeModY = 0;\r
3710\r
3711#ifdef A7ROUTINE\r
3712 if ((rm == 1) && (leng == 0))\r
3713 {\r
3714 if (regx == 7)\r
3715 {\r
3716 BaseCode |= (regx << 9);\r
3717 ModeModY = 16;\r
3718 }\r
3719 if (regy == 7)\r
3720 {\r
3721 BaseCode |= regy;\r
3722 ModeModX = 16;\r
3723 }\r
3724 }\r
3725#endif\r
3726\r
3727 if (rm == 0)\r
3728 mode = 0 ;\r
3729 else\r
3730 mode = 4 ;\r
3731\r
3732 switch (leng)\r
3733 {\r
3734 case 0:\r
3735 Size = 'B';\r
3736 Regname = regnamesshort[0];\r
3737 RegnameEBX = regnamesshort[EBX];\r
3738 break;\r
3739 case 1:\r
3740 Size = 'W';\r
3741 Regname = regnamesword[0];\r
3742 RegnameEBX = regnamesword[EBX];\r
3743 break;\r
3744 case 2:\r
3745 Size = 'L';\r
3746 Regname = regnameslong[0];\r
3747 RegnameEBX = regnameslong[EBX];\r
3748 break;\r
3749 }\r
3750\r
3751 if (OpcodeArray[BaseCode] == -2)\r
3752 {\r
3753 if (type == 0)\r
3754 Operand = "sbb";\r
3755 else\r
3756 Operand = "adc";\r
3757\r
3758 Align();\r
3759 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3760\r
3761 if (mode == 4)\r
3762 SavePreviousPC();\r
3763\r
3764 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3765\r
3766 /* don't add in EA timing for ADDX,SUBX */\r
3767\r
3768 AddEACycles = 0 ;\r
3769\r
3770 if (rm == 0) /* reg to reg */\r
3771 {\r
3772 if (Size != 'L')\r
3773 TimingCycles += 4 ;\r
3774 else\r
3775 TimingCycles += 8 ;\r
3776 }\r
3777 else\r
3778 {\r
3779 if (Size != 'L')\r
3780 TimingCycles += 18 ;\r
3781 else\r
3782 TimingCycles += 30 ;\r
3783 }\r
3784\r
3785 fprintf(fp, "\t\t mov ebx,ecx\n");\r
3786 fprintf(fp, "\t\t and ebx, byte 7\n");\r
3787 fprintf(fp, "\t\t shr ecx, byte 9\n");\r
3788 fprintf(fp, "\t\t and ecx, byte 7\n");\r
3789\r
3790 /* Get Source */\r
3791\r
3792 EffectiveAddressRead(mode+ModeModX,Size,EBX,EBX,"--CDS-B",FALSE);\r
3793\r
3794 /* Get Destination (if needed) */\r
3795\r
3796 if (mode == 4)\r
3797 EffectiveAddressRead(mode+ModeModY,Size,ECX,EAX,"-BCDSDB",FALSE);\r
3798\r
3799 /* Copy the X flag into the Carry Flag */\r
3800\r
3801 CopyX();\r
3802\r
3803 /* Do the sums */\r
3804\r
3805 if (mode == 0)\r
3806 fprintf(fp, "\t\t %s [%s+ecx*4],%s\n",Operand,REG_DAT,RegnameEBX);\r
3807 else\r
3808 fprintf(fp, "\t\t %s %s,%s\n",Operand,Regname,RegnameEBX);\r
3809\r
3810 /* Preserve old Z flag */\r
3811\r
3812 fprintf(fp, "\t\t mov ebx,edx\n");\r
3813\r
3814 /* Set the Flags */\r
3815\r
3816 SetFlags(Size,EAX,FALSE,TRUE,FALSE);\r
3817\r
3818 /* Handle the Z flag */\r
3819\r
3820 Label = GenerateLabel(0,1);\r
3821\r
3822 fprintf(fp, "\t\t jnz short %s\n\n",Label);\r
3823\r
3824 fprintf(fp, "\t\t and dl,0BFh ; Remove Z\n");\r
3825 fprintf(fp, "\t\t and bl,40h ; Mask out Old Z\n");\r
3826 fprintf(fp, "\t\t or dl,bl ; Copy across\n\n");\r
3827 fprintf(fp, "%s:\n",Label);\r
3828\r
3829 /* Update the Data (if needed) */\r
3830\r
3831 if (mode == 4)\r
3832 EffectiveAddressWrite(mode,Size,ECX,FALSE,"---DS-B",TRUE);\r
3833\r
3834 Completed();\r
3835 }\r
3836\r
3837 OpcodeArray[Opcode] = BaseCode ;\r
3838 }\r
3839}\r
3840\r
3841/*\r
3842 * Logicals / Simple Maths (+ and -)\r
3843 *\r
3844 * OR,AND,CMP,EOR,ADD and SUB\r
3845 *\r
3846 */\r
3847\r
3848void dumpx( int start, int reg, int type, char * Op, int dir, int leng, int mode, int sreg )\r
3849{\r
3850 int Opcode,BaseCode ;\r
3851 char Size=' ' ;\r
3852 char * RegnameECX="" ;\r
3853 char * Regname="" ;\r
3854 int Dest ;\r
3855 int SaveEDX ;\r
3856 int SaveDir;\r
3857 char * allow="" ;\r
3858 char * allowtypes[] = { "0-23456789ab----", "--2345678-------",\r
3859 "0123456789ab----", "0-2345678-------"};\r
3860\r
3861 SaveDir = dir;\r
3862\r
3863 switch (type)\r
3864 {\r
3865 case 0: /* or and*/\r
3866 if (dir == 0)\r
3867 allow = allowtypes[0];\r
3868 else\r
3869 allow = allowtypes[1];\r
3870 break ;\r
3871\r
3872 case 1: /* cmp*/\r
3873 allow = allowtypes[2] ;\r
3874 break ;\r
3875\r
3876 case 2: /* eor*/\r
3877 allow = allowtypes[3] ;\r
3878 break ;\r
3879\r
3880 case 3: /* adda suba cmpa*/\r
3881 allow = allowtypes[2] ;\r
3882 break ;\r
3883\r
3884 case 4: /* sub add*/\r
3885 if (dir == 0)\r
3886 allow = allowtypes[0] ;\r
3887 else\r
3888 allow = allowtypes[1] ;\r
3889 break ;\r
3890 }\r
3891\r
3892 if ((type == 4) && (dir == 0) && (leng > 0))\r
3893 {\r
3894 allow = allowtypes[2] ; /* word and long ok*/\r
3895 }\r
3896\r
3897 Opcode = start | (reg << 9 ) | (dir<<8) | (leng<<6) | (mode<<3) | sreg;\r
3898\r
3899 BaseCode = Opcode & 0xf1f8;\r
3900\r
3901 if (mode == 7) BaseCode |= sreg ;\r
3902\r
3903#ifdef A7ROUTINE\r
3904 if ((mode == 3 || mode == 4) && ( leng == 0 ) && (sreg == 7 ))\r
3905 BaseCode |= sreg ;\r
3906#endif\r
3907\r
3908\r
3909\r
3910 /* If Source = Data or Address register - combine into same routine */\r
3911\r
3912 if (((Opcode & 0x38) == 0x08) && (allow[1] != '-'))\r
3913 {\r
3914 BaseCode &= 0xfff7;\r
3915 }\r
3916\r
3917 Dest = EAtoAMN(Opcode, FALSE);\r
3918 SaveEDX = (Dest == 1) || (type == 3);\r
3919\r
3920 if (allow[Dest&0xf] != '-')\r
3921 {\r
3922 if (OpcodeArray[BaseCode] == -2)\r
3923 {\r
3924 switch (leng)\r
3925 {\r
3926 case 0:\r
3927 Size = 'B';\r
3928 Regname = regnamesshort[0];\r
3929 RegnameECX = regnamesshort[ECX];\r
3930 break;\r
3931 case 1:\r
3932 Size = 'W';\r
3933 Regname = regnamesword[0];\r
3934 RegnameECX = regnamesword[ECX];\r
3935 break;\r
3936 case 2:\r
3937 Size = 'L';\r
3938 Regname = regnameslong[0];\r
3939 RegnameECX = regnameslong[ECX];\r
3940 break;\r
3941\r
3942 case 3: /* cmpa adda suba */\r
3943 if (dir == 0)\r
3944 {\r
3945 Size = 'W';\r
3946 Regname = regnamesword[0];\r
3947 RegnameECX = regnamesword[ECX];\r
3948 }\r
3949 else\r
3950 {\r
3951 Size = 'L';\r
3952 Regname = regnameslong[0];\r
3953 RegnameECX = regnameslong[ECX];\r
3954 }\r
3955 dir = 0 ;\r
3956 break ;\r
3957 }\r
3958\r
3959 Align();\r
3960 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
3961\r
3962 if ((Dest >= 2) && (Dest <=10))\r
3963 SavePreviousPC();\r
3964\r
3965 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
3966\r
3967 if (dir==0)\r
3968 {\r
3969 if (Size != 'L')\r
3970 TimingCycles += 4;\r
3971 else\r
3972 TimingCycles += 6;\r
3973 }\r
3974 else\r
3975 {\r
3976 if (Size != 'L')\r
3977 TimingCycles += 8;\r
3978 else\r
3979 TimingCycles += 12;\r
3980 }\r
3981\r
3982 if ((mode == 0) && (dir==0) && (Size == 'L'))\r
3983 TimingCycles += 2 ;\r
3984\r
3985 if ((mode == 1) && (dir==0) && (Size != 'L'))\r
3986 TimingCycles += 4 ;\r
3987\r
3988 if (Dest < 7) /* Others do not need reg.no. */\r
3989 {\r
3990 fprintf(fp, "\t\t mov ebx,ecx\n");\r
3991\r
3992 if ((Dest == 0) & (allow[1] != '-'))\r
3993 fprintf(fp, "\t\t and ebx,byte 15\n");\r
3994 else\r
3995 fprintf(fp, "\t\t and ebx,byte 7\n");\r
3996 }\r
3997\r
3998 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
3999 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4000\r
4001 EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",SaveEDX);\r
4002\r
4003 if (dir == 0)\r
4004 {\r
4005 if (type != 3)\r
4006 {\r
4007 fprintf(fp, "\t\t %s [%s+ECX*4],%s\n",Op ,REG_DAT ,Regname ) ;\r
4008\r
4009 if (type == 4)\r
4010 SetFlags(Size,EAX,FALSE,TRUE,FALSE);\r
4011 else\r
4012 SetFlags(Size,EAX,FALSE,FALSE,FALSE);\r
4013 }\r
4014 else\r
4015 {\r
4016 if (Size == 'W')\r
4017 fprintf(fp, "\t\t cwde\n");\r
4018\r
4019 fprintf(fp, "\t\t %s [%s+ECX*4],EAX\n",Op ,REG_ADD);\r
4020\r
4021 if (Op[0] == 'c')\r
4022 {\r
4023 SetFlags('L',EAX,FALSE,FALSE,FALSE);\r
4024 }\r
4025 }\r
4026 }\r
4027 else\r
4028 {\r
4029 fprintf(fp, "\t\t %s %s,[%s+ECX*4]\n", Op, Regname ,REG_DAT ) ;\r
4030\r
4031 if (type == 4)\r
4032 SetFlags(Size,EAX,FALSE,TRUE,TRUE);\r
4033 else\r
4034 SetFlags(Size,EAX,FALSE,FALSE,TRUE);\r
4035\r
4036 EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",FALSE);\r
4037 }\r
4038 Completed();\r
4039 }\r
4040\r
4041 OpcodeArray[Opcode] = BaseCode;\r
4042 }\r
4043\r
4044 dir = SaveDir;\r
4045}\r
4046\r
4047void typelogicalmath(void)\r
4048{\r
4049 int dir, leng, mode, sreg ,reg ;\r
4050\r
4051 for (reg = 0 ; reg < 8 ; reg++)\r
4052 {\r
4053 /* or */\r
4054 for (dir = 0 ; dir < 2 ; dir++)\r
4055 for (leng = 0 ; leng < 3; leng++)\r
4056 for (mode = 0 ; mode < 8 ; mode++)\r
4057 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4058 dumpx( 0x8000, reg, 0, "or ", dir, leng, mode, sreg ) ;\r
4059\r
4060 /* sub */\r
4061 for (dir = 0 ; dir < 2 ; dir++)\r
4062 for (leng = 0 ; leng < 3; leng++)\r
4063 for (mode = 0 ; mode < 8 ; mode++)\r
4064 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4065 dumpx( 0x9000, reg, 4, "sub", dir, leng, mode, sreg ) ;\r
4066\r
4067 /* suba */\r
4068\r
4069 for (dir = 0 ; dir < 2 ; dir++)\r
4070 for (mode = 0 ; mode < 8 ; mode++)\r
4071 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4072 dumpx( 0x9000, reg, 3, "sub", dir, 3, mode, sreg ) ;\r
4073\r
4074\r
4075 /* cmp */\r
4076 for (leng = 0 ; leng < 3; leng++)\r
4077 for (mode = 0 ; mode < 8 ; mode++)\r
4078 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4079 dumpx( 0xb000, reg, 1, "cmp", 0, leng, mode, sreg ) ;\r
4080\r
4081 /* cmpa */\r
4082\r
4083 for (dir = 0 ; dir < 2 ; dir++)\r
4084 for (mode = 0 ; mode < 8 ; mode++)\r
4085 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4086 dumpx( 0xb000, reg, 3, "cmp", dir, 3, mode, sreg ) ;\r
4087\r
4088 /* adda */\r
4089\r
4090 for (dir = 0 ; dir < 2 ; dir++)\r
4091 for (mode = 0 ; mode < 8 ; mode++)\r
4092 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4093 dumpx( 0xd000, reg, 3, "add", dir, 3, mode, sreg ) ;\r
4094\r
4095\r
4096 /* eor */\r
4097 for (leng = 0 ; leng < 3; leng++)\r
4098 for (mode = 0 ; mode < 8 ; mode++)\r
4099 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4100 dumpx( 0xb100, reg, 2, "xor", 1, leng, mode, sreg ) ;\r
4101\r
4102 /* and */\r
4103 for (dir = 0 ; dir < 2 ; dir++)\r
4104 for (leng = 0 ; leng < 3; leng++)\r
4105 for (mode = 0 ; mode < 8 ; mode++)\r
4106 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4107 dumpx( 0xc000, reg, 0, "and", dir, leng, mode, sreg ) ;\r
4108\r
4109 /* add */\r
4110 for (dir = 0 ; dir < 2 ; dir++)\r
4111 for (leng = 0 ; leng < 3; leng++)\r
4112 for (mode = 0 ; mode < 8 ; mode++)\r
4113 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4114 dumpx( 0xd000, reg, 4, "add", dir, leng, mode, sreg ) ;\r
4115 }\r
4116}\r
4117\r
4118/*\r
4119 * Single commands missed out by routines above\r
4120 *\r
4121 */\r
4122\r
4123void mul(void)\r
4124{\r
4125 int dreg, type, mode, sreg ;\r
4126 int Opcode, BaseCode ;\r
4127 int Dest ;\r
4128 char allow[] = "0-23456789ab-----" ;\r
4129\r
4130 for (dreg = 0 ; dreg < 8 ; dreg++)\r
4131 for (type = 0 ; type < 2 ; type++)\r
4132 for (mode = 0 ; mode < 8 ; mode++)\r
4133 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4134 {\r
4135 Opcode = 0xc0c0 | (dreg<<9) | (type<<8) | (mode<<3) | sreg ;\r
4136 BaseCode = Opcode & 0xc1f8 ;\r
4137 if (mode == 7)\r
4138 {\r
4139 BaseCode |= sreg ;\r
4140 }\r
4141\r
4142 Dest = EAtoAMN(Opcode, FALSE);\r
4143 if (allow[Dest&0x0f] != '-')\r
4144 {\r
4145 if (OpcodeArray[ BaseCode ] == -2)\r
4146 {\r
4147 Align();\r
4148 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
4149\r
4150 if ((Dest >= 2) && (Dest <=10))\r
4151 SavePreviousPC();\r
4152\r
4153 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4154\r
4155 TimingCycles += 70 ;\r
4156\r
4157 if (mode < 7)\r
4158 {\r
4159 fprintf(fp, "\t\t mov ebx,ecx\n");\r
4160 fprintf(fp, "\t\t and ebx,byte 7\n");\r
4161 }\r
4162\r
4163 fprintf(fp, "\t\t shr ecx, byte 9\n");\r
4164 fprintf(fp, "\t\t and ecx, byte 7\n");\r
4165\r
4166 EffectiveAddressRead(Dest,'W',EBX,EAX,"ABCDSDB",FALSE);\r
4167\r
4168 if (type == 0)\r
4169 fprintf(fp, "\t\t mul word [%s+ECX*4]\n",REG_DAT);\r
4170 else\r
4171 fprintf(fp, "\t\t imul word [%s+ECX*4]\n",REG_DAT);\r
4172\r
4173 fprintf(fp, "\t\t shl edx, byte 16\n");\r
4174 fprintf(fp, "\t\t mov dx,ax\n");\r
4175 fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT);\r
4176 SetFlags('L',EDX,TRUE,FALSE,FALSE);\r
4177 Completed();\r
4178 }\r
4179\r
4180 OpcodeArray[Opcode] = BaseCode ;\r
4181 }\r
4182 }\r
4183}\r
4184\r
4185void mull(void)\r
4186{\r
4187 int mode, sreg ;\r
4188 int Opcode, BaseCode ;\r
4189 int Dest ;\r
4190 char allow[] = "0-23456789ab-----" ;\r
4191 char *Label = NULL ;\r
4192\r
4193 for (mode = 0 ; mode < 8 ; mode++)\r
4194 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4195 {\r
4196 Opcode = 0x4c00 | (mode<<3) | sreg ;\r
4197 BaseCode = Opcode & 0x4c38 ;\r
4198 if (mode == 7)\r
4199 {\r
4200 BaseCode |= sreg ;\r
4201 }\r
4202\r
4203 Dest = EAtoAMN(Opcode, FALSE);\r
4204 if (allow[Dest&0x0f] != '-')\r
4205 {\r
4206 if (OpcodeArray[ BaseCode ] == -2)\r
4207 {\r
4208 TimingCycles += 70 ;\r
4209 Align();\r
4210 Label = GenerateLabel(BaseCode,0);\r
4211 fprintf(fp, "%s:\n",Label);\r
4212 if ((Dest >= 2) && (Dest <=10))\r
4213 SavePreviousPC();\r
4214\r
4215 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4216\r
4217 if (mode < 7)\r
4218 {\r
4219 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4220 }\r
4221\r
4222 Memory_Fetch('W', EBX, FALSE ); // fetch the next word\r
4223 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4224\r
4225 EffectiveAddressRead(Dest,'L',ECX,EAX,"ABCDSDB",FALSE); // read from the EA\r
4226\r
4227 fprintf(fp, "\t\t mov ecx,ebx\n"); // save 2nd word in ecx\r
4228 fprintf(fp, "\t\t shr ebx,12\n"); // ebx = Dl register\r
4229 fprintf(fp, "\t\t and ebx,7\n"); // 0-7\r
4230\r
4231 Label = GenerateLabel(BaseCode,1);\r
4232\r
4233 fprintf(fp, "\t\t test ecx,0x0800\n"); // signed/unsigned?\r
4234 fprintf(fp, "\t\t jz short %s\n",Label); // skip if unsigned\r
4235\r
4236 fprintf(fp, "\t\t imul dword [%s+EBX*4]\n",REG_DAT); // signed 32x32->64\r
4237 fprintf(fp, "\t\t jmp short %s_1\n",Label); // skip\r
4238\r
4239 fprintf(fp, "%s:\n",Label);\r
4240 fprintf(fp, "\t\t mul dword [%s+EBX*4]\n",REG_DAT); // unsigned 32x32->64\r
4241\r
4242 fprintf(fp, "%s_1:\n",Label);\r
4243 fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_DAT); // store Dl back\r
4244\r
4245 fprintf(fp, "\t\t test ecx,0x0400\n"); // do we care?\r
4246 fprintf(fp, "\t\t jz short %s_2\n",Label); // if not, skip\r
4247 fprintf(fp, "\t\t and ecx,7\n"); // get Dh register\r
4248 fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); // store upper 32 bits\r
4249 SetFlags('L',EDX,TRUE,FALSE,FALSE); // set the flags\r
4250 fprintf(fp, "\t\t and edx,~0x0800\n"); // clear the overflow\r
4251 fprintf(fp, "\t\t jmp short %s_3\n",Label); // skip\r
4252\r
4253 fprintf(fp, "%s_2:\n",Label);\r
4254 fprintf(fp, "\t\t mov ebx,edx\n"); // save upper 32 in ebx\r
4255 SetFlags('L',EAX,TRUE,FALSE,FALSE); // set the flags\r
4256 fprintf(fp, "\t\t sar eax,31\n"); // eax = sign-extended\r
4257 fprintf(fp, "\t\t test ecx,0x0800\n"); // signed/unsigned?\r
4258 fprintf(fp, "\t\t jnz short %s_4\n",Label); // skip if signed\r
4259 fprintf(fp, "\t\t xor eax,eax\n"); // always use 0 for unsigned\r
4260 fprintf(fp, "%s_4:\n",Label);\r
4261 fprintf(fp, "\t\t cmp eax,ebx\n"); // compare upper 32 against eax\r
4262 fprintf(fp, "\t\t je short %s_3\n",Label); // if equal to sign extension, skip\r
4263 fprintf(fp, "\t\t or edx,0x0800\n"); // set the overflow\r
4264\r
4265 fprintf(fp, "%s_3:\n",Label);\r
4266 Completed();\r
4267 }\r
4268\r
4269 OpcodeArray[Opcode] = BaseCode ;\r
4270 }\r
4271 }\r
4272}\r
4273\r
4274void divl(void)\r
4275{\r
4276 int mode, sreg ;\r
4277 int Opcode, BaseCode ;\r
4278 int Dest ;\r
4279 char allow[] = "0-23456789ab-----" ;\r
4280 char *Label = NULL ;\r
4281\r
4282 for (mode = 0 ; mode < 8 ; mode++)\r
4283 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4284 {\r
4285 Opcode = 0x4c40 | (mode<<3) | sreg ;\r
4286 BaseCode = Opcode & 0x4c78 ;\r
4287 if (mode == 7)\r
4288 {\r
4289 BaseCode |= sreg ;\r
4290 }\r
4291\r
4292 Dest = EAtoAMN(Opcode, FALSE);\r
4293 if (allow[Dest&0x0f] != '-')\r
4294 {\r
4295 if (OpcodeArray[ BaseCode ] == -2)\r
4296 {\r
4297 TimingCycles += 70 ;\r
4298 Align();\r
4299 Label = GenerateLabel(BaseCode,0);\r
4300 fprintf(fp, "%s:\n",Label);\r
4301 if ((Dest >= 2) && (Dest <=10))\r
4302 SavePreviousPC();\r
4303\r
4304 fprintf(fp, "\t\t push edx\n"); // save edx\r
4305 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4306 fprintf(fp, "\t\t and ecx,byte 7\n"); // read from ea\r
4307\r
4308 Memory_Fetch('W', EDX, FALSE ); // fetch 2nd word in ecx\r
4309 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4310\r
4311 EffectiveAddressRead(Dest,'L',ECX,EBX,"---DSDB",FALSE);\r
4312\r
4313 fprintf(fp, "\t\t push esi\n"); // save and 0 esi\r
4314 ClearRegister(ESI);\r
4315\r
4316 Label = GenerateLabel(BaseCode,1);\r
4317\r
4318 fprintf(fp, "\t\t test ebx,ebx\n"); // check divisor against 0\r
4319 fprintf(fp, "\t\t jz near %s_ZERO\n",Label); // handle divide-by-zero\r
4320// low part always used\r
4321 fprintf(fp, "\t\t mov ecx,edx\n"); // ecx = extension word\r
4322 fprintf(fp, "\t\t shr edx,12\n"); // edx = Dq register\r
4323 fprintf(fp, "\t\t and edx,7\n"); // 0-7\r
4324 fprintf(fp, "\t\t mov eax,[%s+edx*4]\n",REG_DAT); // eax = Dq register value\r
4325\r
4326 ClearRegister(EDX); // edx = 0\r
4327 fprintf(fp, "\t\t test ecx,0x0400\n"); // check size\r
4328 fprintf(fp, "\t\t jz short %s_1\n",Label); // skip if 32-bit dividend\r
4329// high longword (64bit)\r
4330 fprintf(fp, "\t\t mov edx,ecx\n"); // edx = extension word\r
4331 fprintf(fp, "\t\t and edx,7\n"); // 0-7\r
4332 fprintf(fp, "\t\t mov edx,[%s+edx*4]\n",REG_DAT); // fetch upper 32-bits\r
4333\r
4334 fprintf(fp, "\t\t test ecx,0x0800\n"); // signed?\r
4335 fprintf(fp, "\t\t jz near %s_3\n",Label); // if not, skip to unsigned 64-bit\r
4336 fprintf(fp, "\t\t jmp near %s_2\n",Label); // skip to signed 64-bit case\r
4337\r
4338 fprintf(fp, "%s_1:\n",Label); // short case\r
4339 ClearRegister(EDX); // clear edx\r
4340 fprintf(fp, "\t\t test ecx,0x0800\n"); // signed?\r
4341 fprintf(fp, "\t\t jz short %s_3\n",Label); // if not, don't convert\r
4342 fprintf(fp, "\t\t cdq\n"); // sign extend into edx\r
4343// signed\r
4344 fprintf(fp, "%s_2:\n",Label); // signed 32/64-bit case\r
4345 fprintf(fp, "\t\t or esi,1\n"); // esi |= 1 to indicate signed\r
4346 fprintf(fp, "\t\t test ebx,ebx\n"); // check divisor sign\r
4347 fprintf(fp, "\t\t jge short %s_2b\n",Label); // if >= 0, don't set\r
4348 fprintf(fp, "\t\t or esi,2\n"); // esi |= 2 to indicate negative divisor\r
4349 fprintf(fp, "\t\t neg ebx\n"); // make positive\r
4350 fprintf(fp, "%s_2b:\n",Label);\r
4351 fprintf(fp, "\t\t test edx,edx\n"); // check dividend sign\r
4352 fprintf(fp, "\t\t jge short %s_3\n",Label); // if >= 0, don't set\r
4353 fprintf(fp, "\t\t push ebx\n"); // save ebx\r
4354 fprintf(fp, "\t\t push ecx\n"); // save ecx\r
4355 ClearRegister(EBX); // clear ebx\r
4356 ClearRegister(ECX); // clear ecx\r
4357 fprintf(fp, "\t\t sub ebx,eax\n"); // ebx = 0 - eax\r
4358 fprintf(fp, "\t\t sbb ecx,edx\n"); // ecx = 0 - edx\r
4359 fprintf(fp, "\t\t mov eax,ebx\n"); // eax = ebx\r
4360 fprintf(fp, "\t\t mov edx,ecx\n"); // edx = ecx\r
4361 fprintf(fp, "\t\t pop ecx\n"); // restore ecx\r
4362 fprintf(fp, "\t\t pop ebx\n"); // restore ebx\r
4363 fprintf(fp, "\t\t or esi,4\n"); // esi |= 4 to indicate negative dividend\r
4364// unsigned\r
4365 fprintf(fp, "%s_3:\n",Label); // unsigned 32/64-bit case\r
4366 fprintf(fp, "\t\t cmp ebx,edx\n"); // check ebx against upper 32 bits\r
4367 fprintf(fp, "\t\t jbe near %s_OVERFLOW\n",Label); // generate overflow\r
4368 fprintf(fp, "\t\t div ebx\n"); // do the divide\r
4369 fprintf(fp, "\t\t test esi,esi\n"); // see if we need to post process\r
4370 fprintf(fp, "\t\t jz short %s_4\n",Label); // if not, skip\r
4371 fprintf(fp, "\t\t jpo short %s_4\n",Label); // if PO (pos*pos or neg*neg), leave the result\r
4372 fprintf(fp, "\t\t neg eax\n"); // negate the result\r
4373\r
4374// store results\r
4375 fprintf(fp, "%s_4:\n",Label);\r
4376 fprintf(fp, "\t\t mov ebx,ecx\n"); // ebx = extension word\r
4377 fprintf(fp, "\t\t and ebx,7\n"); // get Dr in ebx\r
4378 fprintf(fp, "\t\t shr ecx,12\n"); // ecx = Dq\r
4379 fprintf(fp, "\t\t and ecx,7\n"); // 0-7\r
4380 fprintf(fp, "\t\t mov [%s+ebx*4],edx\n",REG_DAT); // store remainder first\r
4381 fprintf(fp, "\t\t mov [%s+ecx*4],eax\n",REG_DAT); // store quotient second\r
4382 fprintf(fp, "\t\t pop esi\n"); // restore esi\r
4383 fprintf(fp, "\t\t pop edx\n"); // restore edx\r
4384 SetFlags('L',EAX,TRUE,FALSE,FALSE); // set the flags\r
4385 fprintf(fp, "%s_5:\n",Label);\r
4386 fprintf(fp, "\t\t and edx,~1\n"); // clear the carry\r
4387 Completed();\r
4388\r
4389 fprintf(fp, "%s_ZERO:\t\t ;Do divide by zero trap\n", Label);\r
4390 /* Correct cycle counter for error */\r
4391 fprintf(fp, "\t\t pop esi\n"); // restore esi\r
4392 fprintf(fp, "\t\t pop edx\n"); // restore edx\r
4393 fprintf(fp, "\t\t add dword [%s],byte %d\n",ICOUNT,95);\r
4394 fprintf(fp,"\t\t jmp short %s_5\n",Label);\r
4395 Exception(5,BaseCode);\r
4396\r
4397 fprintf(fp, "%s_OVERFLOW:\n",Label);\r
4398//set overflow\r
4399 fprintf(fp, "\t\t pop esi\n"); // restore esi\r
4400 fprintf(fp, "\t\t pop edx\n"); // restore edx\r
4401 fprintf(fp, "\t\t or edx,0x0800\n"); // set the overflow bit\r
4402 fprintf(fp, "\t\t jmp near %s_5\n",Label); // done\r
4403\r
4404 }\r
4405\r
4406 OpcodeArray[Opcode] = BaseCode ;\r
4407 }\r
4408 }\r
4409}\r
4410\r
4411void bfext(void)\r
4412{\r
4413// just bfextu/bfexts for now\r
4414 char allow[] = "0-2--56789a-----" ;\r
4415 char *Label = NULL ;\r
4416 int mode,dreg,sign,Opcode,BaseCode,Dest ;\r
4417 for (mode=0; mode<8; mode++)\r
4418 for (dreg=0; dreg<8; dreg++)\r
4419 for (sign=0; sign<2; sign++)\r
4420 {\r
4421 Opcode = 0xe9c0 | (sign<<9) | (mode<<3) | dreg ;\r
4422 BaseCode = Opcode & 0xebf8 ;\r
4423 if (mode == 7)\r
4424 BaseCode |= dreg ;\r
4425 Dest = EAtoAMN(Opcode, FALSE);\r
4426 if (allow[Dest&0xf] != '-')\r
4427 {\r
4428 if (OpcodeArray[BaseCode] == -2)\r
4429 {\r
4430 Align();\r
4431 Label = GenerateLabel(BaseCode,0);\r
4432 fprintf(fp, "%s:\n",Label);\r
4433 Label = GenerateLabel(BaseCode,1);\r
4434 if ((Dest >= 2) && (Dest <=10))\r
4435 SavePreviousPC();\r
4436\r
4437 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4438\r
4439 if (mode < 7)\r
4440 {\r
4441 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4442 }\r
4443\r
4444 Memory_Fetch('W', EAX, FALSE ) ;\r
4445 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4446\r
4447 EffectiveAddressRead(Dest,'L',ECX,EDX,"ABCDSDB",FALSE); // edx = dword\r
4448\r
4449 fprintf(fp, "\t\t mov ecx,eax\n");\r
4450 fprintf(fp, "\t\t shr ecx,byte 6\n");\r
4451 fprintf(fp, "\t\t test eax,0x0800\n");\r
4452 fprintf(fp, "\t\t je short %s_1\n",Label);\r
4453 //get offset from Dx\r
4454 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4455 fprintf(fp, "\t\t mov ecx,[%s+ECX*4]\n",REG_DAT);\r
4456 //get offset from extension\r
4457 fprintf(fp, "%s_1:\n",Label);\r
4458 fprintf(fp, "\t\t and ecx,31\n"); // ecx = offset\r
4459 fprintf(fp, "\t\t mov ebx,eax\n");\r
4460 fprintf(fp, "\t\t test eax,0x0020\n");\r
4461 fprintf(fp, "\t\t je short %s_2\n",Label);\r
4462 //get width from Dy\r
4463 fprintf(fp, "\t\t and ebx,byte 7\n");\r
4464 fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT);\r
4465 //get width from extension\r
4466 fprintf(fp, "%s_2:\n",Label);\r
4467 //fix 0=32\r
4468 fprintf(fp, "\t\t sub ebx,byte 1\n");\r
4469 fprintf(fp, "\t\t and ebx,byte 31\n");\r
4470 fprintf(fp, "\t\t add ebx,byte 1\n"); // ebx = width\r
4471 fprintf(fp, "\t\t rol edx,cl\n");\r
4472 // check for N\r
4473 fprintf(fp, "\t\t mov ecx,32\n");\r
4474 fprintf(fp, "\t\t sub ecx,ebx\n");\r
4475 fprintf(fp, "\t\t mov ebx,edx\n");\r
4476 SetFlags('L',EBX,TRUE,FALSE,FALSE);\r
4477 if (sign)\r
4478 fprintf(fp, "\t\t sar ebx,cl\n");\r
4479 else\r
4480 fprintf(fp, "\t\t shr ebx,cl\n");\r
4481 fprintf(fp, "\t\t shr eax,12\n");\r
4482 fprintf(fp, "\t\t and eax,7\n");\r
4483 fprintf(fp, "\t\t mov [%s+EAX*4],ebx\n",REG_DAT);\r
4484 fprintf(fp, "\t\t test ebx,ebx\n");\r
4485 fprintf(fp, "\t\t jnz short %s_3\n",Label);\r
4486 //zero flag\r
4487 fprintf(fp, "\t\t or edx,40h\n");\r
4488 fprintf(fp, "%s_3:\n",Label);\r
4489 Completed();\r
4490 }\r
4491 OpcodeArray[Opcode] = BaseCode ;\r
4492 }\r
4493 }\r
4494}\r
4495\r
4496/*\r
4497 * not\r
4498 * clr\r
4499 * neg\r
4500 * negx\r
4501 *\r
4502 */\r
4503\r
4504void not(void)\r
4505{\r
4506 int type,leng, mode, sreg ;\r
4507 int Opcode, BaseCode ;\r
4508 int Dest ;\r
4509 int SaveEDX=0;\r
4510 char Size=' ' ;\r
4511 char * Regname="" ;\r
4512 char * RegnameECX ;\r
4513 char * Label;\r
4514\r
4515 char allow[] = "0-2345678-------" ;\r
4516\r
4517 for (type = 0 ; type < 4 ; type++)\r
4518 for (leng = 0 ; leng < 3 ; leng++)\r
4519 for (mode = 0 ; mode < 8 ; mode++)\r
4520 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4521 {\r
4522 Opcode = 0x4000 | (type<<9) | (leng<<6) | (mode<<3) | sreg ;\r
4523 BaseCode = Opcode & 0x46f8 ;\r
4524 if (mode == 7)\r
4525 {\r
4526 BaseCode |= sreg ;\r
4527 }\r
4528\r
4529 // A7+, A7-\r
4530\r
4531#ifdef A7ROUTINE\r
4532 if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5))\r
4533 {\r
4534 BaseCode |= sreg ;\r
4535 }\r
4536#endif\r
4537\r
4538 Dest = EAtoAMN(Opcode, FALSE);\r
4539\r
4540 if (allow[Dest&0x0f] != '-')\r
4541 {\r
4542 switch (leng)\r
4543 {\r
4544 case 0:\r
4545 Size = 'B';\r
4546 Regname = regnamesshort[0];\r
4547 RegnameECX = regnamesshort[ECX];\r
4548 break;\r
4549 case 1:\r
4550 Size = 'W';\r
4551 Regname = regnamesword[0];\r
4552 RegnameECX = regnamesword[ECX];\r
4553 break;\r
4554 case 2:\r
4555 Size = 'L';\r
4556 Regname = regnameslong[0];\r
4557 RegnameECX = regnameslong[ECX];\r
4558 break;\r
4559 }\r
4560\r
4561 if (OpcodeArray[ BaseCode ] == -2)\r
4562 {\r
4563 Align();\r
4564 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
4565\r
4566 if ((Dest >= 2) && (Dest <=10))\r
4567 SavePreviousPC();\r
4568\r
4569 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4570\r
4571 if (Size != 'L')\r
4572 TimingCycles += 4;\r
4573 else\r
4574 TimingCycles += 6;\r
4575\r
4576 if (Dest < 7)\r
4577 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4578\r
4579 if (type == 0) SaveEDX = TRUE;\r
4580 else SaveEDX = FALSE;\r
4581\r
4582 /* CLR does not need to read source (although it does on a real 68000) */\r
4583\r
4584 if (type != 1)\r
4585 {\r
4586 EffectiveAddressRead(Dest,Size,ECX,EAX,"A-CDS-B",SaveEDX);\r
4587 }\r
4588\r
4589 switch (type)\r
4590 {\r
4591 case 0: /* negx */\r
4592\r
4593 /* Preserve old Z flag */\r
4594\r
4595 fprintf(fp, "\t\t mov ebx,edx\n");\r
4596\r
4597 CopyX();\r
4598 fprintf(fp, "\t\t adc %s,byte 0\n", Regname ) ;\r
4599 fprintf(fp, "\t\t neg %s\n", Regname ) ;\r
4600\r
4601 /* Set the Flags */\r
4602\r
4603 SetFlags(Size,EAX,FALSE,TRUE,FALSE);\r
4604\r
4605 /* Handle the Z flag */\r
4606\r
4607 Label = GenerateLabel(0,1);\r
4608\r
4609 fprintf(fp, "\t\t jnz short %s\n\n",Label);\r
4610\r
4611 fprintf(fp, "\t\t and edx,byte -65 ; Remove Z\n");\r
4612 fprintf(fp, "\t\t and ebx,byte 40h ; Mask out Old Z\n");\r
4613 fprintf(fp, "\t\t or edx,ebx ; Copy across\n\n");\r
4614 fprintf(fp, "%s:\n",Label);\r
4615\r
4616 break;\r
4617\r
4618 case 1: /* clr */\r
4619 ClearRegister(EAX);\r
4620 EffectiveAddressWrite(Dest,Size,ECX,TRUE,"----S-B",FALSE);\r
4621 fprintf(fp, "\t\t mov edx,40H\n");\r
4622 break;\r
4623\r
4624 case 2: /* neg */\r
4625 fprintf(fp, "\t\t neg %s\n",Regname ) ;\r
4626 SetFlags(Size,EAX,FALSE,TRUE,TRUE);\r
4627 break;\r
4628\r
4629 case 3: /* not */\r
4630 fprintf(fp, "\t\t xor %s,-1\n",Regname ) ;\r
4631 SetFlags(Size,EAX,FALSE,FALSE,TRUE);\r
4632 break;\r
4633 }\r
4634\r
4635 /* Update (unless CLR command) */\r
4636\r
4637 if (type != 1)\r
4638 EffectiveAddressWrite(Dest,Size,ECX,FALSE,"---DS-B",TRUE);\r
4639\r
4640 Completed();\r
4641 }\r
4642\r
4643 OpcodeArray[Opcode] = BaseCode ;\r
4644 }\r
4645 }\r
4646}\r
4647\r
4648/*\r
4649 * Move to/from USP\r
4650 *\r
4651 */\r
4652\r
4653void moveusp(void)\r
4654{\r
4655 int Opcode, BaseCode ;\r
4656 int dir, sreg ;\r
4657 char * Label;\r
4658\r
4659 for (dir = 0 ; dir < 2 ; dir++)\r
4660 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4661 {\r
4662 Opcode = 0x4e60 | ( dir << 3 ) | sreg ;\r
4663 BaseCode = Opcode & 0x4e68 ;\r
4664\r
4665 if (OpcodeArray[BaseCode] == -2)\r
4666 {\r
4667 Align();\r
4668 Label = GenerateLabel(BaseCode,0);\r
4669 fprintf(fp, "%s\n", Label );\r
4670 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4671\r
4672 TimingCycles += 4;\r
4673\r
4674 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
4675 fprintf(fp, "\t\t jz short OP%d_%4.4x_Trap\n",CPU,BaseCode);\r
4676\r
4677 fprintf(fp, "\t\t and ecx,7\n");\r
4678\r
4679 if (dir == 0) /* reg 2 USP */\r
4680 {\r
4681 fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD);\r
4682 fprintf(fp, "\t\t mov [%s],eax\n",REG_USP);\r
4683 }\r
4684 else\r
4685 {\r
4686 fprintf(fp, "\t\t mov eax,[%s]\n",REG_USP);\r
4687 fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_ADD);\r
4688 }\r
4689 Completed();\r
4690\r
4691 fprintf(fp, "OP%d_%4.4x_Trap:\n",CPU,BaseCode);\r
4692 Exception(8,BaseCode);\r
4693 }\r
4694 OpcodeArray[Opcode] = BaseCode ;\r
4695 }\r
4696}\r
4697\r
4698\r
4699/*\r
4700 * Check\r
4701 *\r
4702 */\r
4703\r
4704void chk(void)\r
4705{\r
4706 int dreg,mode,sreg,size ;\r
4707 int Opcode, BaseCode ;\r
4708 int Dest ;\r
4709 char * Label ;\r
4710\r
4711 char *allow = "0-23456789ab----" ;\r
4712\r
4713 for (size = 0 ; size < (CPU==2 ? 2 : 1); size++)\r
4714 for (dreg = 0 ; dreg < 8; dreg++)\r
4715 for (mode = 0 ; mode < 8; mode++)\r
4716 for (sreg = 0 ; sreg < 8; sreg++)\r
4717 {\r
4718 if (size == 0) /* word */\r
4719 Opcode = 0x4180 | (dreg<<9) | (mode<<3) | sreg ;\r
4720 else /* long */\r
4721 Opcode = 0x4100 | (dreg<<9) | (mode<<3) | sreg ;\r
4722 BaseCode = Opcode & 0x41f8 ;\r
4723\r
4724 if (mode == 7)\r
4725 {\r
4726 BaseCode |= sreg ;\r
4727 }\r
4728\r
4729 Dest = EAtoAMN(Opcode, FALSE);\r
4730\r
4731 if (allow[Dest&0xf] != '-')\r
4732 {\r
4733 if (OpcodeArray[BaseCode] == -2)\r
4734 {\r
4735 Align();\r
4736 Label = GenerateLabel(BaseCode,0);\r
4737 fprintf(fp, "%s:\n", Label );\r
4738 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4739\r
4740 TimingCycles += 10;\r
4741\r
4742 fprintf(fp, "\t\t mov ebx,ecx\n");\r
4743 fprintf(fp, "\t\t shr ebx,byte 9\n");\r
4744 fprintf(fp, "\t\t and ebx,byte 7\n");\r
4745\r
4746 if (Dest < 7)\r
4747 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4748\r
4749 EffectiveAddressRead(Dest,(size == 0) ? 'W' : 'L',ECX,EAX,"----S-B",FALSE);\r
4750\r
4751 if (size == 0) /* word */\r
4752 {\r
4753 fprintf(fp, "\t\t movsx ebx,word [%s+EBX*4]\n",REG_DAT);\r
4754 fprintf(fp, "\t\t movsx eax,ax\n");\r
4755 }\r
4756 else /* long */\r
4757 fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT);\r
4758\r
4759 fprintf(fp, "\t\t test ebx,ebx\n"); /* is word bx < 0 */\r
4760 fprintf(fp, "\t\t jl near OP%d_%4.4x_Trap_minus\n",CPU,BaseCode);\r
4761\r
4762 fprintf(fp, "\t\t cmp ebx,eax\n");\r
4763 fprintf(fp, "\t\t jg near OP%d_%4.4x_Trap_over\n",CPU,BaseCode);\r
4764 Completed();\r
4765\r
4766 /* N is set if data less than zero */\r
4767\r
4768 Align();\r
4769 fprintf(fp, "OP%d_%4.4x_Trap_minus:\n",CPU,BaseCode);\r
4770 fprintf(fp, "\t\t or edx,0x0080\n"); /* N flag = 80H */\r
4771 fprintf(fp, "\t\t jmp short OP%d_%4.4x_Trap_Exception\n",CPU,BaseCode);\r
4772\r
4773 /* N is cleared if greated than compared number */\r
4774\r
4775 Align();\r
4776 fprintf(fp, "OP%d_%4.4x_Trap_over:\n",CPU,BaseCode);\r
4777 fprintf(fp, "\t\t and edx,0x007f\n"); /* N flag = 80H */\r
4778\r
4779 fprintf(fp, "OP%d_%4.4x_Trap_Exception:\n",CPU,BaseCode);\r
4780 fprintf(fp, "\t\t mov al,6\n");\r
4781 Exception(-1,0x10000+BaseCode);\r
4782 Completed();\r
4783\r
4784 }\r
4785\r
4786 OpcodeArray[Opcode] = BaseCode ;\r
4787 }\r
4788 }\r
4789}\r
4790\r
4791void chk2(void)\r
4792{\r
4793#if 0\r
4794 int mode,sreg,size ;\r
4795 int Opcode, BaseCode ;\r
4796 int Dest ;\r
4797 char * Label ;\r
4798\r
4799 char *allow = "--2--56789a-----" ;\r
4800\r
4801 for (size = 0 ; size < 2; size++)\r
4802 for (mode = 0 ; mode < 8; mode++)\r
4803 for (sreg = 0 ; sreg < 8; sreg++)\r
4804 {\r
4805 Opcode = 0x00c0 | (size<<9) | (mode<<3) | sreg;\r
4806 BaseCode = Opcode & 0xfff8 ;\r
4807\r
4808 if (mode == 7)\r
4809 {\r
4810 BaseCode |= sreg ;\r
4811 }\r
4812\r
4813 Dest = EAtoAMN(Opcode, FALSE);\r
4814\r
4815 if (allow[Dest&0xf] != '-')\r
4816 {\r
4817 if (OpcodeArray[BaseCode] == -2)\r
4818 {\r
4819 Align();\r
4820 Label = GenerateLabel(BaseCode,0);\r
4821 fprintf(fp, "%s:\n", Label );\r
4822 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4823\r
4824 TimingCycles += 10;\r
4825\r
4826 fprintf(fp, "\t\t mov ebx,ecx\n");\r
4827 fprintf(fp, "\t\t shr ebx,byte 9\n");\r
4828 fprintf(fp, "\t\t and ebx,byte 7\n");\r
4829\r
4830 if (Dest < 7)\r
4831 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4832\r
4833 EffectiveAddressRead(Dest,'W',ECX,EAX,"----S-B",FALSE);\r
4834\r
4835 if (size == 0) /* word */\r
4836 {\r
4837 fprintf(fp, "\t\t movsx ebx,word [%s+EBX*4]\n",REG_DAT);\r
4838 fprintf(fp, "\t\t movsx eax,ax\n");\r
4839 }\r
4840 else /* long */\r
4841 fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT);\r
4842\r
4843 fprintf(fp, "\t\t test ebx,ebx\n"); /* is word bx < 0 */\r
4844 fprintf(fp, "\t\t jl near OP%d_%4.4x_Trap_minus\n",CPU,BaseCode);\r
4845\r
4846 fprintf(fp, "\t\t cmp ebx,eax\n");\r
4847 fprintf(fp, "\t\t jg near OP%d_%4.4x_Trap_over\n",CPU,BaseCode);\r
4848 Completed();\r
4849\r
4850 /* N is set if data less than zero */\r
4851\r
4852 Align();\r
4853 fprintf(fp, "OP%d_%4.4x_Trap_minus:\n",CPU,BaseCode);\r
4854 fprintf(fp, "\t\t or edx,0x0080\n"); /* N flag = 80H */\r
4855 fprintf(fp, "\t\t jmp short OP%d_%4.4x_Trap_Exception\n",CPU,BaseCode);\r
4856\r
4857 /* N is cleared if greated than compared number */\r
4858\r
4859 Align();\r
4860 fprintf(fp, "OP%d_%4.4x_Trap_over:\n",CPU,BaseCode);\r
4861 fprintf(fp, "\t\t and edx,0x007f\n"); /* N flag = 80H */\r
4862\r
4863 fprintf(fp, "OP%d_%4.4x_Trap_Exception:\n",CPU,BaseCode);\r
4864 fprintf(fp, "\t\t mov al,6\n");\r
4865 Exception(-1,0x10000+BaseCode);\r
4866 Completed();\r
4867\r
4868 }\r
4869\r
4870 OpcodeArray[Opcode] = BaseCode ;\r
4871 }\r
4872 }\r
4873#endif\r
4874}\r
4875\r
4876/*\r
4877 * Load Effective Address\r
4878 */\r
4879\r
4880void LoadEffectiveAddress(void)\r
4881{\r
4882 int Opcode, BaseCode ;\r
4883 int sreg,mode,dreg ;\r
4884 int Dest ;\r
4885 char allow[] = "--2--56789a-----" ;\r
4886\r
4887 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4888 for (mode = 0 ; mode < 8 ; mode++)\r
4889 for (dreg = 0 ; dreg < 8 ; dreg++)\r
4890 {\r
4891 Opcode = 0x41c0 | (sreg<<9) | (mode<<3) | dreg ;\r
4892\r
4893 BaseCode = Opcode & 0x41f8 ;\r
4894\r
4895 if (mode == 7)\r
4896 BaseCode = BaseCode | dreg ;\r
4897\r
4898 Dest = EAtoAMN(BaseCode, FALSE);\r
4899\r
4900 if (allow[Dest&0x0f] != '-')\r
4901 {\r
4902 if (OpcodeArray[BaseCode] == -2)\r
4903 {\r
4904 Align();\r
4905 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
4906 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4907\r
4908 switch (mode)\r
4909 {\r
4910 case 2:\r
4911 TimingCycles += 4;\r
4912 break;\r
4913 case 5:\r
4914 case 7:\r
4915 case 9:\r
4916 TimingCycles += 8;\r
4917 break;\r
4918 case 6:\r
4919 case 8:\r
4920 case 10:\r
4921 TimingCycles += 12;\r
4922 break;\r
4923 }\r
4924\r
4925 if (mode < 7)\r
4926 {\r
4927 fprintf(fp, "\t\t mov ebx,ecx\n");\r
4928 fprintf(fp, "\t\t and ebx,byte 7\n");\r
4929 }\r
4930\r
4931 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
4932 fprintf(fp, "\t\t and ecx,byte 7\n");\r
4933\r
4934 EffectiveAddressCalculate(Dest,'L',EBX,TRUE);\r
4935 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD);\r
4936 Completed();\r
4937 }\r
4938\r
4939 OpcodeArray[Opcode] = BaseCode ;\r
4940 }\r
4941 }\r
4942}\r
4943\r
4944/*\r
4945 * Negate BCD\r
4946 *\r
4947 */\r
4948\r
4949void nbcd(void)\r
4950{\r
4951 int Opcode, BaseCode ;\r
4952 int sreg,mode,Dest ;\r
4953 char allow[] = "0-2345678-------" ;\r
4954\r
4955 for (mode = 0 ; mode < 8 ; mode++)\r
4956 for (sreg = 0 ; sreg < 8 ; sreg++)\r
4957 {\r
4958 Opcode = 0x4800 | (mode<<3) | sreg ;\r
4959 BaseCode = Opcode & 0x4838 ;\r
4960\r
4961 if (mode == 7)\r
4962 BaseCode |= sreg ;\r
4963\r
4964 // A7+, A7-\r
4965\r
4966#ifdef A7ROUTINE\r
4967 if ((sreg == 7) && (mode > 2) && (mode < 5))\r
4968 {\r
4969 BaseCode |= sreg;\r
4970 }\r
4971#endif\r
4972\r
4973 Dest = EAtoAMN(BaseCode, FALSE);\r
4974\r
4975 if (allow[Dest&0xf] != '-')\r
4976 {\r
4977 if (OpcodeArray[BaseCode] == -2)\r
4978 {\r
4979 Align();\r
4980 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
4981\r
4982 if ((Dest >= 2) && (Dest <=10))\r
4983 SavePreviousPC();\r
4984\r
4985 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
4986\r
4987 if (mode < 2)\r
4988 TimingCycles += 6;\r
4989 else\r
4990 TimingCycles += 8;\r
4991\r
4992 fprintf(fp, "\t\t and ecx, byte 7\n");\r
4993\r
4994 EffectiveAddressRead(Dest,'B',ECX,EBX,"--C-SDB",FALSE);\r
4995\r
4996 ClearRegister(EAX);\r
4997 CopyX();\r
4998\r
4999 fprintf(fp, "\t\t sbb al,bl\n");\r
5000 fprintf(fp, "\t\t das\n");\r
5001\r
5002 SetFlags('B',EAX,FALSE,TRUE,TRUE);\r
5003\r
5004 EffectiveAddressWrite(Dest,'B',ECX,EAX,"----S-B",FALSE);\r
5005 Completed();\r
5006 }\r
5007 OpcodeArray[Opcode] = BaseCode ;\r
5008 }\r
5009 }\r
5010}\r
5011\r
5012void tas(void)\r
5013{\r
5014 int Opcode, BaseCode ;\r
5015 int sreg,mode,Dest ;\r
5016 char allow[] = "0-2345678-------" ;\r
5017\r
5018 for (mode = 0 ; mode < 8 ; mode++)\r
5019 for (sreg = 0 ; sreg < 8 ; sreg++)\r
5020 {\r
5021 Opcode = 0x4ac0 | (mode<<3) | sreg ;\r
5022 BaseCode = Opcode & 0x4af8 ;\r
5023\r
5024 if (mode == 7)\r
5025 BaseCode |= sreg ;\r
5026\r
5027#ifdef A7ROUTINE\r
5028 if ((sreg == 7) && (mode > 2) && (mode < 5))\r
5029 {\r
5030 BaseCode |= sreg ;\r
5031 }\r
5032#endif\r
5033\r
5034 Dest = EAtoAMN(BaseCode, FALSE);\r
5035\r
5036 if (allow[Dest&0xf] != '-')\r
5037 {\r
5038 if (OpcodeArray[BaseCode] == -2)\r
5039 {\r
5040 Align();\r
5041 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5042\r
5043 if ((Dest >= 2) && (Dest <=10))\r
5044 SavePreviousPC();\r
5045\r
5046 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5047\r
5048 if (mode < 2)\r
5049 TimingCycles += 4;\r
5050 else\r
5051 TimingCycles += 14;\r
5052\r
5053 fprintf(fp, "\t\t and ecx, byte 7\n");\r
5054\r
5055 EffectiveAddressRead(Dest,'B',ECX,EAX,"--C-SDB",FALSE);\r
5056\r
5057 SetFlags('B',EAX,TRUE,FALSE,TRUE);\r
5058 fprintf(fp, "\t\t or al,128\n");\r
5059\r
5060 EffectiveAddressWrite(Dest,'B',ECX,EAX,"----S-B",FALSE);\r
5061 Completed();\r
5062 }\r
5063 OpcodeArray[Opcode] = BaseCode ;\r
5064 }\r
5065 }\r
5066}\r
5067\r
5068/*\r
5069 * push Effective Address\r
5070 */\r
5071\r
5072void PushEffectiveAddress(void)\r
5073{\r
5074 int Opcode, BaseCode ;\r
5075 int mode,dreg ;\r
5076 int Dest ;\r
5077 char allow[] = "--2--56789a-----" ;\r
5078\r
5079 for (mode = 0 ; mode < 8 ; mode++)\r
5080 for (dreg = 0 ; dreg < 8 ; dreg++)\r
5081 {\r
5082 Opcode = 0x4840 | (mode<<3) | dreg ;\r
5083\r
5084 BaseCode = Opcode & 0x4878 ;\r
5085\r
5086 if (mode == 7)\r
5087 BaseCode = BaseCode | dreg ;\r
5088\r
5089 Dest = EAtoAMN(BaseCode, FALSE);\r
5090\r
5091 if (allow[Dest&0x0f] != '-')\r
5092 {\r
5093 if (OpcodeArray[BaseCode] == -2)\r
5094 {\r
5095 Align();\r
5096 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5097 SavePreviousPC();\r
5098 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5099\r
5100 switch (mode)\r
5101 {\r
5102 case 2:\r
5103 TimingCycles += 12;\r
5104 break;\r
5105 case 5:\r
5106 case 7:\r
5107 case 9:\r
5108 TimingCycles += 16;\r
5109 break;\r
5110 case 6:\r
5111 case 8:\r
5112 case 10:\r
5113 TimingCycles += 20;\r
5114 break;\r
5115 }\r
5116\r
5117 if (mode < 7)\r
5118 {\r
5119 fprintf(fp, "\t\t and ecx,byte 7\n");\r
5120 }\r
5121\r
5122 EffectiveAddressCalculate(Dest,'L',ECX,TRUE);\r
5123\r
5124 fprintf(fp, "\t\t mov ecx,[%s]\t ; Push onto Stack\n",REG_A7);\r
5125 fprintf(fp, "\t\t sub ecx,byte 4\n");\r
5126 fprintf(fp, "\t\t mov [%s],ecx\n",REG_A7);\r
5127 Memory_Write('L',ECX,EDI,"---DS-B",2);\r
5128 Completed();\r
5129 }\r
5130\r
5131 OpcodeArray[Opcode] = BaseCode ;\r
5132 }\r
5133 }\r
5134}\r
5135\r
5136/*\r
5137 * Test\r
5138 *\r
5139 */\r
5140\r
5141void tst(void)\r
5142{\r
5143 int leng, mode, sreg ;\r
5144 int Opcode, BaseCode ;\r
5145 int Dest ;\r
5146 char Size=' ' ;\r
5147 char * Regname ;\r
5148 char * RegnameECX ;\r
5149\r
5150 char allow[] = "0-2345678-------" ;\r
5151 if (CPU==2)\r
5152 allow[1] = '1';\r
5153\r
5154 for (leng = 0 ; leng < 3 ; leng++)\r
5155 for (mode = 0 ; mode < 8 ; mode++)\r
5156 for (sreg = 0 ; sreg < 8 ; sreg++)\r
5157 {\r
5158 Opcode = 0x4a00 | (leng<<6) | (mode<<3) | sreg ;\r
5159 BaseCode = Opcode & 0x4af8 ;\r
5160 if (mode == 7)\r
5161 {\r
5162 BaseCode |= sreg ;\r
5163 }\r
5164\r
5165 // A7+, A7-\r
5166\r
5167#ifdef A7ROUTINE\r
5168 if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5))\r
5169 {\r
5170 BaseCode |= sreg ;\r
5171 }\r
5172#endif\r
5173\r
5174 Dest = EAtoAMN(Opcode, FALSE);\r
5175\r
5176 if ((allow[Dest&0x0f] != '-') || (( mode == 1 ) && (leng != 0)))\r
5177 {\r
5178 switch (leng)\r
5179 {\r
5180 case 0:\r
5181 Size = 'B';\r
5182 Regname = regnamesshort[0];\r
5183 RegnameECX = regnamesshort[ECX];\r
5184 break;\r
5185 case 1:\r
5186 Size = 'W';\r
5187 Regname = regnamesword[0];\r
5188 RegnameECX = regnamesword[ECX];\r
5189 break;\r
5190 case 2:\r
5191 Size = 'L';\r
5192 Regname = regnameslong[0];\r
5193 RegnameECX = regnameslong[ECX];\r
5194 break;\r
5195 }\r
5196\r
5197 if (OpcodeArray[ BaseCode ] == -2)\r
5198 {\r
5199 Align();\r
5200 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5201\r
5202 if ((Dest >= 2) && (Dest <=10))\r
5203 SavePreviousPC();\r
5204\r
5205 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5206\r
5207 TimingCycles += 4;\r
5208\r
5209 if (Dest < 7)\r
5210 fprintf(fp, "\t\t and ecx,byte 7\n");\r
5211\r
5212 EffectiveAddressRead(Dest,Size,ECX,EAX,"----S-B",FALSE);\r
5213\r
5214 SetFlags(Size,EAX,TRUE,FALSE,FALSE);\r
5215 Completed();\r
5216 }\r
5217\r
5218 OpcodeArray[Opcode] = BaseCode ;\r
5219 }\r
5220 }\r
5221}\r
5222\r
5223/*\r
5224 * Move registers too / from memory\r
5225 *\r
5226 */\r
5227\r
5228void movem_reg_ea(void)\r
5229{\r
5230 int leng,mode,sreg ;\r
5231 int Opcode, BaseCode ;\r
5232 int Dest ;\r
5233 char Size ;\r
5234 char * Label ;\r
5235\r
5236 char *allow = "--2-45678-------" ;\r
5237\r
5238 for (leng = 0 ; leng < 2; leng++)\r
5239 for (mode = 0 ; mode < 8; mode++)\r
5240 for (sreg = 0 ; sreg < 8; sreg++)\r
5241 {\r
5242 Opcode = 0x4880 | ( leng<<6) | (mode<<3) | sreg ;\r
5243 BaseCode = Opcode & 0x4cf8 ;\r
5244\r
5245 if (mode == 7)\r
5246 {\r
5247 BaseCode |= sreg ;\r
5248 }\r
5249\r
5250 Dest = EAtoAMN(Opcode, FALSE);\r
5251\r
5252 Size = "WL"[leng] ;\r
5253\r
5254 if (allow[Dest&0xf] != '-')\r
5255 {\r
5256 if (OpcodeArray[BaseCode] == - 2)\r
5257 {\r
5258 Align();\r
5259 Label = GenerateLabel(BaseCode,0);\r
5260 fprintf(fp, "%s:\n",Label ) ;\r
5261 SavePreviousPC();\r
5262 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5263\r
5264 switch (mode)\r
5265 {\r
5266 case 2:\r
5267 case 4:\r
5268 TimingCycles += 8 ;\r
5269 break;\r
5270 case 5:\r
5271 case 7:\r
5272 TimingCycles += 12 ;\r
5273 break;\r
5274 case 6:\r
5275 case 8:\r
5276 TimingCycles += 14 ;\r
5277 break;\r
5278 }\r
5279\r
5280 fprintf(fp, "\t\t push edx\n");\r
5281\r
5282 Memory_Fetch('W',EDX,FALSE);\r
5283 fprintf(fp, "\t\t add esi,byte 2\n");\r
5284\r
5285 if (mode < 7)\r
5286 {\r
5287 fprintf(fp, "\t\t and ecx,byte 7\n");\r
5288 }\r
5289\r
5290 if (mode == 4)\r
5291 {\r
5292 fprintf(fp, "\t\t push ecx\n");\r
5293 fprintf(fp, "\t\t mov edi,[%s+ECX*4]\n",REG_ADD);\r
5294 }\r
5295 else\r
5296 EffectiveAddressCalculate(Dest,'L',ECX,TRUE);\r
5297\r
5298 fprintf(fp, "\t\t mov ebx,1\n");\r
5299\r
5300 /* predecrement uses d0-d7..a0-a7 a7 first*/\r
5301 /* other modes use a7-a0..d7-d0 d0 first*/\r
5302\r
5303 if (Dest != 4)\r
5304 ClearRegister(ECX);\r
5305 else\r
5306 fprintf(fp, "\t\t mov ecx,3Ch\n");\r
5307\r
5308 fprintf(fp, "OP%d_%4.4x_Again:\n",CPU,BaseCode);\r
5309 fprintf(fp, "\t\t test edx,ebx\n");\r
5310 fprintf(fp, "\t\t je OP%d_%4.4x_Skip\n",CPU,BaseCode);\r
5311\r
5312 fprintf(fp, "\t\t mov eax,[%s+ecx]\n",REG_DAT); /* load eax with current reg data */\r
5313\r
5314 if (Dest == 4)\r
5315 {\r
5316 if (Size == 'W') /* adjust pointer before write */\r
5317 fprintf(fp, "\t\t sub edi,byte 2\n");\r
5318 else\r
5319 fprintf(fp, "\t\t sub edi,byte 4\n");\r
5320 }\r
5321\r
5322 Memory_Write(Size,EDI,EAX,"-BCDSDB",1);\r
5323\r
5324 if (Dest != 4)\r
5325 {\r
5326 if (Size == 'W') /* adjust pointer after write */\r
5327 fprintf(fp, "\t\t add edi,byte 2\n");\r
5328 else\r
5329 fprintf(fp, "\t\t add edi,byte 4\n");\r
5330 }\r
5331\r
5332 /* Update Cycle Count */\r
5333\r
5334 if (Size == 'W')\r
5335 fprintf(fp, "\t\t sub dword [%s],byte 4\n",ICOUNT);\r
5336 else\r
5337 fprintf(fp, "\t\t sub dword [%s],byte 8\n",ICOUNT);\r
5338\r
5339 fprintf(fp, "OP%d_%4.4x_Skip:\n",CPU,BaseCode);\r
5340\r
5341 if (Dest != 4)\r
5342 fprintf(fp, "\t\t add ecx,byte 4h\n");\r
5343 else\r
5344 fprintf(fp, "\t\t sub ecx,byte 4h\n");\r
5345\r
5346 fprintf(fp, "\t\t add ebx,ebx\n"); /* faster than shl ebx,1 */\r
5347 fprintf(fp, "\t\t test bx,bx\n"); /* check low 16 bits */\r
5348 fprintf(fp, "\t\t jnz OP%d_%4.4x_Again\n",CPU,BaseCode);\r
5349\r
5350 if (Dest == 4)\r
5351 {\r
5352 fprintf(fp, "\t\t pop ecx\n");\r
5353 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD);\r
5354 }\r
5355\r
5356 fprintf(fp, "\t\t pop edx\n");\r
5357 Completed();\r
5358 }\r
5359\r
5360 OpcodeArray[Opcode] = BaseCode ;\r
5361 }\r
5362 }\r
5363}\r
5364\r
5365void movem_ea_reg(void)\r
5366{\r
5367 int leng,mode,sreg ;\r
5368 int Opcode, BaseCode ;\r
5369 int Dest ;\r
5370 char Size ;\r
5371 char * Label ;\r
5372\r
5373 char *allow = "--23-56789a-----" ;\r
5374\r
5375 for (leng = 0 ; leng < 2; leng++)\r
5376 for (mode = 0 ; mode < 8; mode++)\r
5377 for (sreg = 0 ; sreg < 8; sreg++)\r
5378 {\r
5379 Opcode = 0x4c80 | ( leng<<6) | (mode<<3) | sreg ;\r
5380 BaseCode = Opcode & 0x4cf8 ;\r
5381\r
5382 if (mode == 7)\r
5383 {\r
5384 BaseCode |= sreg ;\r
5385 }\r
5386\r
5387 Dest = EAtoAMN(Opcode, FALSE);\r
5388\r
5389 Size = "WL"[leng] ;\r
5390\r
5391 if (allow[Dest&0xf] != '-')\r
5392 {\r
5393 if (OpcodeArray[BaseCode] == - 2)\r
5394 {\r
5395 Align();\r
5396 Label = GenerateLabel(BaseCode,0);\r
5397\r
5398 fprintf(fp, "%s:\n",Label ) ;\r
5399 SavePreviousPC();\r
5400 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5401\r
5402 switch (mode)\r
5403 {\r
5404 case 2:\r
5405 case 4:\r
5406 TimingCycles += 8 ;\r
5407 break;\r
5408 case 5:\r
5409 case 7:\r
5410 TimingCycles += 12 ;\r
5411 break;\r
5412 case 6:\r
5413 case 8:\r
5414 TimingCycles += 14 ;\r
5415 break;\r
5416 }\r
5417\r
5418 fprintf(fp, "\t\t push edx\n"); /* save edx because sr is unaffected */\r
5419\r
5420 Memory_Fetch('W',EDX,FALSE);\r
5421 fprintf(fp, "\t\t add esi,byte 2\n");\r
5422\r
5423 if (mode < 7)\r
5424 {\r
5425 fprintf(fp, "\t\t and ecx,byte 7\n");\r
5426 }\r
5427\r
5428 if (mode == 3)\r
5429 fprintf(fp, "\t\t push ecx\n"); /* if (An)+ then it needed later */\r
5430\r
5431 EffectiveAddressCalculate(Dest,'L',ECX,TRUE);\r
5432\r
5433 fprintf(fp, "\t\t mov ebx,1\n"); /* setup register list mask */\r
5434\r
5435 /* predecrement uses d0-d7..a0-a7 a7 first*/\r
5436 /* other modes use a7-a0..d7-d0 d0 first*/\r
5437\r
5438 ClearRegister(ECX); /* always start with D0 */\r
5439\r
5440 fprintf(fp, "OP%d_%4.4x_Again:\n",CPU,BaseCode);\r
5441 fprintf(fp, "\t\t test edx,ebx\n"); /* is bit set for this register? */\r
5442 fprintf(fp, "\t\t je OP%d_%4.4x_Skip\n",CPU,BaseCode);\r
5443\r
5444 Memory_Read(Size,EDI,"-BCDSDB",1);\r
5445\r
5446 if (Size == 'W')\r
5447 fprintf(fp, "\t\t cwde\n"); /* word size must be sign extended */\r
5448\r
5449 fprintf(fp, "\t\t mov [%s+ecx],eax\n",REG_DAT); /* load current reg with eax */\r
5450\r
5451 if (Size == 'W') /* adjust pointer after write */\r
5452 fprintf(fp, "\t\t add edi,byte 2\n");\r
5453 else\r
5454 fprintf(fp, "\t\t add edi,byte 4\n");\r
5455\r
5456 /* Update Cycle Count */\r
5457\r
5458 if (Size == 'W')\r
5459 fprintf(fp, "\t\t sub dword [%s],byte 4\n",ICOUNT);\r
5460 else\r
5461 fprintf(fp, "\t\t sub dword [%s],byte 8\n",ICOUNT);\r
5462\r
5463 fprintf(fp, "OP%d_%4.4x_Skip:\n",CPU,BaseCode);\r
5464 fprintf(fp, "\t\t add ecx,byte 4\n"); /* adjust pointer to next reg */\r
5465 fprintf(fp, "\t\t add ebx,ebx\n"); /* Faster than shl ebx,1 */\r
5466 fprintf(fp, "\t\t test bx,bx\n"); /* check low 16 bits */\r
5467 fprintf(fp, "\t\t jnz OP%d_%4.4x_Again\n",CPU,BaseCode);\r
5468\r
5469 if (mode == 3)\r
5470 {\r
5471 fprintf(fp, "\t\t pop ecx\n");\r
5472 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); /* reset Ax if mode = (Ax)+ */\r
5473 }\r
5474\r
5475 fprintf(fp, "\t\t pop edx\n"); /* restore flags */\r
5476 Completed();\r
5477 }\r
5478\r
5479 OpcodeArray[Opcode] = BaseCode ;\r
5480 }\r
5481 }\r
5482}\r
5483\r
5484/*\r
5485 * Link / Unlink\r
5486 *\r
5487 * Local stack space\r
5488 *\r
5489 */\r
5490\r
5491void link(void)\r
5492{\r
5493 int sreg ;\r
5494 int Opcode, BaseCode ;\r
5495\r
5496 for (sreg = 0 ; sreg < 8; sreg++)\r
5497 {\r
5498 Opcode = 0x4e50 | sreg ;\r
5499 BaseCode = 0x4e50 ;\r
5500\r
5501 if (OpcodeArray[BaseCode] == - 2)\r
5502 {\r
5503 Align();\r
5504 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5505 SavePreviousPC();\r
5506 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5507\r
5508 TimingCycles += 16;\r
5509\r
5510 fprintf(fp, "\t\t sub dword [%s],byte 4\n",REG_A7);\r
5511\r
5512 fprintf(fp, "\t\t and ecx, byte 7\n");\r
5513 fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD);\r
5514 fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7);\r
5515 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD);\r
5516\r
5517 Memory_Write('L',EDI,EAX,"---DS-B",1);\r
5518\r
5519 Memory_Fetch('W',EAX,TRUE);\r
5520 fprintf(fp, "\t\t add esi,byte 2\n");\r
5521 fprintf(fp, "\t\t add [%s],eax\n",REG_A7);\r
5522\r
5523 Completed();\r
5524 }\r
5525\r
5526 OpcodeArray[Opcode] = BaseCode ;\r
5527 }\r
5528}\r
5529\r
5530void unlinkasm(void)\r
5531{\r
5532 int sreg ;\r
5533 int Opcode, BaseCode ;\r
5534\r
5535 for (sreg = 0 ; sreg < 8; sreg++)\r
5536 {\r
5537 Opcode = 0x4e58 | sreg ;\r
5538 BaseCode = 0x4e58 ;\r
5539\r
5540 if (OpcodeArray[BaseCode] == - 2)\r
5541 {\r
5542 Align();\r
5543 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5544 SavePreviousPC();\r
5545 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5546\r
5547 TimingCycles += 12;\r
5548\r
5549 fprintf(fp, "\t\t mov ebx,ecx\n");\r
5550 fprintf(fp, "\t\t and ebx, byte 7\n");\r
5551 fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD);\r
5552\r
5553 Memory_Read('L',EDI,"-B-DSDB",1);\r
5554\r
5555 fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD);\r
5556 fprintf(fp, "\t\t add edi,byte 4\n");\r
5557 fprintf(fp, "\t\t mov dword [%s],EDI\n",REG_A7);\r
5558 Completed();\r
5559 }\r
5560\r
5561 OpcodeArray[Opcode] = BaseCode ;\r
5562 }\r
5563}\r
5564\r
5565void trap(void)\r
5566{\r
5567 int Count;\r
5568 int BaseCode = 0x4E40;\r
5569\r
5570 if (OpcodeArray[BaseCode] == -2)\r
5571 {\r
5572 Align();\r
5573 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5574 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5575\r
5576 fprintf(fp, "\t\t mov eax,ecx\n");\r
5577 fprintf(fp, "\t\t and eax,byte 15\n");\r
5578 fprintf(fp, "\t\t or eax,byte 32\n");\r
5579 Exception(-1,BaseCode);\r
5580 Completed();\r
5581 }\r
5582\r
5583 for (Count=0;Count<=15;Count++)\r
5584 OpcodeArray[BaseCode+Count] = BaseCode;\r
5585}\r
5586\r
5587void reset(void)\r
5588{\r
5589 int BaseCode = 0x4E70;\r
5590 char * Label;\r
5591\r
5592 if (OpcodeArray[BaseCode] == -2)\r
5593 {\r
5594 Align();\r
5595 Label = GenerateLabel(BaseCode,0);\r
5596\r
5597 TimingCycles += 132;\r
5598\r
5599 fprintf(fp, "%s:\n", Label );\r
5600 SavePreviousPC();\r
5601\r
5602 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5603 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
5604 fprintf(fp, "\t\t jnz near OP%d_%4.4x_RESET\n",CPU,BaseCode);\r
5605 Exception(8,BaseCode);\r
5606\r
5607 fprintf(fp, "\nOP%d_%4.4x_RESET:\n",CPU,BaseCode);\r
5608\r
5609 /* Prefetch next instruction */\r
5610\r
5611 if(CPU==2)\r
5612 {\r
5613 /* 32 bit memory version */\r
5614\r
5615 fprintf(fp, "\t\t xor esi,2\n"); /* ASG */\r
5616#ifdef STALLCHECK\r
5617 ClearRegister(ECX);\r
5618 fprintf(fp, "\t\t mov cx,[esi+ebp]\n");\r
5619#else\r
5620 fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n");\r
5621#endif\r
5622 fprintf(fp, "\t\t xor esi,2\n"); /* ASG */\r
5623 }\r
5624 else\r
5625 {\r
5626 /* 16 bit memory */\r
5627#ifdef STALLCHECK\r
5628 ClearRegister(ECX);\r
5629 fprintf(fp, "\t\t mov cx,[esi+ebp]\n");\r
5630#else\r
5631 fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n");\r
5632#endif\r
5633 }\r
5634\r
5635 fprintf(fp, "\t\t mov eax,dword [%s]\n", REG_RESET_CALLBACK);\r
5636 fprintf(fp, "\t\t test eax,eax\n");\r
5637 fprintf(fp, "\t\t jz near OP%d_%4.4x_END\n",CPU,BaseCode);\r
5638\r
5639 /* Callback for Reset */\r
5640\r
5641 fprintf(fp, "\t\t mov [%s],ESI,\n",REG_PC);\r
5642 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
5643 fprintf(fp, "\t\t push ECX\n");\r
5644\r
5645 fprintf(fp, "\t\t call [eax]\n");\r
5646\r
5647 fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC);\r
5648 fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR);\r
5649 fprintf(fp, "\t\t pop ECX\n");\r
5650 fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n");\r
5651\r
5652 fprintf(fp, "OP%d_%4.4x_END:\n",CPU,BaseCode);\r
5653 fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,TimingCycles);\r
5654 fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n\n", CPUtype);\r
5655 }\r
5656 OpcodeArray[BaseCode] = BaseCode ;\r
5657}\r
5658\r
5659void nop(void)\r
5660{\r
5661 int BaseCode = 0x4e71 ;\r
5662\r
5663 if (OpcodeArray[BaseCode] == -2)\r
5664 {\r
5665 Align();\r
5666 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5667 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5668\r
5669 TimingCycles += 4;\r
5670\r
5671 Completed();\r
5672 OpcodeArray[BaseCode] = BaseCode ;\r
5673 }\r
5674}\r
5675\r
5676void stop(void)\r
5677{\r
5678 char TrueLabel[16];\r
5679 int BaseCode = 0x4e72 ;\r
5680\r
5681 if (OpcodeArray[BaseCode] == -2)\r
5682 {\r
5683 Align();\r
5684 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5685 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5686\r
5687 TimingCycles += 4;\r
5688\r
5689 /* Must be in Supervisor Mode */\r
5690\r
5691 sprintf(TrueLabel,GenerateLabel(0,1));\r
5692\r
5693 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
5694 fprintf(fp, "\t\t je near %s\n\n",TrueLabel);\r
5695\r
5696 /* Next WORD is new SR */\r
5697\r
5698 Memory_Fetch('W',EAX,FALSE);\r
5699 fprintf(fp, "\t\t add esi,byte 2\n");\r
5700\r
5701 WriteCCR('W');\r
5702\r
5703 /* See if Valid interrupt waiting */\r
5704\r
5705 CheckInterrupt = 0;\r
5706\r
5707 fprintf(fp, "\t\t mov eax,[%s]\n",REG_IRQ);\r
5708 fprintf(fp, "\t\t and eax,byte 07H\n");\r
5709\r
5710 fprintf(fp, "\t\t cmp al,7\t\t ; Always take 7\n");\r
5711 fprintf(fp, "\t\t je near procint\n\n");\r
5712\r
5713 fprintf(fp, "\t\t mov ebx,[%s]\t\t; int mask\n",REG_SRH);\r
5714 fprintf(fp, "\t\t and ebx,byte 07H\n");\r
5715 fprintf(fp, "\t\t cmp eax,ebx\n");\r
5716 fprintf(fp, "\t\t jg near procint\n\n");\r
5717\r
5718 /* No int waiting - clear count, set stop */\r
5719\r
5720 ClearRegister(ECX);\r
5721 fprintf(fp, "\t\t mov [%s],ecx\n",ICOUNT);\r
5722 fprintf(fp, "\t\t or byte [%s],80h\n",REG_IRQ);\r
5723 Completed();\r
5724\r
5725 /* User Mode - Exception */\r
5726\r
5727 Align();\r
5728 fprintf(fp, "%s:\n",TrueLabel);\r
5729 Exception(8,BaseCode);\r
5730\r
5731 OpcodeArray[BaseCode] = BaseCode ;\r
5732 }\r
5733}\r
5734\r
5735void ReturnFromException(void)\r
5736{\r
5737 char TrueLabel[16];\r
5738\r
5739 int BaseCode = 0x4e73;\r
5740\r
5741 Align();\r
5742 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5743 SavePreviousPC();\r
5744 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5745\r
5746 TimingCycles += 20;\r
5747\r
5748 /* Check in Supervisor Mode */\r
5749\r
5750 sprintf(TrueLabel,GenerateLabel(0,1));\r
5751 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
5752 fprintf(fp, "\t\t je near %s\n\n",TrueLabel);\r
5753\r
5754 /* Get SR - Save in EBX */\r
5755\r
5756 fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7);\r
5757 fprintf(fp, "\t\t add dword [%s],byte 6\n",REG_A7);\r
5758 Memory_Read('W',EDI,"-----DB",2);\r
5759 fprintf(fp, "\t\t add edi,byte 2\n");\r
5760 fprintf(fp, "\t\t mov esi,eax\n");\r
5761\r
5762 /* Get PC */\r
5763\r
5764 Memory_Read('L',EDI,"----S-B",0);\r
5765 fprintf(fp, "\t\t xchg esi,eax\n");\r
5766\r
5767 /* Update CCR (and A7) */\r
5768\r
5769 WriteCCR('W');\r
5770\r
5771 MemoryBanking(BaseCode);\r
5772 Completed();\r
5773\r
5774 fprintf(fp, "%s:\n",TrueLabel);\r
5775 Exception(8,0x10000+BaseCode);\r
5776\r
5777 OpcodeArray[BaseCode] = BaseCode;\r
5778}\r
5779\r
5780void trapv(void)\r
5781{\r
5782 int BaseCode = 0x4E76;\r
5783 char * Label;\r
5784\r
5785 if (OpcodeArray[BaseCode] == -2)\r
5786 {\r
5787 Align();\r
5788 Label = GenerateLabel(BaseCode,0);\r
5789 fprintf(fp, "%s\n", Label );\r
5790 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5791\r
5792 TimingCycles += 4;\r
5793\r
5794 fprintf(fp, "\t\t test dh,08h\n");\r
5795 fprintf(fp, "\t\t jz near OP%d_%4.4x_Clear\n",CPU,BaseCode);\r
5796 Exception(7,BaseCode);\r
5797\r
5798 fprintf(fp, "OP%d_%4.4x_Clear:\n",CPU,BaseCode);\r
5799 Completed();\r
5800 }\r
5801 OpcodeArray[BaseCode] = BaseCode ;\r
5802}\r
5803\r
5804void illegal_opcode(void)\r
5805{\r
5806 Align();\r
5807 fprintf(fp, "ILLEGAL:\n");\r
5808 fprintf(fp, "\t\t mov [_illegal_op],ecx\n");\r
5809 fprintf(fp, "\t\t mov [_illegal_pc],esi\n");\r
5810\r
5811#ifdef MAME_DEBUG\r
5812 fprintf(fp, "\t\t jmp ecx\n");\r
5813 fprintf(fp, "\t\t pushad\n");\r
5814 fprintf(fp, "\t\t call _m68k_illegal_opcode\n");\r
5815 fprintf(fp, "\t\t popad\n");\r
5816#endif\r
5817\r
5818 Exception(4,0xFFFE);\r
5819}\r
5820\r
5821/*\r
5822 * Return from subroutine\r
5823 * restoring flags as well\r
5824 *\r
5825 */\r
5826\r
5827void ReturnandRestore(void)\r
5828{\r
5829 int BaseCode = 0x4e77;\r
5830\r
5831 Align();\r
5832 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5833 SavePreviousPC();\r
5834 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5835\r
5836 TimingCycles += 20;\r
5837\r
5838 /* Get SR into ESI */\r
5839\r
5840 fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7);\r
5841 fprintf(fp, "\t\t add dword [%s],byte 6\n",REG_A7);\r
5842\r
5843 Memory_Read('W',EDI,"-----DB",2);\r
5844 fprintf(fp, "\t\t add edi,byte 2\n");\r
5845 fprintf(fp, "\t\t mov esi,eax\n");\r
5846\r
5847 /* Get PC */\r
5848\r
5849 Memory_Read('L',EDI,"----SDB",0);\r
5850 fprintf(fp, "\t\t xchg esi,eax\n");\r
5851\r
5852 /* Update flags */\r
5853\r
5854 WriteCCR('B');\r
5855\r
5856 MemoryBanking(BaseCode);\r
5857 Completed();\r
5858\r
5859 OpcodeArray[BaseCode] = BaseCode;\r
5860}\r
5861\r
5862/*\r
5863 * Return from Subroutine\r
5864 *\r
5865 */\r
5866\r
5867void rts(void)\r
5868{\r
5869 int BaseCode = 0x4e75 ;\r
5870\r
5871 if (OpcodeArray[BaseCode] == -2)\r
5872 {\r
5873 Align();\r
5874 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5875 SavePreviousPC();\r
5876\r
5877 TimingCycles += 16;\r
5878\r
5879 OpcodeArray[BaseCode] = BaseCode ;\r
5880\r
5881 fprintf(fp, "\t\t mov eax,[%s]\n",REG_A7);\r
5882 fprintf(fp, "\t\t add dword [%s],byte 4\n",REG_A7);\r
5883 Memory_Read('L',EAX,"---D--B",1);\r
5884 fprintf(fp, "\t\t mov esi,eax\n");\r
5885 MemoryBanking(BaseCode);\r
5886 Completed();\r
5887 }\r
5888}\r
5889\r
5890void jmp_jsr(void)\r
5891{\r
5892 int Opcode, BaseCode ;\r
5893 int dreg,mode,type ;\r
5894 int Dest ;\r
5895 char allow[] = "--2--56789a-----" ;\r
5896\r
5897 for (type = 0 ; type < 2 ; type++)\r
5898 for (mode = 0 ; mode < 8 ; mode++)\r
5899 for (dreg = 0 ; dreg < 8 ; dreg++)\r
5900 {\r
5901 Opcode = 0x4e80 | (type<<6) | (mode<<3) | dreg ;\r
5902 BaseCode = Opcode & 0x4ef8 ;\r
5903 if (mode == 7)\r
5904 BaseCode = BaseCode | dreg ;\r
5905\r
5906 Dest = EAtoAMN(BaseCode, FALSE);\r
5907 if (allow[Dest&0x0f] != '-')\r
5908 {\r
5909 if (OpcodeArray[BaseCode] == -2)\r
5910 {\r
5911 Align();\r
5912 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
5913 SavePreviousPC();\r
5914 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
5915\r
5916 switch (mode)\r
5917 {\r
5918 case 2:\r
5919 TimingCycles += 8;\r
5920 break;\r
5921 case 5:\r
5922 case 7:\r
5923 case 9:\r
5924 TimingCycles += 10;\r
5925 break;\r
5926 case 8:\r
5927 TimingCycles += 12;\r
5928 break;\r
5929 case 6:\r
5930 case 10:\r
5931 TimingCycles += 14;\r
5932 break;\r
5933 }\r
5934\r
5935 if (type == 0) /* jsr takes 8 more than jmp */\r
5936 TimingCycles += 8;\r
5937\r
5938 if (mode < 7)\r
5939 {\r
5940 fprintf(fp, "\t\t and ecx,byte 7\n");\r
5941 }\r
5942 EffectiveAddressCalculate(Dest,'L',ECX,TRUE);\r
5943\r
5944 /* jsr needs to push PC onto stack */\r
5945\r
5946 if (type == 0)\r
5947 {\r
5948 PushPC(EBX,EAX,"---D-DB",1);\r
5949 }\r
5950\r
5951 fprintf(fp, "\t\t mov esi,edi\n");\r
5952 MemoryBanking(BaseCode);\r
5953 Completed();\r
5954 }\r
5955\r
5956 OpcodeArray[Opcode] = BaseCode ;\r
5957 }\r
5958 }\r
5959}\r
5960\r
5961void cmpm(void)\r
5962{\r
5963 int Opcode, BaseCode ;\r
5964 int regx,leng,regy ;\r
5965 int ModeModX, ModeModY;\r
5966 char Size=' ' ;\r
5967 char * Regname="" ;\r
5968 char * RegnameEBX="" ;\r
5969\r
5970 for (regx = 0 ; regx < 8 ; regx++)\r
5971 for (leng = 0 ; leng < 3 ; leng++)\r
5972 for (regy = 0 ; regy < 8 ; regy++)\r
5973 {\r
5974 Opcode = 0xb108 | (regx<<9) | (leng<<6) | regy ;\r
5975 BaseCode = Opcode & 0xb1c8 ;\r
5976\r
5977 ModeModX = 0;\r
5978 ModeModY = 0;\r
5979\r
5980#ifdef A7ROUTINE\r
5981 if (leng==0)\r
5982 {\r
5983 if (regx==7)\r
5984 {\r
5985 BaseCode |= (regx<<9);\r
5986 ModeModX = 16;\r
5987 }\r
5988\r
5989 if (regy==7)\r
5990 {\r
5991 BaseCode |= regy;\r
5992 ModeModY = 16;\r
5993 }\r
5994 }\r
5995#endif\r
5996\r
5997 switch (leng)\r
5998 {\r
5999 case 0:\r
6000 Size = 'B';\r
6001 Regname = regnamesshort[EAX];\r
6002 RegnameEBX = regnamesshort[EBX];\r
6003 break;\r
6004 case 1:\r
6005 Size = 'W';\r
6006 Regname = regnamesword[EAX];\r
6007 RegnameEBX = regnamesword[EBX];\r
6008 break;\r
6009 case 2:\r
6010 Size = 'L';\r
6011 Regname = regnameslong[EAX];\r
6012 RegnameEBX = regnameslong[EBX];\r
6013 break;\r
6014 }\r
6015\r
6016 if (OpcodeArray[BaseCode] == -2)\r
6017 {\r
6018 Align();\r
6019 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6020 SavePreviousPC();\r
6021 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6022\r
6023 AddEACycles = 0 ;\r
6024\r
6025 if (Size != 'L')\r
6026 TimingCycles += 12 ;\r
6027 else\r
6028 TimingCycles += 20 ;\r
6029\r
6030 fprintf(fp, "\t\t mov ebx,ecx\n");\r
6031 fprintf(fp, "\t\t and ebx, byte 7\n");\r
6032 fprintf(fp, "\t\t shr ecx, byte 9\n");\r
6033 fprintf(fp, "\t\t and ecx, byte 7\n");\r
6034\r
6035 EffectiveAddressRead(3+ModeModY,Size,EBX,EBX,"--C-S-B",FALSE);\r
6036 EffectiveAddressRead(3+ModeModX,Size,ECX,EAX,"-B--S-B",FALSE);\r
6037\r
6038 fprintf(fp, "\t\t cmp %s,%s\n",Regname,RegnameEBX);\r
6039 SetFlags(Size,EAX,FALSE,FALSE,FALSE);\r
6040 Completed();\r
6041 }\r
6042\r
6043 OpcodeArray[Opcode] = BaseCode ;\r
6044 }\r
6045}\r
6046\r
6047void exg(void)\r
6048{\r
6049 int Opcode, BaseCode ;\r
6050 int regx,type,regy ;\r
6051 int opmask[3] = { 0x08, 0x09, 0x11} ;\r
6052\r
6053 for (regx = 0 ; regx < 8 ; regx++)\r
6054 for (type = 0 ; type < 3 ; type++)\r
6055 for (regy = 0 ; regy < 8 ; regy++)\r
6056 {\r
6057 Opcode = 0xc100 | (regx<<9) | (opmask[type]<<3) | regy ;\r
6058 BaseCode = Opcode & 0xc1c8 ;\r
6059\r
6060 if (OpcodeArray[BaseCode] == -2)\r
6061 {\r
6062 Align();\r
6063 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6064 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6065\r
6066 TimingCycles += 6 ;\r
6067\r
6068 fprintf(fp, "\t\t mov ebx,ecx\n");\r
6069 fprintf(fp, "\t\t and ebx,byte 7\n");\r
6070 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
6071 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6072\r
6073 if (type == 0)\r
6074 {\r
6075 fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_DAT);\r
6076 fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_DAT);\r
6077 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_DAT);\r
6078 fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_DAT);\r
6079 }\r
6080 if (type == 1)\r
6081 {\r
6082 fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD);\r
6083 fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD);\r
6084 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD);\r
6085 fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD);\r
6086 }\r
6087 if (type == 2)\r
6088 {\r
6089 fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_DAT);\r
6090 fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD);\r
6091 fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_DAT);\r
6092 fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD);\r
6093 }\r
6094\r
6095 Completed();\r
6096 }\r
6097\r
6098 OpcodeArray[Opcode] = BaseCode ;\r
6099 }\r
6100}\r
6101\r
6102void ext(void)\r
6103{\r
6104 int Opcode, BaseCode ;\r
6105 int type,regy ;\r
6106\r
6107 for (type = 2 ; type < 8 ; type++)\r
6108 for (regy = 0 ; regy < 8 ; regy++)\r
6109 {\r
6110 if (type > 3 && type < 7)\r
6111 continue ;\r
6112 Opcode = 0x4800 | (type<<6) | regy ;\r
6113 BaseCode = Opcode & 0x48c0 ;\r
6114\r
6115 if (OpcodeArray[BaseCode] == -2)\r
6116 {\r
6117 Align();\r
6118 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6119 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6120\r
6121 TimingCycles += 4 ;\r
6122\r
6123 fprintf(fp, "\t\t and ecx, byte 7\n");\r
6124\r
6125 if (type == 2) /* byte to word */\r
6126 {\r
6127 fprintf(fp, "\t\t movsx eax,byte [%s+ECX*4]\n",REG_DAT);\r
6128 fprintf(fp, "\t\t mov [%s+ECX*4],ax\n",REG_DAT);\r
6129 SetFlags('W',EAX,TRUE,FALSE,FALSE);\r
6130 }\r
6131 if (type == 3) /* word to long */\r
6132 {\r
6133 fprintf(fp, "\t\t movsx eax,word [%s+ECX*4]\n",REG_DAT);\r
6134 fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_DAT);\r
6135 SetFlags('L',EAX,TRUE,FALSE,FALSE);\r
6136 }\r
6137 if (type == 7) /* byte to long */\r
6138 {\r
6139 fprintf(fp, "\t\t movsx eax,byte [%s+ECX*4]\n",REG_DAT);\r
6140 fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_DAT);\r
6141 SetFlags('L',EAX,TRUE,FALSE,FALSE);\r
6142 }\r
6143 Completed();\r
6144 }\r
6145\r
6146 OpcodeArray[Opcode] = BaseCode ;\r
6147 }\r
6148}\r
6149\r
6150void swap(void)\r
6151{\r
6152 int Opcode, BaseCode ;\r
6153 int sreg ;\r
6154\r
6155 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6156 {\r
6157 Opcode = 0x4840 | sreg ;\r
6158 BaseCode = Opcode & 0x4840;\r
6159\r
6160 if (OpcodeArray[BaseCode] == -2)\r
6161 {\r
6162 Align();\r
6163 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6164 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6165\r
6166 TimingCycles += 4 ;\r
6167\r
6168 fprintf(fp, "\t\t and ecx, byte 7\n");\r
6169 fprintf(fp, "\t\t mov eax, dword [%s+ECX*4]\n",REG_DAT);\r
6170 fprintf(fp, "\t\t ror eax, 16\n");\r
6171 fprintf(fp, "\t\t test eax,eax\n");\r
6172 fprintf(fp, "\t\t mov dword [%s+ECX*4],eax\n",REG_DAT);\r
6173 SetFlags('L',EAX,FALSE,FALSE,FALSE);\r
6174 Completed();\r
6175 }\r
6176\r
6177 OpcodeArray[Opcode] = BaseCode ;\r
6178 }\r
6179}\r
6180\r
6181/*\r
6182 * Line A and Line F commands\r
6183 *\r
6184 */\r
6185\r
6186void LineA(void)\r
6187{\r
6188 int Count;\r
6189\r
6190 /* Line A */\r
6191\r
6192 Align();\r
6193 fprintf(fp, "%s:\n",GenerateLabel(0xA000,0));\r
6194 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6195 Exception(0x0A,0xA000);\r
6196\r
6197 for (Count=0xA000;Count<0xB000;Count++)\r
6198 {\r
6199 OpcodeArray[Count] = 0xA000;\r
6200 }\r
6201}\r
6202\r
6203void LineF(void)\r
6204{\r
6205 int Count;\r
6206\r
6207 /* Line F */\r
6208\r
6209 Align();\r
6210 fprintf(fp, "%s:\n",GenerateLabel(0xF000,0));\r
6211 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6212 Exception(0x0B,0xF000);\r
6213\r
6214 for (Count=0xF000;Count<0x10000;Count++)\r
6215 {\r
6216 OpcodeArray[Count] = 0xF000;\r
6217 }\r
6218}\r
6219\r
6220/*\r
6221 * Moves To/From CCR and SR\r
6222 *\r
6223 * (Move from CCR is 68010 command)\r
6224 *\r
6225 */\r
6226\r
6227void movesr(void)\r
6228{\r
6229 int Opcode, BaseCode ;\r
6230 int type, mode, sreg ;\r
6231 int Dest ;\r
6232 char allow[] = "0-2345678-------" ;\r
6233 char Size;\r
6234\r
6235 for (type = 0 ; type < 4 ; type++)\r
6236 for (mode = 0 ; mode < 8 ; mode++)\r
6237 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6238 {\r
6239 Opcode = 0x40c0 | (type << 9) | ( mode << 3 ) | sreg ;\r
6240\r
6241 /* To has extra modes */\r
6242\r
6243 if (type > 1)\r
6244 {\r
6245 allow[0x9] = '9';\r
6246 allow[0xa] = 'a';\r
6247 allow[0xb] = 'b' ;\r
6248 }\r
6249\r
6250 if ((type == 0) | (type == 3))\r
6251 Size = 'W'; /* SR */\r
6252 else\r
6253 Size = 'B'; /* CCR */\r
6254\r
6255 BaseCode = Opcode & 0x46f8 ;\r
6256\r
6257 if (mode == 7)\r
6258 BaseCode |= sreg ;\r
6259\r
6260 Dest = EAtoAMN(BaseCode, FALSE);\r
6261\r
6262 if (allow[Dest&0xf] != '-')\r
6263 {\r
6264 if (OpcodeArray[BaseCode] == -2)\r
6265 {\r
6266 char TrueLabel[16];\r
6267\r
6268 Align();\r
6269 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6270\r
6271 if ((Dest >= 2) && (Dest <=10))\r
6272 SavePreviousPC();\r
6273\r
6274 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6275\r
6276 if (type > 1) /* move to */\r
6277 TimingCycles += 12 ;\r
6278 else\r
6279 {\r
6280 if (mode < 2)\r
6281 TimingCycles += 6 ;\r
6282 else\r
6283 TimingCycles += 8 ;\r
6284 }\r
6285\r
6286 /* If Move to SR then must be in Supervisor Mode */\r
6287\r
6288 if (type == 3)\r
6289 {\r
6290 sprintf(TrueLabel,GenerateLabel(0,1));\r
6291\r
6292 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
6293 fprintf(fp, "\t\t je near %s\n\n",TrueLabel);\r
6294 }\r
6295\r
6296 /* 68010 Command ? */\r
6297 if (type==1) CheckCPUtype(1);\r
6298\r
6299\r
6300 if (mode < 7)\r
6301 {\r
6302 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6303 }\r
6304\r
6305 /* Always read/write word 2 bytes */\r
6306 if (type < 2)\r
6307 {\r
6308 ReadCCR(Size,EBX);\r
6309 EffectiveAddressWrite(Dest & 15,'W',ECX,TRUE,"---DS-B",TRUE);\r
6310 }\r
6311 else\r
6312 {\r
6313 EffectiveAddressRead(Dest & 15,'W',ECX,EAX,"----S-B",FALSE);\r
6314 WriteCCR(Size);\r
6315 }\r
6316 Completed();\r
6317\r
6318 /* Exception if not Supervisor Mode */\r
6319\r
6320 if (type == 3)\r
6321 {\r
6322 /* Was in User Mode - Exception */\r
6323\r
6324 fprintf(fp, "%s:\n",TrueLabel);\r
6325 Exception(8,BaseCode);\r
6326 }\r
6327 }\r
6328\r
6329 OpcodeArray[Opcode] = BaseCode ;\r
6330 }\r
6331 }\r
6332}\r
6333\r
6334/*\r
6335 * Decimal mode Add / Subtracts\r
6336 *\r
6337 */\r
6338\r
6339void abcd_sbcd(void)\r
6340{\r
6341 int Opcode, BaseCode ;\r
6342 int regx,type,rm,regy,mode ;\r
6343 int ModeModX;\r
6344 int ModeModY;\r
6345 char *Label;\r
6346\r
6347 for (type = 0 ; type < 2 ; type ++) /* 0=sbcd, 1=abcd */\r
6348 for (regx = 0 ; regx < 8 ; regx++)\r
6349 for (rm = 0 ; rm < 2 ; rm++)\r
6350 for (regy = 0 ; regy < 8 ; regy++)\r
6351 {\r
6352 Opcode = 0x8100 | (type<<14) | (regx<<9) | (rm<<3) | regy ;\r
6353 BaseCode = Opcode & 0xc108 ;\r
6354\r
6355 ModeModX = 0;\r
6356 ModeModY = 0;\r
6357\r
6358 if (rm == 0)\r
6359 mode = 0 ;\r
6360 else\r
6361 {\r
6362 mode = 4 ;\r
6363\r
6364#ifdef A7ROUTINE\r
6365\r
6366 if (regx == 7)\r
6367 {\r
6368 BaseCode |= (regx << 9);\r
6369 ModeModY = 16;\r
6370 }\r
6371 if (regy == 7)\r
6372 {\r
6373 BaseCode |= regy;\r
6374 ModeModX = 16;\r
6375 }\r
6376\r
6377#endif\r
6378 }\r
6379\r
6380 if (OpcodeArray[BaseCode] == -2)\r
6381 {\r
6382 Align();\r
6383 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6384\r
6385 if (mode == 4)\r
6386 SavePreviousPC();\r
6387\r
6388 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6389\r
6390 AddEACycles = 0 ;\r
6391\r
6392 if (rm == 0)\r
6393 TimingCycles += 6 ;\r
6394 else\r
6395 TimingCycles += 18 ;\r
6396\r
6397 fprintf(fp, "\t\t mov ebx,ecx\n");\r
6398 fprintf(fp, "\t\t and ebx, byte 7\n");\r
6399 fprintf(fp, "\t\t shr ecx, byte 9\n");\r
6400 fprintf(fp, "\t\t and ecx, byte 7\n");\r
6401\r
6402 EffectiveAddressRead(mode+ModeModX,'B',EBX,EBX,"--C-S-B",TRUE);\r
6403 EffectiveAddressRead(mode+ModeModY,'B',ECX,EAX,"-BC-SDB",TRUE);\r
6404\r
6405 CopyX();\r
6406\r
6407 if (type == 0)\r
6408 {\r
6409 fprintf(fp, "\t\t sbb al,bl\n");\r
6410 fprintf(fp, "\t\t das\n");\r
6411 }\r
6412 else\r
6413 {\r
6414 fprintf(fp, "\t\t adc al,bl\n");\r
6415 fprintf(fp, "\t\t daa\n");\r
6416 }\r
6417\r
6418 /* Should only clear Zero flag if not zero */\r
6419\r
6420 Label = GenerateLabel(0,1);\r
6421\r
6422 fprintf(fp, "\t\t mov ebx,edx\n");\r
6423 fprintf(fp, "\t\t setc dl\n");\r
6424\r
6425 fprintf(fp, "\t\t jnz short %s\n\n",Label);\r
6426\r
6427 /* Keep original Zero flag */\r
6428 fprintf(fp, "\t\t and bl,40h ; Mask out Old Z\n");\r
6429 fprintf(fp, "\t\t or dl,bl ; Copy across\n\n");\r
6430\r
6431 fprintf(fp, "%s:\n",Label);\r
6432\r
6433 fprintf(fp, "\t\t mov bl,dl\n"); /* copy carry into sign */\r
6434 fprintf(fp, "\t\t and bl,1\n");\r
6435 fprintf(fp, "\t\t shl bl,7\n");\r
6436 fprintf(fp, "\t\t and dl,7Fh\n");\r
6437 fprintf(fp, "\t\t or dl,bl\n");\r
6438\r
6439 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
6440\r
6441 EffectiveAddressWrite(mode,'B',ECX,EAX,"---DS-B",TRUE);\r
6442 Completed();\r
6443 }\r
6444\r
6445 OpcodeArray[Opcode] = BaseCode ;\r
6446 }\r
6447}\r
6448\r
6449/*\r
6450 * Rotate Left / Right\r
6451 *\r
6452 */\r
6453\r
6454void rol_ror(void)\r
6455{\r
6456 int Opcode, BaseCode ;\r
6457 int dreg, dr, leng, ir, sreg ;\r
6458 char Size=' ';\r
6459 char * Label ;\r
6460 char * Regname="" ;\r
6461 char * RegnameECX ;\r
6462\r
6463 for (dreg = 0 ; dreg < 8 ; dreg++)\r
6464 for (dr = 0 ; dr < 2 ; dr++)\r
6465 for (leng = 0 ; leng < 3 ; leng++)\r
6466 for (ir = 0 ; ir < 2 ; ir++)\r
6467 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6468 {\r
6469 Opcode = 0xe018 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ;\r
6470 BaseCode = Opcode & 0xe1f8 ;\r
6471\r
6472 switch (leng)\r
6473 {\r
6474 case 0:\r
6475 Size = 'B';\r
6476 Regname = regnamesshort[0];\r
6477 RegnameECX = regnamesshort[ECX];\r
6478 break;\r
6479 case 1:\r
6480 Size = 'W';\r
6481 Regname = regnamesword[0];\r
6482 RegnameECX = regnamesword[ECX];\r
6483 break;\r
6484 case 2:\r
6485 Size = 'L';\r
6486 Regname = regnameslong[0];\r
6487 RegnameECX = regnameslong[ECX];\r
6488 break;\r
6489 }\r
6490\r
6491 if (OpcodeArray[ BaseCode ] == -2)\r
6492 {\r
6493 Align();\r
6494 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6495 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6496\r
6497 if (Size != 'L')\r
6498 TimingCycles += 6 ;\r
6499 else\r
6500 TimingCycles += 8 ;\r
6501\r
6502 fprintf(fp, "\t\t mov ebx,ecx\n");\r
6503 fprintf(fp, "\t\t and ebx,byte 7\n");\r
6504 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
6505\r
6506 if (ir == 0)\r
6507 {\r
6508 Immediate8();\r
6509 }\r
6510 else\r
6511 {\r
6512 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6513 EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE);\r
6514 fprintf(fp, "\t\t and ecx,byte 63\n");\r
6515 }\r
6516\r
6517 EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE);\r
6518\r
6519 /* shift 0 - no time, no shift and clear carry */\r
6520\r
6521 Label = GenerateLabel(0,1);\r
6522 fprintf(fp, "\t\t jecxz %s\n",Label);\r
6523\r
6524 /* allow 2 cycles per shift */\r
6525\r
6526 fprintf(fp, "\t\t mov edx,ecx\n");\r
6527 fprintf(fp, "\t\t add edx,edx\n");\r
6528 fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT);\r
6529\r
6530 if (dr == 0)\r
6531 fprintf(fp, "\t\t ror %s,cl\n",Regname);\r
6532 else\r
6533 fprintf(fp, "\t\t rol %s,cl\n",Regname);\r
6534\r
6535 fprintf(fp, "\t\t setc ch\n");\r
6536\r
6537 fprintf(fp, "%s:\n",Label);\r
6538\r
6539 SetFlags(Size,EAX,TRUE,FALSE,FALSE);\r
6540/* fprintf(fp, "\t\t and dl,254\n"); Test clears Carry */\r
6541 fprintf(fp, "\t\t or dl,ch\n");\r
6542\r
6543 EffectiveAddressWrite(0,Size,EBX,EAX,"--C-S-B",TRUE);\r
6544\r
6545 Completed();\r
6546 }\r
6547\r
6548 OpcodeArray[Opcode] = BaseCode ;\r
6549 }\r
6550}\r
6551\r
6552void rol_ror_ea(void)\r
6553{\r
6554 int Opcode, BaseCode ;\r
6555 int dr, mode, sreg ;\r
6556 int Dest ;\r
6557 char allow[] = "--2345678-------" ;\r
6558\r
6559 for (dr = 0 ; dr < 2 ; dr++)\r
6560 for (mode = 0 ; mode < 8 ; mode++)\r
6561 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6562 {\r
6563 Opcode = 0xe6c0 | (dr<<8) | (mode<<3) | sreg ;\r
6564 BaseCode = Opcode & 0xfff8 ;\r
6565\r
6566 if (mode == 7)\r
6567 BaseCode |= sreg ;\r
6568\r
6569 Dest = EAtoAMN(BaseCode, FALSE);\r
6570\r
6571 if (allow[Dest&0xf] != '-')\r
6572 {\r
6573 if (OpcodeArray[ BaseCode ] == -2)\r
6574 {\r
6575 Align();\r
6576 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6577\r
6578 if ((Dest >= 2) && (Dest <=10))\r
6579 SavePreviousPC();\r
6580\r
6581 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6582\r
6583 TimingCycles += 8 ;\r
6584\r
6585 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6586 EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE);\r
6587\r
6588 if (dr == 0)\r
6589 fprintf(fp, "\t\t ror ax,1\n");\r
6590 else\r
6591 fprintf(fp, "\t\t rol ax,1\n");\r
6592\r
6593 fprintf(fp, "\t\t setc bl\n");\r
6594 SetFlags('W',EAX,TRUE,FALSE,FALSE);\r
6595/* fprintf(fp, "\t\t and dl,254\n"); Test clears Carry */\r
6596 fprintf(fp, "\t\t or dl,bl\n");\r
6597\r
6598 EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE);\r
6599\r
6600 Completed();\r
6601 }\r
6602\r
6603 OpcodeArray[Opcode] = BaseCode ;\r
6604 }\r
6605 }\r
6606}\r
6607\r
6608/*\r
6609 * Logical Shift Left / Right\r
6610 *\r
6611 */\r
6612\r
6613void lsl_lsr(void)\r
6614{\r
6615 int Opcode, BaseCode ;\r
6616 int dreg, dr, leng, ir, sreg ;\r
6617 char Size=' ';\r
6618 char * Regname="" ;\r
6619 char * RegnameECX="" ;\r
6620 char * RegnameEDX="" ;\r
6621 char * Label ;\r
6622\r
6623 for (dreg = 0 ; dreg < 8 ; dreg++)\r
6624 for (dr = 0 ; dr < 2 ; dr++)\r
6625 for (leng = 0 ; leng < 3 ; leng++)\r
6626 for (ir = 0 ; ir < 2 ; ir++)\r
6627 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6628 {\r
6629 Opcode = 0xe008 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ;\r
6630 BaseCode = Opcode & 0xe1f8 ;\r
6631\r
6632 switch (leng)\r
6633 {\r
6634 case 0:\r
6635 Size = 'B';\r
6636 Regname = regnamesshort[0];\r
6637 RegnameECX = regnamesshort[ECX];\r
6638 RegnameEDX = regnamesshort[EDX];\r
6639 break;\r
6640 case 1:\r
6641 Size = 'W';\r
6642 Regname = regnamesword[0];\r
6643 RegnameECX = regnamesword[ECX];\r
6644 RegnameEDX = regnamesword[EDX];\r
6645 break;\r
6646 case 2:\r
6647 Size = 'L';\r
6648 Regname = regnameslong[0];\r
6649 RegnameECX = regnameslong[ECX];\r
6650 RegnameEDX = regnameslong[EDX];\r
6651 break;\r
6652 }\r
6653\r
6654 if (OpcodeArray[ BaseCode ] == -2)\r
6655 {\r
6656 Align();\r
6657 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6658 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6659\r
6660 if (Size != 'L')\r
6661 TimingCycles += 6 ;\r
6662 else\r
6663 TimingCycles += 8 ;\r
6664\r
6665 fprintf(fp, "\t\t mov ebx,ecx\n");\r
6666 fprintf(fp, "\t\t and ebx,byte 7\n");\r
6667 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
6668\r
6669 if (ir == 0)\r
6670 {\r
6671 Immediate8();\r
6672 }\r
6673 else\r
6674 {\r
6675 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6676 EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE);\r
6677 fprintf(fp, "\t\t and ecx,byte 63\n");\r
6678 }\r
6679\r
6680 /* and 2 cycles per shift */\r
6681\r
6682 fprintf(fp, "\t\t mov edx,ecx\n");\r
6683 fprintf(fp, "\t\t add edx,edx\n");\r
6684 fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT);\r
6685\r
6686 EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE);\r
6687\r
6688 /* ASG: on the 68k, the shift count is mod 64; on the x86, the */\r
6689 /* shift count is mod 32; we need to check for shifts of 32-63 */\r
6690 /* and produce zero */\r
6691 Label = GenerateLabel(0,1);\r
6692 fprintf(fp, "\t\t test cl,0x20\n");\r
6693 fprintf(fp, "\t\t jnz %s_BigShift\n",Label);\r
6694\r
6695 fprintf(fp, "%s_Continue:\n",Label);\r
6696 if (dr == 0)\r
6697 fprintf(fp, "\t\t shr %s,cl\n",Regname);\r
6698 else\r
6699 fprintf(fp, "\t\t shl %s,cl\n",Regname);\r
6700\r
6701 SetFlags(Size,EAX,FALSE,FALSE,FALSE);\r
6702\r
6703 /* Clear Overflow flag */\r
6704 fprintf(fp, "\t\t xor dh,dh\n");\r
6705\r
6706 EffectiveAddressWrite(0,Size,EBX,EAX,"--CDS-B",TRUE);\r
6707\r
6708 /* if shift count is zero clear carry */\r
6709\r
6710 fprintf(fp, "\t\t jecxz %s\n",Label);\r
6711\r
6712 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
6713 Completed();\r
6714\r
6715 Align();\r
6716 fprintf(fp, "%s:\n",Label);\r
6717 fprintf(fp, "\t\t and dl,254\t\t;clear C flag\n");\r
6718 Completed();\r
6719\r
6720 fprintf(fp, "%s_BigShift:\n",Label);\r
6721 if (dr == 0)\r
6722 {\r
6723 fprintf(fp, "\t\t shr %s,16\n",Regname);\r
6724 fprintf(fp, "\t\t shr %s,16\n",Regname);\r
6725 }\r
6726 else\r
6727 {\r
6728 fprintf(fp, "\t\t shl %s,16\n",Regname);\r
6729 fprintf(fp, "\t\t shl %s,16\n",Regname);\r
6730 }\r
6731 fprintf(fp, "\t\t jmp %s_Continue\n",Label);\r
6732 }\r
6733\r
6734 OpcodeArray[Opcode] = BaseCode ;\r
6735 }\r
6736}\r
6737\r
6738void lsl_lsr_ea(void)\r
6739{\r
6740 int Opcode, BaseCode ;\r
6741 int dr, mode, sreg ;\r
6742 int Dest ;\r
6743 char allow[] = "--2345678-------" ;\r
6744\r
6745 for (dr = 0 ; dr < 2 ; dr++)\r
6746 for (mode = 0 ; mode < 8 ; mode++)\r
6747 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6748 {\r
6749 Opcode = 0xe2c0 | (dr<<8) | (mode<<3) | sreg ;\r
6750 BaseCode = Opcode & 0xfff8 ;\r
6751\r
6752 if (mode == 7)\r
6753 BaseCode |= sreg ;\r
6754\r
6755 Dest = EAtoAMN(BaseCode, FALSE);\r
6756\r
6757 if (allow[Dest&0xf] != '-')\r
6758 {\r
6759 if (OpcodeArray[ BaseCode ] == -2)\r
6760 {\r
6761\r
6762 Align();\r
6763 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6764\r
6765 if ((Dest >= 2) && (Dest <=10))\r
6766 SavePreviousPC();\r
6767\r
6768 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6769\r
6770 TimingCycles += 8 ;\r
6771\r
6772 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6773 EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE);\r
6774\r
6775 if (dr == 0)\r
6776 fprintf(fp, "\t\t shr ax,1\n");\r
6777 else\r
6778 fprintf(fp, "\t\t shl ax,1\n");\r
6779\r
6780 SetFlags('W',EAX,FALSE,TRUE,FALSE);\r
6781\r
6782 /* Clear Overflow flag */\r
6783\r
6784 fprintf(fp, "\t\t xor dh,dh\n");\r
6785\r
6786 EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE);\r
6787 Completed();\r
6788 }\r
6789\r
6790 OpcodeArray[Opcode] = BaseCode ;\r
6791 }\r
6792 }\r
6793}\r
6794\r
6795/*\r
6796 * Rotate Left / Right though Extend\r
6797 *\r
6798 */\r
6799\r
6800void roxl_roxr(void)\r
6801{\r
6802 int Opcode, BaseCode ;\r
6803 int dreg, dr, leng, ir, sreg ;\r
6804 char Size=' ' ;\r
6805 char * Regname="" ;\r
6806 char * RegnameECX="" ;\r
6807 char * Label ;\r
6808\r
6809 for (dreg = 0 ; dreg < 8 ; dreg++)\r
6810 for (dr = 0 ; dr < 2 ; dr++)\r
6811 for (leng = 0 ; leng < 3 ; leng++)\r
6812 for (ir = 0 ; ir < 2 ; ir++)\r
6813 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6814 {\r
6815 Opcode = 0xe010 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ;\r
6816 BaseCode = Opcode & 0xe1f8 ;\r
6817\r
6818 switch (leng)\r
6819 {\r
6820 case 0:\r
6821 Size = 'B';\r
6822 Regname = regnamesshort[0];\r
6823 RegnameECX = regnamesshort[ECX];\r
6824 break;\r
6825 case 1:\r
6826 Size = 'W';\r
6827 Regname = regnamesword[0];\r
6828 RegnameECX = regnamesword[ECX];\r
6829 break;\r
6830 case 2:\r
6831 Size = 'L';\r
6832 Regname = regnameslong[0];\r
6833 RegnameECX = regnameslong[ECX];\r
6834 break;\r
6835 }\r
6836\r
6837 if (OpcodeArray[ BaseCode ] == -2)\r
6838 {\r
6839 Align();\r
6840 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6841 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6842\r
6843 if (Size != 'L')\r
6844 TimingCycles += 6 ;\r
6845 else\r
6846 TimingCycles += 8 ;\r
6847\r
6848 fprintf(fp, "\t\t mov ebx,ecx\n");\r
6849 fprintf(fp, "\t\t and ebx,byte 7\n");\r
6850 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
6851\r
6852 if (ir == 0)\r
6853 {\r
6854 Immediate8();\r
6855 }\r
6856 else\r
6857 {\r
6858 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6859 EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE);\r
6860 fprintf(fp, "\t\t and ecx,byte 63\n");\r
6861 }\r
6862\r
6863 /* allow 2 cycles per shift */\r
6864\r
6865 fprintf(fp, "\t\t mov edx,ecx\n");\r
6866 fprintf(fp, "\t\t add edx,edx\n");\r
6867 fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT);\r
6868\r
6869 EffectiveAddressRead(0,Size,EBX,EAX,"-BC-SDB",FALSE);\r
6870\r
6871 /* move X into C so RCR & RCL can be used */\r
6872 /* RCR & RCL only set the carry flag */\r
6873\r
6874 CopyX();\r
6875\r
6876 if (dr == 0)\r
6877 fprintf(fp, "\t\t rcr %s,cl\n",Regname);\r
6878 else\r
6879 fprintf(fp, "\t\t rcl %s,cl\n",Regname);\r
6880\r
6881 fprintf(fp, "\t\t setc ch\n");\r
6882 SetFlags(Size,EAX,TRUE,FALSE,FALSE);\r
6883/* fprintf(fp, "\t\t and dl,254\n"); Test Clears Carry */\r
6884\r
6885 EffectiveAddressWrite(0,Size,EBX,EAX,"--CDS-B",TRUE);\r
6886\r
6887 /* if shift count is zero clear carry */\r
6888\r
6889 Label = GenerateLabel(0,1);\r
6890 fprintf(fp, "\t\t test cl,cl\n");\r
6891 fprintf(fp, "\t\t jz %s\n",Label);\r
6892\r
6893 /* Add in Carry Flag */\r
6894\r
6895 fprintf(fp, "\t\t or dl,ch\n");\r
6896 fprintf(fp, "\t\t mov [%s],dl\n",REG_X);\r
6897 Completed();\r
6898\r
6899\r
6900 /* copy X onto C when shift is zero */\r
6901\r
6902 Align();\r
6903 fprintf(fp, "%s:\n",Label);\r
6904 fprintf(fp, "\t\t mov ecx,[%s]\n",REG_X);\r
6905 fprintf(fp, "\t\t and ecx,byte 1\n");\r
6906 fprintf(fp, "\t\t or edx,ecx\n");\r
6907 Completed();\r
6908 }\r
6909\r
6910 OpcodeArray[Opcode] = BaseCode ;\r
6911 }\r
6912}\r
6913\r
6914void roxl_roxr_ea(void)\r
6915{\r
6916 int Opcode, BaseCode ;\r
6917 int dr, mode, sreg ;\r
6918 int Dest ;\r
6919 char allow[] = "--2345678-------" ;\r
6920\r
6921 for (dr = 0 ; dr < 2 ; dr++)\r
6922 for (mode = 0 ; mode < 8 ; mode++)\r
6923 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6924 {\r
6925 Opcode = 0xe4c0 | (dr<<8) | (mode<<3) | sreg ;\r
6926 BaseCode = Opcode & 0xfff8 ;\r
6927\r
6928 if (mode == 7)\r
6929 BaseCode |= sreg ;\r
6930\r
6931 Dest = EAtoAMN(BaseCode, FALSE);\r
6932\r
6933 if (allow[Dest&0xf] != '-')\r
6934 {\r
6935 if (OpcodeArray[ BaseCode ] == -2)\r
6936 {\r
6937 Align();\r
6938 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
6939\r
6940 if ((Dest >= 2) && (Dest <=10))\r
6941 SavePreviousPC();\r
6942\r
6943 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
6944\r
6945 TimingCycles += 8 ;\r
6946\r
6947 fprintf(fp, "\t\t and ecx,byte 7\n");\r
6948 EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE);\r
6949\r
6950 /* move X into C so RCR & RCL can be used */\r
6951 /* RCR & RCL only set the carry flag */\r
6952\r
6953 CopyX();\r
6954\r
6955 if (dr == 0)\r
6956 fprintf(fp, "\t\t rcr ax,1\n");\r
6957 else\r
6958 fprintf(fp, "\t\t rcl ax,1\n");\r
6959\r
6960 fprintf(fp, "\t\t setc bl\n");\r
6961 SetFlags('W',EAX,TRUE,FALSE,FALSE);\r
6962/* fprintf(fp, "\t\t and dl,254\n"); - Intel Clears on Test */\r
6963 fprintf(fp, "\t\t or dl,bl\n");\r
6964\r
6965 EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE);\r
6966\r
6967 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
6968 Completed();\r
6969 }\r
6970\r
6971 OpcodeArray[Opcode] = BaseCode ;\r
6972 }\r
6973 }\r
6974}\r
6975\r
6976/*\r
6977 * Arithmetic Shift Left / Right\r
6978 *\r
6979 */\r
6980\r
6981void asl_asr(void)\r
6982{\r
6983 int Opcode, BaseCode ;\r
6984 int dreg, dr, leng, ir, sreg ;\r
6985 char Size=' ';\r
6986 char * Sizename="" ;\r
6987 char * Regname="" ;\r
6988 char * RegnameEDX="" ;\r
6989 char * RegnameECX="" ;\r
6990 char * Label;\r
6991\r
6992 /* Normal routines for codes */\r
6993\r
6994 for (dreg = 0 ; dreg < 8 ; dreg++)\r
6995 for (dr = 0 ; dr < 2 ; dr++)\r
6996 for (leng = 0 ; leng < 3 ; leng++)\r
6997 for (ir = 0 ; ir < 2 ; ir++)\r
6998 for (sreg = 0 ; sreg < 8 ; sreg++)\r
6999 {\r
7000 Opcode = 0xe000 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ;\r
7001 BaseCode = Opcode & 0xe1f8 ;\r
7002\r
7003 switch (leng)\r
7004 {\r
7005 case 0:\r
7006 Size = 'B';\r
7007 Regname = regnamesshort[0];\r
7008 RegnameECX = regnamesshort[ECX];\r
7009 RegnameEDX = regnamesshort[EDX];\r
7010 break;\r
7011 case 1:\r
7012 Size = 'W';\r
7013 Regname = regnamesword[0];\r
7014 RegnameECX = regnamesword[ECX];\r
7015 RegnameEDX = regnamesword[EDX];\r
7016 break;\r
7017 case 2:\r
7018 Size = 'L';\r
7019 Regname = regnameslong[0];\r
7020 RegnameECX = regnameslong[ECX];\r
7021 RegnameEDX = regnameslong[EDX];\r
7022 break;\r
7023 }\r
7024\r
7025 if (OpcodeArray[ BaseCode ] == -2)\r
7026 {\r
7027 Align();\r
7028 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
7029 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
7030\r
7031 Label = GenerateLabel(0,1);\r
7032\r
7033 if (Size != 'L')\r
7034 TimingCycles += 6 ;\r
7035 else\r
7036 TimingCycles += 8 ;\r
7037\r
7038 fprintf(fp, "\t\t mov ebx,ecx\n");\r
7039 fprintf(fp, "\t\t and ebx,byte 7\n");\r
7040 fprintf(fp, "\t\t shr ecx,byte 9\n");\r
7041\r
7042 EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE);\r
7043\r
7044 if (ir == 0)\r
7045 {\r
7046 Immediate8();\r
7047 }\r
7048 else\r
7049 {\r
7050 fprintf(fp, "\t\t and ecx,byte 7\n");\r
7051 EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE);\r
7052 fprintf(fp, "\t\t and ecx,byte 63\n");\r
7053 fprintf(fp, "\t\t jz short %s\n",Label);\r
7054 }\r
7055\r
7056 /* allow 2 cycles per shift */\r
7057\r
7058 fprintf(fp, "\t\t mov edx,ecx\n");\r
7059 fprintf(fp, "\t\t add edx,edx\n");\r
7060 fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT);\r
7061\r
7062 if (dr == 0)\r
7063 {\r
7064 /* ASR */\r
7065\r
7066 /* ASG: on the 68k, the shift count is mod 64; on the x86, the */\r
7067 /* shift count is mod 32; we need to check for shifts of 32-63 */\r
7068 /* and effectively shift 31 */\r
7069 fprintf(fp, "\t\t shrd edx,ecx,6\n");\r
7070 fprintf(fp, "\t\t sar edx,31\n");\r
7071 fprintf(fp, "\t\t and edx,31\n");\r
7072 fprintf(fp, "\t\t or ecx,edx\n");\r
7073\r
7074 fprintf(fp, "\t\t sar %s,cl\n",Regname);\r
7075\r
7076 /* Mode 0 write does not affect Flags */\r
7077 EffectiveAddressWrite(0,Size,EBX,EAX,"---DS-B",TRUE);\r
7078\r
7079 /* Update Flags */\r
7080 fprintf(fp, "\t\t lahf\n");\r
7081\r
7082#ifdef STALLCHECK\r
7083 ClearRegister(EDX);\r
7084 fprintf(fp, "\t\t mov dl,ah\n");\r
7085#else\r
7086 fprintf(fp, "\t\t movzx edx,ah\n");\r
7087#endif\r
7088\r
7089 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
7090 }\r
7091 else\r
7092 {\r
7093 /* ASL */\r
7094\r
7095 /* Check to see if Overflow should be set */\r
7096\r
7097 fprintf(fp,"\t\t mov edi,eax\t\t; Save It\n");\r
7098\r
7099 ClearRegister(EDX);\r
7100 fprintf(fp,"\t\t stc\n");\r
7101 fprintf(fp,"\t\t rcr %s,1\t\t; d=1xxxx\n",RegnameEDX);\r
7102 fprintf(fp,"\t\t sar %s,cl\t\t; d=1CCxx\n",RegnameEDX);\r
7103 fprintf(fp,"\t\t and eax,edx\n");\r
7104 fprintf(fp,"\t\t jz short %s_V\t\t; No Overflow\n",Label);\r
7105 fprintf(fp,"\t\t cmp eax,edx\n");\r
7106 fprintf(fp,"\t\t je short %s_V\t\t; No Overflow\n",Label);\r
7107\r
7108 /* Set Overflow */\r
7109 fprintf(fp,"\t\t mov edx,0x800\n");\r
7110 fprintf(fp,"\t\t jmp short %s_OV\n",Label);\r
7111\r
7112 fprintf(fp,"%s_V:\n",Label);\r
7113 ClearRegister(EDX);\r
7114\r
7115 fprintf(fp,"%s_OV:\n",Label);\r
7116\r
7117 /* more than 31 shifts and long */\r
7118\r
7119 if ((ir==1) && (leng==2))\r
7120 {\r
7121 fprintf(fp,"\t\t test cl,0x20\n");\r
7122 fprintf(fp,"\t\t jnz short %s_32\n\n",Label);\r
7123 }\r
7124\r
7125 fprintf(fp,"\t\t mov eax,edi\t\t; Restore It\n");\r
7126\r
7127 fprintf(fp, "\t\t sal %s,cl\n",Regname);\r
7128\r
7129 EffectiveAddressWrite(0,Size,EBX,EAX,"---DS-B",TRUE);\r
7130 fprintf(fp, "\t\t lahf\n");\r
7131 fprintf(fp, "\t\t mov dl,ah\n");\r
7132 fprintf(fp, "\t\t mov [%s],edx\n",REG_X);\r
7133 }\r
7134 Completed();\r
7135\r
7136 if (ir != 0)\r
7137 {\r
7138 Align();\r
7139 fprintf(fp, "%s:\n",Label);\r
7140\r
7141\r
7142 if (dr == 0)\r
7143 {\r
7144 /* ASR - Test clears V and C */\r
7145 SetFlags(Size,EAX,TRUE,FALSE,FALSE);\r
7146 }\r
7147 else\r
7148 {\r
7149 /* ASL - Keep existing Carry flag, Clear V */\r
7150 fprintf(fp, "\t\t mov ebx,edx\n");\r
7151 fprintf(fp, "\t\t and ebx,byte 1\n");\r
7152 SetFlags(Size,EAX,TRUE,FALSE,FALSE);\r
7153 fprintf(fp, "\t\t or edx,ebx\n");\r
7154\r
7155 if (leng==2)\r
7156 {\r
7157 Completed();\r
7158\r
7159 /* > 31 Shifts */\r
7160\r
7161 fprintf(fp, "%s_32:\n",Label);\r
7162 fprintf(fp, "\t\t mov dl,40h\n"); // Zero flag\r
7163 ClearRegister(EAX);\r
7164 EffectiveAddressWrite(0,Size,EBX,EAX,"----S-B",TRUE);\r
7165 }\r
7166 }\r
7167\r
7168 Completed();\r
7169 }\r
7170 }\r
7171\r
7172 OpcodeArray[Opcode] = BaseCode ;\r
7173 }\r
7174\r
7175 /* End with special routines for ASL.x #1,Dx */\r
7176 /* To do correct V setting, ASL needs quite a */\r
7177 /* bit of additional code. A Shift of one has */\r
7178 /* correct flags on Intel, and is very common */\r
7179 /* in 68000 programs. */\r
7180\r
7181 for (leng = 0 ; leng < 3 ; leng++)\r
7182 for (sreg = 0 ; sreg < 8 ; sreg++)\r
7183 {\r
7184 Opcode = 0xe300 | (leng<<6) | sreg ;\r
7185 BaseCode = Opcode & 0xe3c8 ;\r
7186\r
7187 switch (leng)\r
7188 {\r
7189 case 0:\r
7190 Sizename = "byte";\r
7191 break;\r
7192 case 1:\r
7193 Sizename = "word";\r
7194 break;\r
7195 case 2:\r
7196 Sizename = "long";\r
7197 break;\r
7198 }\r
7199\r
7200 if (sreg == 0)\r
7201 {\r
7202 Align();\r
7203 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
7204 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
7205\r
7206 Label = GenerateLabel(0,1);\r
7207\r
7208 if (Size != 'L')\r
7209 TimingCycles += 6 ;\r
7210 else\r
7211 TimingCycles += 8 ;\r
7212\r
7213 fprintf(fp, "\t\t and ecx,byte 7\n");\r
7214 fprintf(fp, "\t\t sal %s [%s+ecx*4],1\n",Sizename,REG_DAT);\r
7215 SetFlags('L',EAX,FALSE,TRUE,FALSE);\r
7216 Completed();\r
7217\r
7218 }\r
7219\r
7220 OpcodeArray[Opcode] = BaseCode ;\r
7221 }\r
7222}\r
7223\r
7224void asl_asr_ea(void)\r
7225{\r
7226 int Opcode, BaseCode ;\r
7227 int dr, mode, sreg ;\r
7228 int Dest ;\r
7229 char allow[] = "--2345678-------" ;\r
7230\r
7231 for (dr = 0 ; dr < 2 ; dr++)\r
7232 for (mode = 0 ; mode < 8 ; mode++)\r
7233 for (sreg = 0 ; sreg < 8 ; sreg++)\r
7234 {\r
7235 Opcode = 0xe0c0 | (dr<<8) | (mode<<3) | sreg ;\r
7236 BaseCode = Opcode & 0xfff8 ;\r
7237\r
7238 if (mode == 7)\r
7239 BaseCode |= sreg ;\r
7240\r
7241 Dest = EAtoAMN(BaseCode, FALSE);\r
7242\r
7243 if (allow[Dest&0xf] != '-')\r
7244 {\r
7245 if (OpcodeArray[ BaseCode ] == -2)\r
7246 {\r
7247\r
7248 Align();\r
7249 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
7250\r
7251 if ((Dest >= 2) && (Dest <=10))\r
7252 SavePreviousPC();\r
7253\r
7254 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
7255\r
7256 TimingCycles += 8 ;\r
7257\r
7258 fprintf(fp, "\t\t and ecx,byte 7\n");\r
7259 EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE);\r
7260\r
7261 if (dr == 0)\r
7262 fprintf(fp, "\t\t sar ax,1\n");\r
7263 else\r
7264 fprintf(fp, "\t\t sal ax,1\n");\r
7265\r
7266 SetFlags('W',EAX,FALSE,TRUE,TRUE);\r
7267\r
7268 EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"----S-B",FALSE);\r
7269 Completed();\r
7270 }\r
7271\r
7272 OpcodeArray[Opcode] = BaseCode ;\r
7273 }\r
7274 }\r
7275}\r
7276\r
7277/*\r
7278 * Divide Commands\r
7279 */\r
7280\r
7281void divides(void)\r
7282{\r
7283 int dreg, type, mode, sreg ;\r
7284 int Opcode, BaseCode ;\r
7285 int Dest ;\r
7286 char allow[] = "0-23456789ab-----" ;\r
7287 char TrapLabel[16];\r
7288 int Cycles;\r
7289\r
7290 int divide_cycles[12] =\r
7291 {\r
7292 38,0,42,42,44,46,50,46,50,46,48,42\r
7293 };\r
7294\r
7295 for (dreg = 0 ; dreg < 8 ; dreg++)\r
7296 for (type = 0 ; type < 2 ; type++)\r
7297 for (mode = 0 ; mode < 8 ; mode++)\r
7298 for (sreg = 0 ; sreg < 8 ; sreg++)\r
7299 {\r
7300 Opcode = 0x80c0 | (dreg<<9) | (type<<8) | (mode<<3) | sreg ;\r
7301 BaseCode = Opcode & 0x81f8 ;\r
7302 if (mode == 7)\r
7303 {\r
7304 BaseCode |= sreg ;\r
7305 }\r
7306\r
7307 Dest = EAtoAMN(Opcode, FALSE);\r
7308 if (allow[Dest&0x0f] != '-')\r
7309 {\r
7310 if (OpcodeArray[ BaseCode ] == -2)\r
7311 {\r
7312 Align();\r
7313 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
7314\r
7315 if ((Dest >= 2) && (Dest <=10))\r
7316 SavePreviousPC();\r
7317\r
7318 fprintf(fp, "\t\t add esi,byte 2\n\n");\r
7319\r
7320\r
7321 /* Save EDX (in case of overflow) */\r
7322\r
7323 fprintf(fp, "\t\t and edx,byte -2\n");\r
7324 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
7325\r
7326\r
7327 /* Cycle Timing (if succeeds OK) */\r
7328\r
7329 Cycles = divide_cycles[Dest & 0x0f] + 95 + (type * 17);\r
7330\r
7331 if (Cycles > 127)\r
7332 fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,Cycles);\r
7333 else\r
7334 fprintf(fp, "\t\t sub dword [%s],byte %d\n",ICOUNT,Cycles);\r
7335\r
7336 if (mode < 7)\r
7337 {\r
7338 fprintf(fp, "\t\t mov ebx,ecx\n");\r
7339 fprintf(fp, "\t\t and ebx,byte 7\n");\r
7340 }\r
7341\r
7342 fprintf(fp, "\t\t shr ecx, byte 9\n");\r
7343 fprintf(fp, "\t\t and ecx, byte 7\n");\r
7344\r
7345 sprintf(TrapLabel, "%s", GenerateLabel(0,1) ) ;\r
7346\r
7347 EffectiveAddressRead(Dest,'W',EBX,EAX,"A-C-SDB",FALSE); /* source */\r
7348\r
7349 fprintf(fp, "\t\t test ax,ax\n");\r
7350 fprintf(fp, "\t\t je near %s_ZERO\t\t;do div by zero trap\n", TrapLabel);\r
7351\r
7352 if (type == 1) /* signed */\r
7353 {\r
7354 fprintf(fp, "\t\t movsx ebx,ax\n");\r
7355 }\r
7356 else\r
7357 {\r
7358 fprintf(fp, "\t\t movzx ebx,ax\n");\r
7359 }\r
7360\r
7361 EffectiveAddressRead(0,'L',ECX,EAX,"ABC-SDB",FALSE); /* dest */\r
7362\r
7363 if (type == 1) /* signed */\r
7364 {\r
7365 fprintf(fp, "\t\t cdq\n"); /* EDX:EAX = 64 bit signed */\r
7366 fprintf(fp, "\t\t idiv ebx\n"); /* EBX = 32 bit */\r
7367\r
7368 /* Check for Overflow */\r
7369\r
7370 fprintf(fp, "\t\t movsx ebx,ax\n");\r
7371 fprintf(fp, "\t\t cmp eax,ebx\n");\r
7372 fprintf(fp, "\t\t jne short %s_OVER\n",TrapLabel);\r
7373 }\r
7374 else\r
7375 {\r
7376 ClearRegister(EDX);\r
7377 fprintf(fp, "\t\t div ebx\n");\r
7378\r
7379 /* Check for Overflow */\r
7380\r
7381 fprintf(fp, "\t\t test eax, 0FFFF0000H\n");\r
7382 fprintf(fp, "\t\t jnz short %s_OVER\n",TrapLabel);\r
7383 }\r
7384\r
7385 /* Sort out Result */\r
7386\r
7387 fprintf(fp, "\t\t shl edx, byte 16\n");\r
7388 fprintf(fp, "\t\t mov dx,ax\n");\r
7389 fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT);\r
7390 SetFlags('W',EDX,TRUE,FALSE,FALSE);\r
7391\r
7392 Completed();\r
7393\r
7394\r
7395 /* Overflow */\r
7396\r
7397 Align();\r
7398 fprintf(fp, "%s_OVER:\n",TrapLabel);\r
7399 fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR);\r
7400 fprintf(fp, "\t\t or edx,0x0800\t\t;V flag\n");\r
7401 Completed();\r
7402\r
7403\r
7404 /* Division by Zero */\r
7405\r
7406 Align();\r
7407 fprintf(fp, "%s_ZERO:\t\t ;Do divide by zero trap\n", TrapLabel);\r
7408\r
7409 /* Correct cycle counter for error */\r
7410\r
7411 fprintf(fp, "\t\t add dword [%s],byte %d\n",ICOUNT,95 + (type * 17));\r
7412 fprintf(fp, "\t\t mov al,5\n");\r
7413 Exception(-1,BaseCode);\r
7414 Completed();\r
7415 }\r
7416\r
7417 OpcodeArray[Opcode] = BaseCode ;\r
7418 }\r
7419 }\r
7420}\r
7421\r
7422\r
7423/*\r
7424 * 68010 Extra Opcodes\r
7425 *\r
7426 * move from CCR is done above\r
7427 *\r
7428 */\r
7429\r
7430void ReturnandDeallocate(void)\r
7431{\r
7432 int BaseCode = 0x4e74 ;\r
7433\r
7434 if (OpcodeArray[BaseCode] == -2)\r
7435 {\r
7436 Align();\r
7437 fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0));\r
7438\r
7439 CheckCPUtype(1);\r
7440\r
7441 SavePreviousPC();\r
7442\r
7443 TimingCycles += 16;\r
7444\r
7445 OpcodeArray[BaseCode] = BaseCode ;\r
7446\r
7447 /* Get Return Address */\r
7448\r
7449 fprintf(fp, "\t\t mov eax,[%s]\n",REG_A7);\r
7450 Memory_Read('L',EAX,"---D--B",1);\r
7451\r
7452\r
7453 /* Get Displacement */\r
7454\r
7455 Memory_Fetch('W',EBX,TRUE);\r
7456\r
7457\r
7458 /* Set PC = New Address */\r
7459\r
7460 fprintf(fp, "\t\t mov esi,eax\n");\r
7461\r
7462\r
7463 /* Correct Stack for Return Address and Displacement */\r
7464\r
7465 fprintf(fp, "\t\t add ebx,byte 4\n");\r
7466 fprintf(fp, "\t\t add dword [%s],ebx\n",REG_A7);\r
7467\r
7468 MemoryBanking(BaseCode);\r
7469 Completed();\r
7470 }\r
7471}\r
7472\r
7473void MoveControlRegister(void)\r
7474{\r
7475 int Direction;\r
7476 int BaseCode = 0x4e7a ;\r
7477\r
7478 for (Direction=0;Direction<2;Direction++)\r
7479 {\r
7480 Align();\r
7481 fprintf(fp, "%s:\n",GenerateLabel(BaseCode+Direction,0));\r
7482\r
7483 TimingCycles += 4; /* Assume same as move usp */\r
7484\r
7485 CheckCPUtype(1);\r
7486\r
7487 fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH);\r
7488 fprintf(fp, "\t\t jz short OP%d_%4.4x_Trap\n",CPU,BaseCode+Direction);\r
7489\r
7490 fprintf(fp, "\t\t add esi,byte 2\n");\r
7491 if (CPU==2)\r
7492 fprintf(fp, "\t\t xor esi,2\n"); /* ASG */\r
7493#ifdef STALLCHECK\r
7494 ClearRegister(EBX);\r
7495 fprintf(fp, "\t\t mov bx,[esi+ebp]\n");\r
7496#else\r
7497 fprintf(fp, "\t\t movzx ebx,word [esi+ebp]\n");\r
7498#endif\r
7499 if (CPU==2)\r
7500 fprintf(fp, "\t\t xor esi,2\n"); /* ASG */\r
7501\r
7502 fprintf(fp, "\t\t add esi,byte 2\n");\r
7503 fprintf(fp, "\t\t mov eax,ebx\n");\r
7504 fprintf(fp, "\t\t mov ecx,ebx\n");\r
7505\r
7506 /* Sort out Register */\r
7507\r
7508 fprintf(fp, "\t\t shr ebx,12\n");\r
7509\r
7510 /* Sort out Control Register ID */\r
7511\r
7512 fprintf(fp, "\t\t and eax,byte 1\n");\r
7513 fprintf(fp, "\t\t shr ecx,10\n");\r
7514 fprintf(fp, "\t\t and ecx,2\n");\r
7515 fprintf(fp, "\t\t or ecx,eax\n");\r
7516\r
7517 if (Direction==0)\r
7518 {\r
7519 /* from Control */\r
7520\r
7521 fprintf(fp, "\t\t mov eax,[%s+ecx*4]\n",REG_SFC);\r
7522 fprintf(fp, "\t\t mov %s,eax\n",REG_DAT_EBX);\r
7523 }\r
7524 else\r
7525 {\r
7526 /* To Control */\r
7527\r
7528 fprintf(fp, "\t\t mov eax,%s\n",REG_DAT_EBX);\r
7529\r
7530 /* Mask out for SFC & DFC */\r
7531\r
7532 fprintf(fp, "\t\t test cl,2\n");\r
7533 fprintf(fp, "\t\t jne short OP%d_%4.4x_Mask\n",CPU,BaseCode+Direction);\r
7534 fprintf(fp, "\t\t and eax,byte 7\n");\r
7535 fprintf(fp, "OP%d_%4.4x_Mask:\n",CPU,BaseCode+Direction);\r
7536\r
7537 /* Write to control */\r
7538\r
7539 fprintf(fp, "\t\t mov [%s+ecx*4],eax\n",REG_SFC);\r
7540 }\r
7541\r
7542 Completed();\r
7543\r
7544 /* Not Supervisor Mode */\r
7545\r
7546 Align();\r
7547 fprintf(fp, "OP%d_%4.4x_Trap:\n",CPU,BaseCode+Direction);\r
7548 Exception(8,BaseCode+Direction);\r
7549\r
7550 OpcodeArray[BaseCode+Direction] = BaseCode+Direction;\r
7551 }\r
7552}\r
7553\r
7554void MoveAddressSpace(void)\r
7555{\r
7556}\r
7557\r
7558/*\r
7559 * Generate Jump Table\r
7560 *\r
7561 */\r
7562\r
7563void JumpTable(void)\r
7564{\r
7565 int Opcode,l,op;\r
7566\r
7567 fprintf(fp, "DD OP%d_1000\n",CPU);\r
7568\r
7569 l = 0 ;\r
7570 for (Opcode=0x0;Opcode<0x10000;)\r
7571 {\r
7572\r
7573 op = OpcodeArray[Opcode];\r
7574\r
7575 fprintf(fp, "DD ");\r
7576\r
7577 l = 1 ;\r
7578 while (op == OpcodeArray[Opcode+l] && ((Opcode+l) & 0xfff) != 0)\r
7579 {\r
7580 l++ ;\r
7581 }\r
7582\r
7583 Opcode += l ;\r
7584\r
7585 if (l > 255)\r
7586 {\r
7587 if (op > -1)\r
7588 fprintf(fp, "OP%d_%4.4x - OP%d_1000\n",CPU,op,CPU);\r
7589 else\r
7590 fprintf(fp, "ILLEGAL - OP%d_1000\n",CPU);\r
7591\r
7592 fprintf(fp, "DW %d\n", l);\r
7593 }\r
7594 else\r
7595 {\r
7596 if (op > -1)\r
7597 fprintf(fp, "(OP%d_%4.4x - OP%d_1000) + (%d * 1000000h)\n",CPU,op,CPU,l);\r
7598 else\r
7599 fprintf(fp, "(ILLEGAL - OP%d_1000) + (%d * 1000000h)\n",CPU,l);\r
7600 }\r
7601 }\r
7602}\r
7603\r
7604void CodeSegmentBegin(void)\r
7605{\r
7606\r
7607/* Messages */\r
7608\r
7609 fprintf(fp, "; Make68K - V%s - Copyright 1998, Mike Coates (mame@btinternet.com)\n", VERSION);\r
7610 fprintf(fp, "; & Darren Olafson (deo@mail.island.net)\n\n");\r
7611\r
7612/* Needed code to make it work! */\r
7613\r
7614 fprintf(fp, "\t\t BITS 32\n\n");\r
7615\r
7616 fprintf(fp, "\t\t GLOBAL %s_RUN\n",CPUtype);\r
7617 fprintf(fp, "\t\t GLOBAL %s_RESET\n",CPUtype);\r
7618 fprintf(fp, "\t\t GLOBAL %s_regs\n",CPUtype);\r
7619 fprintf(fp, "\t\t GLOBAL %s_COMPTABLE\n",CPUtype);\r
7620 fprintf(fp, "\t\t GLOBAL %s_OPCODETABLE\n",CPUtype);\r
7621\r
7622 /* ASG - only one interface to memory now */\r
7623 fprintf(fp, "\t\t EXTERN _m68k_ICount\n");\r
7624 fprintf(fp, "\t\t EXTERN _a68k_memory_intf\n");\r
7625 fprintf(fp, "\t\t EXTERN _mem_amask\n");\r
7626\r
7627 fprintf(fp, "; Vars Mame declares / needs access to\n\n");\r
7628\r
7629 fprintf(fp, "\t\t EXTERN _mame_debug\n");\r
7630 fprintf(fp, "\t\t EXTERN _illegal_op\n");\r
7631 fprintf(fp, "\t\t EXTERN _illegal_pc\n");\r
7632\r
7633 fprintf(fp, "\t\t EXTERN _OP_ROM\n");\r
7634 fprintf(fp, "\t\t EXTERN _OP_RAM\n");\r
7635\r
7636 fprintf(fp, "\t\t EXTERN _opcode_entry\n");\r
7637 fprintf(fp, "\t\t EXTERN _cur_mrhard\n");\r
7638\r
7639//#ifdef MAME_DEBUG\r
7640 fprintf(fp, "\t\t EXTERN _m68k_illegal_opcode\n");\r
7641//#endif\r
7642\r
7643#ifdef OS2\r
7644 fprintf(fp, "\t\t SECTION maincode USE32 FLAT CLASS=CODE\n\n");\r
7645#else\r
7646 fprintf(fp, "\t\t SECTION .text\n\n");\r
7647#endif\r
7648\r
7649\r
7650\r
7651/* Reset routine */\r
7652\r
7653 fprintf(fp, "%s_RESET:\n",CPUtype);\r
7654\r
7655 fprintf(fp, "\t\t pushad\n\n");\r
7656\r
7657 fprintf(fp, "; Build Jump Table (not optimised!)\n\n");\r
7658\r
7659 fprintf(fp, "\t\t lea edi,[%s_OPCODETABLE]\t\t; Jump Table\n", CPUtype);\r
7660 fprintf(fp, "\t\t lea esi,[%s_COMPTABLE]\t\t; RLE Compressed Table\n", CPUtype);\r
7661\r
7662 /* Reference Point in EBP */\r
7663\r
7664 fprintf(fp, "\t\t mov ebp,[esi]\n");\r
7665 fprintf(fp, "\t\t add esi,byte 4\n");\r
7666\r
7667 fprintf(fp, "RESET0:\n");\r
7668 fprintf(fp, "\t\t mov eax,[esi]\n");\r
7669 fprintf(fp, "\t\t mov ecx,eax\n");\r
7670 fprintf(fp, "\t\t and eax,0xffffff\n");\r
7671 fprintf(fp, "\t\t add eax,ebp\n");\r
7672 fprintf(fp, "\t\t add esi,byte 4\n");\r
7673\r
7674 /* if count is zero, then it's a word RLE length */\r
7675\r
7676 fprintf(fp, "\t\t shr ecx,24\n");\r
7677 fprintf(fp, "\t\t jne short RESET1\n");\r
7678\r
7679#ifdef STALLCHECK\r
7680 ClearRegister(ECX);\r
7681 fprintf(fp, "\t\t mov cx,[esi]\t\t; Repeats\n");\r
7682#else\r
7683 fprintf(fp, "\t\t movzx ecx,word [esi]\t\t; Repeats\n");\r
7684#endif\r
7685\r
7686 fprintf(fp, "\t\t add esi,byte 2\n");\r
7687 fprintf(fp, "\t\t jecxz RESET2\t\t; Finished!\n");\r
7688\r
7689 fprintf(fp, "RESET1:\n");\r
7690 fprintf(fp, "\t\t mov [edi],eax\n");\r
7691 fprintf(fp, "\t\t add edi,byte 4\n");\r
7692 fprintf(fp, "\t\t dec ecx\n");\r
7693 fprintf(fp, "\t\t jnz short RESET1\n");\r
7694 fprintf(fp, "\t\t jmp short RESET0\n");\r
7695\r
7696 fprintf(fp, "RESET2:\n");\r
7697 fprintf(fp, "\t\t popad\n");\r
7698 fprintf(fp, "\t\t ret\n\n");\r
7699\r
7700/* Emulation Entry Point */\r
7701\r
7702 Align();\r
7703\r
7704 fprintf(fp, "%s_RUN:\n",CPUtype);\r
7705\r
7706 fprintf(fp, "\t\t pushad\n");\r
7707 fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC);\r
7708 fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR);\r
7709 fprintf(fp, "\t\t mov ebp,dword [_OP_ROM]\n");\r
7710\r
7711 fprintf(fp,"; Check for Interrupt waiting\n\n");\r
7712 fprintf(fp,"\t\t test [%s],byte 07H\n",REG_IRQ);\r
7713 fprintf(fp,"\t\t jne near interrupt\n\n");\r
7714\r
7715 fprintf(fp, "IntCont:\n");\r
7716\r
7717 /* See if was only called to check for Interrupt */\r
7718\r
7719 fprintf(fp, "\t\t test dword [%s],-1\n",ICOUNT);\r
7720 fprintf(fp, "\t\t js short MainExit\n\n");\r
7721\r
7722 if(CPU==2)\r
7723 {\r
7724 /* 32 Bit */\r
7725 fprintf(fp, "\t\t mov eax,2\n"); /* ASG */\r
7726 fprintf(fp, "\t\t xor eax,esi\n"); /* ASG */\r
7727#ifdef STALLCHECK\r
7728 ClearRegister(ECX);\r
7729 fprintf(fp, "\t\t mov cx,[eax+ebp]\n");\r
7730#else\r
7731 fprintf(fp, "\t\t movzx ecx,word [eax+ebp]\n");\r
7732#endif\r
7733 }\r
7734 else\r
7735 {\r
7736 /* 16 Bit Fetch */\r
7737#ifdef STALLCHECK\r
7738 ClearRegister(ECX);\r
7739 fprintf(fp, "\t\t mov cx,[esi+ebp]\n");\r
7740#else\r
7741 fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n");\r
7742#endif\r
7743 }\r
7744 fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n", CPUtype);\r
7745\r
7746 Align();\r
7747\r
7748 fprintf(fp, "MainExit:\n");\r
7749 fprintf(fp, "\t\t mov [%s],esi\t\t; Save PC\n",REG_PC);\r
7750 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
7751 fprintf(fp, "\t\t test byte [%s],20H\n",REG_SRH);\r
7752 fprintf(fp, "\t\t mov eax,[%s]\t\t; Get A7\n",REG_A7);\r
7753 fprintf(fp, "\t\t jne short ME1\t\t; Mode ?\n");\r
7754 fprintf(fp, "\t\t mov [%s],eax\t\t;Save in USP\n",REG_USP);\r
7755 fprintf(fp, "\t\t jmp short MC68Kexit\n");\r
7756 fprintf(fp, "ME1:\n");\r
7757 fprintf(fp, "\t\t mov [%s],eax\n",REG_ISP);\r
7758 fprintf(fp, "MC68Kexit:\n");\r
7759\r
7760 /* If in Debug mode make normal SR register */\r
7761\r
7762#ifdef MAME_DEBUG\r
7763\r
7764 ReadCCR('W', ECX);\r
7765 fprintf(fp, "\t\t mov [%s],eax\n\n",REG_S);\r
7766\r
7767#endif\r
7768\r
7769 fprintf(fp, "\t\t popad\n");\r
7770 fprintf(fp, "\t\t ret\n");\r
7771\r
7772/* Check for Pending Interrupts */\r
7773\r
7774 Align();\r
7775 fprintf(fp, "; Interrupt check\n\n");\r
7776\r
7777 fprintf(fp, "interrupt:\n");\r
7778\r
7779 /* check to exclude interrupts */\r
7780\r
7781 fprintf(fp, "\t\t mov eax,[%s]\n",REG_IRQ);\r
7782 fprintf(fp, "\t\t and eax,byte 07H\n");\r
7783\r
7784 fprintf(fp, "\t\t cmp al,7\t\t ; Always take 7\n");\r
7785 fprintf(fp, "\t\t je short procint\n\n");\r
7786\r
7787 fprintf(fp, "\t\t mov ebx,[%s]\t\t; int mask\n",REG_SRH);\r
7788 fprintf(fp, "\t\t and ebx,byte 07H\n");\r
7789 fprintf(fp, "\t\t cmp eax,ebx\n");\r
7790 fprintf(fp, "\t\t jle near IntCont\n\n");\r
7791\r
7792 /* Take pending Interrupt */\r
7793\r
7794 Align();\r
7795 fprintf(fp, "procint:\n");\r
7796 fprintf(fp, "\t\t and byte [%s],78h\t\t; remove interrupt & stop\n\n",REG_IRQ);\r
7797\r
7798 /* Get Interrupt Vector from callback */\r
7799\r
7800 fprintf(fp, "\t\t push eax\t\t; save level\n\n");\r
7801\r
7802 if (SavedRegs[EBX] == '-')\r
7803 {\r
7804 fprintf(fp, "\t\t push EBX\n");\r
7805 }\r
7806 else\r
7807 {\r
7808 fprintf(fp, "\t\t mov ebx,eax\n");\r
7809 }\r
7810\r
7811 if (SavedRegs[ESI] == '-')\r
7812 {\r
7813 fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC);\r
7814 }\r
7815\r
7816 if (SavedRegs[EDX] == '-')\r
7817 {\r
7818 fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR);\r
7819 }\r
7820\r
7821/* ----- Win32 uses FASTCALL (By Kenjo)----- */\r
7822\r
7823#ifdef FASTCALL\r
7824 fprintf(fp, "\t\t mov %s, eax\t\t; irq line #\n",FASTCALL_FIRST_REG);\r
7825 fprintf(fp, "\t\t call dword [%s]\t; get the IRQ level\n", REG_IRQ_CALLBACK);\r
7826#else\r
7827 fprintf(fp, "\t\t push eax\t\t; irq line #\n");\r
7828 fprintf(fp, "\t\t call dword [%s]\t; get the IRQ level\n", REG_IRQ_CALLBACK);\r
7829 fprintf(fp, "\t\t lea esp,[esp+4]\n");\r
7830#endif\r
7831\r
7832 if (SavedRegs[EDX] == '-')\r
7833 {\r
7834 fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR);\r
7835 }\r
7836\r
7837 if (SavedRegs[ESI] == '-')\r
7838 {\r
7839 fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC);\r
7840 }\r
7841\r
7842 /* Do we want to use normal vector number ? */\r
7843\r
7844\r
7845 fprintf(fp, "\t\t test eax,eax\n");\r
7846 fprintf(fp, "\t\t jns short AUTOVECTOR\n");\r
7847\r
7848 /* Only need EBX restored if default vector to be used */\r
7849\r
7850 if (SavedRegs[EBX] == '-')\r
7851 {\r
7852 fprintf(fp, "\t\t pop EBX\n");\r
7853 }\r
7854\r
7855 /* Just get default vector */\r
7856\r
7857 fprintf(fp, "\t\t mov eax,ebx\n");\r
7858\r
7859 fprintf(fp, "\t\t add eax,byte 24\t\t; Vector\n\n");\r
7860\r
7861 fprintf(fp, "AUTOVECTOR:\n\n");\r
7862\r
7863 Exception(-1,0xFFFF);\r
7864\r
7865 fprintf(fp, "\t\t pop eax\t\t; set Int mask\n");\r
7866 fprintf(fp, "\t\t mov bl,byte [%s]\n",REG_SRH);\r
7867 fprintf(fp, "\t\t and bl,0F8h\n");\r
7868 fprintf(fp, "\t\t or bl,al\n");\r
7869 fprintf(fp, "\t\t mov byte [%s],bl\n\n",REG_SRH);\r
7870 fprintf(fp, "\t\t jmp IntCont\n\n");\r
7871\r
7872/* Exception Routine */\r
7873\r
7874 Align();\r
7875 fprintf(fp, "Exception:\n");\r
7876 fprintf(fp, "\t\t push edx\t\t; Save flags\n");\r
7877 fprintf(fp, "\t\t and eax,0FFH\t\t; Zero Extend IRQ Vector\n");\r
7878\r
7879 fprintf(fp, "\t\t push eax\t\t; Save for Later\n");\r
7880\r
7881 /* Update Cycle Count */\r
7882\r
7883 fprintf(fp, "\t\t mov al,[exception_cycles+eax]\t\t; Get Cycles\n");\r
7884 fprintf(fp, "\t\t sub [%s],eax\t\t; Decrement ICount\n",ICOUNT);\r
7885\r
7886 ReadCCR('W',ECX);\r
7887\r
7888 fprintf(fp, "\t\t mov edi,[%s]\t\t; Get A7\n",REG_A7);\r
7889\r
7890 fprintf(fp, "\t\t test ah,20H\t; Which Mode ?\n");\r
7891 fprintf(fp, "\t\t jne short ExSuperMode\t\t; Supervisor\n");\r
7892\r
7893 fprintf(fp, "\t\t or byte [%s],20H\t; Set Supervisor Mode\n",REG_SRH);\r
7894 fprintf(fp, "\t\t mov [%s],edi\t\t; Save in USP\n",REG_USP);\r
7895 fprintf(fp, "\t\t mov edi,[%s]\t\t; Get ISP\n",REG_ISP);\r
7896\r
7897 /* Write SR first (since it's in a register) */\r
7898\r
7899 fprintf(fp, "ExSuperMode:\n");\r
7900 fprintf(fp, "\t\t sub edi,byte 6\n");\r
7901 fprintf(fp, "\t\t mov [%s],edi\t\t; Put in A7\n",REG_A7);\r
7902 Memory_Write('W',EDI,EAX,"----S-B",2);\r
7903\r
7904 /* Then write PC */\r
7905\r
7906 fprintf(fp, "\t\t add edi,byte 2\n");\r
7907 Memory_Write('L',EDI,ESI,"------B",0);\r
7908\r
7909 /* Get new PC */\r
7910\r
7911 fprintf(fp, "\t\t pop eax\t\t;Level\n");\r
7912 fprintf(fp, "\t\t shl eax,2\n");\r
7913 fprintf(fp, "\t\t add eax,[%s]\n",REG_VBR); /* 68010+ Vector Base */\r
7914\r
7915 /* Direct Read */\r
7916\r
7917 Memory_Read('L',EAX,"------B",0);\r
7918\r
7919 fprintf(fp, "\t\t mov esi,eax\t\t;Set PC\n");\r
7920 fprintf(fp, "\t\t pop edx\t\t; Restore flags\n");\r
7921\r
7922 /* Sort out any bank changes */\r
7923 MemoryBanking(1);\r
7924\r
7925 fprintf(fp, "\t\t ret\n");\r
7926}\r
7927\r
7928void CodeSegmentEnd(void)\r
7929{\r
7930#ifdef OS2\r
7931 fprintf(fp, "\t\t SECTION maindata USE32 FLAT CLASS=DATA\n\n");\r
7932#else\r
7933 fprintf(fp, "\t\t SECTION .data\n");\r
7934#endif\r
7935\r
7936 fprintf(fp, "\n\t\t align 16\n");\r
7937 fprintf(fp, "%s_ICount\n",CPUtype);\r
7938 fprintf(fp, "asm_count\t DD 0\n\n");\r
7939\r
7940 /* Memory structure for 68000 registers */\r
7941 /* Same layout as structure in CPUDEFS.H */\r
7942\r
7943 fprintf(fp, "\n\n; Register Structure\n\n");\r
7944 fprintf(fp, "%s_regs\n",CPUtype);\r
7945\r
7946 fprintf(fp, "R_D0\t DD 0\t\t\t ; Data Registers\n");\r
7947 fprintf(fp, "R_D1\t DD 0\n");\r
7948 fprintf(fp, "R_D2\t DD 0\n");\r
7949 fprintf(fp, "R_D3\t DD 0\n");\r
7950 fprintf(fp, "R_D4\t DD 0\n");\r
7951 fprintf(fp, "R_D5\t DD 0\n");\r
7952 fprintf(fp, "R_D6\t DD 0\n");\r
7953 fprintf(fp, "R_D7\t DD 0\n\n");\r
7954\r
7955 fprintf(fp, "R_A0\t DD 0\t\t\t ; Address Registers\n");\r
7956 fprintf(fp, "R_A1\t DD 0\n");\r
7957 fprintf(fp, "R_A2\t DD 0\n");\r
7958 fprintf(fp, "R_A3\t DD 0\n");\r
7959 fprintf(fp, "R_A4\t DD 0\n");\r
7960 fprintf(fp, "R_A5\t DD 0\n");\r
7961 fprintf(fp, "R_A6\t DD 0\n");\r
7962 fprintf(fp, "R_A7\t DD 0\n\n");\r
7963\r
7964 fprintf(fp, "R_ISP\t DD 0\t\t\t ; Supervisor Stack\n");\r
7965 fprintf(fp, "R_SR_H\t DD 0\t\t\t ; Status Register High TuSuuIII\n");\r
7966 fprintf(fp, "R_CCR\t DD 0\t\t\t ; CCR Register in Intel Format\n");\r
7967 fprintf(fp, "R_XC\t DD 0\t\t\t ; Extended Carry uuuuuuuX\n");\r
7968\r
7969 fprintf(fp, "R_PC\t DD 0\t\t\t ; Program Counter\n");\r
7970 fprintf(fp, "R_IRQ\t DD 0\t\t\t ; IRQ Request Level\n\n");\r
7971 fprintf(fp, "R_SR\t DD 0\t\t\t ; Motorola Format SR\n\n");\r
7972\r
7973 fprintf(fp, "R_IRQ_CALLBACK\t DD 0\t\t\t ; irq callback (get vector)\n\n");\r
7974\r
7975 fprintf(fp, "R_PPC\t DD 0\t\t\t ; Previous Program Counter\n");\r
7976\r
7977 fprintf(fp, "R_RESET_CALLBACK\t DD 0\t\t\t ; Reset Callback\n");\r
7978\r
7979 fprintf(fp, "R_SFC\t DD 0\t\t\t ; Source Function Call\n");\r
7980 fprintf(fp, "R_DFC\t DD 0\t\t\t ; Destination Function Call\n");\r
7981 fprintf(fp, "R_USP\t DD 0\t\t\t ; User Stack\n");\r
7982 fprintf(fp, "R_VBR\t DD 0\t\t\t ; Vector Base\n");\r
7983\r
7984 fprintf(fp, "asmbank\t DD 0\n\n");\r
7985 fprintf(fp, "CPUversion\t DD 0\n\n");\r
7986 fprintf(fp, "FullPC\t DD 0\n\n");\r
7987\r
7988 /* Extra space for variables mame uses for debugger */\r
7989\r
7990 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7991 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7992 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7993 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7994 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7995 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7996 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");\r
7997 fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\n");\r
7998\r
7999 /* Safe Memory Locations */\r
8000\r
8001 fprintf(fp, "\t\t ALIGN 16\n");\r
8002\r
8003 fprintf(fp, "\n\nIntelFlag\t\t\t\t; Intel Flag Lookup Table\n");\r
8004 fprintf(fp, "\t\t DD 0000h,0001h,0800h,0801h,0040h,0041h,0840h,0841h\n");\r
8005 fprintf(fp, "\t\t DD 0080h,0081h,0880h,0881h,00C0h,00C1h,08C0h,08C1h\n");\r
8006 fprintf(fp, "\t\t DD 0100h,0101h,0900h,0901h,0140h,0141h,0940h,0941h\n");\r
8007 fprintf(fp, "\t\t DD 0180h,0181h,0980h,0981h,01C0h,01C1h,09C0h,09C1h\n");\r
8008\r
8009#if 0\r
8010 fprintf(fp, "\n\nImmTable\n");\r
8011 fprintf(fp, "\t\t DD 8,1,2,3,4,5,6,7\n\n");\r
8012#endif\r
8013\r
8014\r
8015\r
8016 /* Exception Timing Table */\r
8017\r
8018 fprintf(fp, "exception_cycles\n");\r
8019 fprintf(fp, "\t\t DB 0, 0, 0, 0, 38, 42, 44, 38, 38, 0, 38, 38, 0, 0, 0, 0\n");\r
8020 fprintf(fp, "\t\t DB 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46\n");\r
8021 fprintf(fp, "\t\t DB 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38\n\n");\r
8022\r
8023 fprintf(fp, "; RLE Compressed Jump Table\n\n");\r
8024\r
8025 fprintf(fp, "%s_COMPTABLE\n\n", CPUtype);\r
8026\r
8027 fprintf(fp, "%cinclude '%s'\n\n",'%', comptab);\r
8028\r
8029 fprintf(fp, "\t\tDW 0,0,0\n\n");\r
8030\r
8031\r
8032/* If Win32, put the table area in .data section (Kenjo) */\r
8033\r
8034#ifdef WIN32\r
8035\r
8036 fprintf(fp, "%s_OPCODETABLE\tTIMES 65536 DD 0\n\n", CPUtype);\r
8037\r
8038#else\r
8039\r
8040#ifdef OS2\r
8041 fprintf(fp, "\t\t SECTION tempdata USE32 FLAT CLASS=BSS\n\n");\r
8042#else\r
8043 fprintf(fp, "\t\t SECTION .bss\n");\r
8044#endif\r
8045\r
8046 fprintf(fp, "%s_OPCODETABLE\tRESD 65536\n\n", CPUtype);\r
8047\r
8048#endif\r
8049\r
8050}\r
8051\r
8052void EmitCode(void)\r
8053{\r
8054 CodeSegmentBegin();\r
8055\r
8056 /* Instructions */\r
8057\r
8058 moveinstructions(); /* 1000 to 3FFF MOVE.X */\r
8059 immediate(); /* 0### XXX.I */\r
8060 bitdynamic(); /* 0### dynamic bit operations */\r
8061 movep(); /* 0### Move Peripheral */\r
8062 bitstatic(); /* 08## static bit operations */\r
8063 LoadEffectiveAddress(); /* 4### */\r
8064 PushEffectiveAddress(); /* ???? */\r
8065 movesr(); /* 4#C# */\r
8066 opcode5(); /* 5000 to 5FFF ADDQ,SUBQ,Scc and DBcc */\r
8067 branchinstructions(); /* 6000 to 6FFF Bcc,BSR */\r
8068 moveq(); /* 7000 to 7FFF MOVEQ */\r
8069 abcd_sbcd(); /* 8### Decimal Add/Sub */\r
8070 typelogicalmath(); /* Various ranges */\r
8071 addx_subx();\r
8072 divides();\r
8073 swap();\r
8074 not(); /* also neg negx clr */\r
8075 moveusp();\r
8076 chk();\r
8077 exg();\r
8078 cmpm();\r
8079 mul();\r
8080 ReturnandRestore();\r
8081 rts();\r
8082 jmp_jsr();\r
8083 nbcd();\r
8084 tas();\r
8085 trap();\r
8086 trapv();\r
8087 reset();\r
8088 nop();\r
8089 stop();\r
8090 ext();\r
8091 ReturnFromException();\r
8092 tst();\r
8093 movem_reg_ea();\r
8094 movem_ea_reg();\r
8095 link();\r
8096 unlinkasm();\r
8097 asl_asr(); /* E### Shift Commands */\r
8098 asl_asr_ea();\r
8099 roxl_roxr();\r
8100 roxl_roxr_ea();\r
8101 lsl_lsr();\r
8102 lsl_lsr_ea();\r
8103 rol_ror();\r
8104 rol_ror_ea();\r
8105 LineA(); /* A000 to AFFF Line A */\r
8106 LineF(); /* F000 to FFFF Line F */\r
8107 illegal_opcode();\r
8108\r
8109 ReturnandDeallocate(); /* 68010 Commands */\r
8110 MoveControlRegister();\r
8111 MoveAddressSpace();\r
8112\r
8113 if(CPU==2) /* 68020 Commands */\r
8114 {\r
8115 divl();\r
8116 mull();\r
8117 bfext();\r
8118 }\r
8119\r
8120 CodeSegmentEnd();\r
8121}\r
8122\r
8123int main(int argc, char **argv)\r
8124{\r
8125 int dwLoop;\r
8126\r
8127 printf("\nMake68K - V%s - Copyright 1998, Mike Coates (mame@btinternet.com)\n", VERSION);\r
8128 printf(" 1999, & Darren Olafson (deo@mail.island.net)\n");\r
8129 printf(" 2000\n");\r
8130\r
8131 if (argc != 4 && argc != 5)\r
8132 {\r
8133 printf("Usage: %s outfile jumptable-outfile type [ppro]\n", argv[0]);\r
8134 exit(1);\r
8135 }\r
8136\r
8137 printf("Building 680%s 2001\n\n",argv[3]);\r
8138\r
8139 for (dwLoop=0;dwLoop<65536;) OpcodeArray[dwLoop++] = -2;\r
8140\r
8141 codebuf=malloc(64);\r
8142 if (!codebuf)\r
8143 {\r
8144 printf ("Memory allocation error\n");\r
8145 exit(3);\r
8146 }\r
8147\r
8148 /* Emit the code */\r
8149 fp = fopen(argv[1], "w");\r
8150 if (!fp)\r
8151 {\r
8152 fprintf(stderr, "Can't open %s for writing\n", argv[1]);\r
8153 exit(1);\r
8154 }\r
8155\r
8156 comptab = argv[2];\r
8157\r
8158\r
8159 CPUtype = malloc(64);\r
8160#ifdef OS2\r
8161 sprintf(CPUtype,"M680%s",argv[3]);\r
8162#else\r
8163 sprintf(CPUtype,"_M680%s",argv[3]);\r
8164#endif\r
8165\r
8166 if(argv[3][0]=='2') CPU = 2;\r
8167 if(argc > 4 && !stricmp(argv[4], "ppro"))\r
8168 {\r
8169 ppro = 1;\r
8170 printf("Generating ppro opcodes\n");\r
8171 }\r
8172\r
8173 EmitCode();\r
8174\r
8175 fclose(fp);\r
8176\r
8177 printf("\n%d Unique Opcodes\n",Opcount);\r
8178\r
8179 /* output Jump table to separate file */\r
8180 fp = fopen(argv[2], "w");\r
8181 if (!fp)\r
8182 {\r
8183 fprintf(stderr, "Can't open %s for writing\n", argv[2]);\r
8184 exit(1);\r
8185 }\r
8186\r
8187 JumpTable();\r
8188\r
8189 fclose(fp);\r
8190\r
8191 exit(0);\r
8192}\r