⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asmout.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "l.h"#define	OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))#define	OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))#define	OP(o,xo) OPVCC((o),(xo),0,0)/* the order is dest, a/s, b/imm for both arithmetic and logical operations */#define	AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))#define	AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))#define	LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))#define	LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))#define	OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))#define	OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))#define	OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))#define	OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\					(((mb)&31L)<<6)|(((me)&31L)<<1))#define	OP_ADD	OPVCC(31,266,0,0)#define	OP_ADDI	OPVCC(14,0,0,0)#define	OP_ADDIS OPVCC(15,0,0,0)#define	OP_ANDI	OPVCC(28,0,0,0)#define	OP_EXTSB	OPVCC(31,954,0,0)#define	OP_EXTSH OPVCC(31,922,0,0)#define	OP_MCRF	OPVCC(19,0,0,0)#define	OP_MCRFS OPVCC(63,64,0,0)#define	OP_MCRXR OPVCC(31,512,0,0)#define	OP_MFCR	OPVCC(31,19,0,0)#define	OP_MFFS	OPVCC(63,583,0,0)#define	OP_MFMSR OPVCC(31,83,0,0)#define	OP_MFSPR OPVCC(31,339,0,0)#define	OP_MFSR	OPVCC(31,595,0,0)#define	OP_MFSRIN	OPVCC(31,659,0,0)#define	OP_MTCRF OPVCC(31,144,0,0)#define	OP_MTFSF OPVCC(63,711,0,0)#define	OP_MTFSFI OPVCC(63,134,0,0)#define	OP_MTMSR OPVCC(31,146,0,0)#define	OP_MTSPR OPVCC(31,467,0,0)#define	OP_MTSR	OPVCC(31,210,0,0)#define	OP_MTSRIN	OPVCC(31,242,0,0)#define	OP_MULLW OPVCC(31,235,0,0)#define	OP_OR	OPVCC(31,444,0,0)#define	OP_ORI	OPVCC(24,0,0,0)#define	OP_RLWINM	OPVCC(21,0,0,0)#define	OP_SUBF	OPVCC(31,40,0,0)#define	oclass(v)	((v).class-1)long	oprrr(int), opirr(int), opload(int), opstore(int), oploadx(int), opstorex(int);intgetmask(uchar *m, ulong v){	int i;	m[0] = m[1] = 0;	if(v != ~0L && v & (1<<31) && v & 1){	/* MB > ME */		if(getmask(m, ~v)){			i = m[0]; m[0] = m[1]+1; m[1] = i-1;			return 1;		}		return 0;	}	for(i=0; i<32; i++)		if(v & (1<<(31-i))){			m[0] = i;			do {				m[1] = i;			} while(++i<32 && (v & (1<<(31-i))) != 0);			for(; i<32; i++)				if(v & (1<<(31-i)))					return 0;			return 1;		}	return 0;}voidmaskgen(Prog *p, uchar *m, ulong v){	if(!getmask(m, v))		diag("cannot generate mask #%lux\n%P", v, p);}static voidreloc(Adr *a, long pc, int sext){	if(a->name == D_EXTERN || a->name == D_STATIC)		dynreloc(a->sym, pc, 1, 1, sext);}	intasmout(Prog *p, Optab *o, int aflag){	long o1, o2, o3, o4, o5, v, t;	Prog *ct;	int r, a;	uchar mask[2];	o1 = 0;	o2 = 0;	o3 = 0;	o4 = 0;	o5 = 0;	switch(o->type) {	default:		if(aflag)			return 0;		diag("unknown type %d", o->type);		if(!debug['a'])			prasm(p);		break;	case 0:		/* pseudo ops */		if(aflag) {			if(p->link) {				if(p->as == ATEXT) {					ct = curtext;					o2 = autosize;					curtext = p;					autosize = p->to.offset + 4;					o1 = asmout(p->link, oplook(p->link), aflag);					curtext = ct;					autosize = o2;				} else					o1 = asmout(p->link, oplook(p->link), aflag);			}			return o1;		}		break;	case 1:		/* mov r1,r2 ==> OR Rs,Rs,Ra */		if(p->to.reg == REGZERO && p->from.type == D_CONST) {			v = regoff(&p->from);			if(r0iszero && v != 0) {				nerrors--;				diag("literal operation on R0\n%P", p);			}			o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);			break;		}		o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);		break;	case 2:		/* int/cr/fp op Rb,[Ra],Rd */		r = p->reg;		if(r == NREG)			r = p->to.reg;		o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);		break;	case 3:		/* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */		v = regoff(&p->from);		r = p->from.reg;		if(r == NREG)			r = o->param;		a = OP_ADDI;		if(o->a1 == C_UCON) {			a = OP_ADDIS;			v >>= 16;		}		if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))			diag("literal operation on R0\n%P", p);		o1 = AOP_IRR(a, p->to.reg, r, v);		break;	case 4:		/* add/mul $scon,[r1],r2 */		v = regoff(&p->from);		r = p->reg;		if(r == NREG)			r = p->to.reg;		if(r0iszero && p->to.reg == 0)			diag("literal operation on R0\n%P", p);		o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);		break;	case 5:		/* syscall */		if(aflag)			return 0;		o1 = oprrr(p->as);		break;	case 6:		/* logical op Rb,[Rs,]Ra; no literal */		r = p->reg;		if(r == NREG)			r = p->to.reg;		o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);		break;	case 7:		/* mov r, soreg ==> stw o(r) */		r = p->to.reg;		if(r == NREG)			r = o->param;		v = regoff(&p->to);		if(p->to.type == D_OREG && p->reg != NREG) {			if(v)				diag("illegal indexed instruction\n%P", p);			o1 = AOP_RRR(opstorex(p->as), p->from.reg, p->reg, r);		} else			o1 = AOP_IRR(opstore(p->as), p->from.reg, r, v);		break;	case 8:		/* mov soreg, r ==> lbz/lhz/lwz o(r) */		r = p->from.reg;		if(r == NREG)			r = o->param;		v = regoff(&p->from);		if(p->from.type == D_OREG && p->reg != NREG) {			if(v)				diag("illegal indexed instruction\n%P", p);			o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);		} else			o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);		break;	case 9:		/* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */		r = p->from.reg;		if(r == NREG)			r = o->param;		v = regoff(&p->from);		if(p->from.type == D_OREG && p->reg != NREG) {			if(v)				diag("illegal indexed instruction\n%P", p);			o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);		} else			o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);		o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);		break;	case 10:		/* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */		r = p->reg;		if(r == NREG)			r = p->to.reg;		o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, r);		break;	case 11:	/* br/bl lbra */		if(aflag)			return 0;		v = 0;		if(p->cond == UP){			if(p->to.sym->type != SUNDEF)				diag("bad branch sym type");			v = (ulong)p->to.sym->value >> (Roffset-2);			dynreloc(p->to.sym, p->pc, 0, 0, 0);		}		else if(p->cond)			v = p->cond->pc - p->pc;		if(v & 03) {			diag("odd branch target address\n%P", p);			v &= ~03;		}		if(v < -(1L<<25) || v >= (1L<<25))			diag("branch too far\n%P", p);		o1 = OP_BR(opirr(p->as), v, 0);		break;	case 12:	/* movb r,r (signed); extsb is on PowerPC but not POWER */		o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);		break;	case 13:	/* mov[bh]z r,r; uses rlwinm not andi. to avoid changing CC */		if(p->as == AMOVBZ)			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);		else if(p->as == AMOVH)			o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);		else if(p->as == AMOVHZ)			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);		else			diag("internal: bad mov[bh]z\n%P", p);		break;/*14 */	case 17:	/* bc bo,bi,lbra (same for now) */	case 16:	/* bc bo,bi,sbra */		if(aflag)			return 0;		a = 0;		if(p->from.type == D_CONST)			a = regoff(&p->from);		r = p->reg;		if(r == NREG)			r = 0;		v = 0;		if(p->cond)			v = p->cond->pc - p->pc;		if(v & 03) {			diag("odd branch target address\n%P", p);			v &= ~03;		}		if(v < -(1L<<16) || v >= (1L<<16))			diag("branch too far\n%P", p);		o1 = OP_BC(opirr(p->as), a, r, v, 0);		break;	case 15:	/* br/bl (r) => mov r,lr; br/bl (lr) */		if(aflag)			return 0;		if(p->as == ABC || p->as == ABCL)			v = regoff(&p->to)&31L;		else			v = 20;	/* unconditional */		r = p->reg;		if(r == NREG)			r = 0;		o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);		o2 = OPVCC(19, 16, 0, 0);		if(p->as == ABL || p->as == ABCL)			o2 |= 1;		o2 = OP_BCR(o2, v, r);		break;	case 18:	/* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */		if(aflag)			return 0;		if(p->as == ABC || p->as == ABCL)			v = regoff(&p->from)&31L;		else			v = 20;	/* unconditional */		r = p->reg;		if(r == NREG)			r = 0;		switch(oclass(p->to)) {		case C_CTR:			o1 = OPVCC(19, 528, 0, 0);			break;		case C_LR:			o1 = OPVCC(19, 16, 0, 0);			break;		default:			diag("bad optab entry (18): %d\n%P", p->to.class, p);			v = 0;		}		if(p->as == ABL || p->as == ABCL)			o1 |= 1;		o1 = OP_BCR(o1, v, r);		break;	case 19:	/* mov $lcon,r ==> cau+or */		v = regoff(&p->from);		o1 = AOP_IRR(OP_ADDIS, p->to.reg, REGZERO, v>>16);		o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, v);		if(dlm)			reloc(&p->from, p->pc, 0);		break;	case 20:	/* add $ucon,,r */		v = regoff(&p->from);		r = p->reg;		if(r == NREG)			r = p->to.reg;		if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))			diag("literal operation on R0\n%P", p);		o1 = AOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16);		break;	case 22:	/* add $lcon,r1,r2 ==> cau+or+add */	/* could do add/sub more efficiently */		v = regoff(&p->from);		if(p->to.reg == REGTMP || p->reg == REGTMP)			diag("cant synthesize large constant\n%P", p);		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);		r = p->reg;		if(r == NREG)			r = p->to.reg;		o3 = AOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);		if(dlm)			reloc(&p->from, p->pc, 0);		break;	case 23:	/* and $lcon,r1,r2 ==> cau+or+and */	/* masks could be done using rlnm etc. */		v = regoff(&p->from);		if(p->to.reg == REGTMP || p->reg == REGTMP)			diag("cant synthesize large constant\n%P", p);		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);		r = p->reg;		if(r == NREG)			r = p->to.reg;		o3 = LOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);		if(dlm)			reloc(&p->from, p->pc, 0);		break;/*24*/	case 26:	/* mov $lsext/auto/oreg,,r2 ==> cau+add */		v = regoff(&p->from);		if(v & 0x8000L)			v += 0x10000L;		if(p->to.reg == REGTMP)			diag("can't synthesize large constant\n%P", p);		r = p->from.reg;		if(r == NREG)			r = o->param;		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);		o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);		break;	case 27:		/* subc ra,$simm,rd => subfic rd,ra,$simm */		v = regoff(&p->from3);		r = p->from.reg;		o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);		break;	case 28:	/* subc r1,$lcon,r2 ==> cau+or+subfc */		v = regoff(&p->from3);		if(p->to.reg == REGTMP || p->from.reg == REGTMP)			diag("can't synthesize large constant\n%P", p);		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);		o3 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, REGTMP);		if(dlm)			reloc(&p->from3, p->pc, 0);		break;/*29, 30, 31 */	case 32:	/* fmul frc,fra,frd */		r = p->reg;		if(r == NREG)			r = p->to.reg;		o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);		break;	case 33:	/* fabs [frb,]frd; fmr. frb,frd */		r = p->from.reg;		if(oclass(p->from) == C_NONE)			r = p->to.reg;		o1 = AOP_RRR(oprrr(p->as), p->to.reg, 0, r);		break;	case 34:	/* FMADDx fra,frb,frc,frd (d=a*b+c) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -