/*****************************************************************************/
/*									     */
/*									     */
/*	CP/M emulator version 0.1					     */
/*									     */
/*	written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de)		     */
/*	June-1994							     */
/*									     */
/*	This file is distributed under the GNU COPYRIGHT		     */
/*	see COPYRIGHT.GNU for Copyright details				     */
/*									     */
/*									     */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>

static const char *str[] = { "op",  "op",  "op",  "op",  "op",  "op",  "op",  "op", "ix", "iy" };
static int off[] = { 0,1,2,3,4,5,6,7,6,6 };
static const char *fetch[] = { "", "", "", "", "", "", "", "", "GETIXOFF\n ", "GETIYOFF\n " };

#define CODE(i)    printf(" opcode (0x%02x)\nop%02x:\n ", i, i)
#define CODEIX(i)  printf(" opcode (0x%02x)\nix%02x:\n ", i, i)
#define CODEIY(i)  printf(" opcode (0x%02x)\niy%02x:\n ", i, i)
#define ZCODE(j,i) printf(" opcode (0x%02x)\n%s%02x:\n ", j+i, str[i], j+off[i])
static const char *fmt[] = {
"%sandb $0xd5,%%ah\t/* ADD A,reg */\n addb %s,%%al\n jmp setaddadc\n",
"%sandb $0xd5,%%ah\t/* ADC A,reg */\n sahf\n adcb %s,%%al\n jmp setaddadc\n",
"%sorb $2,%%ah\t/* SUB reg */\n subb %s,%%al\n jmp setaddadc\n",
"%sorb $2,%%ah\t/* SBC A,reg */\n sahf\n sbbb %s,%%al\n jmp setaddadc\n",
"%sandb %s,%%al\t/* AND reg */\n lahf\n orb $0x10,%%ah\n andb $0xd4,%%ah\n dispatch\n",
"%sxorb %s,%%al\t/* XOR reg */\n lahf\n andb $0xc4,%%ah\n dispatch\n",
"%sorb %s,%%al\t/* OR reg */\n lahf\n andb $0xc4,%%ah\n dispatch\n",
"%sorb $2,%%ah\t/* CP reg */\n cmpb %s,%%al\n jmp setaddadc\n" };

int main(void) {
    static const char *regs[] = { "%ch", "%cl", "%dh", "%dl", "%bh", "%bl",
	      "(%ebx,%ebp)", "%al", "(%edi,%ebp)", "(%edi,%ebp)" };
    static const char *cbregs[] = { "%ch", "%cl", "%dh", "%dl", "%bh", "%bl",
	      "(%edi,%ebp)", "%al" };
    static const char *z80cc[] = { "NZ", "Z", "NC", "C", "PO", "PE", "P", "M" };
    static const char *i386cc[] = { "nz", "z", "nc", "c", "po", "pe", "ns", "s" };

    int i;
    printf("/* loads.s: DO NOT EDIT! Automatically generated by makeloads */\n");
    for (i = 0; i < 64; ++i) {
	if ((i & 7) != (i >> 3)) {
	    CODE(0x40+i);
	    printf("movb %s,%s\n dispatch\n", regs[i&7], regs[i>>3]);
	    if ((i & 7) == 6) {	/* do also ix, iy */
		CODEIX(0x40+i);
		printf("GETIXOFF\n movb (%%edi,%%ebp),%s\n dispatch\n", regs[i>>3]);
		CODEIY(0x40+i);
		printf("GETIYOFF\n movb (%%edi,%%ebp),%s\n dispatch\n", regs[i>>3]);
	    } else if ((i >> 3) == 6)  { /* do also ix, iy */
		CODEIX(0x40+i);
		printf("GETIXOFF\n movb %s,(%%edi,%%ebp)\n dispatch\n", regs[i&7]);
		CODEIY(0x40+i);
		printf("GETIYOFF\n movb %s,(%%edi,%%ebp)\n dispatch\n", regs[i&7]);
	    }
	}
    }
    {   int j;
	for (j = 0x80; j < 0xc0; j += 8) {
	    for (i = 0; i < 10; ++i) {
		ZCODE(j,i);
		printf(fmt[(j-0x80)>>3],  fetch[i], regs[i]);
	    }
	}
    }

    /* RST (nn) */
    for (i = 1; i < 8; ++i) {
	CODE(0xc7+8*i);
	printf("movl $%d,%%edi\t/* RST %02x */\n jmp docall_di\n",
	       i*8, i*8);
    }
    /* JP cc,nnnn */
    for (i = 0; i < 8; ++i) {
	CODE(0xc2+8*i);
	printf("sahf\t/* JP %s,nnnn */\n j%s opc3\n incl %%esi\n"
	       " incl %%esi\n dispatch\n", z80cc[i], i386cc[i]);
    }
    /* RET cc */
    for (i = 0; i < 8; ++i) {
	CODE(0xc0+8*i);
	printf("sahf\t/* RET %s */\n j%s opc9\n dispatch\n",
	       z80cc[i], i386cc[i]);
    }
    /* CALL cc,nnnn */
    for (i = 0; i < 8; ++i) {
	CODE(0xc4+8*i);
	printf("sahf\t/* CALL %s,nnnn */\n j%s opcd\n incl %%esi\n"
	       " incl %%esi\n dispatch\n", z80cc[i], i386cc[i]);
    }

    /* Z80 extended commands with "cb" prefix */
    for (i = 0; i < 64; ++i) {
	static const char *rotcmds[] = {
	    "rolb", "rorb", "rclb", "rcrb", "shlb", "sarb", NULL, "shrb" };
	if ((i >> 3) != 6)
	    printf(" .align NALIGN,0x90\ncb%02x: sahf\n"
		   " %s $1,%s\n movzbl %s,%%edi\n jmp set_SZV\n", i,
		   rotcmds[i>>3], cbregs[i&7], cbregs[i&7]);
    }
    for (i = 0; i < 64; ++i)	/* BIT n,r */
	printf(" .align NALIGN,0x90\ncb%02x: testb $%d,%s\n jmp setbit\n",
	       i+0x40, 1 << (i>>3), cbregs[i&7]);
    for (i = 0; i < 64; ++i)	/* RES n,r */
	printf(" .align NALIGN,0x90\ncb%02x: andb $%d,%s\n dispatch\n",
	       i+0x80, 255-(1 << (i>>3)), cbregs[i&7]);
    for (i = 0; i < 64; ++i)	/* SET n,r */
	printf(" .align NALIGN,0x90\ncb%02x: orb $%d,%s\n dispatch\n",
	       i+0xc0, 1 << (i>>3), cbregs[i&7]);
    return 0;
}
