Exemple #1
0
void emit_op_base_offset(generic_op op, short base_reg, int offset, short use_reg)
{
	switch (op)
	{
	case CLEAR:
		code_buf[code_idx++] = I386_INS_MOV_Ev_Iv;
		emit_base_offset(0, base_reg, offset);
		*((int4 *)&code_buf[code_idx]) = 0;
		code_idx += SIZEOF(int4);
		break;
	case COMPARE:
		code_buf[code_idx++] = I386_INS_CMP_Gv_Ev;
		emit_base_offset(use_reg, base_reg, offset);
		break;
	case INCREMENT:
		code_buf[code_idx++] = I386_INS_Grp5_Prefix;
		emit_base_offset(I386_INS_INC_Ev, base_reg, offset);
		break;
	case LOAD:
		code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
		emit_base_offset(use_reg, base_reg, offset);
		break;
	case LOAD_ADDRESS:
		code_buf[code_idx++] = I386_INS_LEA_Gv_M;
		emit_base_offset(use_reg, base_reg, offset);
		break;
	case PUSH:
		code_buf[code_idx++] = I386_INS_Grp5_Prefix;
		emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset);
		break;
	case PUSH_ADDRESS:
		code_buf[code_idx++] = I386_INS_LEA_Gv_M;
		emit_base_offset(use_reg, base_reg, offset);
		code_buf[code_idx++] = I386_INS_PUSH_eAX + use_reg;
		break;
	case STORE:
		code_buf[code_idx++] = I386_INS_MOV_Ev_Gv;
		emit_base_offset(use_reg, base_reg, offset);
		break;
	case TEST:
		code_buf[code_idx++] = I386_INS_Grp1_Ev_Ib_Prefix;
		emit_base_offset(I386_INS_CMP__, base_reg, offset);
		code_buf[code_idx++] = 0;
		break;
	default:
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
		break;
	}
}
Exemple #2
0
zb_code  *find_line_call(void *addr)
{
	unsigned char temp_char, *call_addr;
	modrm_byte_type modrm_byte, temp_modrm_byte;

	call_addr = (unsigned char *)addr;
	modrm_byte.byte = *(call_addr + 1);
	if (I386_INS_Grp5_Prefix == *call_addr  &&  I386_INS_CALL_Ev == modrm_byte.modrm.reg_opcode)
	{
		call_addr++;
		assert (I386_REG_EBX == modrm_byte.modrm.r_m);
		call_addr++;
		if (I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod)
		{
			if (*((int4 *)call_addr) == xf_linestart * SIZEOF(INTPTR_T) ||
				*((int4 *)call_addr) == xf_zbstart * SIZEOF(INTPTR_T))
				return (zb_code *)call_addr;

			if (*((int4 *)call_addr) != xf_isformal * SIZEOF(INTPTR_T))
				return (zb_code *)addr;

			call_addr += SIZEOF(int4);
		} else if (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod)
		{
			if (*((char *)call_addr) == xf_linestart * SIZEOF(INTPTR_T) ||
				*((char *)call_addr) == xf_zbstart * SIZEOF(INTPTR_T))
				return (zb_code *)call_addr;

			/* XF_ISFORMAL cannot be encoded in a one-byte offset, no point checking for it */

			call_addr += 1;
		}
	}

	emit_base_offset(I386_REG_SP,0x12);
	emit_base_info.modrm_byte.modrm.reg_opcode = I386_REG_RAX ;

	inst_size = 0 ;
	if (MOV_INTO_ARGREG(call_addr+1,I386_INS_MOV_eAX) || MOV_INTO_STACK(call_addr+1,I386_INS_MOV_Ev_Gv) )
	{
		modrm_byte.byte = *(call_addr + 2);

		while (MOV_INTO_ARGREG(call_addr+1,I386_INS_MOV_eAX) || MOV_INTO_STACK(call_addr+1,I386_INS_MOV_Ev_Gv))
		{
			assert((8 == inst_size) || (5 == inst_size) || (6 == inst_size)) ;
			call_addr +=  inst_size ;
			inst_size = 0 ;
		}

		modrm_byte.byte = *(call_addr + 1);
		if (*call_addr++ != I386_INS_Grp5_Prefix  ||  modrm_byte.modrm.reg_opcode != I386_INS_CALL_Ev)
			return (zb_code *)addr;

		assert (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod  ||  I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod);
		assert (I386_REG_RBX == modrm_byte.modrm.r_m);
		call_addr++;
		if (I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod)
		{
			if (*(int4 *)call_addr != xf_linefetch * SIZEOF(INTPTR_T) &&
				*(int4 *)call_addr != xf_zbfetch * SIZEOF(INTPTR_T))
				return (zb_code *)addr;
		} else if (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod)
		{
			if (*(char *)call_addr != xf_linefetch * SIZEOF(INTPTR_T) &&
				*(char *)call_addr != xf_zbfetch * SIZEOF(INTPTR_T))
				return (zb_code *)addr;
		}
	}
	else if (*call_addr == I386_INS_Grp5_Prefix  &&  modrm_byte.modrm.reg_opcode == I386_INS_CALL_Ev)
	{
		modrm_byte.byte = *(call_addr + 1);
		call_addr++;
		assert (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod  ||  I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod);
		assert (I386_REG_EBX == modrm_byte.modrm.r_m);
		call_addr++;
		if (I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod)
		{
			if (*(int4 *)call_addr != xf_linestart * SIZEOF(INTPTR_T) &&
				*(int4 *)call_addr != xf_zbstart * SIZEOF(INTPTR_T))
				return (zb_code *)addr;
		} else if (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod)
		{
			if (*(char *)call_addr != xf_linestart * SIZEOF(INTPTR_T) &&
				*(char *)call_addr != xf_zbstart * SIZEOF(INTPTR_T))
				return (zb_code *)addr;
		}
	}
	return (zb_code *)call_addr;
}
Exemple #3
0
void emit_trip(generic_op op, oprtype *opr, bool val_output, unsigned char use_reg)
{
	unsigned char		base_reg, temp_reg;
	int4			offset, literal;
	triple			*ct;

	if (opr->oprclass == TRIP_REF)
	{
		ct = opr->oprval.tref;
		if (ct->destination.oprclass)
		{
			opr = &ct->destination;
		}
		/* else lit or error */
	}

	switch (cg_phase)
	{
	case CGP_ADDR_OPT:
	case CGP_APPROX_ADDR:
		switch (opr->oprclass)
		{
		case TRIP_REF:
			assert(ct->destination.oprclass == 0);
			assert(val_output);
			switch (ct->opcode)
			{
			case OC_LIT:
				if (run_time)
				{
					int4	pc_value_idx;

					switch (op)
					{
					case LOAD_ADDRESS:
						temp_reg = use_reg;
						break;
					case PUSH:
					case PUSH_ADDRESS:
						temp_reg = I386_REG_ECX;
						break;
					default:
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
						break;
					}
					pc_value_idx = code_idx + 5;
					code_idx += 1 + SIZEOF(int4) + 1;
					emit_addr(0, (int4)ct->operand[0].oprval.mlit->rt_addr, &offset);
					offset -= pc_value_idx;
					force_32 = 1;
					emit_op_base_offset(op, temp_reg, offset, temp_reg);
					force_32 = 0;
				}
				else
				{
					emit_op_alit(op, use_reg);
					code_idx += SIZEOF(int4);
				}
				if (cg_phase == CGP_APPROX_ADDR)
					txtrel_cnt++;
				break;
			case OC_CDLIT:
				if (cg_phase == CGP_APPROX_ADDR)
					define_symbol(GTM_LITERALS, ct->operand[0].oprval.cdlt, 0);
				emit_op_alit(op, use_reg);
				code_idx += SIZEOF(int4);
				break;
			case OC_ILIT:
				literal = ct->operand[0].oprval.ilit;
				switch(op)
				{
				case COMPARE: /* 1byte(opcode) + 1byte(ModR/M) + 4byte(literal) */
					code_idx += 2 + SIZEOF(int4);
					break;
				case LOAD:
					code_idx += 1 + SIZEOF(int4);
					break;
				case PUSH:
					if (literal >= -128  &&  literal <= 127)
						code_idx += 2;
					else
						code_idx += 1 + SIZEOF(int4);
					break;
				default:
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
					break;
				}
				break;
			default:
				assertpro(FALSE && ct->opcode);
				break;
			}
			break;
		case TINT_REF:
		case TVAL_REF:
			assert(val_output);
			offset = sa_temps_offset[opr->oprclass];
			offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass];
			assertpro((0 <= offset) && (65535 >= offset));
			emit_op_base_offset(op, I386_REG_EDI, offset, use_reg);
			break;
		case TCAD_REF:
		case TVAD_REF:
		case TVAR_REF:
			offset = sa_temps_offset[opr->oprclass];
			offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass];
			assertpro((0 <= offset) && (65535 >= offset));
			if (opr->oprclass == TVAR_REF)
				base_reg = I386_REG_ESI;
			else
				base_reg = I386_REG_EDI;
			switch (op)
			{
			case JUMP:
				if (val_output)
				{
					code_idx++;
					emit_base_offset(I386_REG_EAX, base_reg, offset);
				}
				code_idx++;
				if (val_output)
					emit_base_offset(I386_INS_JMP_Ev, I386_REG_EAX, 0);
				else
					emit_base_offset(I386_INS_JMP_Ev, base_reg, offset);
				break;
			case LOAD_ADDRESS:
				code_idx++;
				emit_base_offset(use_reg, base_reg, offset);
				if (opr->oprclass == TVAR_REF)
				{
					code_idx++;
					emit_base_offset(use_reg, use_reg, offsetof(ht_ent_mname, value));
				}
				break;
			case PUSH:
				if (!val_output)
				{
					code_idx++;
					emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset);
				}
				else
				{
					code_idx++;
					emit_base_offset(I386_REG_ECX, base_reg, offset);

					code_idx++;
					emit_base_offset(I386_INS_PUSH_Ev, I386_REG_ECX, 0);
				}
				break;
			case PUSH_ADDRESS:
				if (val_output)
				{
					if (opr->oprclass == TVAR_REF)
					{
						code_idx++;
						emit_base_offset(use_reg, base_reg, offset);
						code_idx++;
						emit_base_offset(I386_INS_PUSH_Ev, use_reg, offsetof(ht_ent_mname, value));
					}
					else
					{
						code_idx++;
						emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset);
					}
				}
				else
				{
					code_idx++;
					emit_base_offset(I386_REG_ECX, base_reg, offset);
					code_idx++;
				}
				break;
			case STORE:
				if (val_output)
				{
					if (use_reg == I386_REG_EAX)
						temp_reg = I386_REG_EDX;
					else
						temp_reg = I386_REG_EAX;
					code_idx++;
					emit_base_offset(temp_reg, base_reg, offset);
				}
				code_idx++;
				if (val_output)
					emit_base_offset(use_reg, temp_reg, 0);
				else
					emit_base_offset(use_reg, base_reg, offset);
				break;
			default:
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
				break;
			}
			break;
		}
		break;
	case CGP_MACHINE:
		switch (opr->oprclass)
		{
		case TRIP_REF:
			assert(ct->destination.oprclass == 0);
			assert(val_output);
			switch (ct->opcode)
			{
			case OC_LIT:
				assert(ct->operand[0].oprclass == MLIT_REF);
				if (run_time)
				{
					int4	pc_value_idx;

					switch(op)
					{
					case LOAD_ADDRESS:
						temp_reg = use_reg;
						break;
					case PUSH:
					case PUSH_ADDRESS:
						temp_reg = I386_REG_ECX;
						break;
					default:
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
						break;
					}
					code_buf[code_idx++] = I386_INS_CALL_Jv;
					*((int4 *)&code_buf[code_idx]) = 0;
					code_idx += SIZEOF(int4);

					pc_value_idx = code_idx;
					code_buf[code_idx++] = I386_INS_POP_eAX + temp_reg;

					emit_addr(0, (int4)ct->operand[0].oprval.mlit->rt_addr, &offset);
					offset -= pc_value_idx;
					force_32 = 1;
					emit_op_base_offset(op, temp_reg, offset, temp_reg);
					force_32 = 0;
				}
				else
				{
					emit_op_alit(op, use_reg);
					emit_addr(code_reference + (code_idx * SIZEOF(unsigned char)),
						(int4)ct->operand[0].oprval.mlit->rt_addr, (int4 *)&code_buf[code_idx]);
					code_idx += SIZEOF(int4);
				}
				break;
			case OC_CDLIT:
				emit_op_alit(op, use_reg);
				emit_reference(code_reference + (code_idx * SIZEOF(unsigned char)),
					ct->operand[0].oprval.cdlt, (uint4 *)&code_buf[code_idx]);
				code_idx += SIZEOF(int4);
				break;
			case OC_ILIT:
				literal = ct->operand[0].oprval.ilit;
				switch (op)
				{
				case COMPARE: /* cmpl $literal,use_reg - 1byte(opcode) + 1byte(ModR/M) + 4byte(literal) */
					code_buf[code_idx++] = I386_INS_Grp1_Ev_Iv_Prefix;
					modrm_byte.modrm.reg_opcode = I386_INS_CMP__;
					modrm_byte.modrm.mod = I386_MOD32_REGISTER;
					modrm_byte.modrm.r_m = use_reg;
					code_buf[code_idx++] = modrm_byte.byte;
					*((int4 *)&code_buf[code_idx]) = literal;
					code_idx += SIZEOF(int4);
					break;
				case LOAD:
					code_buf[code_idx++] = I386_INS_MOV_eAX + use_reg;
					*((int4 *)&code_buf[code_idx]) = literal;
					code_idx += SIZEOF(int4);
					break;
				case PUSH:
					if (literal >= -128  &&  literal <= 127)
					{
						code_buf[code_idx++] = I386_INS_PUSH_Ib;
						code_buf[code_idx++] = literal & 0xff;
					}
					else
					{
						code_buf[code_idx++] = I386_INS_PUSH_Iv;
						*((int4 *)&code_buf[code_idx]) = literal;
						code_idx += SIZEOF(int4);
					}
					break;
				default:
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
					break;
				}
				break;
			default:
				assertpro(FALSE && ct->opcode);
				break;
			}
			break;
		case TINT_REF:
		case TVAL_REF:
			assert(val_output);
			offset = sa_temps_offset[opr->oprclass];
			offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass];
			assertpro((0 <= offset) && (65535 >= offset));
			emit_op_base_offset(op, I386_REG_EDI, offset, use_reg);
			break;
		case TCAD_REF:
		case TVAD_REF:
		case TVAR_REF:
			offset = sa_temps_offset[opr->oprclass];
			offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass];
			assertpro((0 <= offset) && (65535 >= offset));
			if (opr->oprclass == TVAR_REF)
				base_reg = I386_REG_ESI;
			else
				base_reg = I386_REG_EDI;

			switch (op)
			{
			case JUMP:
				assert(use_reg == 0);
				if (val_output)
				{
					code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
					emit_base_offset(I386_REG_EAX, base_reg, offset);
				}
				code_buf[code_idx++] = I386_INS_Grp5_Prefix;
				if (val_output)
					emit_base_offset(I386_INS_JMP_Ev, I386_REG_EAX, 0);
				else
					emit_base_offset(I386_INS_JMP_Ev, base_reg, offset);
				break;
			case LOAD_ADDRESS:
				if (val_output)
					code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
				else
					code_buf[code_idx++] = I386_INS_LEA_Gv_M;
				emit_base_offset(use_reg, base_reg, offset);
				if (opr->oprclass == TVAR_REF)
				{
					code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
					emit_base_offset(use_reg, use_reg, offsetof(ht_ent_mname, value));
				}
				break;
			case PUSH:
				if (val_output)
				{
					code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
					emit_base_offset(I386_REG_ECX, base_reg, offset);

					code_buf[code_idx++] = I386_INS_Grp5_Prefix;
					emit_base_offset(I386_INS_PUSH_Ev, I386_REG_ECX, 0);
				}
				else
				{
					code_buf[code_idx++] = I386_INS_Grp5_Prefix;
					emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset);
				}
				break;
			case PUSH_ADDRESS:
				if (val_output)
				{
					if (opr->oprclass == TVAR_REF)
					{
						code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
						emit_base_offset(use_reg, base_reg, offset);
						code_buf[code_idx++] = I386_INS_Grp5_Prefix;
						emit_base_offset(I386_INS_PUSH_Ev, use_reg, offsetof(ht_ent_mname, value));
					}
					else
					{
						code_buf[code_idx++] = I386_INS_Grp5_Prefix;
						emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset);
					}
				}
				else
				{
					code_buf[code_idx++] = I386_INS_LEA_Gv_M;
					emit_base_offset(I386_REG_ECX, base_reg, offset);

					code_buf[code_idx++] = I386_INS_PUSH_eCX;
				}
				break;
			case STORE:
				if (val_output)
				{
					if (use_reg == I386_REG_EAX)
						temp_reg = I386_REG_EDX;
					else
						temp_reg = I386_REG_EAX;
					assert(temp_reg != use_reg);
					code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
					emit_base_offset(temp_reg, base_reg, offset);
				}
				code_buf[code_idx++] = I386_INS_MOV_Ev_Gv;
				if (val_output)
					emit_base_offset(use_reg, temp_reg, 0);
				else
					emit_base_offset(use_reg, base_reg, offset);
				break;
			default:
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
				break;
			}
			break;
		default:
			assertpro(FALSE && opr->oprclass);
			break;
		}
		break;
	default:
		assertpro(FALSE && cg_phase);
		break;
	}
}
Exemple #4
0
short *emit_vax_inst(short *inst, oprtype **fst_opr, oprtype **lst_opr)
     /* fst_opr and lst_opr are triple operands */
{
	short	sav_in;
	bool	oc_int;
	int4	cnt;
	oprtype *opr;
	triple	*ct;

	code_idx = 0;
	force_32 = 0;

	switch  (cg_phase)
	{
	case CGP_ADDR_OPT:
	case CGP_APPROX_ADDR:
	case CGP_MACHINE:
		switch ((sav_in = *inst++))
		{
			case VXI_BEQL:
			case VXI_BGEQ:
			case VXI_BGTR:
			case VXI_BLEQ:
			case VXI_BLSS:
			case VXI_BNEQ:
			case VXI_BRB:
			case VXI_BRW:
				emit_jmp(sav_in, &inst);
				break;
			case VXI_BLBC:
			case VXI_BLBS:
				assert(VXT_REG == *inst);
				inst++;
				inst++;
				emit_xfer(4*xf_dt_get);
				code_buf[code_idx++] = I386_INS_CMP_eAX_Iv;
				*((int4 *)&code_buf[code_idx]) = 0;
				code_idx += SIZEOF(int4);
				if (sav_in == VXI_BLBC)
					emit_jmp(VXI_BEQL, &inst);
				else
				{
					assert(sav_in == VXI_BLBS);
					emit_jmp(VXI_BNEQ, &inst);
				}
				break;
			case VXI_BICB2:
			case VXI_BISB2:
				assert(VXT_LIT == *inst);
				inst++;
				assert(1 == *inst);
				inst++;
				assert(VXT_REG == *inst);
				inst++;
				inst++;
				if (sav_in == VXI_BICB2)
					emit_xfer(4*xf_dt_false);
				else
				{
					assert(sav_in == VXI_BISB2);
					emit_xfer(4*xf_dt_true);
				}
				break;
			case VXI_CALLS:
				oc_int = TRUE;
				if (VXT_LIT == *inst)
				{
					inst++;
					cnt = (int4) *inst++;
				} else
				{
					assert(VXT_VAL == *inst);
					inst++;
					opr = *(fst_opr + *inst);
					assert(opr->oprclass == TRIP_REF);
					ct = opr->oprval.tref;
					if (ct->destination.oprclass)
					{
						opr = &ct->destination;
					}
					if (opr->oprclass == TRIP_REF)
					{
						assert(ct->opcode == OC_ILIT);
						cnt = ct->operand[0].oprval.ilit;
						if (cnt >= -128  &&  cnt <= 127)
						{
							code_buf[code_idx++] = I386_INS_PUSH_Ib;
							code_buf[code_idx++] = cnt & 0xff;
						}
						else
						{
							code_buf[code_idx++] = I386_INS_PUSH_Iv;
							*((int4 *)&code_buf[code_idx]) = cnt;
							code_idx += SIZEOF(int4);
						}
						cnt++;
						inst++;
					}
					else
					{
						assert(opr->oprclass == TINT_REF);
						oc_int = FALSE;
						opr = *(fst_opr + *inst++);
						emit_trip(PUSH, opr, TRUE, 0);
					}
				}
				assert(VXT_XFER == *inst);
				inst++;
				emit_xfer(*inst++);
				if (oc_int)
				{
					if (cnt)
					{
						code_buf[code_idx++] = I386_INS_LEA_Gv_M;
						emit_base_offset(I386_REG_ESP, I386_REG_ESP, 4*cnt);
					}
				}
				else
				{
					emit_trip(LOAD, opr, TRUE, I386_REG_EDX);

					code_buf[code_idx++] = I386_INS_LEA_Gv_M;
					emit_base_offset(I386_REG_ESP, I386_REG_ESP, 4);
				}
				break;
			case VXI_CLRL:
				assert(VXT_VAL == *inst);
				inst++;
				emit_trip(CLEAR, *(fst_opr + *inst++), TRUE, 0);
				break;
			case VXI_CMPL:
				assert(VXT_VAL == *inst);
				inst++;
				emit_trip(LOAD, *(fst_opr + *inst++), TRUE, I386_REG_EDX);
				assert(VXT_VAL == *inst);
				inst++;
				emit_trip(COMPARE, *(fst_opr + *inst++), TRUE, I386_REG_EDX);
				break;
			case VXI_INCL:
				assert(VXT_VAL == *inst);
				inst++;
				emit_trip(INCREMENT, *(fst_opr + *inst++), TRUE, 0);
				break;
			case VXI_JMP:
				if (VXT_VAL == *inst)
				{
					inst++;
					emit_trip(JUMP, *(fst_opr + *inst++), FALSE, 0);
				}
				else
				{
					emit_jmp(sav_in, &inst);
				}
				break;
			case VXI_JSB:
				assert(VXT_XFER == *inst);
				inst++;
				emit_xfer(*inst++);
				break;
			case VXI_MOVAB:
				if (VXT_JMP == *inst)
				{
					inst += 2;
					emit_pcrel(LOAD_ADDRESS, I386_REG_EAX);
					assert(VXT_ADDR == *inst);
					inst++;
					emit_trip(STORE, *(fst_opr + *inst++), FALSE, I386_REG_EAX);
				} else if ((VXT_ADDR == *inst) || (VXT_VAL == *inst))
				{
					bool	addr;
					unsigned char reg;
					short	save_inst;

					addr = (VXT_VAL == *inst);
					inst++;
					save_inst = *inst++;
					assert(VXT_REG == *inst);
					inst++;
					reg = ((*inst++ & 0x01) ? I386_REG_EDX : I386_REG_EAX); /* r0 and r1 are only ones used */
					emit_trip(LOAD_ADDRESS, *(fst_opr + save_inst), addr, reg);
				} else
					assertpro(FALSE && *inst);
				break;
			case VXI_MOVC3:
				assert(VXT_LIT == *inst);
				inst += 2;
				assert(VXT_VAL == *inst);
				inst++;
				code_buf[code_idx++] = I386_INS_PUSH_eSI;
				code_buf[code_idx++] = I386_INS_PUSH_eDI;

				emit_trip(LOAD_ADDRESS, *(fst_opr + *inst++), TRUE, I386_REG_ECX);

				assert(VXT_VAL == *inst);
				inst++;
				emit_trip(LOAD_ADDRESS, *(fst_opr + *inst++), TRUE, I386_REG_EDI);

				code_buf[code_idx++] = I386_INS_MOV_Gv_Ev;
				modrm_byte.modrm.reg_opcode = I386_REG_ESI;
				modrm_byte.modrm.mod = I386_MOD32_REGISTER;
				modrm_byte.modrm.r_m = I386_REG_ECX;
				code_buf[code_idx++] = modrm_byte.byte;

				code_buf[code_idx++] = I386_INS_MOV_eCX;
				*((int4 *)&code_buf[code_idx]) = (int4)SIZEOF(mval);
				code_idx += SIZEOF(int4);

				code_buf[code_idx++] = I386_INS_REP_E_Prefix;
				code_buf[code_idx++] = I386_INS_MOVSB_Xb_Yb;

				code_buf[code_idx++] = I386_INS_POP_eDI;
				code_buf[code_idx++] = I386_INS_POP_eSI;
				break;
			case VXI_MOVL:
				if (VXT_REG == *inst)
				{
					inst++;
					if (*inst > 0x5f)	/* OC_CURRHD */  /* any mode >= 6 (deferred), any register */
					{
						inst++;
						assert(VXT_ADDR == *inst);
						inst++;

						emit_xfer(4*xf_get_msf);
						emit_op_base_offset(LOAD, I386_REG_EAX, 0, I386_REG_EAX);
						emit_trip(STORE, *(fst_opr + *inst++), FALSE, I386_REG_EAX);
					} else
					{
						bool addr;

						assert(0x50 == *inst);  /* register mode: R0 */
						inst++;
						if ((VXT_VAL == *inst) || (VXT_ADDR == *inst))
						{
							addr = (VXT_VAL == *inst);
							inst++;
							emit_trip(STORE, *(fst_opr + *inst++), addr, I386_REG_EAX);
						}
						else if (VXT_REG == *inst)
						{
							unsigned char	reg;

							inst++;
							if ((*inst & 0x0f) == 10)	/* VAX $TEST */
							{
								code_buf[code_idx++] = I386_INS_PUSH_eAX;
								emit_xfer(4*xf_dt_store);
								code_buf[code_idx++] = I386_INS_POP_eAX;
							}
							else
							{
								code_buf[code_idx++] = I386_INS_MOV_Ev_Gv;
								modrm_byte.modrm.reg_opcode = I386_REG_EAX;
								modrm_byte.modrm.mod = I386_MOD32_REGISTER;
								modrm_byte.modrm.r_m = i386_reg(*inst);
								code_buf[code_idx++] = modrm_byte.byte;
							}
							inst++;
						} else
							assertpro(FALSE && *inst);
					}
				} else if (VXT_VAL == *inst)
				{
					inst++;
					emit_trip(LOAD, *(fst_opr + *inst++), TRUE, I386_REG_EDX);
					assert(VXT_REG == *inst);
					inst++;
					assert(0x51 == *inst);  /* register mode: R1 */
					inst++;
				} else
					assertpro(FALSE && *inst);
				break;
			case VXT_IREPAB:
				assert(VXT_VAL == *inst);
				inst += 2;
				emit_trip(PUSH_ADDRESS, *lst_opr, TRUE, 0);
				break;
			case VXI_PUSHAB:
				if (VXT_JMP == *inst)
				{
					inst += 2;
					emit_pcrel(PUSH_ADDRESS, 0);
				} else if (VXT_VAL == *inst)
				{
					inst++;
					emit_trip(PUSH_ADDRESS, *(fst_opr + *inst++), TRUE, 0);
				} else
					assertpro(FALSE && *inst);
				break;
			case VXT_IREPL:
				assert(VXT_VAL == *inst);
				inst += 2;
				emit_trip(PUSH, *lst_opr, TRUE, 0);
				break;
			case VXI_PUSHL:
				if (VXT_LIT == *inst)
				{
					int4	lit;

					inst++;
					lit = *inst++;
					if (lit >= -128  &&  lit <= 127)
					{
						code_buf[code_idx++] = I386_INS_PUSH_Ib;
						code_buf[code_idx++] = lit & 0xff;
					}
					else
					{
						code_buf[code_idx++] = I386_INS_PUSH_Iv;
						*((int4 *)&code_buf[code_idx]) = lit;
						code_idx += SIZEOF(int4);
					}
				} else if (VXT_ADDR == *inst)
				{
					inst++;
					emit_trip(PUSH, *(fst_opr + *inst++), FALSE, 0);
				} else if (VXT_VAL == *inst)
				{
					inst++;
					emit_trip(PUSH, *(fst_opr + *inst++), TRUE, 0);
				} else
					assertpro(FALSE && *inst);
				break;
			case VXI_TSTL:
				if (VXT_VAL == *inst)
				{
				  inst++;
				  emit_trip(TEST, *(fst_opr + *inst++), TRUE, 0);
				}
				else if (VXT_REG == *inst)
				{
				    inst++;
				    code_buf[code_idx++] = I386_INS_CMP_eAX_Iv;
				    assert(I386_REG_EAX == i386_reg(*inst));	/* VAX R0 */
				    inst++;
				    *((int4 *)&code_buf[code_idx]) = 0;	/* 32 bit immediate 0 */
				    code_idx += SIZEOF(int4);
				} else
					assertpro(FALSE && *inst);
				break;
			default:
				assertpro(FALSE && sav_in);
		}
		break;
	default:
		assertpro(FALSE && cg_phase);
		break;
	}
	assert(code_idx < BUFFERED_CODE_SIZE);
	if (cg_phase == CGP_MACHINE)
	{
         	generated_code_size += code_idx;
		emit_immed ((char *)&code_buf[0], SIZEOF(unsigned char) * code_idx);
	} else if (cg_phase != CGP_ASSEMBLY)
	{
	        if (cg_phase == CGP_APPROX_ADDR)
		{
		      calculated_code_size += code_idx;
		}
		curr_addr += SIZEOF(unsigned char) * code_idx;
	}
	code_reference += SIZEOF(unsigned char) * code_idx;
	jmp_offset -= SIZEOF(unsigned char) * code_idx;
	return inst;
}
Exemple #5
0
/*  Changes here, emit_base_offset, or emit_jmp may require changes in trip_gen case for
	OC_CALL[SP] and FORLCLDO
*/
void emit_xfer(short xfer)
{

	code_buf[code_idx++] = I386_INS_Grp5_Prefix;
	emit_base_offset(I386_INS_CALL_Ev, I386_REG_EBX, (int4)xfer);
}