diff options
Diffstat (limited to 'trunk/src/emu/cpu/alph8201/8201dasm.c')
-rw-r--r-- | trunk/src/emu/cpu/alph8201/8201dasm.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/alph8201/8201dasm.c b/trunk/src/emu/cpu/alph8201/8201dasm.c new file mode 100644 index 00000000000..4cdd76075a0 --- /dev/null +++ b/trunk/src/emu/cpu/alph8201/8201dasm.c @@ -0,0 +1,402 @@ +/**************************************************************************** + Alpha 8201/8301 Disassembler + + Copyright Tatsuyuki Satoh + Originally written for the MAME project. + +****************************************************************************/ + +#include "emu.h" + +#include <ctype.h> + +typedef unsigned char byte; + +#define FMT(a,b) a, b +#define PTRS_PER_FORMAT 2 + +/**************************************************** + +8201 CONFIRMED OPCODES: + +opcode mnemonic function flags +-------- ------------ ------------- ----- +00000000 NOP - -- +00000001 RORA ror A -C +00000010 ROLA rol A -C +00000011 INC RXB RXB+=2 ZC +00000100 DEC RXB RXB-=2 ZC (C=1 means No Borrow: RXB>=2) +00000101 INC A A++ ZC +00000110 DEC A A-- ZC (C=1 means No Borrow: A>=1) +00000110 CPL A A^=$FF -- +00001aaa LD A,(IX0+i) A=[IX0+i] -- +00010aaa LD A,(IX1+i) A=[IX1+i] -- +00011aaa LD (IX2+i),A [IX2+i]=A -- +00111aaa BIT R0.n ZF=R0 bit n Z- +0100aaa0 LD A,Rn A=Rn Z- [1] +0100aaa1 LD Rn,A Rn=A -- +0101aaa0 ADD A,Rn A+=Rn ZC +0101aaa1 SUB A,Rn A-=Rn ZC (C=1 means No Borrow: A>=Rn) +0110aaa0 AND A,Rn A&=Rn Z- +0110aaa1 OR A,Rn A|=Rn Z- +0111aaaa ADD IX0,i IX0+=i -- +1000aaaa ADD IX1,i IX1+=i -- +1001aaaa ADD IX2,i IX2+=i -- +1010aaaa LD RB,i RB=i -- Note: no bounds checking. Can set bank up to F. +1011-0aa LD MB,i set after-jump page +1011-1-- STOP +11000000 imm LD IX0,imm IX0=imm -- +11000001 imm LD IX1,imm IX1=imm -- +11000010 imm LD IX2,imm IX2=imm -- +11000011 imm LD A,imm A=imm -- +11000100 imm LD LP0,imm LP0=imm -- +11000101 imm LD LP1,imm LP1=imm -- +11000110 imm LD LP2,imm LP2=imm -- +11000111 imm LD RXB,imm RXB=imm -- +11001000 imm ADD A,imm A+=imm ZC +11001001 imm SUB A,imm A-=imm ZC (C=1 means No Borrow: A>=imm) +11001010 imm AND A,imm A&=imm Z- +11001011 imm OR A,imm A|=imm Z- +11001100 imm DJNZ LP0,imm LP0--,branch -- +11001101 imm DJNZ LP1,imm LP1--,branch -- +11001110 imm DJNZ LP2,imm LP2--,branch -- +11001111 imm JNZ imm branch if !Z -- +1101--00 imm JNC imm branch if !C -- +1101--01 imm JZ imm branch if Z -- +1101--1- imm J imm branch -- +1110--xx mirror for the above +1111--xx mirror for the above + +Notes: +[1] bug: the Z flag is not updated correctly after a LD A,Rn instruction. Fixed in 8302 (possibly 8301). + + +8302 CONFIRMED OPCODES: +---------------------- +all of the 8201 ones, with stricter decoding for the following: + +11010-00 imm JNC imm branch if !C -- +11010-01 imm JZ imm branch if Z -- +11010-1- imm J imm branch -- + +and these new opcodes: + +opcode mnemonic function flags +-------- ------------ --------------- ----- +11011000 imm LD A,(imm) A=MB:[imm] -- +11011001 imm LD (imm),A MB:[imm]=A -- +11011010 imm CMP A,imm temp=A-imm ZC +11011011 imm XOR A,imm A^=imm Z0 +11011100 imm LD A,R(imm) A=reg(imm) -- +11011101 imm LD R(imm),A reg(imm)=A -- +11011110 imm JC imm branch if C -- +11011111 imm CALL $xx save PC, branch -- + +11100000 EXG A,IX0 A<->IX0 -- +11100001 EXG A,IX1 A<->IX1 -- +11100010 EXG A,IX2 A<->IX2 -- +11100011 EXG A,LP1 A<->LP1 -- +11100100 EXG A,LP2 A<->LP2 -- +11100101 EXG A,RXB A<->RXB -- +11100110 EXG A,LP0 A<->LP0 -- +11100111 EXG A,RB A<->RB -- +11101000 LD IX0,A IX0=A -- +11101001 LD IX1,A IX1=A -- +11101010 LD IX2,A IX2=A -- +11101011 LD LP1,A LP1=A -- +11101100 LD LP2,A LP2=A -- +11101101 LD RXB,A RXB=A -- +11101110 LD LP0,A LP0=A -- +11101111 LD RB,A RB=A -- +11110000 EXG IX0,IX1 IX0<->IX1 -- +11110001 EXG IX0,IX2 IX0<->IX2 -- +11110010 REP LD (IX2),(RXB) equivalent to LD (IX2),(RXB); INC RXB; DJNZ LP0 +11110011 REP LD (RXB),(IX0) equivalent to LD (RXB),(IX0); INC RXB; DJNZ LP0 +11110100 SAVE ZC save ZC -- +11110101 REST ZC restore ZC ZC +11110110 LD (RXB),A reg(RXB)=A -- +11110111 LD A,(RXB) A=reg(RXB) -- +11111000 CMP A,(RXB) temp=A-reg(RXB) ZC +11111001 XOR A,(RXB) A^=reg(RXB) Z0 +11111010 ADD A,CF if (C) A++ ZC +11111011 SUB A,!CF if (!C) A-- ZC +11111100 TST A A==0? Z- +11111101 CLR A A=0 -- +11111110 LD A,(IX0+A) A=[IX0+A] -- +11111111 RET restore PC -- + + +8303 CONFIRMED OPCODES: +---------------------- +all of the 8302 ones, with stricter decoding for the following: + +11010000 imm JNC imm branch if !C -- +11010001 imm JZ imm branch if Z -- +1101001- imm J imm branch -- + +additionally, this opcode is modified to support 11-bit instead of 10-bit +external addressing, this wasn't used in games however. + +1011-0aa LD MB,i modified so that bit 3 is shifted to bit 2 before loading MB. + +and these new opcodes are added: + +110101-- +11010100 imm LD A,(R77:$%02X) +11010101 imm LD (R77:$%02X),A +11010110 imm LD PC,(R77:$%02X) [1] +11010111 imm LD (R77:$%02X),PC [2] + +Notes: +[1] appears to be LD PC,x in the disassembly, however it's LD LP0,x for kouyakyu + which uses a 8304, so the opcode was probably changed again. +[2] appears to be LD x,PC in the disassembly, however it's LD x,LP0 for hvoltage + which uses a 8304 (or 8404?), so the opcode was probably changed again. + +****************************************************/ + + +/****************************************************/ + +static const char *const Formats[] = { + FMT("0000_0000", "NOP"), // 00 + FMT("0000_0001", "RRCA"), // 01 + FMT("0000_0010", "RLCA"), // 02 + FMT("0000_0011", "INC RXB"), // 03 : shougi $360 to $377; splndrbt + FMT("0000_0100", "DEC RXB"), // 04 : not found + FMT("0000_0101", "INC A"), // 05 + FMT("0000_0110", "DEC A"), // 06 + FMT("0000_0111", "CPL A"), // 07 + FMT("0000_1aaa", "LD A,(IX0+%X)"), // 08-0F + FMT("0001_0aaa", "LD A,(IX1+%X)"), // 10-17 + FMT("0001_1aaa", "LD (IX2+%X),A"), // 18-1F + FMT("0010_0aaa", "LD (RXB),(IX0+%X)"),// 20-27 : shougi $360 to $377 + FMT("0010_1aaa", "LD (RXB),(IX1+%X)"),// 28-2f : not found + FMT("0011_0aaa", "LD (IX2+%X),(RXB)"),// 30-37 : not found + FMT("0011_1aaa", "BIT R0.%d"), // 38-3F ZF = R0.a (bit test) + FMT("0100_aaa0", "LD A,R%X"), // 40-4E + FMT("0100_aaa1", "LD R%X,A"), // 41-4F + FMT("0101_aaa0", "ADD A,R%X"), // 50-5E + FMT("0101_aaa1", "SUB A,R%X"), // 51-5F + FMT("0110_aaa0", "AND A,R%X"), // 60-6E + FMT("0110_aaa1", "OR A,R%X"), // 61-6F + FMT("0111_aaaa", "ADD IX0,$%X"), // 70-7f + FMT("1000_aaaa", "ADD IX1,$%X"), // 80-8f + FMT("1001_aaaa", "ADD IX2,$%X"), // 90-9f + FMT("1010_aaaa", "LD RB,%X"), // A0-AF + FMT("1011_x0aa", "LD MB,%X"), // B0-B3 (+ mirrors) + FMT("1011_x1xx", "STOP"), // B4 (+ mirrors) + + FMT("1100_0000 I", "LD IX0,$%02X"), // C0 + FMT("1100_0001 I", "LD IX1,$%02X"), // C1 + FMT("1100_0010 I", "LD IX2,$%02X"), // C2 + FMT("1100_0011 I", "LD A,$%02X"), // C3 + FMT("1100_0100 I", "LD LP0,$%02X"), // C4 + FMT("1100_0101 I", "LD LP1,$%02X"), // C5 + FMT("1100_0110 I", "LD LP2,$%02X"), // C6 + FMT("1100_0111 I", "LD RXB,$%02X"), // C7 : shougi, splndrbt, equites + FMT("1100_1000 I", "ADD A,$%02X"), // C8 + FMT("1100_1001 I", "SUB A,$%02X"), // C9 + FMT("1100_1010 I", "AND A,$%02X"), // CA + FMT("1100_1011 I", "OR A,$%02X"), // CB + FMT("1100_1100 I", "DJNZ LP0,$%02X"), // CC + FMT("1100_1101 I", "DJNZ LP1,$%02X"), // CD + FMT("1100_1110 I", "DJNZ LP2,$%02X"), // CE + FMT("1100_1111 I", "JNZ $%02X"), // CF + FMT("1101_0000 I", "JNC $%02X"), // D0 + FMT("1101_0001 I", "JZ $%02X"), // D1 + FMT("1101_001x I", "J $%02X"), // D2 (+ mirror) + + /* -------------- 830x only ------------- */ + + FMT("1101_0100 I", "LD A,(R77:$%02X)"), // D4 : 8303+ only. exctscc2, bullfgtr + FMT("1101_0101 I", "LD (R77:$%02X),A"), // D5 : 8303+ only. exctscc2, bullfgtr, kouyakyu + FMT("1101_0110 I", "LD LP0,(R77:$%02X)"), // D6 : 8303+ only. kouyakyu + FMT("1101_0111 I", "LD (R77:$%02X),LP0"), // D7 : 8303+ only. hvoltage + FMT("1101_1000 I", "LD A,($%02X)"), // D8 : equites + FMT("1101_1001 I", "LD ($%02X),A"), // D9 : equites + FMT("1101_1010 I", "CMP A,$%02X"), // DA : + FMT("1101_1011 I", "XOR A,$%02X"), // DB : equites splndrbt + FMT("1101_1100 I", "LD A,R($%02X)"), // DC : not found + FMT("1101_1101 I", "LD R($%02X),A"), // DD : equites, splndrbt + FMT("1101_1110 I", "JC $%02X"), // DE : not found + FMT("1101_1111 I", "CALL $%02X"), // DF : + + FMT("1110_0000", "EXG A,IX0"), // E0 : exctsccr + FMT("1110_0001", "EXG A,IX1"), // E1 : not found + FMT("1110_0010", "EXG A,IX2"), // E2 : not found + FMT("1110_0011", "EXG A,LP1"), // E3 : exctsccr in pair with EB + FMT("1110_0100", "EXG A,LP2"), // E4 : not found + FMT("1110_0101", "EXG A,RXB"), // E5 : splndrbt + FMT("1110_0110", "EXG A,LP0"), // E6 : splndrbt, bullfgtr, kouyakyu. EXG, not LD: see splndrbt $3ba to $3d3 + FMT("1110_0111", "EXG A,RB"), // E7 : not found + FMT("1110_1000", "LD IX0,A"), // E8 : + FMT("1110_1001", "LD IX1,A"), // E9 : not found + FMT("1110_1010", "LD IX2,A"), // EA : + FMT("1110_1011", "LD LP1,A"), // EB : exctsccr in pair with E3 + FMT("1110_1100", "LP LP2,A"), // EC : not found + FMT("1110_1101", "LD RXB,A"), // ED : splndrbt + FMT("1110_1110", "LD LP0,A"), // EE : splndrbt, bullfgtr + FMT("1110_1111", "LD RB,A"), // EF : not found + FMT("1111_0000", "EXG IX0,IX1"), // F0 : not found + FMT("1111_0001", "EXG IX0,IX2"), // F1 : splndrbt $2e to $38, equites $40 to $4a + FMT("1111_0010", "REP LD (IX2),(RXB)"),// F2 : splndrbt LD (IX2),(RXB); INC RXB; DJNZ LP0 + FMT("1111_0011", "REP LD (RXB),(IX0)"),// F3 : not found LD (RXB),(IX0); INC RXB; DJNZ LP0 + FMT("1111_0100", "SAVE ZC"), // F4 : not found + FMT("1111_0101", "REST ZC"), // F5 : not found + FMT("1111_0110", "LD (RXB),A"), // F6 : exctsccr + FMT("1111_0111", "LD A,(RXB)"), // F7 : not found + FMT("1111_1000", "CMP A,(RXB)"), // F8 : exctsccr + FMT("1111_1001", "XOR A,(RXB)"), // F9 : exctsccr + FMT("1111_1010", "ADD A,CF"), // FA : + FMT("1111_1011", "SUB A,!CF"), // FB : not found + FMT("1111_1100", "TST A"), // FC : + FMT("1111_1101", "CLR A"), // FD : + FMT("1111_1110", "LD A,(IX0+A)"), // FE : + FMT("1111_1111", "RET"), // FF : + NULL +}; + +#define MAX_OPS (((sizeof(Formats) / sizeof(Formats[0])) - 1) / PTRS_PER_FORMAT) + +typedef struct opcode { + byte mask; + byte bits; + byte type; + byte pmask; + byte pdown; + const char *fmt; +} AD8201Opcode; + +static AD8201Opcode Op[MAX_OPS+1]; +static int OpInizialized = 0; + +static void InitDasm8201(void) +{ + const char *p; + byte mask, bits; + int bit; + int i; + char chr , type; + int pmask , pdown; + + for(i=0;(p=Formats[i*2])!=NULL;i++) + { + mask = 0; + bits = 0; + pmask = 0; + pdown = 0; + type = 0; + bit = 7; + while (*p && bit >= 0) { + chr = *p++; + switch (chr) { + case '1': bits |= 1<<bit; + case '0': mask |= 1<<bit; bit--; break; +#if 0 + case 'b': + type |= 0x80; +#endif + case 'a': + pmask |= 1<<bit; + pdown = bit; + case 'x': + bit --; + break; + case '_': + continue; + default: + fatalerror("Invalid instruction encoding '%s %s'\n", Formats[i*2],Formats[i*2+1]); + } + } + if (bit != -1 ) { + fatalerror("not enough bits in encoding '%s %s' %d\n", Formats[i*2],Formats[i*2+1],bit); + } + + Op[i].mask = mask; + Op[i].bits = bits; + Op[i].pmask = pmask; + Op[i].pdown = pdown; + Op[i].fmt = Formats[i*2+1]; + Op[i].type = type; + + /* 2 byte code ? */ + while (isspace((UINT8)*p)) p++; + if( (*p) ) + Op[i].type |= 0x10; + /* number of param */ + if( (p=strchr(Op[i].fmt,'%'))!=NULL ) + { + Op[i].type |= 0x01; /* single param */ + if(strchr(p+1,'%') ) + Op[i].type |= 0x02; /* double param */ + } + } + + OpInizialized = 1; +} + +CPU_DISASSEMBLE( alpha8201 ) +{ + offs_t dasmflags = 0; + int i; + int op; + int cnt = 1; + int code , disp; + + if (!OpInizialized) InitDasm8201(); + + code = oprom[0]; + op = -1; /* no matching opcode */ + for ( i = 0; i < MAX_OPS; i++) + { + if( (code & Op[i].mask) == Op[i].bits ) + { + if (op != -1) + { + fprintf(stderr, "Error: opcode %02X matches %d (%s) and %d (%s)\n", + code,i,Op[i].fmt,op,Op[op].fmt); + } + op = i; + } + } + + if (op == -1) + { + sprintf(buffer,"db %2.2x",code); + return cnt; + } + + if (Op[op].type & 0x10) + { + disp = opram[1]; + cnt++; + } + else + { + disp = (code & Op[op].pmask) >> Op[op].pdown; + } + + if (Op[op].type & 0x02) + sprintf(buffer, Op[op].fmt,disp,disp); + else if (Op[op].type & 0x01) + sprintf(buffer, Op[op].fmt,disp); + else + sprintf(buffer, "%s",Op[op].fmt); + + switch (code) + { + case 0xcc: + case 0xcd: + case 0xce: + case 0xdf: + dasmflags = DASMFLAG_STEP_OVER; + break; + + case 0xff: + dasmflags = DASMFLAG_STEP_OUT; + break; + } + + return cnt | dasmflags | DASMFLAG_SUPPORTED; +} |