Пример #1
0
Файл: gen.c Проект: irori/8cc
static void emit_switch(Node *node) {
    SAVE;
    char *oswitch = lswitch, *obreak = lbreak;
    emit_expr(node->switchexpr);
    lswitch = make_label();
    lbreak = make_label();
    emit_jmp(lswitch);
    if (node->switchbody)
        emit_expr(node->switchbody);
    emit_label(lswitch);
    emit_label(lbreak);
    lswitch = oswitch;
    lbreak = obreak;
}
Пример #2
0
Файл: gen.c Проект: irori/8cc
static void emit_do(Node *node) {
    SAVE;
    char *begin = make_label();
    char *end = make_label();
    SET_JUMP_LABELS(end, begin);
    emit_label(begin);
    if (node->forbody)
        emit_expr(node->forbody);
    emit_expr(node->forcond);
    emit_je(end);
    emit_jmp(begin);
    emit_label(end);
    RESTORE_JUMP_LABELS();
}
Пример #3
0
Файл: gen.c Проект: irori/8cc
static void emit_ternary(Node *node) {
    SAVE;
    emit_expr(node->cond);
    char *ne = make_label();
    emit_je(ne);
    if (node->then)
        emit_expr(node->then);
    if (node->els) {
        char *end = make_label();
        emit_jmp(end);
        emit_label(ne);
        emit_expr(node->els);
        emit_label(end);
    } else {
        emit_label(ne);
    }
}
Пример #4
0
Файл: gen.c Проект: 4ker/8cc
static void emit_builtin_return_address(Node *node) {
    push("r11");
    assert(vec_len(node->args) == 1);
    emit_expr(vec_head(node->args));
    char *loop = make_label();
    char *end = make_label();
    emit("mov #rbp, #r11");
    emit_label(loop);
    emit("test #rax, #rax");
    emit("jz %s", end);
    emit("mov (#r11), #r11");
    emit("sub $1, #rax");
    emit_jmp(loop);
    emit_label(end);
    emit("mov 8(#r11), #rax");
    pop("r11");
}
Пример #5
0
Файл: gen.c Проект: irori/8cc
static void emit_case(Node *node) {
    SAVE;
    if (!lswitch)
        error("stray case label");
    char *skip = make_label();
    emit_jmp(skip);
    emit_label(lswitch);
    lswitch = make_label();
    emit("cmp $%d, %%eax", node->casebeg);
    if (node->casebeg == node->caseend) {
        emit("jne %s", lswitch);
    } else {
        emit("jl %s", lswitch);
        emit("cmp $%d, %%eax", node->caseend);
        emit("jg %s", lswitch);
    }
    emit_label(skip);
}
Пример #6
0
Файл: gen.c Проект: irori/8cc
static void emit_for(Node *node) {
    SAVE;
    if (node->forinit)
        emit_expr(node->forinit);
    char *begin = make_label();
    char *step = make_label();
    char *end = make_label();
    SET_JUMP_LABELS(end, step);
    emit_label(begin);
    if (node->forcond) {
        emit_expr(node->forcond);
        emit_je(end);
    }
    if (node->forbody)
        emit_expr(node->forbody);
    emit_label(step);
    if (node->forstep)
        emit_expr(node->forstep);
    emit_jmp(begin);
    emit_label(end);
    RESTORE_JUMP_LABELS();
}
Пример #7
0
Файл: gen.c Проект: irori/8cc
static void emit_continue(Node *node) {
    SAVE;
    if (!lcontinue)
        error("stray continue statement");
    emit_jmp(lcontinue);
}
Пример #8
0
Файл: gen.c Проект: irori/8cc
static void emit_break(Node *node) {
    SAVE;
    if (!lbreak)
        error("stray break statement");
    emit_jmp(lbreak);
}
Пример #9
0
Файл: gen.c Проект: irori/8cc
static void emit_goto(Node *node) {
    SAVE;
    assert(node->newlabel);
    emit_jmp(node->newlabel);
}
Пример #10
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;
}