Plan 9 from Bell Labs’s /usr/web/sources/contrib/rsc/8i/fmt.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include "8i.h"

static char *opstr[] = {	/* Edit s/O(.*),/[O\1]=	"\1",/g */
	[OBAD]=	"BAD",
	[O0F]=	"0F",
	[OAAA]=	"AAA",
	[OAAD]=	"AAD",
	[OAAM]=	"AAM",
	[OAAS]=	"AAS",
	[OADC]=	"ADC",
	[OADD]=	"ADD",
	[OAND]=	"AND",
	[OARPL]=	"ARPL",
	[OASIZE]=	"ASIZE",
	[OBOUND]=	"BOUND",
	[OBT]=	"BT",
	[OBTS]=	"BTS",
	[OCALL]=	"CALL",
	[OCBW]=	"CBW",
	[OCLC]=	"CLC",
	[OCLD]=	"CLD",
	[OCLI]=	"CLI",
	[OCMC]=	"CMC",
	[OCMOV]=	"CMOV",
	[OCMP]=	"CMP",
	[OCMPS]=	"CMPS",
	[OCWD]=	"CWD",
	[ODAA]=	"DAA",
	[ODAS]=	"DAS",
	[ODEC]=	"DEC",
	[ODIV]=	"DIV",
	[OENTER]=	"ENTER",
	[OGP1]=	"GP1",
	[OGP2]=	"GP2",
	[OGP3b]=	"GP3b",
	[OGP3v]=	"GP3v",
	[OGP4]=	"GP4",
	[OGP5]=	"GP5",
	[OHLT]=	"HLT",
	[OIDIV]=	"IDIV",
	[OIMUL]=	"IMUL",
	[OIN]=	"IN",
	[OINC]=	"INC",
	[OINS]=	"INS",
	[OINT]=	"INT",
	[OIRET]=	"IRET",
	[OJUMP]=	"JUMP",
	[OLAHF]=	"LAHF",
	[OLFP]=	"LFP",
	[OLEA]=	"LEA",
	[OLEAVE]=	"LEAVE",
	[OLOCK]=	"LOCK",
	[OLODS]=	"LODS",
	[OLOOP]=	"LOOP",
	[OLOOPNZ]=	"LOOPNZ",
	[OLOOPZ]=	"LOOPZ",
	[OMOV]=	"MOV",
	[OMOVS]=	"MOVS",
	[OMUL]=	"MUL",
	[ONEG]=	"NEG",
	[ONOP]=	"NOP",
	[ONOT]=	"NOT",
	[OOR]=	"OR",
	[OOSIZE]=	"OSIZE",
	[OOUT]=	"OUT",
	[OOUTS]=	"OUTS",
	[OPOP]=	"POP",
	[OPOPA]=	"POPA",
	[OPOPF]=	"POPF",
	[OPUSH]=	"PUSH",
	[OPUSHA]=	"PUSHA",
	[OPUSHF]=	"PUSHF",
	[ORCL]=	"RCL",
	[ORCR]=	"RCR",
	[OREPE]=	"REPE",
	[OREPNE]=	"REPNE",
	[ORET]=	"RET",
	[ORETF]=	"RETF",
	[OROL]=	"ROL",
	[OROR]=	"ROR",
	[OSAHF]=	"SAHF",
	[OSAR]=	"SAR",
	[OSBB]=	"SBB",
	[OSCAS]=	"SCAS",
	[OSEG]=	"SEG",
	[OSET]=	"SET",
	[OSHL]=	"SHL",
	[OSHLD]=	"SHLD",
	[OSHR]=	"SHR",
	[OSHRD]=	"SHRD",
	[OSTC]=	"STC",
	[OSTD]=	"STD",
	[OSTI]=	"STI",
	[OSTOS]=	"STOS",
	[OSUB]=	"SUB",
	[OTEST]=	"TEST",
	[OWAIT]=	"WAIT",
	[OXCHG]=	"XCHG",
	[OXLAT]=	"XLAT",
	[OXOR]=	"XOR",
	NUMOP,
};

static char *littlereg[] = {
	"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
};
static char *bigreg[] = {
	"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI",
	"ES", "CS", "SS", "DS", "FS", "GS",
};

static int
isstring(int a)
{
	return a==AXb || a==AXv || a==AYb || a==AYv;
}

static char* memstr[] = {
	"BX+SI",
	"BX+DI",
	"BP+SI",
	"BP+DI",
	"SI",
	"DI",
	"BP",
	"BX",
};

static void
memconv(char *p, Inst *ip, Iarg*)
{
	if(ip->sreg != 'D'){
		sprint(p, "%cS:", ip->sreg);
		p += strlen(p);
	}
	if(ip->mod == 0 && ip->rm == 6){
		sprint(p, "[%lX]", ip->disp);
		return;
	}
	if(ip->mod != 0)
		sprint(p, "[%s%+lX]", memstr[ip->rm], ip->disp);
	else
		sprint(p, "[%s]", memstr[ip->rm]);
}

