//////////////////////////////////////////////////////////////////////////
// Texas Instrument TMS7020 disassembler
// (C) 2008 - Daniel Coulom
// (C) 2009 - Jester
// http://dcexel.free.fr
// danielcoulom@gmail.com
//////////////////////////////////////////////////////////////////////////

/*
desasm7020 sourceFile [-r:0xRelocAdr] [-s:0xStartAdr] [-e:0xEndAdr]
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>

#define NOP    0
#define IDLE   1
#define EINT   2
#define DINT   3
#define SETC   4
#define STSP   5
#define RETS   6
#define RETI   7
#define LDSP   8
#define MOV    9
#define AND   10
#define OR    11
#define XOR   12
#define BTJO  13
#define BTJZ  14
#define ADD   15
#define ADC   16
#define SUB   17
#define SBB   18
#define MPY   19
#define CMP   20
#define DAC   21
#define DSB   22
#define MOVP  23
#define ANDP  24
#define ORP   25
#define XORP  26
#define BTJOP 27
#define BTJZP 28
#define MOVD  29
#define LDA   30
#define STA   31
#define BR    32
#define CMPA  33
#define CALL  34
#define TSTA  35
#define TSTB  36
#define DEC   37
#define INC   38
#define INV   39
#define CLR   40
#define XCHB  41
#define LDVP  42
#define PUSH  43
#define POP   44
#define DJNZ  45
#define DECD  46
#define RR    47
#define RRC   48
#define RL    49
#define RLC   50
#define JMP   51
#define JLT   52
#define JEQ   53
#define JHS   54
#define JGT   55
#define JGE   56
#define JNE   57
#define JL    58
#define TRAP  59
#define WVDP  60
#define INVALID 61

#define VOID            24 //vide  Pas de parametre
#define REGISTER_A      25 //A     Register A
#define REGISTER_B      26 //B     Register B
#define REGISTER_FILE   27 //Rn    Register file register
#define PERIPHERAL_FILE 28 //Pn    Peripheral file register
#define IMMEDIATE_8     29 //%n    Immediat addressing 8 bits
#define IMMEDIATE_16    30 //%n    Immediat addressing 16 bits
#define BRANCH          31 //$n    Branch address
#define DIRECT          32 //@n    Direct addressing
#define INDEXED         33 //@n(B) Direct addressing (B)
#define INDIRECT        34 //*Rn   Indirect addressing
#define RELATIVE        35 //$+    Relative addressing
#define ST              36 //ST    STSP et LDSP

#define GETR i=Mgetc(a++);sprintf(w,"%02x",i&0xff);strcat(hexa,w);sprintf
#define GET1 i=Mgetc(a++)&0xff;sprintf(w,"%02x",i);strcat(hexa,w);sprintf
#define GET2 i=(Mgetc(a++)&0xff)<<8;i|=(Mgetc(a++)&0xff);sprintf(w,"%04x",i);strcat(hexa,w);sprintf
#define CATW ;strcat(param, w)

int a=0;
int reloc,debut,fin;
char *buffer;
char *source;
char w[10];     //zone de travail
char hexa[20];  //adresse et dump hexa
char *mnemo;    //mnemonique de l'instruction
char param[20]; //parametres
char name[][6] = {
"NOP","IDLE","EINT","DINT","SETC","STSP","RETS","RETI","LDSP","MOV","AND",
"OR","XOR","BTJO","BTJZ","ADD","ADC","SUB","SBB","MPY","CMP","DAC","DSB",
"MOVP","ANDP","ORP","XORP","BTJOP","BTJZP","MOVD","LDA","STA","BR","CMPA",
"CALL","TSTA","TSTB","DEC","INC","INV","CLR","XCHB","LVDP","PUSH","POP",
"DJNZ","DECD","RR","RRC","RL","RLC","JMP","JLT","JEQ","JHS","JGT","JGE",
"JNE","JL","TRAP","WVDP","????"};
char registre[][10] = {"A","B","FLGCOM","VALUE0","VALUE1","SUICOM-1","SUICOM",
"WRKSON-1","WRKSON","PTRSON-1","PTRSON","SONFON-1","SONFON","TEMP1-1","TEMP1",
"TEMP2-1","TEMP2","TEMP3-1","TEMP3","TEMP4-1","TEMP4","TEMP5-1","TEMP5",
"TEMP6-1","TEMP6","TEMP7-1","TEMP7","TEMP8-1","TEMP8","TEMP9-1","TEMP9",
"TEMP10-1","TEMP10","RAMADR-1","RAMADR","VDP06","R36","R37","R38","R39",
"R40","R41","R42","R43","R44","R45","R46","R47","R48","R49","R50","R51","R52",
"R53","R54","R55","R56","R57","R58","R59","R60","R61","R62","R63","R64","R65",
"R66","R67","R68","R69","R70","R71","R72","R73","R74","R75","R76","R77","R78",
"R79","R80","R81","R82","R83","R84","R85","R86","R87","R88","R89","R90","R91",
"R92","R93","R94","R95","R96","R97","R98","R99","R100","R101","R102","R103","R104",
"R105","R106","R107","R108","R109","R110","R111","R112","R113","R114","R115","R116","R117",
"R118","R119","R120","R121","R122","R123","R124","R125","R126","R127"};

void erreur(int);
void Decod(int , int , int , int );
int Dasmtms7020(char *, int );
int load(char *, unsigned char*);
char Mgetc(int);
int ManageArguments(int argc, char *argv[]);

int main(int argc, char *argv[])
{
	int nb;
	char ligne[80];
	debut=fin=reloc=0;
	fprintf(stderr,"Desassembleur 7020/7040 Exelvision 2010.01 (c) Daniel Coulom, Jester\n");
	if (ManageArguments(argc,argv))	exit(1);
	
	buffer=malloc(65536);
	if (buffer==NULL) erreur(2);
	
	nb=load(source, buffer);
	if (nb==0) 
	{
		free(buffer);
		exit(1);
	}

	if (!debut) debut=reloc;
	else if (debut>reloc+nb-1) {erreur(4);exit(1);}

	if (!fin) fin=reloc+nb-1;
	else if (fin>reloc+nb-1)  {erreur(4);exit(1);}
	
	nb=fin-reloc+1;
	a=debut-reloc;
	while (a<nb)
	{
		a=Dasmtms7020(ligne, a );
		printf("%s\n",ligne);
	}
	
	free(buffer);
	exit(0);
}

int ManageArguments(int argc, char *argv[])
{	int c;
	
	while ((c = getopt (argc, argv, "hs:e:r:")) != -1)
		switch (c)
		{
			case 'h':
				fprintf(stdout,"Usage: desasm7020 sourceFile [-r:0xRelocAdr] [-s:0xStartAdr] [-e:0xEndAdr]\n");	
				return 1;
			case 'r':
				reloc=strtol(optarg+1,NULL,16);
				break;
			case 's':
				debut=strtol(optarg+1, NULL, 16);
				break;
			case 'e':
				fin=strtol(optarg+1, NULL, 16);
				break;
			case '?':
				if (optopt == 'r' || optopt == 's' || optopt == 'e')
					fprintf (stderr, "Option -%c requires an argument.\n", optopt);
				else if (isprint (optopt))
					fprintf (stderr, "Unknown option `-%c'.\n", optopt);
				else
					fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt);
				return 1;
			default: return 1;
		}

	if (debut && debut<reloc)
		{
		fprintf (stderr,"Bad starting address.\n");
		return 1; }
	
	if (fin && (fin<reloc || fin<debut))
		{
		fprintf (stderr,"Bad ending address.\n");
		return 1; }

	if (argc-optind<1 || argc-optind>1)
		{
		fprintf (stderr,"One argument required: sourceFile.\n");
		return 1; }
		
	source=argv[optind];
	return 0;
}

char Mgetc(int adresse) {return buffer[adresse];}

int load(char *fichier, unsigned char*buffer)
{
	FILE *fd;
	int longueur;
	
	fd=fopen(fichier,"rb");
	if (fd==NULL) {erreur(3); return 0;}
	longueur=fread(buffer,1,65536,fd);
	if (longueur==0) erreur(3);
	fclose(fd);
	return longueur;
}

// Decodage de l'instruction //////////////////////////////////////////////////
void Decod(int op, int p1, int p2, int p3)
{
int i;
mnemo = name[op];
switch(p1)
{
  case VOID: param[0] = 0; break;                      //pas de parametre
  case REGISTER_A: strcpy(param, "A"); break;          //register A
  case REGISTER_B: strcpy(param, "B"); break;          //register B
  case REGISTER_FILE: if (op==42) {GET1(param, "");}  // LVDP
						else {GET1(param, "%s",registre[i]);}		 //register file register
						break;
  case PERIPHERAL_FILE: GET1(param, "P%i", i); break;   //peripheral file register
  case IMMEDIATE_8: GET1(param, "%%$%02X", i); break;  //immediate addressing 8 bits
  case IMMEDIATE_16: GET2(param, "%%$%04X", i); break; //immediate addressing 16 bits
  case BRANCH: GET2(param, "$%04X", i); break;         //branch address
  case DIRECT: GET2(param, "@$%04X", i); break;        //direct addressing
  case INDEXED: GET2(param, "@$%04X(B)", i); break;    //direct addressing (B)
  case INDIRECT: GET1(param, "*%s", registre[i]); break;        //indirect addressing
  case RELATIVE: GETR(param, "$%04X", a + reloc + i); break;   //relative addressing
  case ST: strcpy(param, "ST"); break;                 //ST
  default: sprintf(param, "%i", p1); break;            //TRAP number
}
switch(p2)
{
  case REGISTER_A: strcat(param, ",A"); break;         //register A
  case REGISTER_B: strcat(param, ",B"); break;         //register B
  case REGISTER_FILE: GET1(w, ",%s", registre[i])CATW; break;   //register file register
  case PERIPHERAL_FILE: GET1(w, ",P%i", i)CATW;  //peripheral file register
												if (op==MOVP && i==46)
													{
														i=strlen(param);
														param[i-4]=0;
														mnemo=name[WVDP];
													}
												break;
  case RELATIVE: GETR(w, ",$%04X", a + reloc + i)CATW; break;  //relative addressing
}
switch(p3)
{
  case RELATIVE: GETR(w, ",$%04X", a + reloc + i)CATW; break;  //relative addressing
}
}

// Desassembly ///////////////////////////////////////////////////////////////
int Dasmtms7020(char *string, int address)
{//  string = pointeur vers une chaine recevant la ligne desassemblee
// address = adresse des caracteres a desassembler
//  retour = adresse de l'instruction suivante
int i, opcode;
//initialisations
a = address;
opcode = Mgetc(a++) & 0xff;
sprintf(hexa, "%04X %02x", address+reloc, opcode);
param[0] = 0;
//decodage de l'instruction
switch(opcode)
{
  case 0x00: Decod(NOP,  VOID, VOID, VOID); break;
  case 0x01: Decod(IDLE, VOID, VOID, VOID); break;
  case 0x05: Decod(EINT, VOID, VOID, VOID); break;
  case 0x06: Decod(DINT, VOID, VOID, VOID); break;
  case 0x07: Decod(SETC, VOID, VOID, VOID); break;
  case 0x08: Decod(POP,    ST, VOID, VOID); break;
  case 0x09: Decod(STSP, VOID, VOID, VOID); break;
  case 0x0a: Decod(RETS, VOID, VOID, VOID); break;
  case 0x0b: Decod(RETI, VOID, VOID, VOID); break;
  case 0x0d: Decod(LDSP, VOID, VOID, VOID); break;
  case 0x0e: Decod(PUSH,   ST, VOID, VOID); break;

  case 0x12: Decod(MOV,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x13: Decod(AND,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x14: Decod(OR,   REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x15: Decod(XOR,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x16: Decod(BTJO, REGISTER_FILE, REGISTER_A, RELATIVE); break;
  case 0x17: Decod(BTJZ, REGISTER_FILE, REGISTER_A, RELATIVE); break;
  case 0x18: Decod(ADD,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x19: Decod(ADC,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x1a: Decod(SUB,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x1b: Decod(SBB,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x1c: Decod(MPY,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x1d: Decod(CMP,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x1e: Decod(DAC,  REGISTER_FILE, REGISTER_A, VOID); break;
  case 0x1f: Decod(DSB,  REGISTER_FILE, REGISTER_A, VOID); break;

  case 0x22: Decod(MOV,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x23: Decod(AND,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x24: Decod(OR,   IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x25: Decod(XOR,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x26: Decod(BTJO, IMMEDIATE_8, REGISTER_A, RELATIVE); break;
  case 0x27: Decod(BTJZ, IMMEDIATE_8, REGISTER_A, RELATIVE); break;
  case 0x28: Decod(ADD,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x29: Decod(ADC,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x2a: Decod(SUB,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x2b: Decod(SBB,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x2c: Decod(MPY,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x2d: Decod(CMP,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x2e: Decod(DAC,  IMMEDIATE_8, REGISTER_A, VOID); break;
  case 0x2f: Decod(DSB,  IMMEDIATE_8, REGISTER_A, VOID); break;

  case 0x32: Decod(MOV,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x33: Decod(AND,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x34: Decod(OR,   REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x35: Decod(XOR,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x36: Decod(BTJO, REGISTER_FILE, REGISTER_B, RELATIVE); break;
  case 0x37: Decod(BTJZ, REGISTER_FILE, REGISTER_B, RELATIVE); break;
  case 0x38: Decod(ADD,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x39: Decod(ADC,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x3a: Decod(SUB,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x3b: Decod(SBB,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x3c: Decod(MPY,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x3d: Decod(CMP,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x3e: Decod(DAC,  REGISTER_FILE, REGISTER_B, VOID); break;
  case 0x3f: Decod(DSB,  REGISTER_FILE, REGISTER_B, VOID); break;

  case 0x42: Decod(MOV,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x43: Decod(AND,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x44: Decod(OR,   REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x45: Decod(XOR,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x46: Decod(BTJO, REGISTER_FILE, REGISTER_FILE, RELATIVE); break;
  case 0x47: Decod(BTJZ, REGISTER_FILE, REGISTER_FILE, RELATIVE); break;
  case 0x48: Decod(ADD,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x49: Decod(ADC,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x4a: Decod(SUB,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x4b: Decod(SBB,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x4c: Decod(MPY,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x4d: Decod(CMP,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x4e: Decod(DAC,  REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x4f: Decod(DSB,  REGISTER_FILE, REGISTER_FILE, VOID); break;

  case 0x52: Decod(MOV,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x53: Decod(AND,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x54: Decod(OR,   IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x55: Decod(XOR,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x56: Decod(BTJO, IMMEDIATE_8, REGISTER_B, RELATIVE); break;
  case 0x57: Decod(BTJZ, IMMEDIATE_8, REGISTER_B, RELATIVE); break;
  case 0x58: Decod(ADD,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x59: Decod(ADC,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x5a: Decod(SUB,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x5b: Decod(SBB,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x5c: Decod(MPY,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x5d: Decod(CMP,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x5e: Decod(DAC,  IMMEDIATE_8, REGISTER_B, VOID); break;
  case 0x5f: Decod(DSB,  IMMEDIATE_8, REGISTER_B, VOID); break;

  case 0x62: Decod(MOV,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x63: Decod(AND,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x64: Decod(OR,   REGISTER_B, REGISTER_A, VOID); break;
  case 0x65: Decod(XOR,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x66: Decod(BTJO, REGISTER_B, REGISTER_A, RELATIVE); break;
  case 0x67: Decod(BTJZ, REGISTER_B, REGISTER_A, RELATIVE); break;
  case 0x68: Decod(ADD,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x69: Decod(ADC,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x6a: Decod(SUB,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x6b: Decod(SBB,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x6c: Decod(MPY,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x6d: Decod(CMP,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x6e: Decod(DAC,  REGISTER_B, REGISTER_A, VOID); break;
  case 0x6f: Decod(DSB,  REGISTER_B, REGISTER_A, VOID); break;

  case 0x72: Decod(MOV,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x73: Decod(AND,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x74: Decod(OR,   IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x75: Decod(XOR,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x76: Decod(BTJO, IMMEDIATE_8, REGISTER_FILE, RELATIVE); break;
  case 0x77: Decod(BTJZ, IMMEDIATE_8, REGISTER_FILE, RELATIVE); break;
  case 0x78: Decod(ADD,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x79: Decod(ADC,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x7a: Decod(SUB,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x7b: Decod(SBB,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x7c: Decod(MPY,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x7d: Decod(CMP,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x7e: Decod(DAC,  IMMEDIATE_8, REGISTER_FILE, VOID); break;
  case 0x7f: Decod(DSB,  IMMEDIATE_8, REGISTER_FILE, VOID); break;

  case 0x80: Decod(MOVP, PERIPHERAL_FILE, REGISTER_A, VOID); break;
  case 0x82: Decod(MOVP, REGISTER_A, PERIPHERAL_FILE, VOID); break;
  case 0x83: Decod(ANDP, REGISTER_A, PERIPHERAL_FILE, VOID); break;
  case 0x84: Decod(ORP,  REGISTER_A, PERIPHERAL_FILE, VOID); break;
  case 0x85: Decod(XORP, REGISTER_A, PERIPHERAL_FILE, VOID); break;
  case 0x86: Decod(BTJOP,REGISTER_A, PERIPHERAL_FILE, RELATIVE); break;
  case 0x87: Decod(BTJZP,REGISTER_A, PERIPHERAL_FILE, RELATIVE); break;
  case 0x88: Decod(MOVD, IMMEDIATE_16, REGISTER_FILE, VOID); break;
  case 0x8a: Decod(LDA,  DIRECT, VOID, VOID); break;
  case 0x8b: Decod(STA,  DIRECT, VOID, VOID); break;
  case 0x8c: Decod(BR,   BRANCH, VOID, VOID); break;
  case 0x8d: Decod(CMPA, DIRECT, VOID, VOID); break;
  case 0x8e: Decod(CALL, BRANCH, VOID, VOID); break;

  case 0x91: Decod(MOVP, PERIPHERAL_FILE, REGISTER_B, VOID); break;
  case 0x92: Decod(MOVP, REGISTER_B, PERIPHERAL_FILE, VOID); break;
  case 0x93: Decod(ANDP, REGISTER_B, PERIPHERAL_FILE, VOID); break;
  case 0x94: Decod(ORP,  REGISTER_B, PERIPHERAL_FILE, VOID); break;
  case 0x95: Decod(XORP, REGISTER_B, PERIPHERAL_FILE, VOID); break;
  case 0x96: Decod(BTJOP,REGISTER_B, PERIPHERAL_FILE, RELATIVE); break;
  case 0x97: Decod(BTJZP,REGISTER_B, PERIPHERAL_FILE, RELATIVE); break;
  case 0x98: Decod(MOVD, REGISTER_FILE, REGISTER_FILE, VOID); break;
  case 0x9a: Decod(LDA,  INDIRECT, VOID, VOID); break;
  case 0x9b: Decod(STA,  INDIRECT, VOID, VOID); break;
  case 0x9c: Decod(BR,   INDIRECT, VOID, VOID); break;
  case 0x9d: Decod(CMPA, INDIRECT, VOID, VOID); break;
  case 0x9e: Decod(CALL, INDIRECT, VOID, VOID); break;

  case 0xa2: Decod(MOVP, IMMEDIATE_8, PERIPHERAL_FILE, VOID); break;
  case 0xa3: Decod(ANDP, IMMEDIATE_8, PERIPHERAL_FILE, VOID); break;
  case 0xa4: Decod(ORP,  IMMEDIATE_8, PERIPHERAL_FILE, VOID); break;
  case 0xa5: Decod(XORP, IMMEDIATE_8, PERIPHERAL_FILE, VOID); break;
  case 0xa6: Decod(BTJOP,IMMEDIATE_8, PERIPHERAL_FILE, RELATIVE); break;
  case 0xa7: Decod(BTJZP,IMMEDIATE_8, PERIPHERAL_FILE, RELATIVE); break;
  case 0xa8: Decod(MOVD, INDEXED, REGISTER_FILE, VOID); break;
  case 0xaa: Decod(LDA,  INDEXED, VOID, VOID); break;
  case 0xab: Decod(STA,  INDEXED, VOID, VOID); break;
  case 0xac: Decod(BR,   INDEXED, VOID, VOID); break;
  case 0xad: Decod(CMPA, INDEXED, VOID, VOID); break;
  case 0xae: Decod(CALL, INDEXED, VOID, VOID); break;

  case 0xb0: Decod(TSTA, VOID, VOID, VOID); break;
  case 0xb2: Decod(DEC,  REGISTER_A, VOID, VOID); break;
  case 0xb3: Decod(INC,  REGISTER_A, VOID, VOID); break;
  case 0xb4: Decod(INV,  REGISTER_A, VOID, VOID); break;
  case 0xb5: Decod(CLR,  REGISTER_A, VOID, VOID); break;
  case 0xb6: Decod(XCHB, REGISTER_A, VOID, VOID); break;
  case 0xb7: Decod(INVALID, REGISTER_A, VOID, VOID); break;
  case 0xb8: Decod(PUSH, REGISTER_A, VOID, VOID); break;
  case 0xb9: Decod(POP,  REGISTER_A, VOID, VOID); break;
  case 0xba: Decod(DJNZ, REGISTER_A, RELATIVE, VOID); break;
  case 0xbb: Decod(DECD, REGISTER_A, VOID, VOID); break;
  case 0xbc: Decod(RR,   REGISTER_A, VOID, VOID); break;
  case 0xbd: Decod(RRC,  REGISTER_A, VOID, VOID); break;
  case 0xbe: Decod(RL,   REGISTER_A, VOID, VOID); break;
  case 0xbf: Decod(RLC,  REGISTER_A, VOID, VOID); break;

  case 0xc0: Decod(MOV,  REGISTER_A, REGISTER_B, VOID); break;
  case 0xc1: Decod(TSTB, VOID, VOID, VOID); break;
  case 0xc2: Decod(DEC,  REGISTER_B, VOID, VOID); break;
  case 0xc3: Decod(INC,  REGISTER_B, VOID, VOID); break;
  case 0xc4: Decod(INV,  REGISTER_B, VOID, VOID); break;
  case 0xc5: Decod(CLR,  REGISTER_B, VOID, VOID); break;
  case 0xc6: Decod(XCHB, REGISTER_B, VOID, VOID); break;
  case 0xc7: Decod(INVALID, REGISTER_B, VOID, VOID); break;
  case 0xc8: Decod(PUSH, REGISTER_B, VOID, VOID); break;
  case 0xc9: Decod(POP,  REGISTER_B, VOID, VOID); break;
  case 0xca: Decod(DJNZ, REGISTER_B, RELATIVE, VOID); break;
  case 0xcb: Decod(DECD, REGISTER_B, VOID, VOID); break;
  case 0xcc: Decod(RR,   REGISTER_B, VOID, VOID); break;
  case 0xcd: Decod(RRC,  REGISTER_B, VOID, VOID); break;
  case 0xce: Decod(RL,   REGISTER_B, VOID, VOID); break;
  case 0xcf: Decod(RLC,  REGISTER_B, VOID, VOID); break;

  case 0xd0: Decod(MOV,  REGISTER_A, REGISTER_FILE, VOID); break;
  case 0xd1: Decod(MOV,  REGISTER_B, REGISTER_FILE, VOID); break;
  case 0xd2: Decod(DEC,  REGISTER_FILE, VOID, VOID); break;
  case 0xd3: Decod(INC,  REGISTER_FILE, VOID, VOID); break;
  case 0xd4: Decod(INV,  REGISTER_FILE, VOID, VOID); break;
  case 0xd5: Decod(CLR,  REGISTER_FILE, VOID, VOID); break;
  case 0xd6: Decod(XCHB, REGISTER_FILE, VOID, VOID); break;
  case 0xd7: Decod(LDVP, REGISTER_FILE, VOID, VOID); break;
  case 0xd8: Decod(PUSH, REGISTER_FILE, VOID, VOID); break;
  case 0xd9: Decod(POP,  REGISTER_FILE, VOID, VOID); break;
  case 0xda: Decod(DJNZ, REGISTER_FILE, RELATIVE, VOID); break;
  case 0xdb: Decod(DECD, REGISTER_FILE, VOID, VOID); break;
  case 0xdc: Decod(RR,   REGISTER_FILE, VOID, VOID); break;
  case 0xdd: Decod(RRC,  REGISTER_FILE, VOID, VOID); break;
  case 0xde: Decod(RL,   REGISTER_FILE, VOID, VOID); break;
  case 0xdf: Decod(RLC,  REGISTER_FILE, VOID, VOID); break;

  case 0xe0: Decod(JMP, RELATIVE, VOID, VOID); break;
  case 0xe1: Decod(JLT, RELATIVE, VOID, VOID); break;
  case 0xe2: Decod(JEQ, RELATIVE, VOID, VOID); break;
  case 0xe3: Decod(JHS, RELATIVE, VOID, VOID); break;
  case 0xe4: Decod(JGT, RELATIVE, VOID, VOID); break;
  case 0xe5: Decod(JGE, RELATIVE, VOID, VOID); break;
  case 0xe6: Decod(JNE, RELATIVE, VOID, VOID); break;
  case 0xe7: Decod(JL,  RELATIVE, VOID, VOID); break;
  case 0xe8: Decod(TRAP, 23, VOID, VOID); break;
  case 0xe9: Decod(TRAP, 22, VOID, VOID); break;
  case 0xea: Decod(TRAP, 21, VOID, VOID); break;
  case 0xeb: Decod(TRAP, 20, VOID, VOID); break;
  case 0xec: Decod(TRAP, 19, VOID, VOID); break;
  case 0xed: Decod(TRAP, 18, VOID, VOID); break;
  case 0xee: Decod(TRAP, 17, VOID, VOID); break;
  case 0xef: Decod(TRAP, 16, VOID, VOID); break;

  case 0xf0: Decod(TRAP, 15, VOID, VOID); break;
  case 0xf1: Decod(TRAP, 14, VOID, VOID); break;
  case 0xf2: Decod(TRAP, 13, VOID, VOID); break;
  case 0xf3: Decod(TRAP, 12, VOID, VOID); break;
  case 0xf4: Decod(TRAP, 11, VOID, VOID); break;
  case 0xf5: Decod(TRAP, 10, VOID, VOID); break;
  case 0xf6: Decod(TRAP,  9, VOID, VOID); break;
  case 0xf7: Decod(TRAP,  8, VOID, VOID); break;
  case 0xf8: Decod(TRAP,  7, VOID, VOID); break;
  case 0xf9: Decod(TRAP,  6, VOID, VOID); break;
  case 0xfa: Decod(TRAP,  5, VOID, VOID); break;
  case 0xfb: Decod(TRAP,  4, VOID, VOID); break;
  case 0xfc: Decod(TRAP,  3, VOID, VOID); break;
  case 0xfd: Decod(TRAP,  2, VOID, VOID); break;
  case 0xfe: Decod(TRAP,  1, VOID, VOID); break;
  case 0xff: Decod(TRAP,  0, VOID, VOID); break;

  default: Decod(INVALID, VOID, VOID, VOID);
}
//composition de la ligne desassemblee
strcpy(string, hexa);
for(i = strlen(string); i < 15; i++) strcat(string, " ");
strcat(string, mnemo);
for(i = strlen(string); i < 22; i++) strcat(string, " ");
strcat(string, param);
//retour adresse prochaine instruction
return(a);
}

void erreur(int err)
{
	switch (err)
	{
		case 1: fprintf(stdout,"Usage: desasm7020 sourceFile [-h] [-r:0xRelocAdr] [-s:0xStartAdr] [-e:0xEndAdr]\n");;break;
		case 3: fprintf(stderr,"Cannot open source file.\n");break;
		case 2: fprintf(stderr,"Memory problem.\n");break;
		case 4: fprintf(stderr,"Dump address out of range.\n");break;
		default: fprintf(stderr,"Erreur %i\n",err);
	}
}