static void
argconv(char *p, Inst *ip, Iarg *iarg)
{
	switch(iarg->atype){
	default:
	case ANONE:	/* no argument */
		strcpy(p, "<badarg>");
		break;
	case A0:		/* constant 0 */
		strcpy(p, "0");
		break;
	case A1:		/* constant 1 */
		strcpy(p, "1");
		break;
	case A3:		/* constant 3 */
		strcpy(p, "3");
		break;
	case A4:		/* constant 4 */
		strcpy(p, "4");
		break;
	case AAp:	/* 32-bit or 48-bit direct address */
	case AMp:	/* 32-bit or 48-bit memory address */
		sprint(p, "[%4.4X:%*.*luX]", iarg->seg, ip->opsize/4, ip->opsize/4, iarg->off);
		break;
	case AEp:	/* call indirect through memory */
print("call\n");
		memconv(p, ip, iarg);
		break;
	case AEb:	/* r/m8 from modrm byte */
		if(ip->mod == 3){
			sprint(p, littlereg[iarg->seg]);
			break;
		}
		memconv(p, ip, iarg);
		break;
	case AEv:	/* r/m16 or r/m32 from modrm byte */
	case AEw:	/* r/m16 */
		if(ip->mod == 3){
			sprint(p, bigreg[iarg->seg]);
			break;
		}
		memconv(p, ip, iarg);
		break;
	case AFv:
		break;
	case AGb:	/* r8 from modrm byte */
		sprint(p, littlereg[iarg->seg]);
		break;
	case AGv:	/* r16 or r32 from modrm byte */
	case AGw: /* r/m16 */
		sprint(p, bigreg[iarg->seg]);
		break;
	case AIb:	/* immediate byte */
	case AIc:	/* immediate byte sign-extended */
	case AIw:	/* immediate 16-bit word */
	case AIv:	/* immediate 16-bit or 32-bit word */
		sprint(p, "%*.*lX", ip->opsize/4, ip->opsize/4, iarg->val);
		break;
	case AJb:	/* relative offset byte */
	case AJv:	/* relative offset 16-bit or 32-bit word */
		sprint(p, "%*.*lX", ip->addrsize/4, ip->addrsize/4, iarg->off);
		break;
	case AJr:	/* jump through register */
		sprint(p, bigreg[ip->rm]);
		break;
	case AM:	/* memory address from modrm */
	case AMa:	/* something for bound */
		memconv(p, ip, iarg);
		break;
	case AMa2:
		break;
	case AOb:	/* immediate word-sized offset to a byte */
	case AOv:	/* immediate word-size offset to a word */
		memconv(p, ip, iarg);
		break;
	case ASw:	/* segment register selected by r field of modrm */
		sprint(p, bigreg[iarg->seg]);
		break;
	case AXb:	/* byte at DS:SI (should not be called) */
	case AXv:	/* word at DS:SI */
	case AYb:	/* byte at ES:DI */
	case AYv:	/* word at ES:DI */
		abort();
	case AAL:	/* registers; should be in same order as RAL: etc. */
	case AAH:
	case ABL:
	case ABH:
	case ACL:
	case ACH:
	case ADL:
	case ADH:
		strcpy(p, littlereg[iarg->atype-AAL]);
		break;
	case AAX:	/* registers; should be in same order as RAX: etc. */
	case ABX:
	case ACX:
	case ADX:
	case ABP:
	case ASP:
	case ADI:
	case ASI:
	case AES:
	case ACS:
	case ASS:
	case ADS:
	case AFS:
	case AGS:
		strcpy(p, bigreg[iarg->atype - AAX]);
		break;
	}

}

static char *jmpstr[] = {
	"JO", "JNO", "JC", "JNC", "JZ", "JNZ", "JBE", "JA",
	"JS", "JNS", "JP", "JNP", "JL", "JGE", "JLE", "JG",
};
int
instfmt(Fmt *fmt)
{
	int x;
	char buf[100];
	Inst *ip;

	ip = va_arg(fmt->args, Inst*);
	if(ip == nil){
		fmtstrcpy(fmt, "<null>");
		return 0;
	}
	if(ip->op == OBAD || ip->op >= NUMOP){
		fmtstrcpy(fmt, "ILLEGAL INSTRUCTION");
		return 0;
	}
	buf[0] = '\0';
	if(ip->repeat)
		sprint(buf+strlen(buf), "%s: ", opstr[ip->repeat]);
	if(ip->opsize == 32)
		strcat(buf, "O32: ");
	if(ip->op == OJUMP){
		switch(ip->i){
		case 0xE3:
			strcat(buf, "JCXZ");
			break;
		case 0xEB:
		case 0xE9:
		case 0xEA:
		case 0xFF:
			strcat(buf, "JMP");
			break;
		default:
			strcat(buf, jmpstr[ip->i&0xF]);
			break;
		}
	}else
		strcat(buf, opstr[ip->op]);
	sprint(buf+strlen(buf), "(%c)", ip->opsize==8 ? 'B' : ip->opsize == 16 ? 'W' : 'L');
	if(isstring(x=ip->arg1.atype) || isstring(x=ip->arg2.atype)){
	//	if(ip->opsize == 8)
	//		strcat(buf, "B");
	//	else
	//		strcat(buf, "W");
		USED(x);
	}else{
		if(ip->arg1.atype){
			strcat(buf, "\t");
			argconv(buf+strlen(buf), ip, &ip->arg1);
		}
		if(ip->arg2.atype){
			strcat(buf, ", ");
			argconv(buf+strlen(buf), ip, &ip->arg2);
		}
		if(ip->arg3.atype){
			strcat(buf, ", ");
			argconv(buf+strlen(buf), ip, &ip->arg3);
		}
	}
	fmtstrcpy(fmt, buf);
	return 0;
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.