Fix some errors on arm64-asm.c, rename some variables, fix several code style declarations
This commit is contained in:
parent
af686a796b
commit
61537d899a
18 changed files with 2851 additions and 2852 deletions
238
arm-asm.c
238
arm-asm.c
|
@ -24,9 +24,9 @@
|
|||
#define CONFIG_TCC_ASM
|
||||
#define NB_ASM_REGS 16
|
||||
|
||||
ST_FUNC void g(TCCState* S, int c);
|
||||
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||
ST_FUNC void g(TCCState *S, int c);
|
||||
ST_FUNC void gen_le16(TCCState *S, int c);
|
||||
ST_FUNC void gen_le32(TCCState *S, int c);
|
||||
|
||||
/*************************************************************/
|
||||
#else
|
||||
|
@ -100,10 +100,10 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
|
||||
op->type = 0;
|
||||
|
||||
if (S->tccpp_tok == '{') { // regset literal
|
||||
if (S->tok == '{') { // regset literal
|
||||
next(S); // skip '{'
|
||||
while (S->tccpp_tok != '}' && S->tccpp_tok != TOK_EOF) {
|
||||
reg = asm_parse_regvar(S, S->tccpp_tok);
|
||||
while (S->tok != '}' && S->tok != TOK_EOF) {
|
||||
reg = asm_parse_regvar(S, S->tok);
|
||||
if (reg == -1) {
|
||||
expect(S, "register");
|
||||
return;
|
||||
|
@ -113,11 +113,11 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
if ((1 << reg) < regset)
|
||||
tcc_warning(S, "registers will be processed in ascending order by hardware--but are not specified in ascending order here");
|
||||
regset |= 1 << reg;
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
break;
|
||||
next(S); // skip ','
|
||||
}
|
||||
if (S->tccpp_tok != '}')
|
||||
if (S->tok != '}')
|
||||
expect(S, "'}'");
|
||||
next(S); // skip '}'
|
||||
if (regset == 0) {
|
||||
|
@ -128,22 +128,22 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
op->regset = regset;
|
||||
}
|
||||
return;
|
||||
} else if ((reg = asm_parse_regvar(S, S->tccpp_tok)) != -1) {
|
||||
} else if ((reg = asm_parse_regvar(S, S->tok)) != -1) {
|
||||
next(S); // skip register name
|
||||
op->type = OP_REG32;
|
||||
op->reg = (uint8_t) reg;
|
||||
return;
|
||||
} else if ((reg = asm_parse_vfp_regvar(S->tccpp_tok, 0)) != -1) {
|
||||
} else if ((reg = asm_parse_vfp_regvar(S->tok, 0)) != -1) {
|
||||
next(S); // skip register name
|
||||
op->type = OP_VREG32;
|
||||
op->reg = (uint8_t) reg;
|
||||
return;
|
||||
} else if ((reg = asm_parse_vfp_regvar(S->tccpp_tok, 1)) != -1) {
|
||||
} else if ((reg = asm_parse_vfp_regvar(S->tok, 1)) != -1) {
|
||||
next(S); // skip register name
|
||||
op->type = OP_VREG64;
|
||||
op->reg = (uint8_t) reg;
|
||||
return;
|
||||
} else if (S->tccpp_tok == '#' || S->tccpp_tok == '$') {
|
||||
} else if (S->tok == '#' || S->tok == '$') {
|
||||
/* constant value */
|
||||
next(S); // skip '#' or '$'
|
||||
}
|
||||
|
@ -160,44 +160,44 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
}
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(TCCState* S, int c)
|
||||
ST_FUNC void g(TCCState *S, int c)
|
||||
{
|
||||
int ind1;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
ind1 = S->tccgen_ind + 1;
|
||||
ind1 = S->ind + 1;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
cur_text_section->data[S->tccgen_ind] = c;
|
||||
S->tccgen_ind = ind1;
|
||||
cur_text_section->data[S->ind] = c;
|
||||
S->ind = ind1;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le16 (TCCState* S, int i)
|
||||
ST_FUNC void gen_le16 (TCCState *S, int i)
|
||||
{
|
||||
g(S, i);
|
||||
g(S, i>>8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32 (TCCState* S, int i)
|
||||
ST_FUNC void gen_le32 (TCCState *S, int i)
|
||||
{
|
||||
int ind1;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
ind1 = S->tccgen_ind + 4;
|
||||
ind1 = S->ind + 4;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
cur_text_section->data[S->tccgen_ind++] = i & 0xFF;
|
||||
cur_text_section->data[S->tccgen_ind++] = (i >> 8) & 0xFF;
|
||||
cur_text_section->data[S->tccgen_ind++] = (i >> 16) & 0xFF;
|
||||
cur_text_section->data[S->tccgen_ind++] = (i >> 24) & 0xFF;
|
||||
cur_text_section->data[S->ind++] = i & 0xFF;
|
||||
cur_text_section->data[S->ind++] = (i >> 8) & 0xFF;
|
||||
cur_text_section->data[S->ind++] = (i >> 16) & 0xFF;
|
||||
cur_text_section->data[S->ind++] = (i >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||
ST_FUNC void gen_expr32(TCCState *S, ExprValue *pe)
|
||||
{
|
||||
gen_le32(S, pe->v);
|
||||
}
|
||||
|
||||
static uint32_t condition_code_of_token(TCCState* S, int token) {
|
||||
static uint32_t condition_code_of_token(TCCState *S, int token) {
|
||||
if (token < TOK_ASM_nopeq) {
|
||||
expect(S, "condition-enabled instruction");
|
||||
return 0;
|
||||
|
@ -205,15 +205,15 @@ static uint32_t condition_code_of_token(TCCState* S, int token) {
|
|||
return (token - TOK_ASM_nopeq) & 15;
|
||||
}
|
||||
|
||||
static void asm_emit_opcode(TCCState* S, int token, uint32_t opcode) {
|
||||
static void asm_emit_opcode(TCCState *S, int token, uint32_t opcode) {
|
||||
gen_le32(S, (condition_code_of_token(S, token) << 28) | opcode);
|
||||
}
|
||||
|
||||
static void asm_emit_unconditional_opcode(TCCState* S, uint32_t opcode) {
|
||||
static void asm_emit_unconditional_opcode(TCCState *S, uint32_t opcode) {
|
||||
gen_le32(S, opcode);
|
||||
}
|
||||
|
||||
static void asm_emit_coprocessor_opcode(TCCState* S, uint32_t high_nibble, uint8_t cp_number, uint8_t cp_opcode, uint8_t cp_destination_register, uint8_t cp_n_operand_register, uint8_t cp_m_operand_register, uint8_t cp_opcode2, int inter_processor_transfer)
|
||||
static void asm_emit_coprocessor_opcode(TCCState *S, uint32_t high_nibble, uint8_t cp_number, uint8_t cp_opcode, uint8_t cp_destination_register, uint8_t cp_n_operand_register, uint8_t cp_m_operand_register, uint8_t cp_opcode2, int inter_processor_transfer)
|
||||
{
|
||||
uint32_t opcode = 0xe000000;
|
||||
if (inter_processor_transfer)
|
||||
|
@ -233,7 +233,7 @@ static void asm_emit_coprocessor_opcode(TCCState* S, uint32_t high_nibble, uint8
|
|||
asm_emit_unconditional_opcode(S, (high_nibble << 28) | opcode);
|
||||
}
|
||||
|
||||
static void asm_nullary_opcode(TCCState* S, int token)
|
||||
static void asm_nullary_opcode(TCCState *S, int token)
|
||||
{
|
||||
switch (ARM_INSTRUCTION_GROUP(token)) {
|
||||
case TOK_ASM_nopeq:
|
||||
|
@ -276,7 +276,7 @@ static void asm_binary_opcode(TCCState *S, int token)
|
|||
uint32_t encoded_rotation = 0;
|
||||
uint64_t amount;
|
||||
parse_operand(S, &ops[0]);
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -328,9 +328,9 @@ static void asm_binary_opcode(TCCState *S, int token)
|
|||
if (ops[1].reg == 13)
|
||||
tcc_warning(S, "Using 'sp' as operand with '%s' is deprecated by ARM", get_tok_str(S, token, NULL));
|
||||
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S); // skip ','
|
||||
if (S->tccpp_tok == TOK_ASM_ror) {
|
||||
if (S->tok == TOK_ASM_ror) {
|
||||
next(S); // skip 'ror'
|
||||
parse_operand(S, &rotation);
|
||||
if (rotation.type != OP_IM8) {
|
||||
|
@ -387,15 +387,15 @@ static void asm_coprocessor_opcode(TCCState *S, int token) {
|
|||
uint8_t high_nibble;
|
||||
uint8_t mrc = 0;
|
||||
|
||||
if (S->tccpp_tok >= TOK_ASM_p0 && S->tccpp_tok <= TOK_ASM_p15) {
|
||||
coprocessor = S->tccpp_tok - TOK_ASM_p0;
|
||||
if (S->tok >= TOK_ASM_p0 && S->tok <= TOK_ASM_p15) {
|
||||
coprocessor = S->tok - TOK_ASM_p0;
|
||||
next(S);
|
||||
} else {
|
||||
expect(S, "'p<number>'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -407,21 +407,21 @@ static void asm_coprocessor_opcode(TCCState *S, int token) {
|
|||
}
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
if (i == 0 && token != TOK_ASM_cdp2 && (ARM_INSTRUCTION_GROUP(token) == TOK_ASM_mrceq || ARM_INSTRUCTION_GROUP(token) == TOK_ASM_mcreq)) {
|
||||
if (S->tccpp_tok >= TOK_ASM_r0 && S->tccpp_tok <= TOK_ASM_r15) {
|
||||
registers[i] = S->tccpp_tok - TOK_ASM_r0;
|
||||
if (S->tok >= TOK_ASM_r0 && S->tok <= TOK_ASM_r15) {
|
||||
registers[i] = S->tok - TOK_ASM_r0;
|
||||
next(S);
|
||||
} else {
|
||||
expect(S, "'r<number>'");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (S->tccpp_tok >= TOK_ASM_c0 && S->tccpp_tok <= TOK_ASM_c15) {
|
||||
registers[i] = S->tccpp_tok - TOK_ASM_c0;
|
||||
if (S->tok >= TOK_ASM_c0 && S->tok <= TOK_ASM_c15) {
|
||||
registers[i] = S->tok - TOK_ASM_c0;
|
||||
next(S);
|
||||
} else {
|
||||
expect(S, "'c<number>'");
|
||||
|
@ -429,7 +429,7 @@ static void asm_coprocessor_opcode(TCCState *S, int token) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
parse_operand(S, &opcode2);
|
||||
} else {
|
||||
|
@ -493,11 +493,11 @@ static void asm_block_data_transfer_opcode(TCCState *S, int token)
|
|||
Operand ops[2];
|
||||
int nb_ops = 1;
|
||||
parse_operand(S, &ops[0]);
|
||||
if (S->tccpp_tok == '!') {
|
||||
if (S->tok == '!') {
|
||||
op0_exclam = 1;
|
||||
next(S); // skip '!'
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S); // skip comma
|
||||
parse_operand(S, &ops[1]);
|
||||
++nb_ops;
|
||||
|
@ -600,17 +600,17 @@ static void asm_block_data_transfer_opcode(TCCState *S, int token)
|
|||
|
||||
NB_SHIFT: will be set to 1 iff SHIFT is filled. Note that for rrx, there's no need to fill SHIFT.
|
||||
SHIFT: will be filled in with the shift operand to use, if any. */
|
||||
static uint32_t asm_parse_optional_shift(TCCState* S, int* nb_shift, Operand* shift)
|
||||
static uint32_t asm_parse_optional_shift(TCCState *S, int* nb_shift, Operand* shift)
|
||||
{
|
||||
uint32_t opcode = 0;
|
||||
*nb_shift = 0;
|
||||
switch (S->tccpp_tok) {
|
||||
switch (S->tok) {
|
||||
case TOK_ASM_asl:
|
||||
case TOK_ASM_lsl:
|
||||
case TOK_ASM_asr:
|
||||
case TOK_ASM_lsr:
|
||||
case TOK_ASM_ror:
|
||||
switch (S->tccpp_tok) {
|
||||
switch (S->tok) {
|
||||
case TOK_ASM_asl:
|
||||
/* fallthrough */
|
||||
case TOK_ASM_lsl:
|
||||
|
@ -677,15 +677,15 @@ static void asm_data_processing_opcode(TCCState *S, int token)
|
|||
uint32_t opcode_nos = opcode_idx >> 1; // without "s"; "OpCode" in ARM docs
|
||||
|
||||
for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ) {
|
||||
if (S->tccpp_tok == TOK_ASM_asl || S->tccpp_tok == TOK_ASM_lsl || S->tccpp_tok == TOK_ASM_lsr || S->tccpp_tok == TOK_ASM_asr || S->tccpp_tok == TOK_ASM_ror || S->tccpp_tok == TOK_ASM_rrx)
|
||||
if (S->tok == TOK_ASM_asl || S->tok == TOK_ASM_lsl || S->tok == TOK_ASM_lsr || S->tok == TOK_ASM_asr || S->tok == TOK_ASM_ror || S->tok == TOK_ASM_rrx)
|
||||
break;
|
||||
parse_operand(S, &ops[nb_ops]);
|
||||
++nb_ops;
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
break;
|
||||
next(S); // skip ','
|
||||
}
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
operands |= asm_parse_optional_shift(S, &nb_shift, &shift);
|
||||
if (nb_ops < 2)
|
||||
|
@ -852,7 +852,7 @@ static void asm_shift_opcode(TCCState *S, int token)
|
|||
|
||||
for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
|
||||
parse_operand(S, &ops[nb_ops]);
|
||||
if (S->tccpp_tok != ',') {
|
||||
if (S->tok != ',') {
|
||||
++nb_ops;
|
||||
break;
|
||||
}
|
||||
|
@ -961,7 +961,7 @@ static void asm_multiplication_opcode(TCCState *S, int token)
|
|||
|
||||
for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
|
||||
parse_operand(S, &ops[nb_ops]);
|
||||
if (S->tccpp_tok != ',') {
|
||||
if (S->tok != ',') {
|
||||
++nb_ops;
|
||||
break;
|
||||
}
|
||||
|
@ -1043,7 +1043,7 @@ static void asm_long_multiplication_opcode(TCCState *S, int token)
|
|||
|
||||
for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
|
||||
parse_operand(S, &ops[nb_ops]);
|
||||
if (S->tccpp_tok != ',') {
|
||||
if (S->tok != ',') {
|
||||
++nb_ops;
|
||||
break;
|
||||
}
|
||||
|
@ -1133,7 +1133,7 @@ static void asm_single_data_transfer_opcode(TCCState *S, int token)
|
|||
expect(S, "(destination operand) register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
expect(S, "at least two arguments");
|
||||
else
|
||||
next(S); // skip ','
|
||||
|
@ -1146,14 +1146,14 @@ static void asm_single_data_transfer_opcode(TCCState *S, int token)
|
|||
expect(S, "register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
expect(S, "at least three arguments");
|
||||
else
|
||||
next(S); // skip ','
|
||||
break;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok != '[')
|
||||
if (S->tok != '[')
|
||||
expect(S, "'['");
|
||||
else
|
||||
next(S); // skip '['
|
||||
|
@ -1165,14 +1165,14 @@ static void asm_single_data_transfer_opcode(TCCState *S, int token)
|
|||
expect(S, "(first source operand) register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ']') {
|
||||
if (S->tok == ']') {
|
||||
next(S);
|
||||
closed_bracket = 1;
|
||||
// exclam = 1; // implicit in hardware; don't do it in software
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S); // skip ','
|
||||
if (S->tccpp_tok == '-') {
|
||||
if (S->tok == '-') {
|
||||
op2_minus = 1;
|
||||
next(S);
|
||||
}
|
||||
|
@ -1182,7 +1182,7 @@ static void asm_single_data_transfer_opcode(TCCState *S, int token)
|
|||
tcc_error(S, "Using 'pc' for register offset in '%s' is not implemented by ARM", get_tok_str(S, token, NULL));
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
opcode |= asm_parse_optional_shift(S, &nb_shift, &shift);
|
||||
if (opcode == 0)
|
||||
|
@ -1196,12 +1196,12 @@ static void asm_single_data_transfer_opcode(TCCState *S, int token)
|
|||
opcode |= 1 << 24; // add offset before transfer
|
||||
}
|
||||
if (!closed_bracket) {
|
||||
if (S->tccpp_tok != ']')
|
||||
if (S->tok != ']')
|
||||
expect(S, "']'");
|
||||
else
|
||||
next(S); // skip ']'
|
||||
opcode |= 1 << 24; // add offset before transfer
|
||||
if (S->tccpp_tok == '!') {
|
||||
if (S->tok == '!') {
|
||||
exclam = 1;
|
||||
next(S); // skip '!'
|
||||
}
|
||||
|
@ -1389,33 +1389,33 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *S, int token)
|
|||
// Note: ldc p2, c0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+4
|
||||
// Note: ldc p3, c0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+4
|
||||
|
||||
if (S->tccpp_tok >= TOK_ASM_p0 && S->tccpp_tok <= TOK_ASM_p15) {
|
||||
coprocessor = S->tccpp_tok - TOK_ASM_p0;
|
||||
if (S->tok >= TOK_ASM_p0 && S->tok <= TOK_ASM_p15) {
|
||||
coprocessor = S->tok - TOK_ASM_p0;
|
||||
next(S);
|
||||
} else {
|
||||
expect(S, "'c<number>'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
||||
if (S->tccpp_tok >= TOK_ASM_c0 && S->tccpp_tok <= TOK_ASM_c15) {
|
||||
coprocessor_destination_register = S->tccpp_tok - TOK_ASM_c0;
|
||||
if (S->tok >= TOK_ASM_c0 && S->tok <= TOK_ASM_c15) {
|
||||
coprocessor_destination_register = S->tok - TOK_ASM_c0;
|
||||
next(S);
|
||||
} else {
|
||||
expect(S, "'c<number>'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
||||
if (S->tccpp_tok != '[')
|
||||
if (S->tok != '[')
|
||||
expect(S, "'['");
|
||||
else
|
||||
next(S); // skip '['
|
||||
|
@ -1425,14 +1425,14 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *S, int token)
|
|||
expect(S, "(first source operand) register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ']') {
|
||||
if (S->tok == ']') {
|
||||
next(S);
|
||||
closed_bracket = 1;
|
||||
// exclam = 1; // implicit in hardware; don't do it in software
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S); // skip ','
|
||||
if (S->tccpp_tok == '-') {
|
||||
if (S->tok == '-') {
|
||||
op2_minus = 1;
|
||||
next(S);
|
||||
}
|
||||
|
@ -1453,12 +1453,12 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *S, int token)
|
|||
preincrement = 1; // add offset before transfer
|
||||
}
|
||||
if (!closed_bracket) {
|
||||
if (S->tccpp_tok != ']')
|
||||
if (S->tok != ']')
|
||||
expect(S, "']'");
|
||||
else
|
||||
next(S); // skip ']'
|
||||
preincrement = 1; // add offset before transfer
|
||||
if (S->tccpp_tok == '!') {
|
||||
if (S->tok == '!') {
|
||||
exclam = 1;
|
||||
next(S); // skip '!'
|
||||
}
|
||||
|
@ -1528,12 +1528,12 @@ static void asm_floating_point_single_data_transfer_opcode(TCCState *S, int toke
|
|||
return;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
||||
if (S->tccpp_tok != '[')
|
||||
if (S->tok != '[')
|
||||
expect(S, "'['");
|
||||
else
|
||||
next(S); // skip '['
|
||||
|
@ -1543,7 +1543,7 @@ static void asm_floating_point_single_data_transfer_opcode(TCCState *S, int toke
|
|||
expect(S, "(first source operand) register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S); // skip ','
|
||||
parse_operand(S, &ops[2]);
|
||||
if (ops[2].type != OP_IM8 && ops[2].type != OP_IM8N) {
|
||||
|
@ -1555,7 +1555,7 @@ static void asm_floating_point_single_data_transfer_opcode(TCCState *S, int toke
|
|||
ops[2].type = OP_IM8;
|
||||
ops[2].e.v = 0;
|
||||
}
|
||||
if (S->tccpp_tok != ']')
|
||||
if (S->tok != ']')
|
||||
expect(S, "']'");
|
||||
else
|
||||
next(S); // skip ']'
|
||||
|
@ -1593,11 +1593,11 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *S, int token
|
|||
break;
|
||||
default:
|
||||
parse_operand(S, &ops[0]);
|
||||
if (S->tccpp_tok == '!') {
|
||||
if (S->tok == '!') {
|
||||
op0_exclam = 1;
|
||||
next(S); // skip '!'
|
||||
}
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S); // skip comma
|
||||
else {
|
||||
expect(S, "','");
|
||||
|
@ -1605,16 +1605,16 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *S, int token
|
|||
}
|
||||
}
|
||||
|
||||
if (S->tccpp_tok != '{') {
|
||||
if (S->tok != '{') {
|
||||
expect(S, "'{'");
|
||||
return;
|
||||
}
|
||||
next(S); // skip '{'
|
||||
first_regset_register = asm_parse_vfp_regvar(S->tccpp_tok, 1);
|
||||
if ((first_regset_register = asm_parse_vfp_regvar(S->tccpp_tok, 1)) != -1) {
|
||||
first_regset_register = asm_parse_vfp_regvar(S->tok, 1);
|
||||
if ((first_regset_register = asm_parse_vfp_regvar(S->tok, 1)) != -1) {
|
||||
coprocessor = CP_DOUBLE_PRECISION_FLOAT;
|
||||
next(S);
|
||||
} else if ((first_regset_register = asm_parse_vfp_regvar(S->tccpp_tok, 0)) != -1) {
|
||||
} else if ((first_regset_register = asm_parse_vfp_regvar(S->tok, 0)) != -1) {
|
||||
coprocessor = CP_SINGLE_PRECISION_FLOAT;
|
||||
next(S);
|
||||
} else {
|
||||
|
@ -1622,9 +1622,9 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *S, int token
|
|||
return;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == '-') {
|
||||
if (S->tok == '-') {
|
||||
next(S);
|
||||
if ((last_regset_register = asm_parse_vfp_regvar(S->tccpp_tok, coprocessor == CP_DOUBLE_PRECISION_FLOAT)) != -1)
|
||||
if ((last_regset_register = asm_parse_vfp_regvar(S->tok, coprocessor == CP_DOUBLE_PRECISION_FLOAT)) != -1)
|
||||
next(S);
|
||||
else {
|
||||
expect(S, "floating-point register");
|
||||
|
@ -1637,7 +1637,7 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *S, int token
|
|||
tcc_error(S, "registers will be processed in ascending order by hardware--but are not specified in ascending order here");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok != '}') {
|
||||
if (S->tok != '}') {
|
||||
expect(S, "'}'");
|
||||
return;
|
||||
}
|
||||
|
@ -1688,7 +1688,7 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *S, int token
|
|||
#define VMOV_FRACTIONAL_DIGITS 7
|
||||
#define VMOV_ONE 10000000 /* pow(10, VMOV_FRACTIONAL_DIGITS) */
|
||||
|
||||
static uint32_t vmov_parse_fractional_part(TCCState* S, const char* s)
|
||||
static uint32_t vmov_parse_fractional_part(TCCState *S, const char* s)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
int i;
|
||||
|
@ -1720,16 +1720,16 @@ static int vmov_linear_approx_index(uint32_t beginning, uint32_t end, uint32_t v
|
|||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t vmov_parse_immediate_value(TCCState* S) {
|
||||
static uint32_t vmov_parse_immediate_value(TCCState *S) {
|
||||
uint32_t value;
|
||||
unsigned long integral_value;
|
||||
const char *p;
|
||||
|
||||
if (S->tccpp_tok != TOK_PPNUM) {
|
||||
if (S->tok != TOK_PPNUM) {
|
||||
expect(S, "immediate value");
|
||||
return 0;
|
||||
}
|
||||
p = S->tccpp_tokc.str.data;
|
||||
p = S->tokc.str.data;
|
||||
errno = 0;
|
||||
integral_value = strtoul(p, (char **)&p, 0);
|
||||
|
||||
|
@ -1747,7 +1747,7 @@ static uint32_t vmov_parse_immediate_value(TCCState* S) {
|
|||
return value;
|
||||
}
|
||||
|
||||
static uint8_t vmov_encode_immediate_value(TCCState* S, uint32_t value)
|
||||
static uint8_t vmov_encode_immediate_value(TCCState *S, uint32_t value)
|
||||
{
|
||||
uint32_t limit;
|
||||
uint32_t end = 0;
|
||||
|
@ -1785,10 +1785,10 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *S
|
|||
|
||||
operands[0] = CRd;
|
||||
|
||||
if (S->tccpp_tok == '#' || S->tccpp_tok == '$') {
|
||||
if (S->tok == '#' || S->tok == '$') {
|
||||
next(S);
|
||||
}
|
||||
if (S->tccpp_tok == '-') {
|
||||
if (S->tok == '-') {
|
||||
op_minus = 1;
|
||||
next(S);
|
||||
}
|
||||
|
@ -1956,7 +1956,7 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *S, int toke
|
|||
break;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -2078,7 +2078,7 @@ static void asm_floating_point_data_processing_opcode(TCCState *S, int token) {
|
|||
|
||||
for (nb_ops = 0; nb_ops < 3; ) {
|
||||
// Note: Necessary because parse_operand can't parse decimal numerals.
|
||||
if (nb_ops == 1 && (S->tccpp_tok == '#' || S->tccpp_tok == '$' || S->tccpp_tok == TOK_PPNUM || S->tccpp_tok == '-')) {
|
||||
if (nb_ops == 1 && (S->tok == '#' || S->tok == '$' || S->tok == TOK_PPNUM || S->tok == '-')) {
|
||||
asm_floating_point_immediate_data_processing_opcode_tail(S, token, coprocessor, ops[0].reg);
|
||||
return;
|
||||
}
|
||||
|
@ -2100,7 +2100,7 @@ static void asm_floating_point_data_processing_opcode(TCCState *S, int token) {
|
|||
return;
|
||||
}
|
||||
++nb_ops;
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
break;
|
||||
|
@ -2239,7 +2239,7 @@ static void asm_floating_point_data_processing_opcode(TCCState *S, int token) {
|
|||
asm_emit_coprocessor_opcode(S, condition_code_of_token(S, token), coprocessor, opcode1, ops[0].reg, (ops[1].type == OP_IM8) ? ops[1].e.v : ops[1].reg, (ops[2].type == OP_IM8) ? ops[2].e.v : ops[2].reg, opcode2, 0);
|
||||
}
|
||||
|
||||
static void asm_floating_point_status_register_opcode(TCCState* S, int token)
|
||||
static void asm_floating_point_status_register_opcode(TCCState *S, int token)
|
||||
{
|
||||
uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT;
|
||||
uint8_t opcode;
|
||||
|
@ -2248,7 +2248,7 @@ static void asm_floating_point_status_register_opcode(TCCState* S, int token)
|
|||
switch (ARM_INSTRUCTION_GROUP(token)) {
|
||||
case TOK_ASM_vmrseq:
|
||||
opcode = 0xf;
|
||||
if (S->tccpp_tok == TOK_ASM_apsr_nzcv) {
|
||||
if (S->tok == TOK_ASM_apsr_nzcv) {
|
||||
arm_operand.type = OP_REG32;
|
||||
arm_operand.reg = 15; // not PC
|
||||
next(S); // skip apsr_nzcv
|
||||
|
@ -2260,11 +2260,11 @@ static void asm_floating_point_status_register_opcode(TCCState* S, int token)
|
|||
}
|
||||
}
|
||||
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
expect(S, "','");
|
||||
else
|
||||
next(S); // skip ','
|
||||
vfp_sys_reg = asm_parse_vfp_status_regvar(S->tccpp_tok);
|
||||
vfp_sys_reg = asm_parse_vfp_status_regvar(S->tok);
|
||||
next(S); // skip vfp sys reg
|
||||
if (arm_operand.type == OP_REG32 && arm_operand.reg == 15 && vfp_sys_reg != 1) {
|
||||
tcc_error(S, "'%s' only supports the variant 'vmrs apsr_nzcv, fpscr' here", get_tok_str(S, token, NULL));
|
||||
|
@ -2273,9 +2273,9 @@ static void asm_floating_point_status_register_opcode(TCCState* S, int token)
|
|||
break;
|
||||
case TOK_ASM_vmsreq:
|
||||
opcode = 0xe;
|
||||
vfp_sys_reg = asm_parse_vfp_status_regvar(S->tccpp_tok);
|
||||
vfp_sys_reg = asm_parse_vfp_status_regvar(S->tok);
|
||||
next(S); // skip vfp sys reg
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
expect(S, "','");
|
||||
else
|
||||
next(S); // skip ','
|
||||
|
@ -2329,12 +2329,12 @@ static void asm_misc_single_data_transfer_opcode(TCCState *S, int token)
|
|||
expect(S, "(destination operand) register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
expect(S, "at least two arguments");
|
||||
else
|
||||
next(S); // skip ','
|
||||
|
||||
if (S->tccpp_tok != '[')
|
||||
if (S->tok != '[')
|
||||
expect(S, "'['");
|
||||
else
|
||||
next(S); // skip '['
|
||||
|
@ -2346,14 +2346,14 @@ static void asm_misc_single_data_transfer_opcode(TCCState *S, int token)
|
|||
expect(S, "(first source operand) register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ']') {
|
||||
if (S->tok == ']') {
|
||||
next(S);
|
||||
closed_bracket = 1;
|
||||
// exclam = 1; // implicit in hardware; don't do it in software
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S); // skip ','
|
||||
if (S->tccpp_tok == '-') {
|
||||
if (S->tok == '-') {
|
||||
op2_minus = 1;
|
||||
next(S);
|
||||
}
|
||||
|
@ -2365,12 +2365,12 @@ static void asm_misc_single_data_transfer_opcode(TCCState *S, int token)
|
|||
opcode |= 1 << 24; // add offset before transfer
|
||||
}
|
||||
if (!closed_bracket) {
|
||||
if (S->tccpp_tok != ']')
|
||||
if (S->tok != ']')
|
||||
expect(S, "']'");
|
||||
else
|
||||
next(S); // skip ']'
|
||||
opcode |= 1 << 24; // add offset before transfer
|
||||
if (S->tccpp_tok == '!') {
|
||||
if (S->tok == '!') {
|
||||
exclam = 1;
|
||||
next(S); // skip '!'
|
||||
}
|
||||
|
@ -2439,7 +2439,7 @@ static void asm_misc_single_data_transfer_opcode(TCCState *S, int token)
|
|||
}
|
||||
|
||||
/* Note: almost dupe of encbranch in arm-gen.c */
|
||||
static uint32_t encbranchoffset(TCCState* S, int pos, int addr, int fail)
|
||||
static uint32_t encbranchoffset(TCCState *S, int pos, int addr, int fail)
|
||||
{
|
||||
addr-=pos+8;
|
||||
addr/=4;
|
||||
|
@ -2467,7 +2467,7 @@ static void asm_branch_opcode(TCCState *S, int token)
|
|||
tcc_error(S, "invalid branch target");
|
||||
return;
|
||||
}
|
||||
jmp_disp = encbranchoffset(S, S->tccgen_ind, e.v + esym->st_value, 1);
|
||||
jmp_disp = encbranchoffset(S, S->ind, e.v + esym->st_value, 1);
|
||||
break;
|
||||
default:
|
||||
parse_operand(S, &op);
|
||||
|
@ -2501,7 +2501,7 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
|
|||
{
|
||||
while (token == TOK_LINEFEED) {
|
||||
next(S);
|
||||
token = S->tccpp_tok;
|
||||
token = S->tok;
|
||||
}
|
||||
if (token == TOK_EOF)
|
||||
return;
|
||||
|
@ -2737,7 +2737,7 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, SValue *sv, int modifier)
|
||||
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str, SValue *sv, int modifier)
|
||||
{
|
||||
int r, reg, size, val;
|
||||
char buf[64];
|
||||
|
@ -2814,7 +2814,7 @@ ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, SValue *sv, int mo
|
|||
}
|
||||
|
||||
/* generate prolog and epilog code for asm statement */
|
||||
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
|
||||
ST_FUNC void asm_gen_code(TCCState *S, ASMOperand *operands, int nb_operands,
|
||||
int nb_outputs, int is_output,
|
||||
uint8_t *clobber_regs,
|
||||
int out_reg)
|
||||
|
@ -2900,7 +2900,7 @@ ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
|
|||
|
||||
/* return the constraint priority (we allocate first the lowest
|
||||
numbered constraints) */
|
||||
static inline int constraint_priority(TCCState* S, const char *str)
|
||||
static inline int constraint_priority(TCCState *S, const char *str)
|
||||
{
|
||||
int priority, c, pr;
|
||||
|
||||
|
@ -2956,7 +2956,7 @@ static const char *skip_constraint_modifiers(const char *p)
|
|||
|
||||
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
|
||||
|
||||
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
|
||||
ST_FUNC void asm_compute_constraints(TCCState *S, ASMOperand *operands,
|
||||
int nb_operands, int nb_outputs,
|
||||
const uint8_t *clobber_regs,
|
||||
int *pout_reg)
|
||||
|
@ -3191,7 +3191,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
|
|||
#endif
|
||||
}
|
||||
|
||||
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str)
|
||||
ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
|
||||
{
|
||||
int reg;
|
||||
TokenSym *ts;
|
||||
|
|
46
arm64-asm.c
46
arm64-asm.c
|
@ -9,9 +9,9 @@
|
|||
#define CONFIG_TCC_ASM
|
||||
#define NB_ASM_REGS 16
|
||||
|
||||
ST_FUNC void g(TCCState* S, int c);
|
||||
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||
ST_FUNC void g(TCCState *S, int c);
|
||||
ST_FUNC void gen_le16(TCCState *S, int c);
|
||||
ST_FUNC void gen_le32(TCCState *S, int c);
|
||||
|
||||
/*************************************************************/
|
||||
#else
|
||||
|
@ -19,74 +19,74 @@ ST_FUNC void gen_le32(TCCState* S, int c);
|
|||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
|
||||
static void asm_error(void)
|
||||
static void asm_error(TCCState *S)
|
||||
{
|
||||
tcc_error("ARM asm not implemented.");
|
||||
tcc_error(S, "ARM asm not implemented.");
|
||||
}
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(TCCState* S, int c)
|
||||
ST_FUNC void g(TCCState *S, int c)
|
||||
{
|
||||
int ind1;
|
||||
if (nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
ind1 = S->ind + 1;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
cur_text_section->data[S->ind] = c;
|
||||
S->ind = ind1;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le16 (TCCState* S, int i)
|
||||
ST_FUNC void gen_le16 (TCCState *S, int i)
|
||||
{
|
||||
g(S, i);
|
||||
g(S, i>>8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32 (TCCState* S, int i)
|
||||
ST_FUNC void gen_le32 (TCCState *S, int i)
|
||||
{
|
||||
gen_le16(S, i);
|
||||
gen_le16(S, i>>16);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||
ST_FUNC void gen_expr32(TCCState *S, ExprValue *pe)
|
||||
{
|
||||
gen_le32(S, pe->v);
|
||||
}
|
||||
|
||||
ST_FUNC void asm_opcode(TCCState *S, int opcode)
|
||||
{
|
||||
asm_error();
|
||||
asm_error(S);
|
||||
}
|
||||
|
||||
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
|
||||
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str, SValue *sv, int modifier)
|
||||
{
|
||||
asm_error();
|
||||
asm_error(S);
|
||||
}
|
||||
|
||||
/* generate prolog and epilog code for asm statement */
|
||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
ST_FUNC void asm_gen_code(TCCState *S, ASMOperand *operands, int nb_operands,
|
||||
int nb_outputs, int is_output,
|
||||
uint8_t *clobber_regs,
|
||||
int out_reg)
|
||||
{
|
||||
}
|
||||
|
||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
ST_FUNC void asm_compute_constraints(TCCState *S, ASMOperand *operands,
|
||||
int nb_operands, int nb_outputs,
|
||||
const uint8_t *clobber_regs,
|
||||
int *pout_reg)
|
||||
{
|
||||
}
|
||||
|
||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
||||
ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
|
||||
{
|
||||
asm_error();
|
||||
asm_error(S);
|
||||
}
|
||||
|
||||
ST_FUNC int asm_parse_regvar (int t)
|
||||
ST_FUNC int asm_parse_regvar (TCCState *S, int t)
|
||||
{
|
||||
asm_error();
|
||||
asm_error(S);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
284
arm64-gen.c
284
arm64-gen.c
|
@ -107,13 +107,13 @@ static uint32_t fltr(int r)
|
|||
// Add an instruction to text section:
|
||||
ST_FUNC void o(TCCState *S, unsigned int c)
|
||||
{
|
||||
int ind1 = S->tccgen_ind + 4;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
int ind1 = S->ind + 4;
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
write32le(cur_text_section->data + S->tccgen_ind, c);
|
||||
S->tccgen_ind = ind1;
|
||||
write32le(cur_text_section->data + S->ind, c);
|
||||
S->ind = ind1;
|
||||
}
|
||||
|
||||
static int arm64_encode_bimm64(uint64_t x)
|
||||
|
@ -452,9 +452,9 @@ static void arm64_strv(TCCState *S, int sz_, int dst, int bas, uint64_t off)
|
|||
|
||||
static void arm64_sym(TCCState *S, int r, Sym *sym, unsigned long addend)
|
||||
{
|
||||
greloca(S, cur_text_section, sym, S->tccgen_ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
greloca(S, cur_text_section, sym, S->ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
o(S, 0x90000000 | r); // adrp xr, #sym
|
||||
greloca(S, cur_text_section, sym, S->tccgen_ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
greloca(S, cur_text_section, sym, S->ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
o(S, 0xf9400000 | r | (r << 5)); // ld xr,[xr, #sym]
|
||||
if (addend) {
|
||||
// add xr, xr, #addend
|
||||
|
@ -654,14 +654,14 @@ ST_FUNC void store(TCCState *S, int r, SValue *sv)
|
|||
|
||||
static void arm64_gen_bl_or_b(TCCState *S, int b)
|
||||
{
|
||||
if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (S->tccgen_vtop->r & VT_SYM)) {
|
||||
greloca(S, cur_text_section, S->tccgen_vtop->sym, S->tccgen_ind,
|
||||
if ((S->vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (S->vtop->r & VT_SYM)) {
|
||||
greloca(S, cur_text_section, S->vtop->sym, S->ind,
|
||||
b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0);
|
||||
o(S, 0x14000000 | (uint32_t)!b << 31); // b/bl .
|
||||
}
|
||||
else {
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
S->tccgen_vtop->r &= ~VT_MUSTBOUND;
|
||||
S->vtop->r &= ~VT_MUSTBOUND;
|
||||
#endif
|
||||
o(S, 0xd61f0000 | (uint32_t)!b << 21 | intr(S, gv(S, RC_R30)) << 5); // br/blr
|
||||
}
|
||||
|
@ -673,7 +673,7 @@ static void gen_bounds_call(TCCState *S, int v)
|
|||
{
|
||||
Sym *sym = external_helper_sym(S, v);
|
||||
|
||||
greloca(S, cur_text_section, sym, S->tccgen_ind, R_AARCH64_CALL26, 0);
|
||||
greloca(S, cur_text_section, sym, S->ind, R_AARCH64_CALL26, 0);
|
||||
o(S, 0x94000000); // bl
|
||||
}
|
||||
|
||||
|
@ -681,7 +681,7 @@ static void gen_bounds_prolog(TCCState *S)
|
|||
{
|
||||
/* leave some room for bound checking code */
|
||||
S->func_bound_offset = lbounds_section->data_offset;
|
||||
S->func_bound_ind = S->tccgen_ind;
|
||||
S->func_bound_ind = S->ind;
|
||||
S->func_bound_add_epilog = 0;
|
||||
o(S, 0xd503201f); /* nop -> mov x0, lbound section pointer */
|
||||
o(S, 0xd503201f);
|
||||
|
@ -703,27 +703,27 @@ static void gen_bounds_epilog(TCCState *S)
|
|||
bounds_ptr = section_ptr_add(S, lbounds_section, sizeof(addr_t));
|
||||
*bounds_ptr = 0;
|
||||
|
||||
sym_data = get_sym_ref(S, &S->tccgen_char_pointer_type, lbounds_section,
|
||||
sym_data = get_sym_ref(S, &S->char_pointer_type, lbounds_section,
|
||||
S->func_bound_offset, lbounds_section->data_offset);
|
||||
|
||||
/* generate bound local allocation */
|
||||
if (offset_modified) {
|
||||
saved_ind = S->tccgen_ind;
|
||||
S->tccgen_ind = S->func_bound_ind;
|
||||
greloca(S, cur_text_section, sym_data, S->tccgen_ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
saved_ind = S->ind;
|
||||
S->ind = S->func_bound_ind;
|
||||
greloca(S, cur_text_section, sym_data, S->ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
o(S, 0x90000000 | 0); // adrp x0, #sym_data
|
||||
greloca(S, cur_text_section, sym_data, S->tccgen_ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
o(S, 0xf9400000 | 0 | (0 << 5)); // ld x0,[x0, #sym_data]
|
||||
gen_bounds_call(S, TOK___bound_local_new);
|
||||
S->tccgen_ind = saved_ind;
|
||||
S->ind = saved_ind;
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
o(S, 0xf81f0fe0); /* str x0, [sp, #-16]! */
|
||||
o(S, 0x3c9f0fe0); /* str q0, [sp, #-16]! */
|
||||
greloca(S, cur_text_section, sym_data, S->tccgen_ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
o(S, 0x90000000 | 0); // adrp x0, #sym_data
|
||||
greloca(S, cur_text_section, sym_data, S->tccgen_ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
o(S, 0xf9400000 | 0 | (0 << 5)); // ld x0,[x0, #sym_data]
|
||||
gen_bounds_call(S, TOK___bound_local_delete);
|
||||
o(S, 0x3cc107e0); /* ldr q0, [sp], #16 */
|
||||
|
@ -977,7 +977,7 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
gbound_args(S, nb_args);
|
||||
#endif
|
||||
|
||||
return_type = &S->tccgen_vtop[-nb_args].type.ref->type;
|
||||
return_type = &S->vtop[-nb_args].type.ref->type;
|
||||
if ((return_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
--nb_args;
|
||||
|
||||
|
@ -987,14 +987,14 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
|
||||
t[0] = return_type;
|
||||
for (i = 0; i < nb_args; i++)
|
||||
t[nb_args - i] = &S->tccgen_vtop[-i].type;
|
||||
t[nb_args - i] = &S->vtop[-i].type;
|
||||
|
||||
stack = arm64_pcs(nb_args, t, a);
|
||||
|
||||
// Allocate space for structs replaced by pointer:
|
||||
for (i = nb_args; i; i--)
|
||||
if (a[i] & 1) {
|
||||
SValue *arg = &S->tccgen_vtop[i - nb_args];
|
||||
SValue *arg = &S->vtop[i - nb_args];
|
||||
int align, size = type_size(&arg->type, &align);
|
||||
assert((arg->type.t & VT_BTYPE) == VT_STRUCT);
|
||||
stack = (stack + align - 1) & -align;
|
||||
|
@ -1005,7 +1005,7 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
stack = (stack + 15) >> 4 << 4;
|
||||
|
||||
/* fetch cpu flag before generating any code */
|
||||
if ((S->tccgen_vtop->r & VT_VALMASK) == VT_CMP)
|
||||
if ((S->vtop->r & VT_VALMASK) == VT_CMP)
|
||||
gv(S, RC_INT);
|
||||
|
||||
if (stack >= 0x1000000) // 16Mb
|
||||
|
@ -1017,13 +1017,13 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
|
||||
// First pass: set all values on stack
|
||||
for (i = nb_args; i; i--) {
|
||||
vpushv(S, S->tccgen_vtop - nb_args + i);
|
||||
vpushv(S, S->vtop - nb_args + i);
|
||||
|
||||
if (a[i] & 1) {
|
||||
// struct replaced by pointer
|
||||
int r = get_reg(S, RC_INT);
|
||||
arm64_spoff(S, intr(S, r), a1[i]);
|
||||
vset(S, &S->tccgen_vtop->type, r | VT_LVAL, 0);
|
||||
vset(S, &S->vtop->type, r | VT_LVAL, 0);
|
||||
vswap(S);
|
||||
vstore(S);
|
||||
if (a[i] >= 32) {
|
||||
|
@ -1035,36 +1035,36 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
}
|
||||
else if (a[i] >= 32) {
|
||||
// value on stack
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
int r = get_reg(S, RC_INT);
|
||||
arm64_spoff(S, intr(S, r), a[i] - 32);
|
||||
vset(S, &S->tccgen_vtop->type, r | VT_LVAL, 0);
|
||||
vset(S, &S->vtop->type, r | VT_LVAL, 0);
|
||||
vswap(S);
|
||||
vstore(S);
|
||||
}
|
||||
else if (is_float(S->tccgen_vtop->type.t)) {
|
||||
else if (is_float(S->vtop->type.t)) {
|
||||
gv(S, RC_FLOAT);
|
||||
arm64_strv(S, arm64_type_size(S->tccgen_vtop[0].type.t),
|
||||
fltr(S->tccgen_vtop[0].r), 31, a[i] - 32);
|
||||
arm64_strv(S, arm64_type_size(S->vtop[0].type.t),
|
||||
fltr(S->vtop[0].r), 31, a[i] - 32);
|
||||
}
|
||||
else {
|
||||
gv(S, RC_INT);
|
||||
arm64_strx(S, arm64_type_size(S->tccgen_vtop[0].type.t),
|
||||
intr(S, S->tccgen_vtop[0].r), 31, a[i] - 32);
|
||||
arm64_strx(S, arm64_type_size(S->vtop[0].type.t),
|
||||
intr(S, S->vtop[0].r), 31, a[i] - 32);
|
||||
}
|
||||
}
|
||||
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
}
|
||||
|
||||
// Second pass: assign values to registers
|
||||
for (i = nb_args; i; i--, S->tccgen_vtop--) {
|
||||
for (i = nb_args; i; i--, S->vtop--) {
|
||||
if (a[i] < 16 && !(a[i] & 1)) {
|
||||
// value in general-purpose registers
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
int align, size = type_size(&S->tccgen_vtop->type, &align);
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
int align, size = type_size(&S->vtop->type, &align);
|
||||
if (size) {
|
||||
S->tccgen_vtop->type.t = VT_PTR;
|
||||
S->vtop->type.t = VT_PTR;
|
||||
gaddrof(S);
|
||||
gv(S, RC_R(a[i] / 2));
|
||||
arm64_ldrs(S, a[i] / 2, size);
|
||||
|
@ -1078,9 +1078,9 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
arm64_spoff(S, a[i] / 2, a1[i]);
|
||||
else if (a[i] < 32) {
|
||||
// value in floating-point registers
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
uint32_t j, sz, n = arm64_hfa(&S->tccgen_vtop->type, &sz);
|
||||
S->tccgen_vtop->type.t = VT_PTR;
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
uint32_t j, sz, n = arm64_hfa(&S->vtop->type, &sz);
|
||||
S->vtop->type.t = VT_PTR;
|
||||
gaddrof(S);
|
||||
gv(S, RC_R30);
|
||||
for (j = 0; j < n; j++)
|
||||
|
@ -1098,7 +1098,7 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
if (a[0] == 1) {
|
||||
// indirect return: set x8 and discard the stack value
|
||||
gv(S, RC_R(8));
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
}
|
||||
else
|
||||
// return in registers: keep the address for after the call
|
||||
|
@ -1107,7 +1107,7 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
|
||||
save_regs(S, 0);
|
||||
arm64_gen_bl_or_b(S, 0);
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
if (stack & 0xfff)
|
||||
o(S, 0x910003ff | (stack & 0xfff) << 10); // add sp,sp,#(n)
|
||||
if (stack >> 12)
|
||||
|
@ -1119,7 +1119,7 @@ ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
|||
if (bt == VT_STRUCT && !(a[0] & 1)) {
|
||||
// A struct was returned in registers, so write it out:
|
||||
gv(S, RC_R(8));
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
if (a[0] == 0) {
|
||||
int align, size = type_size(return_type, &align);
|
||||
assert(size <= 16);
|
||||
|
@ -1220,11 +1220,11 @@ ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym)
|
|||
tcc_free(S, t);
|
||||
|
||||
o(S, 0x910003fd); // mov x29,sp
|
||||
arm64_func_sub_sp_offset = S->tccgen_ind;
|
||||
arm64_func_sub_sp_offset = S->ind;
|
||||
// In gfunc_epilog these will be replaced with code to decrement SP:
|
||||
o(S, 0xd503201f); // nop
|
||||
o(S, 0xd503201f); // nop
|
||||
S->tccgen_loc = 0;
|
||||
S->loc = 0;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (S->do_bounds_check)
|
||||
gen_bounds_prolog(S);
|
||||
|
@ -1234,7 +1234,7 @@ ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym)
|
|||
ST_FUNC void gen_va_start(TCCState *S)
|
||||
{
|
||||
int r;
|
||||
--S->tccgen_vtop; // we don't need the "arg"
|
||||
--S->vtop; // we don't need the "arg"
|
||||
gaddrof(S);
|
||||
r = intr(S, gv(S, RC_INT));
|
||||
|
||||
|
@ -1264,7 +1264,7 @@ ST_FUNC void gen_va_start(TCCState *S)
|
|||
arm64_movimm(S, 30, arm64_func_va_list_vr_offs);
|
||||
o(S, 0xb9001c1e | r << 5); // str w30,[x(r),#28]
|
||||
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_va_arg(TCCState *S, CType *t)
|
||||
|
@ -1281,7 +1281,7 @@ ST_FUNC void gen_va_arg(TCCState *S, CType *t)
|
|||
gaddrof(S);
|
||||
r0 = intr(S, gv(S, RC_INT));
|
||||
r1 = get_reg(S, RC_INT);
|
||||
S->tccgen_vtop[0].r = r1 | VT_LVAL;
|
||||
S->vtop[0].r = r1 | VT_LVAL;
|
||||
r1 = intr(S, r1);
|
||||
|
||||
if (!hfa) {
|
||||
|
@ -1310,7 +1310,7 @@ ST_FUNC void gen_va_arg(TCCState *S, CType *t)
|
|||
uint32_t b1, b2;
|
||||
o(S, 0xb9401c1e | r0 << 5); // ldr w30,[x(r0),#28] // __vr_offs
|
||||
o(S, 0x310003c0 | r1 | rsz << 10); // adds w(r1),w30,#(rsz)
|
||||
b1 = S->tccgen_ind; o(S, 0x5400000d); // b.le lab1
|
||||
b1 = S->ind; o(S, 0x5400000d); // b.le lab1
|
||||
o(S, 0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack
|
||||
if (fsize == 16) {
|
||||
o(S, 0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15
|
||||
|
@ -1318,9 +1318,9 @@ ST_FUNC void gen_va_arg(TCCState *S, CType *t)
|
|||
}
|
||||
o(S, 0x9100001e | r1 << 5 | ssz << 10); // add x30,x(r1),#(ssz)
|
||||
o(S, 0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
|
||||
b2 = S->tccgen_ind; o(S, 0x14000000); // b lab2
|
||||
b2 = S->ind; o(S, 0x14000000); // b lab2
|
||||
// lab1:
|
||||
write32le(cur_text_section->data + b1, 0x5400000d | (S->tccgen_ind - b1) << 3);
|
||||
write32le(cur_text_section->data + b1, 0x5400000d | (S->ind - b1) << 3);
|
||||
o(S, 0xb9001c00 | r1 | r0 << 5); // str w(r1),[x(r0),#28] // __vr_offs
|
||||
o(S, 0xf9400800 | r1 | r0 << 5); // ldr x(r1),[x(r0),#16] // __vr_top
|
||||
if (hfa == 1 || fsize == 16)
|
||||
|
@ -1328,9 +1328,9 @@ ST_FUNC void gen_va_arg(TCCState *S, CType *t)
|
|||
else {
|
||||
// We need to change the layout of this HFA.
|
||||
// Get some space on the stack using global variable "loc":
|
||||
S->tccgen_loc = (S->tccgen_loc - size) & -(uint32_t)align;
|
||||
S->loc = (S->loc - size) & -(uint32_t)align;
|
||||
o(S, 0x8b3ec000 | 30 | r1 << 5); // add x30,x(r1),w30,sxtw
|
||||
arm64_movimm(S, r1, S->tccgen_loc);
|
||||
arm64_movimm(S, r1, S->loc);
|
||||
o(S, 0x8b0003a0 | r1 | r1 << 16); // add x(r1),x29,x(r1)
|
||||
o(S, 0x4c402bdc | (uint32_t)fsize << 7 |
|
||||
(uint32_t)(hfa == 2) << 15 |
|
||||
|
@ -1340,7 +1340,7 @@ ST_FUNC void gen_va_arg(TCCState *S, CType *t)
|
|||
(uint32_t)(hfa != 3) << 21); // st(hfa) {v28.(s|d),...}[0],[x(r1)]
|
||||
}
|
||||
// lab2:
|
||||
write32le(cur_text_section->data + b2, 0x14000000 | (S->tccgen_ind - b2) >> 2);
|
||||
write32le(cur_text_section->data + b2, 0x14000000 | (S->ind - b2) >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1380,7 +1380,7 @@ ST_FUNC void gfunc_return(TCCState *S, CType *func_type)
|
|||
}
|
||||
case 16:
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
uint32_t j, sz, n = arm64_hfa(&S->tccgen_vtop->type, &sz);
|
||||
uint32_t j, sz, n = arm64_hfa(&S->vtop->type, &sz);
|
||||
gaddrof(S);
|
||||
gv(S, RC_R(0));
|
||||
for (j = 0; j < n; j++)
|
||||
|
@ -1394,7 +1394,7 @@ ST_FUNC void gfunc_return(TCCState *S, CType *func_type)
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_epilog(TCCState *S)
|
||||
|
@ -1404,10 +1404,10 @@ ST_FUNC void gfunc_epilog(TCCState *S)
|
|||
gen_bounds_epilog(S);
|
||||
#endif
|
||||
|
||||
if (S->tccgen_loc) {
|
||||
if (S->loc) {
|
||||
// Insert instructions to subtract size of stack frame from SP.
|
||||
unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
|
||||
uint64_t diff = (-S->tccgen_loc + 15) & ~15;
|
||||
uint64_t diff = (-S->loc + 15) & ~15;
|
||||
if (!(diff >> 24)) {
|
||||
if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff)
|
||||
write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10);
|
||||
|
@ -1452,8 +1452,8 @@ ST_FUNC void gen_fill_nops(TCCState *S, int bytes)
|
|||
// Generate forward branch to label:
|
||||
ST_FUNC int gjmp(TCCState *S, int t)
|
||||
{
|
||||
int r = S->tccgen_ind;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
int r = S->ind;
|
||||
if (S->nocode_wanted)
|
||||
return t;
|
||||
o(S, t);
|
||||
return r;
|
||||
|
@ -1462,8 +1462,8 @@ ST_FUNC int gjmp(TCCState *S, int t)
|
|||
// Generate branch to known address:
|
||||
ST_FUNC void gjmp_addr(TCCState *S, int a)
|
||||
{
|
||||
assert(a - S->tccgen_ind + 0x8000000 < 0x10000000);
|
||||
o(S, 0x14000000 | ((a - S->tccgen_ind) >> 2 & 0x3ffffff));
|
||||
assert(a - S->ind + 0x8000000 < 0x10000000);
|
||||
o(S, 0x14000000 | ((a - S->ind) >> 2 & 0x3ffffff));
|
||||
}
|
||||
|
||||
ST_FUNC int gjmp_append(TCCState *S, int n, int t)
|
||||
|
@ -1483,7 +1483,7 @@ ST_FUNC int gjmp_append(TCCState *S, int n, int t)
|
|||
void arm64_vset_VT_CMP(TCCState *S, int op)
|
||||
{
|
||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||
S->tccgen_vtop->cmp_r = S->tccgen_vtop->r;
|
||||
S->vtop->cmp_r = S->vtop->r;
|
||||
vset_VT_CMP(S, 0x80);
|
||||
}
|
||||
}
|
||||
|
@ -1505,16 +1505,16 @@ static void arm64_load_cmp(TCCState *S, int r, SValue *sv)
|
|||
|
||||
ST_FUNC int gjmp_cond(TCCState *S, int op, int t)
|
||||
{
|
||||
int bt = S->tccgen_vtop->type.t & VT_BTYPE;
|
||||
int bt = S->vtop->type.t & VT_BTYPE;
|
||||
|
||||
int inv = op & 1;
|
||||
S->tccgen_vtop->r = S->tccgen_vtop->cmp_r;
|
||||
S->vtop->r = S->vtop->cmp_r;
|
||||
|
||||
if (bt == VT_LDOUBLE) {
|
||||
uint32_t a, b, f = fltr(gv(S, RC_FLOAT));
|
||||
a = get_reg(S, RC_INT);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop[0].r = a;
|
||||
S->vtop[0].r = a;
|
||||
b = get_reg(S, RC_INT);
|
||||
a = intr(S, a);
|
||||
b = intr(S, b);
|
||||
|
@ -1522,7 +1522,7 @@ ST_FUNC int gjmp_cond(TCCState *S, int op, int t)
|
|||
o(S, 0x4e183c00 | b | f << 5); // mov x(b),v(f).d[1]
|
||||
o(S, 0xaa000400 | a | a << 5 | b << 16); // orr x(a),x(a),x(b),lsl #1
|
||||
o(S, 0xb4000040 | a | !!inv << 24); // cbz/cbnz x(a),.+8
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
}
|
||||
else if (bt == VT_FLOAT || bt == VT_DOUBLE) {
|
||||
uint32_t a = fltr(gv(S, RC_FLOAT));
|
||||
|
@ -1639,20 +1639,20 @@ static void arm64_gen_opil(TCCState *S, int op, uint32_t l)
|
|||
uint64_t val;
|
||||
int rev = 1;
|
||||
|
||||
if (arm64_iconst(0, &S->tccgen_vtop[0])) {
|
||||
if (arm64_iconst(0, &S->vtop[0])) {
|
||||
vswap(S);
|
||||
rev = 0;
|
||||
}
|
||||
if (arm64_iconst(&val, &S->tccgen_vtop[-1])) {
|
||||
if (arm64_iconst(&val, &S->vtop[-1])) {
|
||||
gv(S, RC_INT);
|
||||
a = intr(S, S->tccgen_vtop[0].r);
|
||||
--S->tccgen_vtop;
|
||||
a = intr(S, S->vtop[0].r);
|
||||
--S->vtop;
|
||||
x = get_reg(S, RC_INT);
|
||||
++S->tccgen_vtop;
|
||||
++S->vtop;
|
||||
if (arm64_gen_opic(S, op, l, rev, val, intr(S, x), a)) {
|
||||
S->tccgen_vtop[0].r = x;
|
||||
S->vtop[0].r = x;
|
||||
vswap(S);
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1661,13 +1661,13 @@ static void arm64_gen_opil(TCCState *S, int op, uint32_t l)
|
|||
}
|
||||
|
||||
gv2(S, RC_INT, RC_INT);
|
||||
assert(S->tccgen_vtop[-1].r < VT_CONST && S->tccgen_vtop[0].r < VT_CONST);
|
||||
a = intr(S, S->tccgen_vtop[-1].r);
|
||||
b = intr(S, S->tccgen_vtop[0].r);
|
||||
S->tccgen_vtop -= 2;
|
||||
assert(S->vtop[-1].r < VT_CONST && S->vtop[0].r < VT_CONST);
|
||||
a = intr(S, S->vtop[-1].r);
|
||||
b = intr(S, S->vtop[0].r);
|
||||
S->vtop -= 2;
|
||||
x = get_reg(S, RC_INT);
|
||||
++S->tccgen_vtop;
|
||||
S->tccgen_vtop[0].r = x;
|
||||
++S->vtop;
|
||||
S->vtop[0].r = x;
|
||||
x = intr(S, x);
|
||||
|
||||
switch (op) {
|
||||
|
@ -1768,7 +1768,7 @@ ST_FUNC void gen_opi(TCCState *S, int op)
|
|||
arm64_vset_VT_CMP(S, op);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_opl(TCCState* S, int op)
|
||||
ST_FUNC void gen_opl(TCCState *S, int op)
|
||||
{
|
||||
arm64_gen_opil(S, op, 1);
|
||||
arm64_vset_VT_CMP(S, op);
|
||||
|
@ -1778,8 +1778,8 @@ ST_FUNC void gen_opf(TCCState *S, int op)
|
|||
{
|
||||
uint32_t x, a, b, dbl;
|
||||
|
||||
if (S->tccgen_vtop[0].type.t == VT_LDOUBLE) {
|
||||
CType type = S->tccgen_vtop[0].type;
|
||||
if (S->vtop[0].type.t == VT_LDOUBLE) {
|
||||
CType type = S->vtop[0].type;
|
||||
int func = 0;
|
||||
int cond = -1;
|
||||
switch (op) {
|
||||
|
@ -1799,9 +1799,9 @@ ST_FUNC void gen_opf(TCCState *S, int op)
|
|||
vrott(S, 3);
|
||||
gfunc_call(S, 2);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = cond < 0 ? REG_FRET : REG_IRET;
|
||||
S->vtop->r = cond < 0 ? REG_FRET : REG_IRET;
|
||||
if (cond < 0)
|
||||
S->tccgen_vtop->type = type;
|
||||
S->vtop->type = type;
|
||||
else {
|
||||
o(S, 0x7100001f); // cmp w0,#0
|
||||
o(S, 0x1a9f07e0 | (uint32_t)cond << 12); // cset w0,(cond)
|
||||
|
@ -1809,24 +1809,24 @@ ST_FUNC void gen_opf(TCCState *S, int op)
|
|||
return;
|
||||
}
|
||||
|
||||
dbl = S->tccgen_vtop[0].type.t != VT_FLOAT;
|
||||
dbl = S->vtop[0].type.t != VT_FLOAT;
|
||||
gv2(S, RC_FLOAT, RC_FLOAT);
|
||||
assert(S->tccgen_vtop[-1].r < VT_CONST && S->tccgen_vtop[0].r < VT_CONST);
|
||||
a = fltr(S->tccgen_vtop[-1].r);
|
||||
b = fltr(S->tccgen_vtop[0].r);
|
||||
S->tccgen_vtop -= 2;
|
||||
assert(S->vtop[-1].r < VT_CONST && S->vtop[0].r < VT_CONST);
|
||||
a = fltr(S->vtop[-1].r);
|
||||
b = fltr(S->vtop[0].r);
|
||||
S->vtop -= 2;
|
||||
switch (op) {
|
||||
case TOK_EQ: case TOK_NE:
|
||||
case TOK_LT: case TOK_GE: case TOK_LE: case TOK_GT:
|
||||
x = get_reg(S, RC_INT);
|
||||
++S->tccgen_vtop;
|
||||
S->tccgen_vtop[0].r = x;
|
||||
++S->vtop;
|
||||
S->vtop[0].r = x;
|
||||
x = intr(S, x);
|
||||
break;
|
||||
default:
|
||||
x = get_reg(S, RC_FLOAT);
|
||||
++S->tccgen_vtop;
|
||||
S->tccgen_vtop[0].r = x;
|
||||
++S->vtop;
|
||||
S->vtop[0].r = x;
|
||||
x = fltr(x);
|
||||
break;
|
||||
}
|
||||
|
@ -1894,7 +1894,7 @@ ST_FUNC void gen_cvt_csti(TCCState *S, int t)
|
|||
ST_FUNC void gen_cvt_itof(TCCState *S, int t)
|
||||
{
|
||||
if (t == VT_LDOUBLE) {
|
||||
int f = S->tccgen_vtop->type.t;
|
||||
int f = S->vtop->type.t;
|
||||
int func = (f & VT_BTYPE) == VT_LLONG ?
|
||||
(f & VT_UNSIGNED ? TOK___floatunditf : TOK___floatditf) :
|
||||
(f & VT_UNSIGNED ? TOK___floatunsitf : TOK___floatsitf);
|
||||
|
@ -1902,18 +1902,18 @@ ST_FUNC void gen_cvt_itof(TCCState *S, int t)
|
|||
vrott(S, 2);
|
||||
gfunc_call(S, 1);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->type.t = t;
|
||||
S->tccgen_vtop->r = REG_FRET;
|
||||
S->vtop->type.t = t;
|
||||
S->vtop->r = REG_FRET;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
int d, n = intr(S, gv(S, RC_INT));
|
||||
int s = !(S->tccgen_vtop->type.t & VT_UNSIGNED);
|
||||
uint32_t l = ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LLONG);
|
||||
--S->tccgen_vtop;
|
||||
int s = !(S->vtop->type.t & VT_UNSIGNED);
|
||||
uint32_t l = ((S->vtop->type.t & VT_BTYPE) == VT_LLONG);
|
||||
--S->vtop;
|
||||
d = get_reg(S, RC_FLOAT);
|
||||
++S->tccgen_vtop;
|
||||
S->tccgen_vtop[0].r = d;
|
||||
++S->vtop;
|
||||
S->vtop[0].r = d;
|
||||
o(S, 0x1e220000 | (uint32_t)!s << 16 |
|
||||
(uint32_t)(t != VT_FLOAT) << 22 | fltr(d) |
|
||||
l << 31 | n << 5); // [us]cvtf [sd](d),[wx](n)
|
||||
|
@ -1922,7 +1922,7 @@ ST_FUNC void gen_cvt_itof(TCCState *S, int t)
|
|||
|
||||
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t)
|
||||
{
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
|
||||
int func = (t & VT_BTYPE) == VT_LLONG ?
|
||||
(t & VT_UNSIGNED ? TOK___fixunstfdi : TOK___fixtfdi) :
|
||||
(t & VT_UNSIGNED ? TOK___fixunstfsi : TOK___fixtfsi);
|
||||
|
@ -1930,17 +1930,17 @@ ST_FUNC void gen_cvt_ftoi(TCCState *S, int t)
|
|||
vrott(S, 2);
|
||||
gfunc_call(S, 1);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->type.t = t;
|
||||
S->tccgen_vtop->r = REG_IRET;
|
||||
S->vtop->type.t = t;
|
||||
S->vtop->r = REG_IRET;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
int d, n = fltr(gv(S, RC_FLOAT));
|
||||
uint32_t l = ((S->tccgen_vtop->type.t & VT_BTYPE) != VT_FLOAT);
|
||||
--S->tccgen_vtop;
|
||||
uint32_t l = ((S->vtop->type.t & VT_BTYPE) != VT_FLOAT);
|
||||
--S->vtop;
|
||||
d = get_reg(S, RC_INT);
|
||||
++S->tccgen_vtop;
|
||||
S->tccgen_vtop[0].r = d;
|
||||
++S->vtop;
|
||||
S->vtop[0].r = d;
|
||||
o(S, 0x1e380000 |
|
||||
(uint32_t)!!(t & VT_UNSIGNED) << 16 |
|
||||
(uint32_t)((t & VT_BTYPE) == VT_LLONG) << 31 | intr(S, d) |
|
||||
|
@ -1950,7 +1950,7 @@ ST_FUNC void gen_cvt_ftoi(TCCState *S, int t)
|
|||
|
||||
ST_FUNC void gen_cvt_ftof(TCCState *S, int t)
|
||||
{
|
||||
int f = S->tccgen_vtop[0].type.t & VT_BTYPE;
|
||||
int f = S->vtop[0].type.t & VT_BTYPE;
|
||||
assert(t == VT_FLOAT || t == VT_DOUBLE || t == VT_LDOUBLE);
|
||||
assert(f == VT_FLOAT || f == VT_DOUBLE || f == VT_LDOUBLE);
|
||||
if (t == f)
|
||||
|
@ -1964,18 +1964,18 @@ ST_FUNC void gen_cvt_ftof(TCCState *S, int t)
|
|||
vrott(S, 2);
|
||||
gfunc_call(S, 1);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->type.t = t;
|
||||
S->tccgen_vtop->r = REG_FRET;
|
||||
S->vtop->type.t = t;
|
||||
S->vtop->r = REG_FRET;
|
||||
}
|
||||
else {
|
||||
int x, a;
|
||||
gv(S, RC_FLOAT);
|
||||
assert(S->tccgen_vtop[0].r < VT_CONST);
|
||||
a = fltr(S->tccgen_vtop[0].r);
|
||||
--S->tccgen_vtop;
|
||||
assert(S->vtop[0].r < VT_CONST);
|
||||
a = fltr(S->vtop[0].r);
|
||||
--S->vtop;
|
||||
x = get_reg(S, RC_FLOAT);
|
||||
++S->tccgen_vtop;
|
||||
S->tccgen_vtop[0].r = x;
|
||||
++S->vtop;
|
||||
S->vtop[0].r = x;
|
||||
x = fltr(x);
|
||||
|
||||
if (f == VT_FLOAT)
|
||||
|
@ -1986,16 +1986,16 @@ ST_FUNC void gen_cvt_ftof(TCCState *S, int t)
|
|||
}
|
||||
|
||||
/* increment tcov counter */
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv)
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv)
|
||||
{
|
||||
int r1, r2;
|
||||
|
||||
vpushv(S, sv);
|
||||
S->tccgen_vtop->r = r1 = get_reg(S, RC_INT);
|
||||
S->vtop->r = r1 = get_reg(S, RC_INT);
|
||||
r2 = get_reg(S, RC_INT);
|
||||
greloca(S, cur_text_section, sv->sym, S->tccgen_ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
greloca(S, cur_text_section, sv->sym, S->ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
o(S, 0x90000000 | r1); // adrp r1, #sym
|
||||
greloca(S, cur_text_section, sv->sym, S->tccgen_ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
greloca(S, cur_text_section, sv->sym, S->ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
o(S, 0xf9400000 | r1 | (r1 << 5)); // ld xr,[xr, #sym]
|
||||
o(S, 0xf9400000 | (intr(S, r1)<<5) | intr(S, r2)); // ldr r2, [r1]
|
||||
o(S, 0x91000400 | (intr(S, r2)<<5) | intr(S, r2)); // add r2, r2, #1
|
||||
|
@ -2006,7 +2006,7 @@ ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv)
|
|||
ST_FUNC void ggoto(TCCState *S)
|
||||
{
|
||||
arm64_gen_bl_or_b(S, 1);
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_clear_cache(TCCState *S)
|
||||
|
@ -2014,17 +2014,17 @@ ST_FUNC void gen_clear_cache(TCCState *S)
|
|||
uint32_t beg, end, dsz, isz, p, lab1, b1;
|
||||
gv2(S, RC_INT, RC_INT);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = get_reg(S, RC_INT);
|
||||
S->vtop->r = get_reg(S, RC_INT);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = get_reg(S, RC_INT);
|
||||
S->vtop->r = get_reg(S, RC_INT);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = get_reg(S, RC_INT);
|
||||
beg = intr(S, S->tccgen_vtop[-4].r); // x0
|
||||
end = intr(S, S->tccgen_vtop[-3].r); // x1
|
||||
dsz = intr(S, S->tccgen_vtop[-2].r); // x2
|
||||
isz = intr(S, S->tccgen_vtop[-1].r); // x3
|
||||
p = intr(S, S->tccgen_vtop[0].r); // x4
|
||||
S->tccgen_vtop -= 5;
|
||||
S->vtop->r = get_reg(S, RC_INT);
|
||||
beg = intr(S, S->vtop[-4].r); // x0
|
||||
end = intr(S, S->vtop[-3].r); // x1
|
||||
dsz = intr(S, S->vtop[-2].r); // x2
|
||||
isz = intr(S, S->vtop[-1].r); // x3
|
||||
p = intr(S, S->vtop[0].r); // x4
|
||||
S->vtop -= 5;
|
||||
|
||||
o(S, 0xd53b0020 | isz); // mrs x(isz),ctr_el0
|
||||
o(S, 0x52800080 | p); // mov w(p),#4
|
||||
|
@ -2034,23 +2034,23 @@ ST_FUNC void gen_clear_cache(TCCState *S)
|
|||
o(S, 0x1ac02000 | isz | p << 5 | isz << 16); // lsl w(isz),w(p),w(isz)
|
||||
o(S, 0x51000400 | p | dsz << 5); // sub w(p),w(dsz),#1
|
||||
o(S, 0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p)
|
||||
b1 = S->tccgen_ind; o(S, 0x14000000); // b
|
||||
lab1 = S->tccgen_ind;
|
||||
b1 = S->ind; o(S, 0x14000000); // b
|
||||
lab1 = S->ind;
|
||||
o(S, 0xd50b7b20 | p); // dc cvau,x(p)
|
||||
o(S, 0x8b000000 | p | p << 5 | dsz << 16); // add x(p),x(p),x(dsz)
|
||||
write32le(cur_text_section->data + b1, 0x14000000 | (S->tccgen_ind - b1) >> 2);
|
||||
write32le(cur_text_section->data + b1, 0x14000000 | (S->ind - b1) >> 2);
|
||||
o(S, 0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end)
|
||||
o(S, 0x54ffffa3 | ((lab1 - S->tccgen_ind) << 3 & 0xffffe0)); // b.cc lab1
|
||||
o(S, 0x54ffffa3 | ((lab1 - S->ind) << 3 & 0xffffe0)); // b.cc lab1
|
||||
o(S, 0xd5033b9f); // dsb ish
|
||||
o(S, 0x51000400 | p | isz << 5); // sub w(p),w(isz),#1
|
||||
o(S, 0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p)
|
||||
b1 = S->tccgen_ind; o(S, 0x14000000); // b
|
||||
lab1 = S->tccgen_ind;
|
||||
b1 = S->ind; o(S, 0x14000000); // b
|
||||
lab1 = S->ind;
|
||||
o(S, 0xd50b7520 | p); // ic ivau,x(p)
|
||||
o(S, 0x8b000000 | p | p << 5 | isz << 16); // add x(p),x(p),x(isz)
|
||||
write32le(cur_text_section->data + b1, 0x14000000 | (S->tccgen_ind - b1) >> 2);
|
||||
write32le(cur_text_section->data + b1, 0x14000000 | (S->ind - b1) >> 2);
|
||||
o(S, 0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end)
|
||||
o(S, 0x54ffffa3 | ((lab1 - S->tccgen_ind) << 3 & 0xffffe0)); // b.cc lab1
|
||||
o(S, 0x54ffffa3 | ((lab1 - S->ind) << 3 & 0xffffe0)); // b.cc lab1
|
||||
o(S, 0xd5033b9f); // dsb ish
|
||||
o(S, 0xd5033fdf); // isb
|
||||
}
|
||||
|
@ -2074,7 +2074,7 @@ ST_FUNC void gen_vla_alloc(TCCState *S, CType *type, int align) {
|
|||
uint32_t r;
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
if (S->do_bounds_check)
|
||||
vpushv(S, S->tccgen_vtop);
|
||||
vpushv(S, S->vtop);
|
||||
#endif
|
||||
r = intr(S, gv(S, RC_INT));
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
@ -2089,8 +2089,8 @@ ST_FUNC void gen_vla_alloc(TCCState *S, CType *type, int align) {
|
|||
#if defined(CONFIG_TCC_BCHECK)
|
||||
if (S->do_bounds_check) {
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = TREG_R(0);
|
||||
o(S, 0x910003e0 | S->tccgen_vtop->r); // mov r0,sp
|
||||
S->vtop->r = TREG_R(0);
|
||||
o(S, 0x910003e0 | S->vtop->r); // mov r0,sp
|
||||
vswap(S);
|
||||
vpush_helper_func(S, TOK___bound_new_region);
|
||||
vrott(S, 3);
|
||||
|
|
104
i386-asm.c
104
i386-asm.c
|
@ -282,7 +282,7 @@ static inline int get_reg_shift(TCCState *S)
|
|||
static int asm_parse_numeric_reg(TCCState *S, int t, unsigned int *type)
|
||||
{
|
||||
int reg = -1;
|
||||
if (t >= TOK_IDENT && t < S->tccpp_tok_ident) {
|
||||
if (t >= TOK_IDENT && t < S->tok_ident) {
|
||||
const char *s = S->tccpp_table_ident[t - TOK_IDENT]->str;
|
||||
char c;
|
||||
*type = OP_REG64;
|
||||
|
@ -318,24 +318,24 @@ static int asm_parse_numeric_reg(TCCState *S, int t, unsigned int *type)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int asm_parse_reg(TCCState* S, unsigned int *type)
|
||||
static int asm_parse_reg(TCCState *S, unsigned int *type)
|
||||
{
|
||||
int reg = 0;
|
||||
*type = 0;
|
||||
if (S->tccpp_tok != '%')
|
||||
if (S->tok != '%')
|
||||
goto error_32;
|
||||
next(S);
|
||||
if (S->tccpp_tok >= TOK_ASM_eax && S->tccpp_tok <= TOK_ASM_edi) {
|
||||
reg = S->tccpp_tok - TOK_ASM_eax;
|
||||
if (S->tok >= TOK_ASM_eax && S->tok <= TOK_ASM_edi) {
|
||||
reg = S->tok - TOK_ASM_eax;
|
||||
*type = OP_REG32;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
} else if (S->tccpp_tok >= TOK_ASM_rax && S->tccpp_tok <= TOK_ASM_rdi) {
|
||||
reg = S->tccpp_tok - TOK_ASM_rax;
|
||||
} else if (S->tok >= TOK_ASM_rax && S->tok <= TOK_ASM_rdi) {
|
||||
reg = S->tok - TOK_ASM_rax;
|
||||
*type = OP_REG64;
|
||||
} else if (S->tccpp_tok == TOK_ASM_rip) {
|
||||
} else if (S->tok == TOK_ASM_rip) {
|
||||
reg = -2; /* Probably should use different escape code. */
|
||||
*type = OP_REG64;
|
||||
} else if ((reg = asm_parse_numeric_reg(S, S->tccpp_tok, type)) >= 0
|
||||
} else if ((reg = asm_parse_numeric_reg(S, S->tok, type)) >= 0
|
||||
&& (*type == OP_REG32 || *type == OP_REG64)) {
|
||||
;
|
||||
#endif
|
||||
|
@ -354,15 +354,15 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
const char *p;
|
||||
|
||||
indir = 0;
|
||||
if (S->tccpp_tok == '*') {
|
||||
if (S->tok == '*') {
|
||||
next(S);
|
||||
indir = OP_INDIR;
|
||||
}
|
||||
|
||||
if (S->tccpp_tok == '%') {
|
||||
if (S->tok == '%') {
|
||||
next(S);
|
||||
if (S->tccpp_tok >= TOK_ASM_al && S->tccpp_tok <= TOK_ASM_db7) {
|
||||
reg = S->tccpp_tok - TOK_ASM_al;
|
||||
if (S->tok >= TOK_ASM_al && S->tok <= TOK_ASM_db7) {
|
||||
reg = S->tok - TOK_ASM_al;
|
||||
op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
|
||||
op->reg = reg & 7;
|
||||
if ((op->type & OP_REG) && op->reg == TREG_XAX)
|
||||
|
@ -371,21 +371,21 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
op->type |= OP_CL;
|
||||
else if (op->type == OP_REG16 && op->reg == TREG_XDX)
|
||||
op->type |= OP_DX;
|
||||
} else if (S->tccpp_tok >= TOK_ASM_dr0 && S->tccpp_tok <= TOK_ASM_dr7) {
|
||||
} else if (S->tok >= TOK_ASM_dr0 && S->tok <= TOK_ASM_dr7) {
|
||||
op->type = OP_DB;
|
||||
op->reg = S->tccpp_tok - TOK_ASM_dr0;
|
||||
} else if (S->tccpp_tok >= TOK_ASM_es && S->tccpp_tok <= TOK_ASM_gs) {
|
||||
op->reg = S->tok - TOK_ASM_dr0;
|
||||
} else if (S->tok >= TOK_ASM_es && S->tok <= TOK_ASM_gs) {
|
||||
op->type = OP_SEG;
|
||||
op->reg = S->tccpp_tok - TOK_ASM_es;
|
||||
} else if (S->tccpp_tok == TOK_ASM_st) {
|
||||
op->reg = S->tok - TOK_ASM_es;
|
||||
} else if (S->tok == TOK_ASM_st) {
|
||||
op->type = OP_ST;
|
||||
op->reg = 0;
|
||||
next(S);
|
||||
if (S->tccpp_tok == '(') {
|
||||
if (S->tok == '(') {
|
||||
next(S);
|
||||
if (S->tccpp_tok != TOK_PPNUM)
|
||||
if (S->tok != TOK_PPNUM)
|
||||
goto reg_error;
|
||||
p = S->tccpp_tokc.str.data;
|
||||
p = S->tokc.str.data;
|
||||
reg = p[0] - '0';
|
||||
if ((unsigned)reg >= 8 || p[1] != '\0')
|
||||
goto reg_error;
|
||||
|
@ -397,19 +397,19 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
op->type |= OP_ST0;
|
||||
goto no_skip;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
} else if (S->tccpp_tok >= TOK_ASM_spl && S->tccpp_tok <= TOK_ASM_dil) {
|
||||
} else if (S->tok >= TOK_ASM_spl && S->tok <= TOK_ASM_dil) {
|
||||
op->type = OP_REG8 | OP_REG8_LOW;
|
||||
op->reg = 4 + S->tccpp_tok - TOK_ASM_spl;
|
||||
} else if ((op->reg = asm_parse_numeric_reg(S, S->tccpp_tok, &op->type)) >= 0) {
|
||||
op->reg = 4 + S->tok - TOK_ASM_spl;
|
||||
} else if ((op->reg = asm_parse_numeric_reg(S, S->tok, &op->type)) >= 0) {
|
||||
;
|
||||
#endif
|
||||
} else {
|
||||
reg_error:
|
||||
tcc_error(S, "unknown register %%%s", get_tok_str(S, S->tccpp_tok, &S->tccpp_tokc));
|
||||
tcc_error(S, "unknown register %%%s", get_tok_str(S, S->tok, &S->tokc));
|
||||
}
|
||||
next(S);
|
||||
no_skip: ;
|
||||
} else if (S->tccpp_tok == '$') {
|
||||
} else if (S->tok == '$') {
|
||||
/* constant value */
|
||||
next(S);
|
||||
asm_expr(S, &e);
|
||||
|
@ -433,19 +433,19 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
op->reg = -1;
|
||||
op->reg2 = -1;
|
||||
op->shift = 0;
|
||||
if (S->tccpp_tok != '(') {
|
||||
if (S->tok != '(') {
|
||||
asm_expr(S, &e);
|
||||
op->e = e;
|
||||
} else {
|
||||
next(S);
|
||||
if (S->tccpp_tok == '%') {
|
||||
if (S->tok == '%') {
|
||||
unget_tok(S, '(');
|
||||
op->e.v = 0;
|
||||
op->e.sym = NULL;
|
||||
} else {
|
||||
/* bracketed offset expression */
|
||||
asm_expr(S, &e);
|
||||
if (S->tccpp_tok != ')')
|
||||
if (S->tok != ')')
|
||||
expect(S, ")");
|
||||
next(S);
|
||||
op->e.v = e.v;
|
||||
|
@ -453,18 +453,18 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
}
|
||||
op->e.pcrel = 0;
|
||||
}
|
||||
if (S->tccpp_tok == '(') {
|
||||
if (S->tok == '(') {
|
||||
unsigned int type = 0;
|
||||
next(S);
|
||||
if (S->tccpp_tok != ',') {
|
||||
if (S->tok != ',') {
|
||||
op->reg = asm_parse_reg(S, &type);
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
if (S->tccpp_tok != ',') {
|
||||
if (S->tok != ',') {
|
||||
op->reg2 = asm_parse_reg(S, &type);
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
op->shift = get_reg_shift(S);
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
}
|
||||
|
||||
/* XXX: unify with C code output ? */
|
||||
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||
ST_FUNC void gen_expr32(TCCState *S, ExprValue *pe)
|
||||
{
|
||||
if (pe->pcrel)
|
||||
/* If PC-relative, always set VT_SYM, even without symbol,
|
||||
|
@ -491,14 +491,14 @@ ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
|||
}
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe)
|
||||
ST_FUNC void gen_expr64(TCCState *S, ExprValue *pe)
|
||||
{
|
||||
gen_addr64(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: unify with C code output ? */
|
||||
static void gen_disp32(TCCState* S, ExprValue *pe)
|
||||
static void gen_disp32(TCCState *S, ExprValue *pe)
|
||||
{
|
||||
Sym *sym = pe->sym;
|
||||
ElfSym *esym = elfsym(S, sym);
|
||||
|
@ -507,7 +507,7 @@ static void gen_disp32(TCCState* S, ExprValue *pe)
|
|||
that the TCC compiler behaves differently here because
|
||||
it always outputs a relocation to ease (future) code
|
||||
elimination in the linker */
|
||||
gen_le32(S, pe->v + esym->st_value - S->tccgen_ind - 4);
|
||||
gen_le32(S, pe->v + esym->st_value - S->ind - 4);
|
||||
} else {
|
||||
if (sym && sym->type.t == VT_VOID) {
|
||||
sym->type.t = VT_FUNC;
|
||||
|
@ -518,7 +518,7 @@ static void gen_disp32(TCCState* S, ExprValue *pe)
|
|||
}
|
||||
|
||||
/* generate the modrm operand */
|
||||
static inline int asm_modrm(TCCState* S, int reg, Operand *op)
|
||||
static inline int asm_modrm(TCCState *S, int reg, Operand *op)
|
||||
{
|
||||
int mod, reg1, reg2, sib_reg1;
|
||||
|
||||
|
@ -538,7 +538,7 @@ static inline int asm_modrm(TCCState* S, int reg, Operand *op)
|
|||
ExprValue *pe = &op->e;
|
||||
g(S, 0x05 + (reg << 3));
|
||||
gen_addrpc32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
return S->tccgen_ind;
|
||||
return S->ind;
|
||||
#endif
|
||||
} else {
|
||||
sib_reg1 = op->reg;
|
||||
|
@ -581,7 +581,7 @@ static inline int asm_modrm(TCCState* S, int reg, Operand *op)
|
|||
#define REX_X 0x42
|
||||
#define REX_B 0x41
|
||||
|
||||
static void asm_rex(TCCState* S, int width64, Operand *ops, int nb_ops, int *op_type,
|
||||
static void asm_rex(TCCState *S, int width64, Operand *ops, int nb_ops, int *op_type,
|
||||
int regi, int rmi)
|
||||
{
|
||||
unsigned char rex = width64 ? 0x48 : 0;
|
||||
|
@ -705,13 +705,13 @@ ST_FUNC void asm_opcode(TCCState *S, int opcode)
|
|||
seg_prefix = 0;
|
||||
alltypes = 0;
|
||||
for(;;) {
|
||||
if (S->tccpp_tok == ';' || S->tccpp_tok == TOK_LINEFEED)
|
||||
if (S->tok == ';' || S->tok == TOK_LINEFEED)
|
||||
break;
|
||||
if (nb_ops >= MAX_OPERANDS) {
|
||||
tcc_error(S, "incorrect number of operands");
|
||||
}
|
||||
parse_operand(S, pop);
|
||||
if (S->tccpp_tok == ':') {
|
||||
if (S->tok == ':') {
|
||||
if (pop->type != OP_SEG || seg_prefix)
|
||||
tcc_error(S, "incorrect prefix");
|
||||
seg_prefix = segment_prefixes[pop->reg];
|
||||
|
@ -723,7 +723,7 @@ ST_FUNC void asm_opcode(TCCState *S, int opcode)
|
|||
}
|
||||
pop++;
|
||||
nb_ops++;
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
break;
|
||||
next(S);
|
||||
}
|
||||
|
@ -1038,7 +1038,7 @@ again:
|
|||
esym = elfsym(S, ops[0].e.sym);
|
||||
if (!esym || esym->st_shndx != cur_text_section->sh_num)
|
||||
goto no_short_jump;
|
||||
jmp_disp = ops[0].e.v + esym->st_value - S->tccgen_ind - 2 - (v >= 0xff);
|
||||
jmp_disp = ops[0].e.v + esym->st_value - S->ind - 2 - (v >= 0xff);
|
||||
if (jmp_disp == (int8_t)jmp_disp) {
|
||||
/* OK to generate jump */
|
||||
ops[0].e.sym = 0;
|
||||
|
@ -1136,12 +1136,12 @@ again:
|
|||
|
||||
/* after immediate operands, adjust pc-relative address */
|
||||
if (pc)
|
||||
add32le(cur_text_section->data + pc - 4, pc - S->tccgen_ind);
|
||||
add32le(cur_text_section->data + pc - 4, pc - S->ind);
|
||||
}
|
||||
|
||||
/* return the constraint priority (we allocate first the lowest
|
||||
numbered constraints) */
|
||||
static inline int constraint_priority(TCCState* S, const char *str)
|
||||
static inline int constraint_priority(TCCState *S, const char *str)
|
||||
{
|
||||
int priority, c, pr;
|
||||
|
||||
|
@ -1200,7 +1200,7 @@ static const char *skip_constraint_modifiers(const char *p)
|
|||
|
||||
/* If T (a token) is of the form "%reg" returns the register
|
||||
number and type, otherwise return -1. */
|
||||
ST_FUNC int asm_parse_regvar (TCCState* S, int t)
|
||||
ST_FUNC int asm_parse_regvar (TCCState *S, int t)
|
||||
{
|
||||
const char *s;
|
||||
Operand op;
|
||||
|
@ -1225,7 +1225,7 @@ ST_FUNC int asm_parse_regvar (TCCState* S, int t)
|
|||
|
||||
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
|
||||
|
||||
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
|
||||
ST_FUNC void asm_compute_constraints(TCCState *S, ASMOperand *operands,
|
||||
int nb_operands, int nb_outputs,
|
||||
const uint8_t *clobber_regs,
|
||||
int *pout_reg)
|
||||
|
@ -1471,7 +1471,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
|
|||
#endif
|
||||
}
|
||||
|
||||
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
|
||||
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str,
|
||||
SValue *sv, int modifier)
|
||||
{
|
||||
int r, reg, size, val;
|
||||
|
@ -1593,7 +1593,7 @@ ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
|
|||
}
|
||||
|
||||
/* generate prolog and epilog code for asm statement */
|
||||
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
|
||||
ST_FUNC void asm_gen_code(TCCState *S, ASMOperand *operands, int nb_operands,
|
||||
int nb_outputs, int is_output,
|
||||
uint8_t *clobber_regs,
|
||||
int out_reg)
|
||||
|
@ -1697,7 +1697,7 @@ ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str)
|
||||
ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
|
||||
{
|
||||
int reg;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
|
|
258
i386-gen.c
258
i386-gen.c
|
@ -100,24 +100,24 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
|||
static unsigned long func_sub_sp_offset;
|
||||
static int func_ret_sub;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
static void gen_bounds_prolog(TCCState* S);
|
||||
static void gen_bounds_epilog(TCCState* S);
|
||||
static void gen_bounds_prolog(TCCState *S);
|
||||
static void gen_bounds_epilog(TCCState *S);
|
||||
#endif
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(TCCState* S, int c)
|
||||
ST_FUNC void g(TCCState *S, int c)
|
||||
{
|
||||
int ind1;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
ind1 = S->tccgen_ind + 1;
|
||||
ind1 = S->ind + 1;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
cur_text_section->data[S->tccgen_ind] = c;
|
||||
S->tccgen_ind = ind1;
|
||||
cur_text_section->data[S->ind] = c;
|
||||
S->ind = ind1;
|
||||
}
|
||||
|
||||
ST_FUNC void o(TCCState* S, unsigned int c)
|
||||
ST_FUNC void o(TCCState *S, unsigned int c)
|
||||
{
|
||||
while (c) {
|
||||
g(S, c);
|
||||
|
@ -125,13 +125,13 @@ ST_FUNC void o(TCCState* S, unsigned int c)
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le16(TCCState* S, int v)
|
||||
ST_FUNC void gen_le16(TCCState *S, int v)
|
||||
{
|
||||
g(S, v);
|
||||
g(S, v >> 8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32(TCCState* S, int c)
|
||||
ST_FUNC void gen_le32(TCCState *S, int c)
|
||||
{
|
||||
g(S, c);
|
||||
g(S, c >> 8);
|
||||
|
@ -140,7 +140,7 @@ ST_FUNC void gen_le32(TCCState* S, int c)
|
|||
}
|
||||
|
||||
/* output a symbol and patch all calls to it */
|
||||
ST_FUNC void gsym_addr(TCCState* S, int t, int a)
|
||||
ST_FUNC void gsym_addr(TCCState *S, int t, int a)
|
||||
{
|
||||
while (t) {
|
||||
unsigned char *ptr = cur_text_section->data + t;
|
||||
|
@ -151,18 +151,18 @@ ST_FUNC void gsym_addr(TCCState* S, int t, int a)
|
|||
}
|
||||
|
||||
/* instruction + 4 bytes data. Return the address of the data */
|
||||
static int oad(TCCState* S, int c, int s)
|
||||
static int oad(TCCState *S, int c, int s)
|
||||
{
|
||||
int t;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return s;
|
||||
o(S, c);
|
||||
t = S->tccgen_ind;
|
||||
t = S->ind;
|
||||
gen_le32(S, s);
|
||||
return t;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_fill_nops(TCCState* S, int bytes)
|
||||
ST_FUNC void gen_fill_nops(TCCState *S, int bytes)
|
||||
{
|
||||
while (bytes--)
|
||||
g(S, 0x90);
|
||||
|
@ -172,23 +172,23 @@ ST_FUNC void gen_fill_nops(TCCState* S, int bytes)
|
|||
#define gjmp2(s, instr,lbl) oad(s, instr,lbl)
|
||||
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
ST_FUNC void gen_addr32(TCCState* S, int r, Sym *sym, int c)
|
||||
ST_FUNC void gen_addr32(TCCState *S, int r, Sym *sym, int c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloc(S, cur_text_section, sym, S->tccgen_ind, R_386_32);
|
||||
greloc(S, cur_text_section, sym, S->ind, R_386_32);
|
||||
gen_le32(S, c);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_addrpc32(TCCState* S, int r, Sym *sym, int c)
|
||||
ST_FUNC void gen_addrpc32(TCCState *S, int r, Sym *sym, int c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloc(S, cur_text_section, sym, S->tccgen_ind, R_386_PC32);
|
||||
greloc(S, cur_text_section, sym, S->ind, R_386_PC32);
|
||||
gen_le32(S, c - 4);
|
||||
}
|
||||
|
||||
/* generate a modrm reference. 'op_reg' contains the additional 3
|
||||
opcode bits */
|
||||
static void gen_modrm(TCCState* S, int op_reg, int r, Sym *sym, int c)
|
||||
static void gen_modrm(TCCState *S, int op_reg, int r, Sym *sym, int c)
|
||||
{
|
||||
op_reg = op_reg << 3;
|
||||
if ((r & VT_VALMASK) == VT_CONST) {
|
||||
|
@ -210,7 +210,7 @@ static void gen_modrm(TCCState* S, int op_reg, int r, Sym *sym, int c)
|
|||
}
|
||||
|
||||
/* load 'r' from value 'sv' */
|
||||
ST_FUNC void load(TCCState* S, int r, SValue *sv)
|
||||
ST_FUNC void load(TCCState *S, int r, SValue *sv)
|
||||
{
|
||||
int v, t, ft, fc, fr;
|
||||
SValue v1;
|
||||
|
@ -290,7 +290,7 @@ ST_FUNC void load(TCCState* S, int r, SValue *sv)
|
|||
}
|
||||
|
||||
/* store register 'r' in lvalue 'v' */
|
||||
ST_FUNC void store(TCCState* S, int r, SValue *v)
|
||||
ST_FUNC void store(TCCState *S, int r, SValue *v)
|
||||
{
|
||||
int fr, bt, ft, fc;
|
||||
|
||||
|
@ -332,7 +332,7 @@ ST_FUNC void store(TCCState* S, int r, SValue *v)
|
|||
}
|
||||
}
|
||||
|
||||
static void gadd_sp(TCCState* S, int val)
|
||||
static void gadd_sp(TCCState *S, int val)
|
||||
{
|
||||
if (val == (char)val) {
|
||||
o(S, 0xc483);
|
||||
|
@ -343,24 +343,24 @@ static void gadd_sp(TCCState* S, int val)
|
|||
}
|
||||
|
||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE
|
||||
static void gen_static_call(TCCState* S, int v)
|
||||
static void gen_static_call(TCCState *S, int v)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
sym = external_helper_sym(S, v);
|
||||
oad(S, 0xe8, -4);
|
||||
greloc(S, cur_text_section, sym, S->tccgen_ind-4, R_386_PC32);
|
||||
greloc(S, cur_text_section, sym, S->ind-4, R_386_PC32);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 'is_jmp' is '1' if it is a jump */
|
||||
static void gcall_or_jmp(TCCState* S, int is_jmp)
|
||||
static void gcall_or_jmp(TCCState *S, int is_jmp)
|
||||
{
|
||||
int r;
|
||||
if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (S->tccgen_vtop->r & VT_SYM)) {
|
||||
if ((S->vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (S->vtop->r & VT_SYM)) {
|
||||
/* constant and relocation case */
|
||||
greloc(S, cur_text_section, S->tccgen_vtop->sym, S->tccgen_ind + 1, R_386_PC32);
|
||||
oad(S, 0xe8 + is_jmp, S->tccgen_vtop->c.i - 4); /* call/jmp im */
|
||||
greloc(S, cur_text_section, S->vtop->sym, S->ind + 1, R_386_PC32);
|
||||
oad(S, 0xe8 + is_jmp, S->vtop->c.i - 4); /* call/jmp im */
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
r = gv(S, RC_INT);
|
||||
|
@ -402,7 +402,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
|
|||
/* Generate function call. The function address is pushed first, then
|
||||
all the parameters in call order. This functions pops all the
|
||||
parameters and the function address. */
|
||||
ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
||||
ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
||||
{
|
||||
int size, align, r, args_size, i, func_call;
|
||||
Sym *func_sym;
|
||||
|
@ -414,8 +414,8 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
|
||||
args_size = 0;
|
||||
for(i = 0;i < nb_args; i++) {
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
size = type_size(&S->tccgen_vtop->type, &align);
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
size = type_size(&S->vtop->type, &align);
|
||||
/* align to stack align size */
|
||||
size = (size + 3) & ~3;
|
||||
/* allocate the necessary size on stack */
|
||||
|
@ -434,15 +434,15 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
r = get_reg(S, RC_INT);
|
||||
o(S, 0xe089 + (r << 8)); /* mov %esp, r */
|
||||
}
|
||||
vset(S, &S->tccgen_vtop->type, r | VT_LVAL, 0);
|
||||
vset(S, &S->vtop->type, r | VT_LVAL, 0);
|
||||
vswap(S);
|
||||
vstore(S);
|
||||
args_size += size;
|
||||
} else if (is_float(S->tccgen_vtop->type.t)) {
|
||||
} else if (is_float(S->vtop->type.t)) {
|
||||
gv(S, RC_FLOAT); /* only one float register */
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_FLOAT)
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_FLOAT)
|
||||
size = 4;
|
||||
else if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_DOUBLE)
|
||||
else if ((S->vtop->type.t & VT_BTYPE) == VT_DOUBLE)
|
||||
size = 8;
|
||||
else
|
||||
size = 12;
|
||||
|
@ -458,19 +458,19 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
/* simple type (currently always same size) */
|
||||
/* XXX: implicit cast ? */
|
||||
r = gv(S, RC_INT);
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
size = 8;
|
||||
o(S, 0x50 + S->tccgen_vtop->r2); /* push r */
|
||||
o(S, 0x50 + S->vtop->r2); /* push r */
|
||||
} else {
|
||||
size = 4;
|
||||
}
|
||||
o(S, 0x50 + r); /* push r */
|
||||
args_size += size;
|
||||
}
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
}
|
||||
save_regs(S, 0); /* save used temporary registers */
|
||||
func_sym = S->tccgen_vtop->type.ref;
|
||||
func_sym = S->vtop->type.ref;
|
||||
func_call = func_sym->f.func_call;
|
||||
/* fast call case */
|
||||
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
|
||||
|
@ -493,7 +493,7 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
}
|
||||
}
|
||||
#if !defined(TCC_TARGET_PE) && !TARGETOS_FreeBSD || TARGETOS_OpenBSD
|
||||
else if ((S->tccgen_vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT)
|
||||
else if ((S->vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT)
|
||||
args_size -= 4;
|
||||
#endif
|
||||
|
||||
|
@ -501,7 +501,7 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
|
||||
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
|
||||
gadd_sp(S, args_size);
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
|
@ -511,7 +511,7 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
#endif
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
||||
ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
int addr, align, size, func_call, fastcall_nb_regs;
|
||||
|
@ -523,7 +523,7 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
sym = func_type->ref;
|
||||
func_call = sym->f.func_call;
|
||||
addr = 8;
|
||||
S->tccgen_loc = 0;
|
||||
S->loc = 0;
|
||||
S->tccgen_func_vc = 0;
|
||||
|
||||
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
|
||||
|
@ -538,8 +538,8 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
}
|
||||
param_index = 0;
|
||||
|
||||
S->tccgen_ind += FUNC_PROLOG_SIZE;
|
||||
func_sub_sp_offset = S->tccgen_ind;
|
||||
S->ind += FUNC_PROLOG_SIZE;
|
||||
func_sub_sp_offset = S->ind;
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
#if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD
|
||||
|
@ -567,10 +567,10 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
#endif
|
||||
if (param_index < fastcall_nb_regs) {
|
||||
/* save FASTCALL register */
|
||||
S->tccgen_loc -= 4;
|
||||
S->loc -= 4;
|
||||
o(S, 0x89); /* movl */
|
||||
gen_modrm(S, fastcall_regs_ptr[param_index], VT_LOCAL, NULL, S->tccgen_loc);
|
||||
param_addr = S->tccgen_loc;
|
||||
gen_modrm(S, fastcall_regs_ptr[param_index], VT_LOCAL, NULL, S->loc);
|
||||
param_addr = S->loc;
|
||||
} else {
|
||||
param_addr = addr;
|
||||
addr += size;
|
||||
|
@ -595,7 +595,7 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
}
|
||||
|
||||
/* generate function epilog */
|
||||
ST_FUNC void gfunc_epilog(TCCState* S)
|
||||
ST_FUNC void gfunc_epilog(TCCState *S)
|
||||
{
|
||||
addr_t v, saved_ind;
|
||||
|
||||
|
@ -605,7 +605,7 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
#endif
|
||||
|
||||
/* align local size to word & save local variables */
|
||||
v = (-S->tccgen_loc + 3) & -4;
|
||||
v = (-S->loc + 3) & -4;
|
||||
|
||||
#if USE_EBX
|
||||
o(S, 0x8b);
|
||||
|
@ -620,8 +620,8 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
g(S, func_ret_sub);
|
||||
g(S, func_ret_sub >> 8);
|
||||
}
|
||||
saved_ind = S->tccgen_ind;
|
||||
S->tccgen_ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
|
||||
saved_ind = S->ind;
|
||||
S->ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (v >= 4096) {
|
||||
oad(S, 0xb8, v); /* mov stacksize, %eax */
|
||||
|
@ -637,33 +637,33 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
#endif
|
||||
}
|
||||
o(S, 0x53 * USE_EBX); /* push ebx */
|
||||
S->tccgen_ind = saved_ind;
|
||||
S->ind = saved_ind;
|
||||
}
|
||||
|
||||
/* generate a jump to a label */
|
||||
ST_FUNC int gjmp(TCCState* S, int t)
|
||||
ST_FUNC int gjmp(TCCState *S, int t)
|
||||
{
|
||||
return gjmp2(S, 0xe9, t);
|
||||
}
|
||||
|
||||
/* generate a jump to a fixed address */
|
||||
ST_FUNC void gjmp_addr(TCCState* S, int a)
|
||||
ST_FUNC void gjmp_addr(TCCState *S, int a)
|
||||
{
|
||||
int r;
|
||||
r = a - S->tccgen_ind - 2;
|
||||
r = a - S->ind - 2;
|
||||
if (r == (char)r) {
|
||||
g(S, 0xeb);
|
||||
g(S, r);
|
||||
} else {
|
||||
oad(S, 0xe9, a - S->tccgen_ind - 5);
|
||||
oad(S, 0xe9, a - S->ind - 5);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* generate a jump to a fixed address */
|
||||
ST_FUNC void gjmp_cond_addr(TCCState* S, int a, int op)
|
||||
ST_FUNC void gjmp_cond_addr(TCCState *S, int a, int op)
|
||||
{
|
||||
int r = a - S->tccgen_ind - 2;
|
||||
int r = a - S->ind - 2;
|
||||
if (r == (char)r)
|
||||
g(S, op - 32), g(r);
|
||||
else
|
||||
|
@ -671,7 +671,7 @@ ST_FUNC void gjmp_cond_addr(TCCState* S, int a, int op)
|
|||
}
|
||||
#endif
|
||||
|
||||
ST_FUNC int gjmp_append(TCCState* S, int n, int t)
|
||||
ST_FUNC int gjmp_append(TCCState *S, int n, int t)
|
||||
{
|
||||
void *p;
|
||||
/* insert vtop->c jump list in t */
|
||||
|
@ -685,14 +685,14 @@ ST_FUNC int gjmp_append(TCCState* S, int n, int t)
|
|||
return t;
|
||||
}
|
||||
|
||||
ST_FUNC int gjmp_cond(TCCState* S, int op, int t)
|
||||
ST_FUNC int gjmp_cond(TCCState *S, int op, int t)
|
||||
{
|
||||
g(S, 0x0f);
|
||||
t = gjmp2(S, op - 16, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_opi(TCCState* S, int op)
|
||||
ST_FUNC void gen_opi(TCCState *S, int op)
|
||||
{
|
||||
int r, fr, opc, c;
|
||||
|
||||
|
@ -701,12 +701,12 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
case TOK_ADDC1: /* add with carry generation */
|
||||
opc = 0;
|
||||
gen_op8:
|
||||
if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
if ((S->vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant case */
|
||||
vswap(S);
|
||||
r = gv(S, RC_INT);
|
||||
vswap(S);
|
||||
c = S->tccgen_vtop->c.i;
|
||||
c = S->vtop->c.i;
|
||||
if (c == (char)c) {
|
||||
/* generate inc and dec for smaller code */
|
||||
if ((c == 1 || c == -1) && (op == '+' || op == '-')) {
|
||||
|
@ -723,12 +723,12 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
}
|
||||
} else {
|
||||
gv2(S, RC_INT, RC_INT);
|
||||
r = S->tccgen_vtop[-1].r;
|
||||
fr = S->tccgen_vtop[0].r;
|
||||
r = S->vtop[-1].r;
|
||||
fr = S->vtop[0].r;
|
||||
o(S, (opc << 3) | 0x01);
|
||||
o(S, 0xc0 + r + fr * 8);
|
||||
}
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
if (op >= TOK_ULT && op <= TOK_GT)
|
||||
vset_VT_CMP(S, op);
|
||||
break;
|
||||
|
@ -753,9 +753,9 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
goto gen_op8;
|
||||
case '*':
|
||||
gv2(S, RC_INT, RC_INT);
|
||||
r = S->tccgen_vtop[-1].r;
|
||||
fr = S->tccgen_vtop[0].r;
|
||||
S->tccgen_vtop--;
|
||||
r = S->vtop[-1].r;
|
||||
fr = S->vtop[0].r;
|
||||
S->vtop--;
|
||||
o(S, 0xaf0f); /* imul fr, r */
|
||||
o(S, 0xc0 + fr + r * 8);
|
||||
break;
|
||||
|
@ -769,23 +769,23 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
opc = 7;
|
||||
gen_shift:
|
||||
opc = 0xc0 | (opc << 3);
|
||||
if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
if ((S->vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant case */
|
||||
vswap(S);
|
||||
r = gv(S, RC_INT);
|
||||
vswap(S);
|
||||
c = S->tccgen_vtop->c.i & 0x1f;
|
||||
c = S->vtop->c.i & 0x1f;
|
||||
o(S, 0xc1); /* shl/shr/sar $xxx, r */
|
||||
o(S, opc | r);
|
||||
g(S, c);
|
||||
} else {
|
||||
/* we generate the shift in ecx */
|
||||
gv2(S, RC_INT, RC_ECX);
|
||||
r = S->tccgen_vtop[-1].r;
|
||||
r = S->vtop[-1].r;
|
||||
o(S, 0xd3); /* shl/shr/sar %cl, r */
|
||||
o(S, opc | r);
|
||||
}
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
break;
|
||||
case '/':
|
||||
case TOK_UDIV:
|
||||
|
@ -796,16 +796,16 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
/* first operand must be in eax */
|
||||
/* XXX: need better constraint for second operand */
|
||||
gv2(S, RC_EAX, RC_ECX);
|
||||
r = S->tccgen_vtop[-1].r;
|
||||
fr = S->tccgen_vtop[0].r;
|
||||
S->tccgen_vtop--;
|
||||
r = S->vtop[-1].r;
|
||||
fr = S->vtop[0].r;
|
||||
S->vtop--;
|
||||
save_reg(S, TREG_EDX);
|
||||
/* save EAX too if used otherwise */
|
||||
save_reg_upstack(S, TREG_EAX, 1);
|
||||
if (op == TOK_UMULL) {
|
||||
o(S, 0xf7); /* mul fr */
|
||||
o(S, 0xe0 + fr);
|
||||
S->tccgen_vtop->r2 = TREG_EDX;
|
||||
S->vtop->r2 = TREG_EDX;
|
||||
r = TREG_EAX;
|
||||
} else {
|
||||
if (op == TOK_UDIV || op == TOK_UMOD) {
|
||||
|
@ -820,7 +820,7 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
else
|
||||
r = TREG_EAX;
|
||||
}
|
||||
S->tccgen_vtop->r = r;
|
||||
S->vtop->r = r;
|
||||
break;
|
||||
default:
|
||||
opc = 7;
|
||||
|
@ -831,7 +831,7 @@ ST_FUNC void gen_opi(TCCState* S, int op)
|
|||
/* generate a floating point operation 'v = t1 op t2' instruction. The
|
||||
two operands are guaranteed to have the same floating point type */
|
||||
/* XXX: need to use ST1 too */
|
||||
ST_FUNC void gen_opf(TCCState* S, int op)
|
||||
ST_FUNC void gen_opf(TCCState *S, int op)
|
||||
{
|
||||
int a, ft, fc, swapped, r;
|
||||
|
||||
|
@ -842,17 +842,17 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
}
|
||||
|
||||
/* convert constants to memory references */
|
||||
if ((S->tccgen_vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
if ((S->vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
vswap(S);
|
||||
gv(S, RC_FLOAT);
|
||||
vswap(S);
|
||||
}
|
||||
if ((S->tccgen_vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
|
||||
if ((S->vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
|
||||
gv(S, RC_FLOAT);
|
||||
|
||||
/* must put at least one value in the floating point register */
|
||||
if ((S->tccgen_vtop[-1].r & VT_LVAL) &&
|
||||
(S->tccgen_vtop[0].r & VT_LVAL)) {
|
||||
if ((S->vtop[-1].r & VT_LVAL) &&
|
||||
(S->vtop[0].r & VT_LVAL)) {
|
||||
vswap(S);
|
||||
gv(S, RC_FLOAT);
|
||||
vswap(S);
|
||||
|
@ -860,13 +860,13 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
swapped = 0;
|
||||
/* swap the stack if needed so that t1 is the register and t2 is
|
||||
the memory reference */
|
||||
if (S->tccgen_vtop[-1].r & VT_LVAL) {
|
||||
if (S->vtop[-1].r & VT_LVAL) {
|
||||
vswap(S);
|
||||
swapped = 1;
|
||||
}
|
||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||
/* load on stack second operand */
|
||||
load(S, TREG_ST0, S->tccgen_vtop);
|
||||
load(S, TREG_ST0, S->vtop);
|
||||
save_reg(S, TREG_EAX); /* eax is used by FP comparison code */
|
||||
if (op == TOK_GE || op == TOK_GT)
|
||||
swapped = !swapped;
|
||||
|
@ -893,12 +893,12 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
o(S, 0x45c4f6); /* test $0x45, %ah */
|
||||
op = TOK_EQ;
|
||||
}
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
vset_VT_CMP(S, op);
|
||||
} else {
|
||||
/* no memory reference possible for long double operations */
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
|
||||
load(S, TREG_ST0, S->tccgen_vtop);
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
|
||||
load(S, TREG_ST0, S->vtop);
|
||||
swapped = !swapped;
|
||||
}
|
||||
|
||||
|
@ -921,14 +921,14 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
a++;
|
||||
break;
|
||||
}
|
||||
ft = S->tccgen_vtop->type.t;
|
||||
fc = S->tccgen_vtop->c.i;
|
||||
ft = S->vtop->type.t;
|
||||
fc = S->vtop->c.i;
|
||||
if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
||||
o(S, 0xde); /* fxxxp %st, %st(1) */
|
||||
o(S, 0xc1 + (a << 3));
|
||||
} else {
|
||||
/* if saved lvalue, then we must reload it */
|
||||
r = S->tccgen_vtop->r;
|
||||
r = S->vtop->r;
|
||||
if ((r & VT_VALMASK) == VT_LLOCAL) {
|
||||
SValue v1;
|
||||
r = get_reg(S, RC_INT);
|
||||
|
@ -944,48 +944,48 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
o(S, 0xdc);
|
||||
else
|
||||
o(S, 0xd8);
|
||||
gen_modrm(S, a, r, S->tccgen_vtop->sym, fc);
|
||||
gen_modrm(S, a, r, S->vtop->sym, fc);
|
||||
}
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
|
||||
and 'long long' cases. */
|
||||
ST_FUNC void gen_cvt_itof(TCCState* S, int t)
|
||||
ST_FUNC void gen_cvt_itof(TCCState *S, int t)
|
||||
{
|
||||
save_reg(S, TREG_ST0);
|
||||
gv(S, RC_INT);
|
||||
if ((S->tccgen_vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
if ((S->vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
/* signed long long to float/double/long double (unsigned case
|
||||
is handled generically) */
|
||||
o(S, 0x50 + S->tccgen_vtop->r2); /* push r2 */
|
||||
o(S, 0x50 + (S->tccgen_vtop->r & VT_VALMASK)); /* push r */
|
||||
o(S, 0x50 + S->vtop->r2); /* push r2 */
|
||||
o(S, 0x50 + (S->vtop->r & VT_VALMASK)); /* push r */
|
||||
o(S, 0x242cdf); /* fildll (%esp) */
|
||||
o(S, 0x08c483); /* add $8, %esp */
|
||||
S->tccgen_vtop->r2 = VT_CONST;
|
||||
} else if ((S->tccgen_vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
|
||||
S->vtop->r2 = VT_CONST;
|
||||
} else if ((S->vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
|
||||
(VT_INT | VT_UNSIGNED)) {
|
||||
/* unsigned int to float/double/long double */
|
||||
o(S, 0x6a); /* push $0 */
|
||||
g(S, 0x00);
|
||||
o(S, 0x50 + (S->tccgen_vtop->r & VT_VALMASK)); /* push r */
|
||||
o(S, 0x50 + (S->vtop->r & VT_VALMASK)); /* push r */
|
||||
o(S, 0x242cdf); /* fildll (%esp) */
|
||||
o(S, 0x08c483); /* add $8, %esp */
|
||||
} else {
|
||||
/* int to float/double/long double */
|
||||
o(S, 0x50 + (S->tccgen_vtop->r & VT_VALMASK)); /* push r */
|
||||
o(S, 0x50 + (S->vtop->r & VT_VALMASK)); /* push r */
|
||||
o(S, 0x2404db); /* fildl (%esp) */
|
||||
o(S, 0x04c483); /* add $4, %esp */
|
||||
}
|
||||
S->tccgen_vtop->r2 = VT_CONST;
|
||||
S->tccgen_vtop->r = TREG_ST0;
|
||||
S->vtop->r2 = VT_CONST;
|
||||
S->vtop->r = TREG_ST0;
|
||||
}
|
||||
|
||||
/* convert fp to int 't' type */
|
||||
ST_FUNC void gen_cvt_ftoi(TCCState* S, int t)
|
||||
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t)
|
||||
{
|
||||
int bt = S->tccgen_vtop->type.t & VT_BTYPE;
|
||||
int bt = S->vtop->type.t & VT_BTYPE;
|
||||
if (bt == VT_FLOAT)
|
||||
vpush_helper_func(S, TOK___fixsfdi);
|
||||
else if (bt == VT_LDOUBLE)
|
||||
|
@ -995,20 +995,20 @@ ST_FUNC void gen_cvt_ftoi(TCCState* S, int t)
|
|||
vswap(S);
|
||||
gfunc_call(S, 1);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = REG_IRET;
|
||||
S->vtop->r = REG_IRET;
|
||||
if ((t & VT_BTYPE) == VT_LLONG)
|
||||
S->tccgen_vtop->r2 = REG_IRE2;
|
||||
S->vtop->r2 = REG_IRE2;
|
||||
}
|
||||
|
||||
/* convert from one floating point type to another */
|
||||
ST_FUNC void gen_cvt_ftof(TCCState* S, int t)
|
||||
ST_FUNC void gen_cvt_ftof(TCCState *S, int t)
|
||||
{
|
||||
/* all we have to do on i386 is to put the float in a register */
|
||||
gv(S, RC_FLOAT);
|
||||
}
|
||||
|
||||
/* char/short to int conversion */
|
||||
ST_FUNC void gen_cvt_csti(TCCState* S, int t)
|
||||
ST_FUNC void gen_cvt_csti(TCCState *S, int t)
|
||||
{
|
||||
int r, sz, xl;
|
||||
r = gv(S, RC_INT);
|
||||
|
@ -1021,39 +1021,39 @@ ST_FUNC void gen_cvt_csti(TCCState* S, int t)
|
|||
}
|
||||
|
||||
/* increment tcov counter */
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv)
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv)
|
||||
{
|
||||
o(S, 0x0583); /* addl $1, xxx */
|
||||
greloc(S, cur_text_section, sv->sym, S->tccgen_ind, R_386_32);
|
||||
greloc(S, cur_text_section, sv->sym, S->ind, R_386_32);
|
||||
gen_le32(S, 0);
|
||||
o(S, 1);
|
||||
o(S, 0x1583); /* addcl $0, xxx */
|
||||
greloc(S, cur_text_section, sv->sym, S->tccgen_ind, R_386_32);
|
||||
greloc(S, cur_text_section, sv->sym, S->ind, R_386_32);
|
||||
gen_le32(S, 4);
|
||||
g(S, 0);
|
||||
}
|
||||
|
||||
/* computed goto support */
|
||||
ST_FUNC void ggoto(TCCState* S)
|
||||
ST_FUNC void ggoto(TCCState *S)
|
||||
{
|
||||
gcall_or_jmp(S, 1);
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
}
|
||||
|
||||
/* bound check support functions */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
|
||||
static void gen_bounds_prolog(TCCState* S)
|
||||
static void gen_bounds_prolog(TCCState *S)
|
||||
{
|
||||
/* leave some room for bound checking code */
|
||||
S->func_bound_offset = lbounds_section->data_offset;
|
||||
S->func_bound_ind = S->tccgen_ind;
|
||||
S->func_bound_ind = S->ind;
|
||||
S->func_bound_add_epilog = 0;
|
||||
oad(S, 0xb8, 0); /* lbound section pointer */
|
||||
oad(S, 0xb8, 0); /* call to function */
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(TCCState* S)
|
||||
static void gen_bounds_epilog(TCCState *S)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
|
@ -1067,22 +1067,22 @@ static void gen_bounds_epilog(TCCState* S)
|
|||
bounds_ptr = section_ptr_add(S, lbounds_section, sizeof(addr_t));
|
||||
*bounds_ptr = 0;
|
||||
|
||||
sym_data = get_sym_ref(S, &S->tccgen_char_pointer_type, lbounds_section,
|
||||
sym_data = get_sym_ref(S, &S->char_pointer_type, lbounds_section,
|
||||
S->func_bound_offset, lbounds_section->data_offset);
|
||||
|
||||
/* generate bound local allocation */
|
||||
if (offset_modified) {
|
||||
saved_ind = S->tccgen_ind;
|
||||
S->tccgen_ind = S->func_bound_ind;
|
||||
greloc(S, cur_text_section, sym_data, S->tccgen_ind + 1, R_386_32);
|
||||
S->tccgen_ind = S->tccgen_ind + 5;
|
||||
saved_ind = S->ind;
|
||||
S->ind = S->func_bound_ind;
|
||||
greloc(S, cur_text_section, sym_data, S->ind + 1, R_386_32);
|
||||
S->ind = S->ind + 5;
|
||||
gen_static_call(S, TOK___bound_local_new);
|
||||
S->tccgen_ind = saved_ind;
|
||||
S->ind = saved_ind;
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
o(S, 0x5250); /* save returned value, if any */
|
||||
greloc(S, cur_text_section, sym_data, S->tccgen_ind + 1, R_386_32);
|
||||
greloc(S, cur_text_section, sym_data, S->ind + 1, R_386_32);
|
||||
oad(S, 0xb8, 0); /* mov %eax, xxx */
|
||||
gen_static_call(S, TOK___bound_local_delete);
|
||||
o(S, 0x585a); /* restore returned value, if any */
|
||||
|
@ -1090,20 +1090,20 @@ static void gen_bounds_epilog(TCCState* S)
|
|||
#endif
|
||||
|
||||
/* Save the stack pointer onto the stack */
|
||||
ST_FUNC void gen_vla_sp_save(TCCState* S, int addr) {
|
||||
ST_FUNC void gen_vla_sp_save(TCCState *S, int addr) {
|
||||
/* mov %esp,addr(%ebp)*/
|
||||
o(S, 0x89);
|
||||
gen_modrm(S, TREG_ESP, VT_LOCAL, NULL, addr);
|
||||
}
|
||||
|
||||
/* Restore the SP from a location on the stack */
|
||||
ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr) {
|
||||
ST_FUNC void gen_vla_sp_restore(TCCState *S, int addr) {
|
||||
o(S, 0x8b);
|
||||
gen_modrm(S, TREG_ESP, VT_LOCAL, NULL, addr);
|
||||
}
|
||||
|
||||
/* Subtract from the stack pointer, and push the resulting value onto the stack */
|
||||
ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align) {
|
||||
ST_FUNC void gen_vla_alloc(TCCState *S, CType *type, int align) {
|
||||
int use_call = 0;
|
||||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
|
44
libtcc.c
44
libtcc.c
|
@ -233,7 +233,7 @@ PUB_FUNC char *tcc_fileextension (const char *name)
|
|||
return e ? e : strchr(b, 0);
|
||||
}
|
||||
|
||||
ST_FUNC char *tcc_load_text(TCCState* S, int fd)
|
||||
ST_FUNC char *tcc_load_text(TCCState *S, int fd)
|
||||
{
|
||||
int len = lseek(fd, 0, SEEK_END);
|
||||
char *buf = load_data(S, fd, 0, len + 1);
|
||||
|
@ -275,12 +275,12 @@ PUB_FUNC void *tcc_mallocz_base(unsigned long size)
|
|||
|
||||
#ifndef MEM_DEBUG
|
||||
|
||||
PUB_FUNC void tcc_free(TCCState* S, void *ptr)
|
||||
PUB_FUNC void tcc_free(TCCState *S, void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
PUB_FUNC void *tcc_malloc(TCCState* S, unsigned long size)
|
||||
PUB_FUNC void *tcc_malloc(TCCState *S, unsigned long size)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = malloc(size);
|
||||
|
@ -289,7 +289,7 @@ PUB_FUNC void *tcc_malloc(TCCState* S, unsigned long size)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
PUB_FUNC void *tcc_mallocz(TCCState* S, unsigned long size)
|
||||
PUB_FUNC void *tcc_mallocz(TCCState *S, unsigned long size)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = tcc_malloc(S, size);
|
||||
|
@ -298,7 +298,7 @@ PUB_FUNC void *tcc_mallocz(TCCState* S, unsigned long size)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
PUB_FUNC void *tcc_realloc(TCCState* S, void *ptr, unsigned long size)
|
||||
PUB_FUNC void *tcc_realloc(TCCState *S, void *ptr, unsigned long size)
|
||||
{
|
||||
void *ptr1;
|
||||
ptr1 = realloc(ptr, size);
|
||||
|
@ -307,7 +307,7 @@ PUB_FUNC void *tcc_realloc(TCCState* S, void *ptr, unsigned long size)
|
|||
return ptr1;
|
||||
}
|
||||
|
||||
PUB_FUNC char *tcc_strdup(TCCState* S, const char *str)
|
||||
PUB_FUNC char *tcc_strdup(TCCState *S, const char *str)
|
||||
{
|
||||
char *ptr;
|
||||
ptr = tcc_malloc(S, strlen(str) + 1);
|
||||
|
@ -361,7 +361,7 @@ static mem_debug_header_t *malloc_check(void *ptr, const char *msg)
|
|||
return header;
|
||||
}
|
||||
|
||||
PUB_FUNC void *tcc_malloc_debug(TCCState* S, unsigned long size, const char *file, int line)
|
||||
PUB_FUNC void *tcc_malloc_debug(TCCState *S, unsigned long size, const char *file, int line)
|
||||
{
|
||||
int ofs;
|
||||
mem_debug_header_t *header;
|
||||
|
@ -392,7 +392,7 @@ PUB_FUNC void *tcc_malloc_debug(TCCState* S, unsigned long size, const char *fil
|
|||
return MEM_USER_PTR(header);
|
||||
}
|
||||
|
||||
PUB_FUNC void tcc_free_debug(TCCState* S, void *ptr)
|
||||
PUB_FUNC void tcc_free_debug(TCCState *S, void *ptr)
|
||||
{
|
||||
mem_debug_header_t *header;
|
||||
if (!ptr)
|
||||
|
@ -409,7 +409,7 @@ PUB_FUNC void tcc_free_debug(TCCState* S, void *ptr)
|
|||
free(header);
|
||||
}
|
||||
|
||||
PUB_FUNC void *tcc_mallocz_debug(TCCState* S, unsigned long size, const char *file, int line)
|
||||
PUB_FUNC void *tcc_mallocz_debug(TCCState *S, unsigned long size, const char *file, int line)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = tcc_malloc_debug(S, size,file,line);
|
||||
|
@ -417,7 +417,7 @@ PUB_FUNC void *tcc_mallocz_debug(TCCState* S, unsigned long size, const char *fi
|
|||
return ptr;
|
||||
}
|
||||
|
||||
PUB_FUNC void *tcc_realloc_debug(TCCState* S, void *ptr, unsigned long size, const char *file, int line)
|
||||
PUB_FUNC void *tcc_realloc_debug(TCCState *S, void *ptr, unsigned long size, const char *file, int line)
|
||||
{
|
||||
mem_debug_header_t *header;
|
||||
int mem_debug_chain_update = 0;
|
||||
|
@ -443,7 +443,7 @@ PUB_FUNC void *tcc_realloc_debug(TCCState* S, void *ptr, unsigned long size, con
|
|||
return MEM_USER_PTR(header);
|
||||
}
|
||||
|
||||
PUB_FUNC char *tcc_strdup_debug(TCCState* S, const char *str, const char *file, int line)
|
||||
PUB_FUNC char *tcc_strdup_debug(TCCState *S, const char *str, const char *file, int line)
|
||||
{
|
||||
char *ptr;
|
||||
ptr = tcc_malloc_debug(S, strlen(str) + 1, file, line);
|
||||
|
@ -532,7 +532,7 @@ int vio_close(vio_fd *fd) {
|
|||
/********************************************************/
|
||||
/* dynarrays */
|
||||
|
||||
ST_FUNC void dynarray_add(TCCState* S, void *ptab, int *nb_ptr, void *data)
|
||||
ST_FUNC void dynarray_add(TCCState *S, void *ptab, int *nb_ptr, void *data)
|
||||
{
|
||||
int nb, nb_alloc;
|
||||
void **pp;
|
||||
|
@ -552,7 +552,7 @@ ST_FUNC void dynarray_add(TCCState* S, void *ptab, int *nb_ptr, void *data)
|
|||
*nb_ptr = nb;
|
||||
}
|
||||
|
||||
ST_FUNC void dynarray_reset(TCCState* S, void *pp, int *n)
|
||||
ST_FUNC void dynarray_reset(TCCState *S, void *pp, int *n)
|
||||
{
|
||||
void **p;
|
||||
for (p = *(void***)pp; *n; ++p, --*n)
|
||||
|
@ -608,7 +608,7 @@ static void tcc_split_path(TCCState *S, void *p_ary, int *p_nb_ary, const char *
|
|||
/* error1() modes */
|
||||
enum { ERROR_WARN, ERROR_NOABORT, ERROR_ERROR };
|
||||
|
||||
static void error1(TCCState* S, int mode, const char *fmt, va_list ap)
|
||||
static void error1(TCCState *S, int mode, const char *fmt, va_list ap)
|
||||
{
|
||||
BufferedFile **pf, *f;
|
||||
CString cs;
|
||||
|
@ -650,7 +650,7 @@ static void error1(TCCState* S, int mode, const char *fmt, va_list ap)
|
|||
cstr_printf(S, &cs, "In file included from %s:%d:\n",
|
||||
(*pf)->filename, (*pf)->line_num);
|
||||
cstr_printf(S, &cs, "%s:%d: ",
|
||||
f->filename, (*pf)->line_num - !!(S->tccpp_tok_flags & TOK_FLAG_BOL));
|
||||
f->filename, (*pf)->line_num - !!(S->tok_flags & TOK_FLAG_BOL));
|
||||
} else if (S->current_filename) {
|
||||
cstr_printf(S, &cs, "%s: ", S->current_filename);
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ LIBTCCAPI void *tcc_get_error_opaque(TCCState *S)
|
|||
}
|
||||
|
||||
/* error without aborting current compilation */
|
||||
PUB_FUNC void _tcc_error_noabort(TCCState* S, const char *fmt, ...)
|
||||
PUB_FUNC void _tcc_error_noabort(TCCState *S, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
@ -707,14 +707,14 @@ PUB_FUNC void _tcc_error_noabort(TCCState* S, const char *fmt, ...)
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
PUB_FUNC void _tcc_error(TCCState* S, const char *fmt, ...)
|
||||
PUB_FUNC void _tcc_error(TCCState *S, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
for (;;) error1(S, ERROR_ERROR, fmt, ap);
|
||||
}
|
||||
|
||||
PUB_FUNC void _tcc_warning(TCCState* S, const char *fmt, ...)
|
||||
PUB_FUNC void _tcc_warning(TCCState *S, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
@ -744,10 +744,10 @@ ST_FUNC void tcc_open_bf(TCCState *S, const char *filename, int initlen)
|
|||
bf->fd = -1;
|
||||
bf->prev = S->tccpp_file;
|
||||
S->tccpp_file = bf;
|
||||
S->tccpp_tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
S->tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
}
|
||||
|
||||
ST_FUNC void tcc_close(TCCState* S)
|
||||
ST_FUNC void tcc_close(TCCState *S)
|
||||
{
|
||||
BufferedFile *bf = S->tccpp_file;
|
||||
if (bf->fd > 0) {
|
||||
|
@ -1388,7 +1388,7 @@ static const char *skip_linker_arg(const char **str)
|
|||
return s2;
|
||||
}
|
||||
|
||||
static void copy_linker_arg(TCCState* S, char **pp, const char *s, int sep)
|
||||
static void copy_linker_arg(TCCState *S, char **pp, const char *s, int sep)
|
||||
{
|
||||
const char *q = s;
|
||||
char *p = *pp;
|
||||
|
@ -1723,7 +1723,7 @@ static void args_parser_add_file(TCCState *S, const char* filename, int filetype
|
|||
dynarray_add(S, &S->files, &S->nb_files, f);
|
||||
}
|
||||
|
||||
static int args_parser_make_argv(TCCState* S, const char *r, int *argc, char ***argv)
|
||||
static int args_parser_make_argv(TCCState *S, const char *r, int *argc, char ***argv)
|
||||
{
|
||||
int ret = 0, q, c;
|
||||
CString str;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
#define CONFIG_TCC_ASM
|
||||
#define NB_ASM_REGS 32
|
||||
|
||||
ST_FUNC void g(TCCState* S, int c);
|
||||
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||
ST_FUNC void g(TCCState *S, int c);
|
||||
ST_FUNC void gen_le16(TCCState *S, int c);
|
||||
ST_FUNC void gen_le32(TCCState *S, int c);
|
||||
|
||||
/*************************************************************/
|
||||
#else
|
||||
|
@ -20,44 +20,44 @@ ST_FUNC void gen_le32(TCCState* S, int c);
|
|||
#include "tcc.h"
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(TCCState* S, int c)
|
||||
ST_FUNC void g(TCCState *S, int c)
|
||||
{
|
||||
int ind1;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
ind1 = S->tccgen_ind + 1;
|
||||
ind1 = S->ind + 1;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
cur_text_section->data[S->tccgen_ind] = c;
|
||||
S->tccgen_ind = ind1;
|
||||
cur_text_section->data[S->ind] = c;
|
||||
S->ind = ind1;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le16 (TCCState* S, int i)
|
||||
ST_FUNC void gen_le16 (TCCState *S, int i)
|
||||
{
|
||||
g(S, i);
|
||||
g(S, i>>8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32 (TCCState* S, int i)
|
||||
ST_FUNC void gen_le32 (TCCState *S, int i)
|
||||
{
|
||||
int ind1;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
ind1 = S->tccgen_ind + 4;
|
||||
ind1 = S->ind + 4;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
cur_text_section->data[S->tccgen_ind++] = i & 0xFF;
|
||||
cur_text_section->data[S->tccgen_ind++] = (i >> 8) & 0xFF;
|
||||
cur_text_section->data[S->tccgen_ind++] = (i >> 16) & 0xFF;
|
||||
cur_text_section->data[S->tccgen_ind++] = (i >> 24) & 0xFF;
|
||||
cur_text_section->data[S->ind++] = i & 0xFF;
|
||||
cur_text_section->data[S->ind++] = (i >> 8) & 0xFF;
|
||||
cur_text_section->data[S->ind++] = (i >> 16) & 0xFF;
|
||||
cur_text_section->data[S->ind++] = (i >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||
ST_FUNC void gen_expr32(TCCState *S, ExprValue *pe)
|
||||
{
|
||||
gen_le32(S, pe->v);
|
||||
}
|
||||
|
||||
static void asm_emit_opcode(TCCState* S, uint32_t opcode) {
|
||||
static void asm_emit_opcode(TCCState *S, uint32_t opcode) {
|
||||
gen_le32(S, opcode);
|
||||
}
|
||||
|
||||
|
@ -128,12 +128,12 @@ static void parse_operand(TCCState *S, Operand *op)
|
|||
|
||||
op->type = 0;
|
||||
|
||||
if ((reg = asm_parse_regvar(S, S->tccpp_tok)) != -1) {
|
||||
if ((reg = asm_parse_regvar(S, S->tok)) != -1) {
|
||||
next(S); // skip register name
|
||||
op->type = OP_REG;
|
||||
op->reg = (uint8_t) reg;
|
||||
return;
|
||||
} else if (S->tccpp_tok == '$') {
|
||||
} else if (S->tok == '$') {
|
||||
/* constant value */
|
||||
next(S); // skip '#' or '$'
|
||||
}
|
||||
|
@ -207,11 +207,11 @@ static void asm_emit_u(TCCState *S, int token, uint32_t opcode, const Operand* r
|
|||
gen_le32(S, opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
|
||||
}
|
||||
|
||||
static void asm_binary_opcode(TCCState* S, int token)
|
||||
static void asm_binary_opcode(TCCState *S, int token)
|
||||
{
|
||||
Operand ops[2];
|
||||
parse_operand(S, &ops[0]);
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -230,7 +230,7 @@ static void asm_binary_opcode(TCCState* S, int token)
|
|||
}
|
||||
|
||||
/* caller: Add funct3, funct7 into opcode */
|
||||
static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
||||
static void asm_emit_r(TCCState *S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
||||
{
|
||||
if (rd->type != OP_REG) {
|
||||
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
|
||||
|
@ -255,7 +255,7 @@ static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* r
|
|||
}
|
||||
|
||||
/* caller: Add funct3 into opcode */
|
||||
static void asm_emit_i(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
||||
static void asm_emit_i(TCCState *S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
||||
{
|
||||
if (rd->type != OP_REG) {
|
||||
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
|
||||
|
@ -283,12 +283,12 @@ static void asm_shift_opcode(TCCState *S, int token)
|
|||
{
|
||||
Operand ops[3];
|
||||
parse_operand(S, &ops[0]);
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
parse_operand(S, &ops[1]);
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -336,16 +336,16 @@ static void asm_shift_opcode(TCCState *S, int token)
|
|||
}
|
||||
}
|
||||
|
||||
static void asm_data_processing_opcode(TCCState* S, int token)
|
||||
static void asm_data_processing_opcode(TCCState *S, int token)
|
||||
{
|
||||
Operand ops[3];
|
||||
parse_operand(S, &ops[0]);
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
parse_operand(S, &ops[1]);
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -414,7 +414,7 @@ static void asm_data_processing_opcode(TCCState* S, int token)
|
|||
}
|
||||
|
||||
/* caller: Add funct3 to opcode */
|
||||
static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
|
||||
static void asm_emit_s(TCCState *S, int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
|
||||
{
|
||||
if (rs1->type != OP_REG) {
|
||||
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
|
||||
|
@ -442,7 +442,7 @@ static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* r
|
|||
}
|
||||
}
|
||||
|
||||
static void asm_data_transfer_opcode(TCCState* S, int token)
|
||||
static void asm_data_transfer_opcode(TCCState *S, int token)
|
||||
{
|
||||
Operand ops[3];
|
||||
parse_operand(S, &ops[0]);
|
||||
|
@ -450,7 +450,7 @@ static void asm_data_transfer_opcode(TCCState* S, int token)
|
|||
expect(S, "register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -459,7 +459,7 @@ static void asm_data_transfer_opcode(TCCState* S, int token)
|
|||
expect(S, "register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -511,7 +511,7 @@ static void asm_data_transfer_opcode(TCCState* S, int token)
|
|||
}
|
||||
}
|
||||
|
||||
static void asm_branch_opcode(TCCState* S, int token)
|
||||
static void asm_branch_opcode(TCCState *S, int token)
|
||||
{
|
||||
// Branch (RS1,RS2,IMM); SB-format
|
||||
uint32_t opcode = (0x18 << 2) | 3;
|
||||
|
@ -522,7 +522,7 @@ static void asm_branch_opcode(TCCState* S, int token)
|
|||
expect(S, "register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -531,7 +531,7 @@ static void asm_branch_opcode(TCCState* S, int token)
|
|||
expect(S, "register");
|
||||
return;
|
||||
}
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
next(S);
|
||||
else
|
||||
expect(S, "','");
|
||||
|
@ -709,7 +709,7 @@ ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
|
|||
clobber_regs[reg] = 1;
|
||||
}
|
||||
|
||||
ST_FUNC int asm_parse_regvar (TCCState* S, int t)
|
||||
ST_FUNC int asm_parse_regvar (TCCState *S, int t)
|
||||
{
|
||||
if (t >= TOK_ASM_x0 && t <= TOK_ASM_pc) { /* register name */
|
||||
switch (t) {
|
||||
|
|
394
riscv64-gen.c
394
riscv64-gen.c
|
@ -100,37 +100,37 @@ static int is_freg(int r)
|
|||
return r >= 8 && r < 16;
|
||||
}
|
||||
|
||||
ST_FUNC void o(TCCState* S, unsigned int c)
|
||||
ST_FUNC void o(TCCState *S, unsigned int c)
|
||||
{
|
||||
int ind1 = S->tccgen_ind + 4;
|
||||
if (S->tccgen_nocode_wanted)
|
||||
int ind1 = S->ind + 4;
|
||||
if (S->nocode_wanted)
|
||||
return;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(S, cur_text_section, ind1);
|
||||
write32le(cur_text_section->data + S->tccgen_ind, c);
|
||||
S->tccgen_ind = ind1;
|
||||
write32le(cur_text_section->data + S->ind, c);
|
||||
S->ind = ind1;
|
||||
}
|
||||
|
||||
static void EIu(TCCState* S, uint32_t opcode, uint32_t func3,
|
||||
static void EIu(TCCState *S, uint32_t opcode, uint32_t func3,
|
||||
uint32_t rd, uint32_t rs1, uint32_t imm)
|
||||
{
|
||||
o(S, opcode | (func3 << 12) | (rd << 7) | (rs1 << 15) | (imm << 20));
|
||||
}
|
||||
|
||||
static void ER(TCCState* S, uint32_t opcode, uint32_t func3,
|
||||
static void ER(TCCState *S, uint32_t opcode, uint32_t func3,
|
||||
uint32_t rd, uint32_t rs1, uint32_t rs2, uint32_t func7)
|
||||
{
|
||||
o(S, opcode | func3 << 12 | rd << 7 | rs1 << 15 | rs2 << 20 | func7 << 25);
|
||||
}
|
||||
|
||||
static void EI(TCCState* S, uint32_t opcode, uint32_t func3,
|
||||
static void EI(TCCState *S, uint32_t opcode, uint32_t func3,
|
||||
uint32_t rd, uint32_t rs1, uint32_t imm)
|
||||
{
|
||||
assert(! ((imm + (1 << 11)) >> 12));
|
||||
EIu(S, opcode, func3, rd, rs1, imm);
|
||||
}
|
||||
|
||||
static void ES(TCCState* S, uint32_t opcode, uint32_t func3,
|
||||
static void ES(TCCState *S, uint32_t opcode, uint32_t func3,
|
||||
uint32_t rs1, uint32_t rs2, uint32_t imm)
|
||||
{
|
||||
assert(! ((imm + (1 << 11)) >> 12));
|
||||
|
@ -139,7 +139,7 @@ static void ES(TCCState* S, uint32_t opcode, uint32_t func3,
|
|||
}
|
||||
|
||||
// Patch all branches in list pointed to by t to branch to a:
|
||||
ST_FUNC void gsym_addr(TCCState* S, int t_, int a_)
|
||||
ST_FUNC void gsym_addr(TCCState *S, int t_, int a_)
|
||||
{
|
||||
uint32_t t = t_;
|
||||
uint32_t a = a_;
|
||||
|
@ -158,7 +158,7 @@ ST_FUNC void gsym_addr(TCCState* S, int t_, int a_)
|
|||
}
|
||||
}
|
||||
|
||||
static int load_symofs(TCCState* S, int r, SValue *sv, int forstore)
|
||||
static int load_symofs(TCCState *S, int r, SValue *sv, int forstore)
|
||||
{
|
||||
int rr, doload = 0;
|
||||
int fc = sv->c.i, v = sv->r & VT_VALMASK;
|
||||
|
@ -166,21 +166,21 @@ static int load_symofs(TCCState* S, int r, SValue *sv, int forstore)
|
|||
Sym label = {0};
|
||||
assert(v == VT_CONST);
|
||||
if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax
|
||||
greloca(S, cur_text_section, sv->sym, S->tccgen_ind,
|
||||
greloca(S, cur_text_section, sv->sym, S->ind,
|
||||
R_RISCV_PCREL_HI20, sv->c.i);
|
||||
sv->c.i = 0;
|
||||
} else {
|
||||
if (((unsigned)fc + (1 << 11)) >> 12)
|
||||
tcc_error(S, "unimp: large addend for global address (0x%lx)", (long)sv->c.i);
|
||||
greloca(S, cur_text_section, sv->sym, S->tccgen_ind,
|
||||
greloca(S, cur_text_section, sv->sym, S->ind,
|
||||
R_RISCV_GOT_HI20, 0);
|
||||
doload = 1;
|
||||
}
|
||||
label.type.t = VT_VOID | VT_STATIC;
|
||||
put_extern_sym(S, &label, cur_text_section, S->tccgen_ind, 0);
|
||||
put_extern_sym(S, &label, cur_text_section, S->ind, 0);
|
||||
rr = is_ireg(r) ? ireg(r) : 5;
|
||||
o(S, 0x17 | (rr << 7)); // auipc RR, 0 %pcrel_hi(sym)+addend
|
||||
greloca(S, cur_text_section, &label, S->tccgen_ind,
|
||||
greloca(S, cur_text_section, &label, S->ind,
|
||||
doload || !forstore
|
||||
? R_RISCV_PCREL_LO12_I : R_RISCV_PCREL_LO12_S, 0);
|
||||
if (doload) {
|
||||
|
@ -201,7 +201,7 @@ static int load_symofs(TCCState* S, int r, SValue *sv, int forstore)
|
|||
return rr;
|
||||
}
|
||||
|
||||
static void load_large_constant(TCCState* S, int rr, int fc, uint32_t pi)
|
||||
static void load_large_constant(TCCState *S, int rr, int fc, uint32_t pi)
|
||||
{
|
||||
if (fc < 0)
|
||||
pi++;
|
||||
|
@ -215,7 +215,7 @@ static void load_large_constant(TCCState* S, int rr, int fc, uint32_t pi)
|
|||
EI(S, 0x13, 1, rr, rr, 8); // slli RR, RR, 8
|
||||
}
|
||||
|
||||
ST_FUNC void load(TCCState* S, int r, SValue *sv)
|
||||
ST_FUNC void load(TCCState *S, int r, SValue *sv)
|
||||
{
|
||||
int fr = sv->r;
|
||||
int v = fr & VT_VALMASK;
|
||||
|
@ -314,9 +314,9 @@ ST_FUNC void load(TCCState* S, int r, SValue *sv)
|
|||
| (func7 << 25)); // fmv.{w.x, x.w, d.x, x.d} RR, VR
|
||||
}
|
||||
} else if (v == VT_CMP) {
|
||||
int op = S->tccgen_vtop->cmp_op;
|
||||
int a = S->tccgen_vtop->cmp_r & 0xff;
|
||||
int b = (S->tccgen_vtop->cmp_r >> 8) & 0xff;
|
||||
int op = S->vtop->cmp_op;
|
||||
int a = S->vtop->cmp_r & 0xff;
|
||||
int b = (S->vtop->cmp_r >> 8) & 0xff;
|
||||
int inv = 0;
|
||||
switch (op) {
|
||||
case TOK_ULT:
|
||||
|
@ -353,14 +353,14 @@ ST_FUNC void load(TCCState* S, int r, SValue *sv)
|
|||
int t = v & 1;
|
||||
assert(is_ireg(r));
|
||||
EI(S, 0x13, 0, rr, 0, t); // addi RR, x0, t
|
||||
gjmp_addr(S, S->tccgen_ind + 8);
|
||||
gjmp_addr(S, S->ind + 8);
|
||||
gsym(S, fc);
|
||||
EI(S, 0x13, 0, rr, 0, t ^ 1); // addi RR, x0, !t
|
||||
} else
|
||||
tcc_error(S, "unimp: load(non-const)");
|
||||
}
|
||||
|
||||
ST_FUNC void store(TCCState* S, int r, SValue *sv)
|
||||
ST_FUNC void store(TCCState *S, int r, SValue *sv)
|
||||
{
|
||||
int fr = sv->r & VT_VALMASK;
|
||||
int rr = is_ireg(r) ? ireg(r) : freg(r), ptrreg;
|
||||
|
@ -403,22 +403,22 @@ ST_FUNC void store(TCCState* S, int r, SValue *sv)
|
|||
ptrreg, rr, fc); // RR, fc(base)
|
||||
}
|
||||
|
||||
static void gcall_or_jmp(TCCState* S, int docall)
|
||||
static void gcall_or_jmp(TCCState *S, int docall)
|
||||
{
|
||||
int tr = docall ? 1 : 5; // ra or t0
|
||||
if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
||||
((S->tccgen_vtop->r & VT_SYM) && S->tccgen_vtop->c.i == (int)S->tccgen_vtop->c.i)) {
|
||||
if ((S->vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
||||
((S->vtop->r & VT_SYM) && S->vtop->c.i == (int)S->vtop->c.i)) {
|
||||
/* constant symbolic case -> simple relocation */
|
||||
greloca(S, cur_text_section, S->tccgen_vtop->sym, S->tccgen_ind,
|
||||
R_RISCV_CALL_PLT, (int)S->tccgen_vtop->c.i);
|
||||
greloca(S, cur_text_section, S->vtop->sym, S->ind,
|
||||
R_RISCV_CALL_PLT, (int)S->vtop->c.i);
|
||||
o(S, 0x17 | (tr << 7)); // auipc TR, 0 %call(func)
|
||||
EI(S, 0x67, 0, tr, tr, 0);// jalr TR, r(TR)
|
||||
} else if (S->tccgen_vtop->r < VT_CONST) {
|
||||
int r = ireg(S->tccgen_vtop->r);
|
||||
} else if (S->vtop->r < VT_CONST) {
|
||||
int r = ireg(S->vtop->r);
|
||||
EI(S, 0x67, 0, tr, r, 0); // jalr TR, 0(R)
|
||||
} else {
|
||||
int r = TREG_RA;
|
||||
load(S, r, S->tccgen_vtop);
|
||||
load(S, r, S->vtop);
|
||||
r = ireg(r);
|
||||
EI(S, 0x67, 0, tr, r, 0); // jalr TR, 0(R)
|
||||
}
|
||||
|
@ -426,20 +426,20 @@ static void gcall_or_jmp(TCCState* S, int docall)
|
|||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
||||
static void gen_bounds_call(TCCState* S, int v)
|
||||
static void gen_bounds_call(TCCState *S, int v)
|
||||
{
|
||||
Sym *sym = external_helper_sym(S, v);
|
||||
|
||||
greloca(S, cur_text_section, sym, S->tccgen_ind, R_RISCV_CALL_PLT, 0);
|
||||
greloca(S, cur_text_section, sym, S->ind, R_RISCV_CALL_PLT, 0);
|
||||
o(S, 0x17 | (1 << 7)); // auipc TR, 0 %call(func)
|
||||
EI(S, 0x67, 0, 1, 1, 0); // jalr TR, r(TR)
|
||||
}
|
||||
|
||||
static void gen_bounds_prolog(TCCState* S)
|
||||
static void gen_bounds_prolog(TCCState *S)
|
||||
{
|
||||
/* leave some room for bound checking code */
|
||||
S->func_bound_offset = lbounds_section->data_offset;
|
||||
S->func_bound_ind = S->tccgen_ind;
|
||||
S->func_bound_ind = S->ind;
|
||||
S->func_bound_add_epilog = 0;
|
||||
o(S, 0x00000013); /* ld a0,#lbound section pointer */
|
||||
o(S, 0x00000013);
|
||||
|
@ -447,7 +447,7 @@ static void gen_bounds_prolog(TCCState* S)
|
|||
o(S, 0x00000013);
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(TCCState* S)
|
||||
static void gen_bounds_epilog(TCCState *S)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
|
@ -463,31 +463,31 @@ static void gen_bounds_epilog(TCCState* S)
|
|||
bounds_ptr = section_ptr_add(S, lbounds_section, sizeof(addr_t));
|
||||
*bounds_ptr = 0;
|
||||
|
||||
sym_data = get_sym_ref(S, &S->tccgen_char_pointer_type, lbounds_section,
|
||||
sym_data = get_sym_ref(S, &S->char_pointer_type, lbounds_section,
|
||||
S->func_bound_offset, lbounds_section->data_offset);
|
||||
|
||||
label.type.t = VT_VOID | VT_STATIC;
|
||||
/* generate bound local allocation */
|
||||
if (offset_modified) {
|
||||
saved_ind = S->tccgen_ind;
|
||||
S->tccgen_ind = S->func_bound_ind;
|
||||
put_extern_sym(S, &label, cur_text_section, S->tccgen_ind, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->tccgen_ind, R_RISCV_GOT_HI20, 0);
|
||||
saved_ind = S->ind;
|
||||
S->ind = S->func_bound_ind;
|
||||
put_extern_sym(S, &label, cur_text_section, S->ind, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->ind, R_RISCV_GOT_HI20, 0);
|
||||
o(S, 0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
|
||||
greloca(S, cur_text_section, &label, S->tccgen_ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
greloca(S, cur_text_section, &label, S->ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
EI(S, 0x03, 3, 10, 10, 0); // ld a0, 0(a0)
|
||||
gen_bounds_call(S, TOK___bound_local_new);
|
||||
S->tccgen_ind = saved_ind;
|
||||
S->ind = saved_ind;
|
||||
label.c = 0; /* force new local ELF symbol */
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
o(S, 0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
|
||||
o(S, 0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
|
||||
put_extern_sym(S, &label, cur_text_section, S->tccgen_ind, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->tccgen_ind, R_RISCV_GOT_HI20, 0);
|
||||
put_extern_sym(S, &label, cur_text_section, S->ind, 0);
|
||||
greloca(S, cur_text_section, sym_data, S->ind, R_RISCV_GOT_HI20, 0);
|
||||
o(S, 0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
|
||||
greloca(S, cur_text_section, &label, S->tccgen_ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
greloca(S, cur_text_section, &label, S->ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
EI(S, 0x03, 3, 10, 10, 0); // ld a0, 0(a0)
|
||||
gen_bounds_call(S, TOK___bound_local_delete);
|
||||
o(S, 0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
|
||||
|
@ -540,7 +540,7 @@ static void reg_pass(CType *type, int *prc, int *fieldofs, int named)
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
||||
ST_FUNC void gfunc_call(TCCState *S, int nb_args)
|
||||
{
|
||||
int i, align, size, areg[2];
|
||||
int *info = tcc_malloc(S, (nb_args + 1) * sizeof (int));
|
||||
|
@ -556,11 +556,11 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
|
||||
areg[0] = 0; /* int arg regs */
|
||||
areg[1] = 8; /* float arg regs */
|
||||
sa = S->tccgen_vtop[-nb_args].type.ref->next;
|
||||
sa = S->vtop[-nb_args].type.ref->next;
|
||||
for (i = 0; i < nb_args; i++) {
|
||||
int nregs, byref = 0, tempofs;
|
||||
int prc[3], fieldofs[3];
|
||||
sv = &S->tccgen_vtop[1 + i - nb_args];
|
||||
sv = &S->vtop[1 + i - nb_args];
|
||||
sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c
|
||||
size = type_size(&sv->type, &align);
|
||||
if (size > 16) {
|
||||
|
@ -617,7 +617,7 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
stack_add = stack_adj + tempspace;
|
||||
|
||||
/* fetch cpu flag before generating any code */
|
||||
if ((S->tccgen_vtop->r & VT_VALMASK) == VT_CMP)
|
||||
if ((S->vtop->r & VT_VALMASK) == VT_CMP)
|
||||
gv(S, RC_INT);
|
||||
|
||||
if (stack_add) {
|
||||
|
@ -631,15 +631,15 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
for (i = ofs = 0; i < nb_args; i++) {
|
||||
if (info[i] & (64 | 32)) {
|
||||
vrotb(S, nb_args - i);
|
||||
size = type_size(&S->tccgen_vtop->type, &align);
|
||||
size = type_size(&S->vtop->type, &align);
|
||||
if (info[i] & 64) {
|
||||
vset(S, &S->tccgen_char_pointer_type, TREG_SP, 0);
|
||||
vset(S, &S->char_pointer_type, TREG_SP, 0);
|
||||
vpushi(S, stack_adj + (info[i] >> 7));
|
||||
gen_op(S, '+');
|
||||
vpushv(S, S->tccgen_vtop); // this replaces the old argument
|
||||
vpushv(S, S->vtop); // this replaces the old argument
|
||||
vrott(S, 3);
|
||||
indir(S);
|
||||
S->tccgen_vtop->type = S->tccgen_vtop[-1].type;
|
||||
S->vtop->type = S->vtop[-1].type;
|
||||
vswap(S);
|
||||
vstore(S);
|
||||
vpop(S);
|
||||
|
@ -649,18 +649,18 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
if (align < XLEN)
|
||||
align = XLEN;
|
||||
/* Once we support offseted regs we can do this:
|
||||
vset(S, &S->tccgen_vtop->type, TREG_SP | VT_LVAL, ofs);
|
||||
vset(S, &S->vtop->type, TREG_SP | VT_LVAL, ofs);
|
||||
to construct the lvalue for the outgoing stack slot,
|
||||
until then we have to jump through hoops. */
|
||||
vset(S, &S->tccgen_char_pointer_type, TREG_SP, 0);
|
||||
vset(S, &S->char_pointer_type, TREG_SP, 0);
|
||||
ofs = (ofs + align - 1) & -align;
|
||||
vpushi(S, ofs);
|
||||
gen_op(S, '+');
|
||||
indir(S);
|
||||
S->tccgen_vtop->type = S->tccgen_vtop[-1].type;
|
||||
S->vtop->type = S->vtop[-1].type;
|
||||
vswap(S);
|
||||
vstore(S);
|
||||
S->tccgen_vtop->r = S->tccgen_vtop->r2 = VT_CONST; // this arg is done
|
||||
S->vtop->r = S->vtop->r2 = VT_CONST; // this arg is done
|
||||
ofs += size;
|
||||
}
|
||||
vrott(S, nb_args - i);
|
||||
|
@ -680,11 +680,11 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
r2 = r2 & 64 ? 0 : (r2 >> 7) & 31;
|
||||
assert(r2 <= 16);
|
||||
vrotb(S, i+1);
|
||||
origtype = S->tccgen_vtop->type;
|
||||
size = type_size(&S->tccgen_vtop->type, &align);
|
||||
origtype = S->vtop->type;
|
||||
size = type_size(&S->vtop->type, &align);
|
||||
if (size == 0)
|
||||
goto done;
|
||||
loadt = S->tccgen_vtop->type.t & VT_BTYPE;
|
||||
loadt = S->vtop->type.t & VT_BTYPE;
|
||||
if (loadt == VT_STRUCT) {
|
||||
loadt = (ii >> 12) & VT_BTYPE;
|
||||
}
|
||||
|
@ -697,18 +697,18 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
r2--;
|
||||
} else if (r2) {
|
||||
test_lvalue(S);
|
||||
vpushv(S, S->tccgen_vtop);
|
||||
vpushv(S, S->vtop);
|
||||
}
|
||||
S->tccgen_vtop->type.t = loadt | (S->tccgen_vtop->type.t & VT_UNSIGNED);
|
||||
S->vtop->type.t = loadt | (S->vtop->type.t & VT_UNSIGNED);
|
||||
gv(S, r < 8 ? RC_R(r) : RC_F(r - 8));
|
||||
S->tccgen_vtop->type = origtype;
|
||||
S->vtop->type = origtype;
|
||||
|
||||
if (r2 && loadt != VT_LDOUBLE) {
|
||||
r2--;
|
||||
assert(r2 < 16 || r2 == TREG_RA);
|
||||
vswap(S);
|
||||
gaddrof(S);
|
||||
S->tccgen_vtop->type = S->tccgen_char_pointer_type;
|
||||
S->vtop->type = S->char_pointer_type;
|
||||
vpushi(S, ii >> 20);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if ((origtype.t & VT_BTYPE) == VT_STRUCT)
|
||||
|
@ -719,27 +719,27 @@ ST_FUNC void gfunc_call(TCCState* S, int nb_args)
|
|||
S->do_bounds_check = bc_save;
|
||||
#endif
|
||||
indir(S);
|
||||
S->tccgen_vtop->type = origtype;
|
||||
loadt = S->tccgen_vtop->type.t & VT_BTYPE;
|
||||
S->vtop->type = origtype;
|
||||
loadt = S->vtop->type.t & VT_BTYPE;
|
||||
if (loadt == VT_STRUCT) {
|
||||
loadt = (ii >> 16) & VT_BTYPE;
|
||||
}
|
||||
save_reg_upstack(S, r2, 1);
|
||||
S->tccgen_vtop->type.t = loadt | (S->tccgen_vtop->type.t & VT_UNSIGNED);
|
||||
load(S, r2, S->tccgen_vtop);
|
||||
S->vtop->type.t = loadt | (S->vtop->type.t & VT_UNSIGNED);
|
||||
load(S, r2, S->vtop);
|
||||
assert(r2 < VT_CONST);
|
||||
S->tccgen_vtop--;
|
||||
S->tccgen_vtop->r2 = r2;
|
||||
S->vtop--;
|
||||
S->vtop->r2 = r2;
|
||||
}
|
||||
if (info[nb_args - 1 - i] & 16) {
|
||||
ES(S, 0x23, 3, 2, ireg(S->tccgen_vtop->r2), splitofs); // sd t0, ofs(sp)
|
||||
S->tccgen_vtop->r2 = VT_CONST;
|
||||
} else if (loadt == VT_LDOUBLE && S->tccgen_vtop->r2 != r2) {
|
||||
assert(S->tccgen_vtop->r2 <= 7 && r2 <= 7);
|
||||
ES(S, 0x23, 3, 2, ireg(S->vtop->r2), splitofs); // sd t0, ofs(sp)
|
||||
S->vtop->r2 = VT_CONST;
|
||||
} else if (loadt == VT_LDOUBLE && S->vtop->r2 != r2) {
|
||||
assert(S->vtop->r2 <= 7 && r2 <= 7);
|
||||
/* XXX we'd like to have 'gv' move directly into
|
||||
the right class instead of us fixing it up. */
|
||||
EI(S, 0x13, 0, ireg(r2), ireg(S->tccgen_vtop->r2), 0); // mv Ra+1, RR2
|
||||
S->tccgen_vtop->r2 = r2;
|
||||
EI(S, 0x13, 0, ireg(r2), ireg(S->vtop->r2), 0); // mv Ra+1, RR2
|
||||
S->vtop->r2 = r2;
|
||||
}
|
||||
done:
|
||||
vrott(S, i+1);
|
||||
|
@ -748,7 +748,7 @@ done:
|
|||
vrotb(S, nb_args + 1);
|
||||
save_regs(S, nb_args + 1);
|
||||
gcall_or_jmp(S, 1);
|
||||
S->tccgen_vtop -= nb_args + 1;
|
||||
S->vtop -= nb_args + 1;
|
||||
if (stack_add) {
|
||||
if (stack_add >= 0x1000) {
|
||||
o(S, 0x37 | (5 << 7) | (stack_add & 0xfffff000)); //lui t0, upper(v)
|
||||
|
@ -763,7 +763,7 @@ done:
|
|||
|
||||
static int func_sub_sp_offset, num_va_regs, func_va_list_ofs;
|
||||
|
||||
ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
||||
ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
int i, addr, align, size;
|
||||
|
@ -773,9 +773,9 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
CType *type;
|
||||
|
||||
sym = func_type->ref;
|
||||
S->tccgen_loc = -16; // for ra and s0
|
||||
func_sub_sp_offset = S->tccgen_ind;
|
||||
S->tccgen_ind += 5 * 4;
|
||||
S->loc = -16; // for ra and s0
|
||||
func_sub_sp_offset = S->ind;
|
||||
S->ind += 5 * 4;
|
||||
|
||||
areg[0] = 0, areg[1] = 0;
|
||||
addr = 0;
|
||||
|
@ -783,9 +783,9 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
implicit pointer parameter */
|
||||
size = type_size(&S->tccgen_func_vt, &align);
|
||||
if (size > 2 * XLEN) {
|
||||
S->tccgen_loc -= 8;
|
||||
S->tccgen_func_vc = S->tccgen_loc;
|
||||
ES(S, 0x23, 3, 8, 10 + areg[0]++, S->tccgen_loc); // sd a0, loc(s0)
|
||||
S->loc -= 8;
|
||||
S->tccgen_func_vc = S->loc;
|
||||
ES(S, 0x23, 3, 8, 10 + areg[0]++, S->loc); // sd a0, loc(s0)
|
||||
}
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
|
@ -795,7 +795,7 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
type = &sym->type;
|
||||
size = type_size(type, &align);
|
||||
if (size > 2 * XLEN) {
|
||||
type = &S->tccgen_char_pointer_type;
|
||||
type = &S->char_pointer_type;
|
||||
size = align = byref = 8;
|
||||
}
|
||||
reg_pass(type, prc, fieldofs, 1);
|
||||
|
@ -810,18 +810,18 @@ ST_FUNC void gfunc_prolog(TCCState* S, Sym *func_sym)
|
|||
param_addr = addr;
|
||||
addr += size;
|
||||
} else {
|
||||
S->tccgen_loc -= regcount * 8; // XXX could reserve only 'size' bytes
|
||||
param_addr = S->tccgen_loc;
|
||||
S->loc -= regcount * 8; // XXX could reserve only 'size' bytes
|
||||
param_addr = S->loc;
|
||||
for (i = 0; i < regcount; i++) {
|
||||
if (areg[prc[1+i] - 1] >= 8) {
|
||||
assert(i == 1 && regcount == 2 && !(addr & 7));
|
||||
EI(S, 0x03, 3, 5, 8, addr); // ld t0, addr(s0)
|
||||
addr += 8;
|
||||
ES(S, 0x23, 3, 8, 5, S->tccgen_loc + i*8); // sd t0, loc(s0)
|
||||
ES(S, 0x23, 3, 8, 5, S->loc + i*8); // sd t0, loc(s0)
|
||||
} else if (prc[1+i] == RC_FLOAT) {
|
||||
ES(S, 0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + areg[1]++, S->tccgen_loc + (fieldofs[i+1] >> 4)); // fs[wd] FAi, loc(s0)
|
||||
ES(S, 0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + areg[1]++, S->loc + (fieldofs[i+1] >> 4)); // fs[wd] FAi, loc(s0)
|
||||
} else {
|
||||
ES(S, 0x23, 3, 8, 10 + areg[0]++, S->tccgen_loc + i*8); // sd aX, loc(s0) // XXX
|
||||
ES(S, 0x23, 3, 8, 10 + areg[0]++, S->loc + i*8); // sd aX, loc(s0) // XXX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -864,22 +864,22 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
|
|||
return nregs;
|
||||
}
|
||||
|
||||
ST_FUNC void arch_transfer_ret_regs(TCCState* S, int aftercall)
|
||||
ST_FUNC void arch_transfer_ret_regs(TCCState *S, int aftercall)
|
||||
{
|
||||
int prc[3], fieldofs[3];
|
||||
reg_pass(&S->tccgen_vtop->type, prc, fieldofs, 1);
|
||||
reg_pass(&S->vtop->type, prc, fieldofs, 1);
|
||||
assert(prc[0] == 2 && prc[1] != prc[2] && !(fieldofs[1] >> 4));
|
||||
assert(S->tccgen_vtop->r == (VT_LOCAL | VT_LVAL));
|
||||
vpushv(S, S->tccgen_vtop);
|
||||
S->tccgen_vtop->type.t = fieldofs[1] & VT_BTYPE;
|
||||
(aftercall ? store : load)(S, prc[1] == RC_INT ? REG_IRET : REG_FRET, S->tccgen_vtop);
|
||||
S->tccgen_vtop->c.i += fieldofs[2] >> 4;
|
||||
S->tccgen_vtop->type.t = fieldofs[2] & VT_BTYPE;
|
||||
(aftercall ? store : load)(S, prc[2] == RC_INT ? REG_IRET : REG_FRET, S->tccgen_vtop);
|
||||
S->tccgen_vtop--;
|
||||
assert(S->vtop->r == (VT_LOCAL | VT_LVAL));
|
||||
vpushv(S, S->vtop);
|
||||
S->vtop->type.t = fieldofs[1] & VT_BTYPE;
|
||||
(aftercall ? store : load)(S, prc[1] == RC_INT ? REG_IRET : REG_FRET, S->vtop);
|
||||
S->vtop->c.i += fieldofs[2] >> 4;
|
||||
S->vtop->type.t = fieldofs[2] & VT_BTYPE;
|
||||
(aftercall ? store : load)(S, prc[2] == RC_INT ? REG_IRET : REG_FRET, S->vtop);
|
||||
S->vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_epilog(TCCState* S)
|
||||
ST_FUNC void gfunc_epilog(TCCState *S)
|
||||
{
|
||||
int v, saved_ind, d, large_ofs_ind;
|
||||
|
||||
|
@ -888,8 +888,8 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
gen_bounds_epilog(S);
|
||||
#endif
|
||||
|
||||
S->tccgen_loc = (S->tccgen_loc - num_va_regs * 8);
|
||||
d = v = (-S->tccgen_loc + 15) & -16;
|
||||
S->loc = (S->loc - num_va_regs * 8);
|
||||
d = v = (-S->loc + 15) & -16;
|
||||
|
||||
if (v >= (1 << 11)) {
|
||||
d = 16;
|
||||
|
@ -901,7 +901,7 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
EI(S, 0x03, 3, 8, 2, d - 16 - num_va_regs * 8); // ld s0, v-16(sp)
|
||||
EI(S, 0x13, 0, 2, 2, d); // addi sp, sp, v
|
||||
EI(S, 0x67, 0, 0, 1, 0); // jalr x0, 0(x1), aka ret
|
||||
large_ofs_ind = S->tccgen_ind;
|
||||
large_ofs_ind = S->ind;
|
||||
if (v >= (1 << 11)) {
|
||||
EI(S, 0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d
|
||||
o(S, 0x37 | (5 << 7) | ((0x800 + (v-16)) & 0xfffff000)); //lui t0, upper(v)
|
||||
|
@ -909,9 +909,9 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
ER(S, 0x33, 0, 2, 2, 5, 0x20); // sub sp, sp, t0
|
||||
gjmp_addr(S, func_sub_sp_offset + 5*4);
|
||||
}
|
||||
saved_ind = S->tccgen_ind;
|
||||
saved_ind = S->ind;
|
||||
|
||||
S->tccgen_ind = func_sub_sp_offset;
|
||||
S->ind = func_sub_sp_offset;
|
||||
EI(S, 0x13, 0, 2, 2, -d); // addi sp, sp, -d
|
||||
ES(S, 0x23, 3, 2, 1, d - 8 - num_va_regs * 8); // sd ra, d-8(sp)
|
||||
ES(S, 0x23, 3, 2, 8, d - 16 - num_va_regs * 8); // sd s0, d-16(sp)
|
||||
|
@ -919,18 +919,18 @@ ST_FUNC void gfunc_epilog(TCCState* S)
|
|||
EI(S, 0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d
|
||||
else
|
||||
gjmp_addr(S, large_ofs_ind);
|
||||
if ((S->tccgen_ind - func_sub_sp_offset) != 5*4)
|
||||
if ((S->ind - func_sub_sp_offset) != 5*4)
|
||||
EI(S, 0x13, 0, 0, 0, 0); // addi x0, x0, 0 == nop
|
||||
S->tccgen_ind = saved_ind;
|
||||
S->ind = saved_ind;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_va_start(TCCState *S)
|
||||
{
|
||||
S->tccgen_vtop--;
|
||||
vset(S, &S->tccgen_char_pointer_type, VT_LOCAL, func_va_list_ofs);
|
||||
S->vtop--;
|
||||
vset(S, &S->char_pointer_type, VT_LOCAL, func_va_list_ofs);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_fill_nops(TCCState* S, int bytes)
|
||||
ST_FUNC void gen_fill_nops(TCCState *S, int bytes)
|
||||
{
|
||||
if ((bytes & 3))
|
||||
tcc_error(S, "alignment of code section not multiple of 4");
|
||||
|
@ -941,18 +941,18 @@ ST_FUNC void gen_fill_nops(TCCState* S, int bytes)
|
|||
}
|
||||
|
||||
// Generate forward branch to label:
|
||||
ST_FUNC int gjmp(TCCState* S, int t)
|
||||
ST_FUNC int gjmp(TCCState *S, int t)
|
||||
{
|
||||
if (S->tccgen_nocode_wanted)
|
||||
if (S->nocode_wanted)
|
||||
return t;
|
||||
o(S, t);
|
||||
return S->tccgen_ind - 4;
|
||||
return S->ind - 4;
|
||||
}
|
||||
|
||||
// Generate branch to known address:
|
||||
ST_FUNC void gjmp_addr(TCCState* S, int a)
|
||||
ST_FUNC void gjmp_addr(TCCState *S, int a)
|
||||
{
|
||||
uint32_t r = a - S->tccgen_ind, imm;
|
||||
uint32_t r = a - S->ind, imm;
|
||||
if ((r + (1 << 21)) & ~((1U << 22) - 2)) {
|
||||
o(S, 0x17 | (5 << 7) | (((r + 0x800) & 0xfffff000))); // lui RR, up(r)
|
||||
r = (int)r << 20 >> 20;
|
||||
|
@ -966,11 +966,11 @@ ST_FUNC void gjmp_addr(TCCState* S, int a)
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC int gjmp_cond(TCCState* S, int op, int t)
|
||||
ST_FUNC int gjmp_cond(TCCState *S, int op, int t)
|
||||
{
|
||||
int tmp;
|
||||
int a = S->tccgen_vtop->cmp_r & 0xff;
|
||||
int b = (S->tccgen_vtop->cmp_r >> 8) & 0xff;
|
||||
int a = S->vtop->cmp_r & 0xff;
|
||||
int b = (S->vtop->cmp_r >> 8) & 0xff;
|
||||
switch (op) {
|
||||
case TOK_ULT: op = 6; break;
|
||||
case TOK_UGE: op = 7; break;
|
||||
|
@ -987,7 +987,7 @@ ST_FUNC int gjmp_cond(TCCState* S, int op, int t)
|
|||
return gjmp(S, t);
|
||||
}
|
||||
|
||||
ST_FUNC int gjmp_append(TCCState* S, int n, int t)
|
||||
ST_FUNC int gjmp_append(TCCState *S, int n, int t)
|
||||
{
|
||||
void *p;
|
||||
/* insert jump list n into t */
|
||||
|
@ -1001,22 +1001,22 @@ ST_FUNC int gjmp_append(TCCState* S, int n, int t)
|
|||
return t;
|
||||
}
|
||||
|
||||
static void gen_opil(TCCState* S, int op, int ll)
|
||||
static void gen_opil(TCCState *S, int op, int ll)
|
||||
{
|
||||
int a, b, d;
|
||||
int func3 = 0;
|
||||
ll = ll ? 0 : 8;
|
||||
if ((S->tccgen_vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
int fc = S->tccgen_vtop->c.i;
|
||||
if (fc == S->tccgen_vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) {
|
||||
if ((S->vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
int fc = S->vtop->c.i;
|
||||
if (fc == S->vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) {
|
||||
int cll = 0;
|
||||
int m = ll ? 31 : 63;
|
||||
vswap(S);
|
||||
gv(S, RC_INT);
|
||||
a = ireg(S->tccgen_vtop[0].r);
|
||||
--S->tccgen_vtop;
|
||||
a = ireg(S->vtop[0].r);
|
||||
--S->vtop;
|
||||
d = get_reg(S, RC_INT);
|
||||
++S->tccgen_vtop;
|
||||
++S->vtop;
|
||||
vswap(S);
|
||||
switch (op) {
|
||||
case '-':
|
||||
|
@ -1028,12 +1028,12 @@ static void gen_opil(TCCState* S, int op, int ll)
|
|||
cll = ll;
|
||||
do_cop:
|
||||
EI(S, 0x13 | cll, func3, ireg(d), a, fc);
|
||||
--S->tccgen_vtop;
|
||||
--S->vtop;
|
||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||
vset_VT_CMP(S, TOK_NE);
|
||||
S->tccgen_vtop->cmp_r = ireg(d) | 0 << 8;
|
||||
S->vtop->cmp_r = ireg(d) | 0 << 8;
|
||||
} else
|
||||
S->tccgen_vtop[0].r = d;
|
||||
S->vtop[0].r = d;
|
||||
return;
|
||||
case TOK_LE:
|
||||
if (fc >= (1 << 11) - 1)
|
||||
|
@ -1057,33 +1057,33 @@ static void gen_opil(TCCState* S, int op, int ll)
|
|||
case TOK_GE: /* -> TOK_LT */
|
||||
case TOK_GT: /* -> TOK_LE */
|
||||
gen_opil(S, op - 1, !ll);
|
||||
S->tccgen_vtop->cmp_op ^= 1;
|
||||
S->vtop->cmp_op ^= 1;
|
||||
return;
|
||||
|
||||
case TOK_NE:
|
||||
case TOK_EQ:
|
||||
if (fc)
|
||||
gen_opil(S, '-', !ll), a = ireg(S->tccgen_vtop++->r);
|
||||
--S->tccgen_vtop;
|
||||
gen_opil(S, '-', !ll), a = ireg(S->vtop++->r);
|
||||
--S->vtop;
|
||||
vset_VT_CMP(S, op);
|
||||
S->tccgen_vtop->cmp_r = a | 0 << 8;
|
||||
S->vtop->cmp_r = a | 0 << 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
gv2(S, RC_INT, RC_INT);
|
||||
a = ireg(S->tccgen_vtop[-1].r);
|
||||
b = ireg(S->tccgen_vtop[0].r);
|
||||
S->tccgen_vtop -= 2;
|
||||
a = ireg(S->vtop[-1].r);
|
||||
b = ireg(S->vtop[0].r);
|
||||
S->vtop -= 2;
|
||||
d = get_reg(S, RC_INT);
|
||||
S->tccgen_vtop++;
|
||||
S->tccgen_vtop[0].r = d;
|
||||
S->vtop++;
|
||||
S->vtop[0].r = d;
|
||||
d = ireg(d);
|
||||
switch (op) {
|
||||
default:
|
||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||
vset_VT_CMP(S, op);
|
||||
S->tccgen_vtop->cmp_r = a | b << 8;
|
||||
S->vtop->cmp_r = a | b << 8;
|
||||
break;
|
||||
}
|
||||
tcc_error(S, "implement me: %s(%s)", __FUNCTION__, get_tok_str(S, op, NULL));
|
||||
|
@ -1132,21 +1132,21 @@ static void gen_opil(TCCState* S, int op, int ll)
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gen_opi(TCCState* S, int op)
|
||||
ST_FUNC void gen_opi(TCCState *S, int op)
|
||||
{
|
||||
gen_opil(S, op, 0);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_opl(TCCState* S, int op)
|
||||
ST_FUNC void gen_opl(TCCState *S, int op)
|
||||
{
|
||||
gen_opil(S, op, 1);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_opf(TCCState* S, int op)
|
||||
ST_FUNC void gen_opf(TCCState *S, int op)
|
||||
{
|
||||
int rs1, rs2, rd, dbl, invert;
|
||||
if (S->tccgen_vtop[0].type.t == VT_LDOUBLE) {
|
||||
CType type = S->tccgen_vtop[0].type;
|
||||
if (S->vtop[0].type.t == VT_LDOUBLE) {
|
||||
CType type = S->vtop[0].type;
|
||||
int func = 0;
|
||||
int cond = -1;
|
||||
switch (op) {
|
||||
|
@ -1166,10 +1166,10 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
vrott(S, 3);
|
||||
gfunc_call(S, 2);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = REG_IRET;
|
||||
S->tccgen_vtop->r2 = cond < 0 ? TREG_R(1) : VT_CONST;
|
||||
S->vtop->r = REG_IRET;
|
||||
S->vtop->r2 = cond < 0 ? TREG_R(1) : VT_CONST;
|
||||
if (cond < 0)
|
||||
S->tccgen_vtop->type = type;
|
||||
S->vtop->type = type;
|
||||
else {
|
||||
vpushi(S, 0);
|
||||
gen_opil(S, op, 1);
|
||||
|
@ -1178,11 +1178,11 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
}
|
||||
|
||||
gv2(S, RC_FLOAT, RC_FLOAT);
|
||||
assert(S->tccgen_vtop->type.t == VT_DOUBLE || S->tccgen_vtop->type.t == VT_FLOAT);
|
||||
dbl = S->tccgen_vtop->type.t == VT_DOUBLE;
|
||||
rs1 = freg(S->tccgen_vtop[-1].r);
|
||||
rs2 = freg(S->tccgen_vtop->r);
|
||||
S->tccgen_vtop--;
|
||||
assert(S->vtop->type.t == VT_DOUBLE || S->vtop->type.t == VT_FLOAT);
|
||||
dbl = S->vtop->type.t == VT_DOUBLE;
|
||||
rs1 = freg(S->vtop[-1].r);
|
||||
rs2 = freg(S->vtop->r);
|
||||
S->vtop--;
|
||||
invert = 0;
|
||||
switch(op) {
|
||||
default:
|
||||
|
@ -1191,7 +1191,7 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
op = 0; // fadd
|
||||
arithop:
|
||||
rd = get_reg(S, RC_FLOAT);
|
||||
S->tccgen_vtop->r = rd;
|
||||
S->vtop->r = rd;
|
||||
rd = freg(rd);
|
||||
ER(S, 0x53, 7, rd, rs1, rs2, dbl | (op << 2)); // fop.[sd] RD, RS1, RS2 (dyn rm)
|
||||
break;
|
||||
|
@ -1208,7 +1208,7 @@ ST_FUNC void gen_opf(TCCState* S, int op)
|
|||
op = 2; // EQ
|
||||
cmpop:
|
||||
rd = get_reg(S, RC_INT);
|
||||
S->tccgen_vtop->r = rd;
|
||||
S->vtop->r = rd;
|
||||
rd = ireg(rd);
|
||||
ER(S, 0x53, op, rd, rs1, rs2, dbl | 0x50); // fcmp.[sd] RD, RS1, RS2 (op == eq/lt/le)
|
||||
if (invert)
|
||||
|
@ -1241,11 +1241,11 @@ ST_FUNC void gen_cvt_sxtw(TCCState *S)
|
|||
Let's try to not do anything here. */
|
||||
}
|
||||
|
||||
ST_FUNC void gen_cvt_itof(TCCState* S, int t)
|
||||
ST_FUNC void gen_cvt_itof(TCCState *S, int t)
|
||||
{
|
||||
int rr = ireg(gv(S, RC_INT)), dr;
|
||||
int u = S->tccgen_vtop->type.t & VT_UNSIGNED;
|
||||
int l = (S->tccgen_vtop->type.t & VT_BTYPE) == VT_LLONG;
|
||||
int u = S->vtop->type.t & VT_UNSIGNED;
|
||||
int l = (S->vtop->type.t & VT_BTYPE) == VT_LLONG;
|
||||
if (t == VT_LDOUBLE) {
|
||||
int func = l ?
|
||||
(u ? TOK___floatunditf : TOK___floatditf) :
|
||||
|
@ -1254,22 +1254,22 @@ ST_FUNC void gen_cvt_itof(TCCState* S, int t)
|
|||
vrott(S, 2);
|
||||
gfunc_call(S, 1);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->type.t = t;
|
||||
S->tccgen_vtop->r = REG_IRET;
|
||||
S->tccgen_vtop->r2 = TREG_R(1);
|
||||
S->vtop->type.t = t;
|
||||
S->vtop->r = REG_IRET;
|
||||
S->vtop->r2 = TREG_R(1);
|
||||
} else {
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
dr = get_reg(S, RC_FLOAT);
|
||||
S->tccgen_vtop++;
|
||||
S->tccgen_vtop->r = dr;
|
||||
S->vtop++;
|
||||
S->vtop->r = dr;
|
||||
dr = freg(dr);
|
||||
EIu(S, 0x53, 7, dr, rr, ((0x68 | (t == VT_DOUBLE ? 1 : 0)) << 5) | (u ? 1 : 0) | (l ? 2 : 0)); // fcvt.[sd].[wl][u]
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gen_cvt_ftoi(TCCState* S, int t)
|
||||
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t)
|
||||
{
|
||||
int ft = S->tccgen_vtop->type.t & VT_BTYPE;
|
||||
int ft = S->vtop->type.t & VT_BTYPE;
|
||||
int l = (t & VT_BTYPE) == VT_LLONG;
|
||||
int u = t & VT_UNSIGNED;
|
||||
if (ft == VT_LDOUBLE) {
|
||||
|
@ -1280,22 +1280,22 @@ ST_FUNC void gen_cvt_ftoi(TCCState* S, int t)
|
|||
vrott(S, 2);
|
||||
gfunc_call(S, 1);
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->type.t = t;
|
||||
S->tccgen_vtop->r = REG_IRET;
|
||||
S->vtop->type.t = t;
|
||||
S->vtop->r = REG_IRET;
|
||||
} else {
|
||||
int rr = freg(gv(S, RC_FLOAT)), dr;
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
dr = get_reg(S, RC_INT);
|
||||
S->tccgen_vtop++;
|
||||
S->tccgen_vtop->r = dr;
|
||||
S->vtop++;
|
||||
S->vtop->r = dr;
|
||||
dr = ireg(dr);
|
||||
EIu(S, 0x53, 1, dr, rr, ((0x60 | (ft == VT_DOUBLE ? 1 : 0)) << 5) | (u ? 1 : 0) | (l ? 2 : 0)); // fcvt.[wl][u].[sd] rtz
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gen_cvt_ftof(TCCState* S, int dt)
|
||||
ST_FUNC void gen_cvt_ftof(TCCState *S, int dt)
|
||||
{
|
||||
int st = S->tccgen_vtop->type.t & VT_BTYPE, rs, rd;
|
||||
int st = S->vtop->type.t & VT_BTYPE, rs, rd;
|
||||
dt &= VT_BTYPE;
|
||||
if (st == dt)
|
||||
return;
|
||||
|
@ -1312,21 +1312,21 @@ ST_FUNC void gen_cvt_ftof(TCCState* S, int dt)
|
|||
gv(S, RC_F(0));
|
||||
else {
|
||||
gv(S, RC_R(0));
|
||||
assert(S->tccgen_vtop->r2 < 7);
|
||||
if (S->tccgen_vtop->r2 != 1 + S->tccgen_vtop->r) {
|
||||
EI(S, 0x13, 0, ireg(S->tccgen_vtop->r) + 1, ireg(S->tccgen_vtop->r2), 0); // mv Ra+1, RR2
|
||||
S->tccgen_vtop->r2 = 1 + S->tccgen_vtop->r;
|
||||
assert(S->vtop->r2 < 7);
|
||||
if (S->vtop->r2 != 1 + S->vtop->r) {
|
||||
EI(S, 0x13, 0, ireg(S->vtop->r) + 1, ireg(S->vtop->r2), 0); // mv Ra+1, RR2
|
||||
S->vtop->r2 = 1 + S->vtop->r;
|
||||
}
|
||||
}
|
||||
vpush_helper_func(S, func);
|
||||
gcall_or_jmp(S, 1);
|
||||
S->tccgen_vtop -= 2;
|
||||
S->vtop -= 2;
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->type.t = dt;
|
||||
S->vtop->type.t = dt;
|
||||
if (dt == VT_LDOUBLE)
|
||||
S->tccgen_vtop->r = REG_IRET, S->tccgen_vtop->r2 = REG_IRET+1;
|
||||
S->vtop->r = REG_IRET, S->vtop->r2 = REG_IRET+1;
|
||||
else
|
||||
S->tccgen_vtop->r = REG_FRET;
|
||||
S->vtop->r = REG_FRET;
|
||||
} else {
|
||||
assert (dt == VT_FLOAT || dt == VT_DOUBLE);
|
||||
assert (st == VT_FLOAT || st == VT_DOUBLE);
|
||||
|
@ -1336,59 +1336,59 @@ ST_FUNC void gen_cvt_ftof(TCCState* S, int dt)
|
|||
EI(S, 0x53, 0, freg(rd), freg(rs), 0x21 << 5); // fcvt.d.s RD, RS (no rm)
|
||||
else
|
||||
EI(S, 0x53, 7, freg(rd), freg(rs), (0x20 << 5) | 1); // fcvt.s.d RD, RS (dyn rm)
|
||||
S->tccgen_vtop->r = rd;
|
||||
S->vtop->r = rd;
|
||||
}
|
||||
}
|
||||
|
||||
/* increment tcov counter */
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv)
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv)
|
||||
{
|
||||
int r1, r2;
|
||||
Sym label = {0};
|
||||
label.type.t = VT_VOID | VT_STATIC;
|
||||
|
||||
vpushv(S, sv);
|
||||
S->tccgen_vtop->r = r1 = get_reg(S, RC_INT);
|
||||
S->vtop->r = r1 = get_reg(S, RC_INT);
|
||||
r2 = get_reg(S, RC_INT);
|
||||
r1 = ireg(r1);
|
||||
r2 = ireg(r2);
|
||||
greloca(S, cur_text_section, sv->sym, S->tccgen_ind, R_RISCV_PCREL_HI20, 0);
|
||||
put_extern_sym(S, &label, cur_text_section, S->tccgen_ind, 0);
|
||||
greloca(S, cur_text_section, sv->sym, S->ind, R_RISCV_PCREL_HI20, 0);
|
||||
put_extern_sym(S, &label, cur_text_section, S->ind, 0);
|
||||
o(S, 0x17 | (r1 << 7)); // auipc RR, 0 %pcrel_hi(sym)
|
||||
greloca(S, cur_text_section, &label, S->tccgen_ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
greloca(S, cur_text_section, &label, S->ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
EI(S, 0x03, 3, r2, r1, 0); // ld r2, x[r1]
|
||||
EI(S, 0x13, 0, r2, r2, 1); // addi r2, r2, #1
|
||||
greloca(S, cur_text_section, sv->sym, S->tccgen_ind, R_RISCV_PCREL_HI20, 0);
|
||||
greloca(S, cur_text_section, sv->sym, S->ind, R_RISCV_PCREL_HI20, 0);
|
||||
label.c = 0; /* force new local ELF symbol */
|
||||
put_extern_sym(S, &label, cur_text_section, S->tccgen_ind, 0);
|
||||
put_extern_sym(S, &label, cur_text_section, S->ind, 0);
|
||||
o(S, 0x17 | (r1 << 7)); // auipc RR, 0 %pcrel_hi(sym)
|
||||
greloca(S, cur_text_section, &label, S->tccgen_ind, R_RISCV_PCREL_LO12_S, 0);
|
||||
greloca(S, cur_text_section, &label, S->ind, R_RISCV_PCREL_LO12_S, 0);
|
||||
ES(S, 0x23, 3, r1, r2, 0); // sd r2, [r1]
|
||||
vpop(S);
|
||||
}
|
||||
|
||||
ST_FUNC void ggoto(TCCState* S)
|
||||
ST_FUNC void ggoto(TCCState *S)
|
||||
{
|
||||
gcall_or_jmp(S, 0);
|
||||
S->tccgen_vtop--;
|
||||
S->vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_vla_sp_save(TCCState* S, int addr)
|
||||
ST_FUNC void gen_vla_sp_save(TCCState *S, int addr)
|
||||
{
|
||||
ES(S, 0x23, 3, 8, 2, addr); // sd sp, fc(s0)
|
||||
}
|
||||
|
||||
ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr)
|
||||
ST_FUNC void gen_vla_sp_restore(TCCState *S, int addr)
|
||||
{
|
||||
EI(S, 0x03, 3, 2, 8, addr); // ld sp, fc(s0)
|
||||
}
|
||||
|
||||
ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align)
|
||||
ST_FUNC void gen_vla_alloc(TCCState *S, CType *type, int align)
|
||||
{
|
||||
int rr;
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
if (S->do_bounds_check)
|
||||
vpushv(S, S->tccgen_vtop);
|
||||
vpushv(S, S->vtop);
|
||||
#endif
|
||||
rr = ireg(gv(S, RC_INT));
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
@ -1403,7 +1403,7 @@ ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align)
|
|||
#if defined(CONFIG_TCC_BCHECK)
|
||||
if (S->do_bounds_check) {
|
||||
vpushi(S, 0);
|
||||
S->tccgen_vtop->r = TREG_R(0);
|
||||
S->vtop->r = TREG_R(0);
|
||||
o(S, 0x00010513); /* mv a0,sp */
|
||||
vswap(S);
|
||||
vpush_helper_func(S, TOK___bound_new_region);
|
||||
|
|
323
tcc.h
323
tcc.h
|
@ -1074,21 +1074,21 @@ struct TCCState {
|
|||
/* ------------ tccpp.c ------------ */
|
||||
|
||||
struct BufferedFile *tccpp_file;
|
||||
int tccpp_ch, tccpp_tok;
|
||||
CValue tccpp_tokc;
|
||||
int tccpp_ch, tok;
|
||||
CValue tokc;
|
||||
const int *tccpp_macro_ptr;
|
||||
int tccpp_parse_flags;
|
||||
int tccpp_tok_flags;
|
||||
CString tccpp_tokcstr; /* current parsed string, if any */
|
||||
int tok_flags;
|
||||
CString tokcstr; /* current parsed string, if any */
|
||||
CString tccpp_cstr_buf;
|
||||
CString tccpp_macro_equal_buf;
|
||||
TokenString tccpp_tokstr_buf;
|
||||
TokenString tokstr_buf;
|
||||
TokenString *tccpp_macro_stack;
|
||||
|
||||
/* display benchmark infos */
|
||||
int tccpp_total_lines;
|
||||
int tccpp_total_bytes;
|
||||
int tccpp_tok_ident;
|
||||
int tok_ident;
|
||||
TokenSym **tccpp_table_ident;
|
||||
|
||||
int *tccpp_macro_ptr_allocated;
|
||||
|
@ -1096,7 +1096,7 @@ struct TCCState {
|
|||
int tccpp_unget_saved_buffer[TOK_MAX_SIZE + 1];
|
||||
int tccpp_unget_buffer_enabled;
|
||||
TokenSym *tccpp_hash_ident[TOK_HASH_SIZE];
|
||||
char tccpp_token_buf[STRING_MAX_SIZE + 1];
|
||||
char token_buf[STRING_MAX_SIZE + 1];
|
||||
/* true if isid(c) || isnum(c) */
|
||||
unsigned char tccpp_isidnum_table[256-CH_EOF];
|
||||
|
||||
|
@ -1105,8 +1105,8 @@ struct TCCState {
|
|||
int tccpp_pp_expr;
|
||||
int tccpp_pp_counter;
|
||||
|
||||
TinyAlloc *tccpp_toksym_alloc;
|
||||
TinyAlloc *tccpp_tokstr_alloc;
|
||||
TinyAlloc *toksym_alloc;
|
||||
TinyAlloc *tokstr_alloc;
|
||||
|
||||
/*----------- tccasm.c --------*/
|
||||
Section *tccasm_last_text_section; /* to handle .previous asm directive */
|
||||
|
@ -1114,18 +1114,18 @@ struct TCCState {
|
|||
/* ------------ tccgen.c ------------ */
|
||||
|
||||
Sym *tccgen_global_stack;
|
||||
Sym *tccgen_local_stack;
|
||||
Sym *tccgen_local_label_stack;
|
||||
Sym *local_stack;
|
||||
Sym *local_label_stack;
|
||||
Sym *tccgen_global_label_stack;
|
||||
Sym *tccgen_define_stack;
|
||||
CType tccgen_int_type, tccgen_func_old_type, tccgen_char_type, tccgen_char_pointer_type;
|
||||
SValue *tccgen_vtop;
|
||||
CType tccgen_int_type, tccgen_func_old_type, tccgen_char_type, char_pointer_type;
|
||||
SValue *vtop;
|
||||
SValue tccgen__vstack[1 + VSTACK_SIZE];
|
||||
int tccgen_rsym, tccgen_anon_sym, tccgen_ind, tccgen_loc;
|
||||
int tccgen_rsym, tccgen_anon_sym, ind, loc;
|
||||
char tccgen_debug_modes;
|
||||
|
||||
int tccgen_const_wanted; /* true if constant wanted */
|
||||
int tccgen_nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
int tccgen_global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
CType tccgen_func_vt; /* current function return type (used by return instruction) */
|
||||
int tccgen_func_var; /* true if current function is variadic */
|
||||
|
@ -1136,7 +1136,7 @@ struct TCCState {
|
|||
void **tccgen_sym_pools;
|
||||
int tccgen_nb_sym_pools;
|
||||
Sym *tccgen_all_cleanups, *tccgen_pending_gotos;
|
||||
int tccgen_local_scope;
|
||||
int local_scope;
|
||||
int tccgen_in_sizeof;
|
||||
int tccgen_in_generic;
|
||||
int tccgen_section_sym;
|
||||
|
@ -1155,7 +1155,7 @@ struct TCCState {
|
|||
int tccgen_debug_next_type;
|
||||
debug_hash_t *tccgen_debug_hash;
|
||||
int tccgen_n_debug_hash;
|
||||
debug_info_t *tccgen_debug_info, *tccgen_debug_info_root;
|
||||
debug_info_t *debug_info, *debug_info_root;
|
||||
|
||||
unsigned char tccgen_prec[256];
|
||||
|
||||
|
@ -1374,22 +1374,22 @@ PUB_FUNC void tcc_free_base(void *ptr);
|
|||
PUB_FUNC void *tcc_malloc_base(unsigned long size);
|
||||
PUB_FUNC void *tcc_mallocz_base(unsigned long size);
|
||||
#ifndef MEM_DEBUG
|
||||
PUB_FUNC void tcc_free(TCCState* S, void *ptr);
|
||||
PUB_FUNC void *tcc_malloc(TCCState* S, unsigned long size);
|
||||
PUB_FUNC void *tcc_mallocz(TCCState* S, unsigned long size);
|
||||
PUB_FUNC void *tcc_realloc(TCCState* S, void *ptr, unsigned long size);
|
||||
PUB_FUNC char *tcc_strdup(TCCState* S, const char *str);
|
||||
PUB_FUNC void tcc_free(TCCState *S, void *ptr);
|
||||
PUB_FUNC void *tcc_malloc(TCCState *S, unsigned long size);
|
||||
PUB_FUNC void *tcc_mallocz(TCCState *S, unsigned long size);
|
||||
PUB_FUNC void *tcc_realloc(TCCState *S, void *ptr, unsigned long size);
|
||||
PUB_FUNC char *tcc_strdup(TCCState *S, const char *str);
|
||||
#else
|
||||
#define tcc_free(s, ptr) tcc_free_debug(s, ptr)
|
||||
#define tcc_malloc(s, size) tcc_malloc_debug(s, size, __FILE__, __LINE__)
|
||||
#define tcc_mallocz(s, size) tcc_mallocz_debug(s, size, __FILE__, __LINE__)
|
||||
#define tcc_realloc(s, ptr, size) tcc_realloc_debug(s, ptr, size, __FILE__, __LINE__)
|
||||
#define tcc_strdup(s, str) tcc_strdup_debug(s, str, __FILE__, __LINE__)
|
||||
PUB_FUNC void tcc_free_debug(TCCState* S, void *ptr);
|
||||
PUB_FUNC void *tcc_malloc_debug(TCCState* S, unsigned long size, const char *file, int line);
|
||||
PUB_FUNC void *tcc_mallocz_debug(TCCState* S, unsigned long size, const char *file, int line);
|
||||
PUB_FUNC void *tcc_realloc_debug(TCCState* S, void *ptr, unsigned long size, const char *file, int line);
|
||||
PUB_FUNC char *tcc_strdup_debug(TCCState* S, const char *str, const char *file, int line);
|
||||
PUB_FUNC void tcc_free_debug(TCCState *S, void *ptr);
|
||||
PUB_FUNC void *tcc_malloc_debug(TCCState *S, unsigned long size, const char *file, int line);
|
||||
PUB_FUNC void *tcc_mallocz_debug(TCCState *S, unsigned long size, const char *file, int line);
|
||||
PUB_FUNC void *tcc_realloc_debug(TCCState *S, void *ptr, unsigned long size, const char *file, int line);
|
||||
PUB_FUNC char *tcc_strdup_debug(TCCState *S, const char *str, const char *file, int line);
|
||||
#endif
|
||||
|
||||
#define free(p) use_tcc_free(S, p)
|
||||
|
@ -1397,22 +1397,22 @@ PUB_FUNC char *tcc_strdup_debug(TCCState* S, const char *str, const char *file,
|
|||
#define realloc(p, s) use_tcc_realloc(S, p, s)
|
||||
#undef strdup
|
||||
#define strdup(s) use_tcc_strdup(S, s)
|
||||
PUB_FUNC void _tcc_error_noabort(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||
PUB_FUNC NORETURN void _tcc_error(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||
PUB_FUNC void _tcc_warning(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||
PUB_FUNC void _tcc_error_noabort(TCCState *S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||
PUB_FUNC NORETURN void _tcc_error(TCCState *S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||
PUB_FUNC void _tcc_warning(TCCState *S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||
#define tcc_internal_error(S, msg) tcc_error(S, "internal compiler error\n"\
|
||||
"%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
|
||||
|
||||
/* other utilities */
|
||||
ST_FUNC void dynarray_add(TCCState* S, void *ptab, int *nb_ptr, void *data);
|
||||
ST_FUNC void dynarray_reset(TCCState* S, void *pp, int *n);
|
||||
ST_INLN void cstr_ccat(TCCState* S, CString *cstr, int ch);
|
||||
ST_FUNC void cstr_cat(TCCState* S, CString *cstr, const char *str, int len);
|
||||
ST_FUNC void cstr_wccat(TCCState* S, CString *cstr, int ch);
|
||||
ST_FUNC void cstr_new(TCCState* S, CString *cstr);
|
||||
ST_FUNC void cstr_free(TCCState* S, CString *cstr);
|
||||
ST_FUNC int cstr_printf(TCCState* S, CString *cs, const char *fmt, ...) PRINTF_LIKE(3,4);
|
||||
ST_FUNC int cstr_vprintf(TCCState* S, CString *cstr, const char *fmt, va_list ap);
|
||||
ST_FUNC void dynarray_add(TCCState *S, void *ptab, int *nb_ptr, void *data);
|
||||
ST_FUNC void dynarray_reset(TCCState *S, void *pp, int *n);
|
||||
ST_INLN void cstr_ccat(TCCState *S, CString *cstr, int ch);
|
||||
ST_FUNC void cstr_cat(TCCState *S, CString *cstr, const char *str, int len);
|
||||
ST_FUNC void cstr_wccat(TCCState *S, CString *cstr, int ch);
|
||||
ST_FUNC void cstr_new(TCCState *S, CString *cstr);
|
||||
ST_FUNC void cstr_free(TCCState *S, CString *cstr);
|
||||
ST_FUNC int cstr_printf(TCCState *S, CString *cs, const char *fmt, ...) PRINTF_LIKE(3,4);
|
||||
ST_FUNC int cstr_vprintf(TCCState *S, CString *cstr, const char *fmt, va_list ap);
|
||||
ST_FUNC void cstr_reset(CString *cstr);
|
||||
|
||||
ST_FUNC void tcc_open_bf(TCCState *S, const char *filename, int initlen);
|
||||
|
@ -1499,36 +1499,36 @@ enum line_macro_output_format {
|
|||
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
||||
};
|
||||
|
||||
ST_FUNC TokenSym *tok_alloc(TCCState* S, const char *str, int len);
|
||||
ST_FUNC int tok_alloc_const(TCCState* S, const char *str);
|
||||
ST_FUNC const char *get_tok_str(TCCState* S, int v, CValue *cv);
|
||||
ST_FUNC void begin_macro(TCCState* S, TokenString *str, int alloc);
|
||||
ST_FUNC void end_macro(TCCState* S);
|
||||
ST_FUNC int set_idnum(TCCState* S, int c, int val);
|
||||
ST_FUNC TokenSym *tok_alloc(TCCState *S, const char *str, int len);
|
||||
ST_FUNC int tok_alloc_const(TCCState *S, const char *str);
|
||||
ST_FUNC const char *get_tok_str(TCCState *S, int v, CValue *cv);
|
||||
ST_FUNC void begin_macro(TCCState *S, TokenString *str, int alloc);
|
||||
ST_FUNC void end_macro(TCCState *S);
|
||||
ST_FUNC int set_idnum(TCCState *S, int c, int val);
|
||||
ST_INLN void tok_str_new(TokenString *s);
|
||||
ST_FUNC TokenString *tok_str_alloc(TCCState* S);
|
||||
ST_FUNC void tok_str_free(TCCState* S, TokenString *s);
|
||||
ST_FUNC void tok_str_free_str(TCCState* S, int *str);
|
||||
ST_FUNC void tok_str_add(TCCState* S, TokenString *s, int t);
|
||||
ST_FUNC void tok_str_add_tok(TCCState* S, TokenString *s);
|
||||
ST_INLN void define_push(TCCState* S, int v, int macro_type, int *str, Sym *first_arg);
|
||||
ST_FUNC void define_undef(TCCState* S, Sym *s);
|
||||
ST_INLN Sym *define_find(TCCState* S, int v);
|
||||
ST_FUNC void free_defines(TCCState* S, Sym *b);
|
||||
ST_FUNC Sym *label_find(TCCState* S, int v);
|
||||
ST_FUNC Sym *label_push(TCCState* S, Sym **ptop, int v, int flags);
|
||||
ST_FUNC void label_pop(TCCState* S, Sym **ptop, Sym *slast, int keep);
|
||||
ST_FUNC void parse_define(TCCState* S);
|
||||
ST_FUNC void preprocess(TCCState* S, int is_bof);
|
||||
ST_FUNC void next(TCCState* S);
|
||||
ST_INLN void unget_tok(TCCState* S, int last_tok);
|
||||
ST_FUNC TokenString *tok_str_alloc(TCCState *S);
|
||||
ST_FUNC void tok_str_free(TCCState *S, TokenString *s);
|
||||
ST_FUNC void tok_str_free_str(TCCState *S, int *str);
|
||||
ST_FUNC void tok_str_add(TCCState *S, TokenString *s, int t);
|
||||
ST_FUNC void tok_str_add_tok(TCCState *S, TokenString *s);
|
||||
ST_INLN void define_push(TCCState *S, int v, int macro_type, int *str, Sym *first_arg);
|
||||
ST_FUNC void define_undef(TCCState *S, Sym *s);
|
||||
ST_INLN Sym *define_find(TCCState *S, int v);
|
||||
ST_FUNC void free_defines(TCCState *S, Sym *b);
|
||||
ST_FUNC Sym *label_find(TCCState *S, int v);
|
||||
ST_FUNC Sym *label_push(TCCState *S, Sym **ptop, int v, int flags);
|
||||
ST_FUNC void label_pop(TCCState *S, Sym **ptop, Sym *slast, int keep);
|
||||
ST_FUNC void parse_define(TCCState *S);
|
||||
ST_FUNC void preprocess(TCCState *S, int is_bof);
|
||||
ST_FUNC void next(TCCState *S);
|
||||
ST_INLN void unget_tok(TCCState *S, int last_tok);
|
||||
ST_FUNC void preprocess_start(TCCState *S, int filetype);
|
||||
ST_FUNC void preprocess_end(TCCState *S);
|
||||
ST_FUNC void tccpp_new(TCCState *S);
|
||||
ST_FUNC void tccpp_delete(TCCState *S);
|
||||
ST_FUNC int tcc_preprocess(TCCState *S);
|
||||
ST_FUNC void skip(TCCState* S, int c);
|
||||
ST_FUNC NORETURN void expect(TCCState* S, const char *msg);
|
||||
ST_FUNC void skip(TCCState *S, int c);
|
||||
ST_FUNC NORETURN void expect(TCCState *S, const char *msg);
|
||||
|
||||
/* space excluding newline */
|
||||
static inline int is_space(int ch) {
|
||||
|
@ -1559,77 +1559,76 @@ ST_FUNC void tcc_debug_putfile(TCCState *S, const char *filename);
|
|||
ST_FUNC void tccgen_init(TCCState *S);
|
||||
ST_FUNC int tccgen_compile(TCCState *S);
|
||||
ST_FUNC void tccgen_finish(TCCState *S);
|
||||
ST_FUNC void check_vstack(TCCState* S);
|
||||
ST_FUNC void check_vstack(TCCState *S);
|
||||
|
||||
ST_INLN int is_float(int t);
|
||||
ST_FUNC int ieee_finite(double d);
|
||||
ST_FUNC int exact_log2p1(int i);
|
||||
ST_FUNC void test_lvalue(TCCState* S);
|
||||
ST_FUNC void test_lvalue(TCCState *S);
|
||||
|
||||
ST_FUNC ElfSym *elfsym(TCCState* S, Sym *);
|
||||
ST_FUNC void update_storage(TCCState* S, Sym *sym);
|
||||
ST_FUNC void put_extern_sym2(TCCState* S, Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
||||
ST_FUNC void put_extern_sym(TCCState* S, Sym *sym, Section *section, addr_t value, unsigned long size);
|
||||
ST_FUNC ElfSym *elfsym(TCCState *S, Sym *);
|
||||
ST_FUNC void update_storage(TCCState *S, Sym *sym);
|
||||
ST_FUNC void put_extern_sym2(TCCState *S, Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
||||
ST_FUNC void put_extern_sym(TCCState *S, Sym *sym, Section *section, addr_t value, unsigned long size);
|
||||
#if PTR_SIZE == 4
|
||||
ST_FUNC void greloc(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type);
|
||||
ST_FUNC void greloc(TCCState *S, Section *s, Sym *sym, unsigned long offset, int type);
|
||||
#endif
|
||||
ST_FUNC void greloca(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||
ST_FUNC void greloca(TCCState *S, Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||
|
||||
ST_INLN void sym_free(TCCState* S, Sym *sym);
|
||||
ST_FUNC Sym *sym_push(TCCState* S, int v, CType *type, int r, int c);
|
||||
ST_FUNC void sym_pop(TCCState* S, Sym **ptop, Sym *b, int keep);
|
||||
ST_FUNC Sym *sym_push2(TCCState* S, Sym **ps, int v, int t, int c);
|
||||
ST_INLN void sym_free(TCCState *S, Sym *sym);
|
||||
ST_FUNC Sym *sym_push(TCCState *S, int v, CType *type, int r, int c);
|
||||
ST_FUNC void sym_pop(TCCState *S, Sym **ptop, Sym *b, int keep);
|
||||
ST_FUNC Sym *sym_push2(TCCState *S, Sym **ps, int v, int t, int c);
|
||||
ST_FUNC Sym *sym_find2(Sym *s, int v);
|
||||
ST_INLN Sym *sym_find(TCCState* S, int v);
|
||||
ST_INLN Sym *struct_find(TCCState* S, int v);
|
||||
ST_INLN Sym *sym_find(TCCState *S, int v);
|
||||
ST_INLN Sym *struct_find(TCCState *S, int v);
|
||||
|
||||
ST_FUNC Sym *global_identifier_push(TCCState* S, int v, int t, int c);
|
||||
ST_FUNC Sym *external_global_sym(TCCState* S, int v, CType *type);
|
||||
ST_FUNC Sym *external_helper_sym(TCCState* S, int v);
|
||||
ST_FUNC void vpush_helper_func(TCCState* S, int v);
|
||||
ST_FUNC void vset(TCCState* S, CType *type, int r, int v);
|
||||
ST_FUNC void vset_VT_CMP(TCCState* S, int op);
|
||||
ST_FUNC void vpushi(TCCState* S, int v);
|
||||
ST_FUNC void vpushv(TCCState* S, SValue *v);
|
||||
ST_FUNC void vpushsym(TCCState* S, CType *type, Sym *sym);
|
||||
ST_FUNC void vswap(TCCState* S);
|
||||
ST_FUNC void vrote(TCCState* S, SValue *e, int n);
|
||||
ST_FUNC void vrott(TCCState* S, int n);
|
||||
ST_FUNC void vrotb(TCCState* S, int n);
|
||||
ST_FUNC void vpop(TCCState* S);
|
||||
ST_FUNC Sym *global_identifier_push(TCCState *S, int v, int t, int c);
|
||||
ST_FUNC Sym *external_global_sym(TCCState *S, int v, CType *type);
|
||||
ST_FUNC Sym *external_helper_sym(TCCState *S, int v);
|
||||
ST_FUNC void vpush_helper_func(TCCState *S, int v);
|
||||
ST_FUNC void vset(TCCState *S, CType *type, int r, int v);
|
||||
ST_FUNC void vset_VT_CMP(TCCState *S, int op);
|
||||
ST_FUNC void vpushi(TCCState *S, int v);
|
||||
ST_FUNC void vpushv(TCCState *S, SValue *v);
|
||||
ST_FUNC void vpushsym(TCCState *S, CType *type, Sym *sym);
|
||||
ST_FUNC void vswap(TCCState *S);
|
||||
ST_FUNC void vrote(TCCState *S, SValue *e, int n);
|
||||
ST_FUNC void vrott(TCCState *S, int n);
|
||||
ST_FUNC void vrotb(TCCState *S, int n);
|
||||
ST_FUNC void vpop(TCCState *S);
|
||||
#if PTR_SIZE == 4
|
||||
ST_FUNC void lexpand(TCCState* S);
|
||||
ST_FUNC void lexpand(TCCState *S);
|
||||
#endif
|
||||
#ifdef TCC_TARGET_ARM
|
||||
ST_FUNC int get_reg_ex(TCCState* S, int rc, int rc2);
|
||||
ST_FUNC int get_reg_ex(TCCState *S, int rc, int rc2);
|
||||
#endif
|
||||
ST_FUNC void save_reg(TCCState* S, int r);
|
||||
ST_FUNC void save_reg_upstack(TCCState* S, int r, int n);
|
||||
ST_FUNC int get_reg(TCCState* S, int rc);
|
||||
ST_FUNC void save_regs(TCCState* S, int n);
|
||||
ST_FUNC void gaddrof(TCCState* S);
|
||||
ST_FUNC int gv(TCCState* S, int rc);
|
||||
ST_FUNC void gv2(TCCState* S, int rc1, int rc2);
|
||||
ST_FUNC void gen_op(TCCState* S, int op);
|
||||
ST_FUNC void save_reg(TCCState *S, int r);
|
||||
ST_FUNC void save_reg_upstack(TCCState *S, int r, int n);
|
||||
ST_FUNC int get_reg(TCCState *S, int rc);
|
||||
ST_FUNC void save_regs(TCCState *S, int n);
|
||||
ST_FUNC void gaddrof(TCCState *S);
|
||||
ST_FUNC int gv(TCCState *S, int rc);
|
||||
ST_FUNC void gv2(TCCState *S, int rc1, int rc2);
|
||||
ST_FUNC void gen_op(TCCState *S, int op);
|
||||
ST_FUNC int type_size(CType *type, int *a);
|
||||
ST_FUNC void mk_pointer(TCCState* S, CType *type);
|
||||
ST_FUNC void vstore(TCCState* S);
|
||||
ST_FUNC void inc(TCCState* S, int post, int c);
|
||||
ST_FUNC void parse_mult_str (TCCState* S, CString *astr, const char *msg);
|
||||
ST_FUNC void parse_asm_str(TCCState* S, CString *astr);
|
||||
ST_FUNC void indir(TCCState* S);
|
||||
ST_FUNC void unary(TCCState* S);
|
||||
ST_FUNC void gexpr(TCCState* S);
|
||||
ST_FUNC int expr_const(TCCState* S);
|
||||
ST_FUNC void mk_pointer(TCCState *S, CType *type);
|
||||
ST_FUNC void vstore(TCCState *S);
|
||||
ST_FUNC void inc(TCCState *S, int post, int c);
|
||||
ST_FUNC void parse_mult_str (TCCState *S, CString *astr, const char *msg);
|
||||
ST_FUNC void parse_asm_str(TCCState *S, CString *astr);
|
||||
ST_FUNC void indir(TCCState *S);
|
||||
ST_FUNC void unary(TCCState *S);
|
||||
ST_FUNC void gexpr(TCCState *S);
|
||||
ST_FUNC int expr_const(TCCState *S);
|
||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
|
||||
ST_FUNC Sym *get_sym_ref(TCCState* S, CType *type, Section *sec, unsigned long offset, unsigned long size);
|
||||
ST_FUNC Sym *get_sym_ref(TCCState *S, CType *type, Section *sec, unsigned long offset, unsigned long size);
|
||||
#endif
|
||||
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
|
||||
ST_FUNC int classify_x86_64_va_arg(CType *ty);
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
ST_FUNC void gbound_args(TCCState* S, int nb_args);
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
ST_FUNC void gbound_args(TCCState *S, int nb_args);
|
||||
#endif
|
||||
|
||||
/* ------------ tccelf.c ------------ */
|
||||
|
@ -1657,14 +1656,14 @@ ST_FUNC void tccelf_end_file(TCCState *S);
|
|||
ST_FUNC void tccelf_bounds_new(TCCState *S);
|
||||
#endif
|
||||
ST_FUNC Section *new_section(TCCState *S, const char *name, int sh_type, int sh_flags);
|
||||
ST_FUNC void section_realloc(TCCState* S, Section *sec, unsigned long new_size);
|
||||
ST_FUNC size_t section_add(TCCState* S, Section *sec, addr_t size, int align);
|
||||
ST_FUNC void *section_ptr_add(TCCState* S, Section *sec, addr_t size);
|
||||
ST_FUNC void section_realloc(TCCState *S, Section *sec, unsigned long new_size);
|
||||
ST_FUNC size_t section_add(TCCState *S, Section *sec, addr_t size, int align);
|
||||
ST_FUNC void *section_ptr_add(TCCState *S, Section *sec, addr_t size);
|
||||
ST_FUNC Section *find_section(TCCState *S, const char *name);
|
||||
ST_FUNC Section *new_symtab(TCCState *S, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
||||
|
||||
ST_FUNC int put_elf_str(TCCState* S, Section *s, const char *sym);
|
||||
ST_FUNC int put_elf_sym(TCCState* S, Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||
ST_FUNC int put_elf_str(TCCState *S, Section *s, const char *sym);
|
||||
ST_FUNC int put_elf_sym(TCCState *S, Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||
ST_FUNC int set_elf_sym(Section *S, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||
ST_FUNC int find_elf_sym(Section *S, const char *name);
|
||||
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
|
||||
|
@ -1679,7 +1678,7 @@ ST_FUNC void relocate_syms(TCCState *S, Section *symtab, int do_resolve);
|
|||
ST_FUNC void relocate_sections(TCCState *S);
|
||||
|
||||
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
|
||||
ST_FUNC void *load_data(TCCState* S, int fd, unsigned long file_offset, unsigned long size);
|
||||
ST_FUNC void *load_data(TCCState *S, int fd, unsigned long file_offset, unsigned long size);
|
||||
ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
|
||||
ST_FUNC int tcc_load_object_file(TCCState *S, int fd, unsigned long file_offset);
|
||||
ST_FUNC int tcc_load_archive(TCCState *S, int fd, int alacarte);
|
||||
|
@ -1733,31 +1732,31 @@ ST_FUNC void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||
ST_DATA const char * const target_machine_defs;
|
||||
ST_DATA const int reg_classes[NB_REGS];
|
||||
|
||||
ST_FUNC void gsym_addr(TCCState* S, int t, int a);
|
||||
ST_FUNC void gsym(TCCState* S, int t);
|
||||
ST_FUNC void gsym_addr(TCCState *S, int t, int a);
|
||||
ST_FUNC void gsym(TCCState *S, int t);
|
||||
ST_FUNC void load(TCCState *S, int r, SValue *sv);
|
||||
ST_FUNC void store(TCCState *S, int r, SValue *v);
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||
ST_FUNC void gfunc_call(TCCState *S, int nb_args);
|
||||
ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym);
|
||||
ST_FUNC void gfunc_epilog(TCCState *S);
|
||||
ST_FUNC void gen_fill_nops(TCCState* S, int);
|
||||
ST_FUNC int gjmp(TCCState* S, int t);
|
||||
ST_FUNC void gjmp_addr(TCCState* S, int a);
|
||||
ST_FUNC int gjmp_cond(TCCState* S, int op, int t);
|
||||
ST_FUNC void gen_fill_nops(TCCState *S, int);
|
||||
ST_FUNC int gjmp(TCCState *S, int t);
|
||||
ST_FUNC void gjmp_addr(TCCState *S, int a);
|
||||
ST_FUNC int gjmp_cond(TCCState *S, int op, int t);
|
||||
ST_FUNC int gjmp_append(TCCState *S, int n, int t);
|
||||
ST_FUNC void gen_opi(TCCState* S, int op);
|
||||
ST_FUNC void gen_opf(TCCState* S, int op);
|
||||
ST_FUNC void gen_opi(TCCState *S, int op);
|
||||
ST_FUNC void gen_opf(TCCState *S, int op);
|
||||
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t);
|
||||
ST_FUNC void gen_cvt_itof(TCCState *S, int t);
|
||||
ST_FUNC void gen_cvt_ftof(TCCState *S, int t);
|
||||
ST_FUNC void ggoto(TCCState *S);
|
||||
#ifndef TCC_TARGET_C67
|
||||
ST_FUNC void o(TCCState* S, unsigned int c);
|
||||
ST_FUNC void o(TCCState *S, unsigned int c);
|
||||
#endif
|
||||
ST_FUNC void gen_vla_sp_save(TCCState* S, int addr);
|
||||
ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr);
|
||||
ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align);
|
||||
ST_FUNC void gen_vla_sp_save(TCCState *S, int addr);
|
||||
ST_FUNC void gen_vla_sp_restore(TCCState *S, int addr);
|
||||
ST_FUNC void gen_vla_alloc(TCCState *S, CType *type, int align);
|
||||
|
||||
static inline uint16_t read16le(unsigned char *p) {
|
||||
return p[0] | (uint16_t)p[1] << 8;
|
||||
|
@ -1786,26 +1785,26 @@ static inline void add64le(unsigned char *p, int64_t x) {
|
|||
|
||||
/* ------------ i386-gen.c ------------ */
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
||||
ST_FUNC void g(TCCState* S, int c);
|
||||
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||
ST_FUNC void g(TCCState *S, int c);
|
||||
ST_FUNC void gen_le16(TCCState *S, int c);
|
||||
ST_FUNC void gen_le32(TCCState *S, int c);
|
||||
#endif
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_addr32(TCCState* S, int r, Sym *sym, int c);
|
||||
ST_FUNC void gen_addrpc32(TCCState* S, int r, Sym *sym, int c);
|
||||
ST_FUNC void gen_cvt_csti(TCCState* S, int t);
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||
ST_FUNC void gen_addr32(TCCState *S, int r, Sym *sym, int c);
|
||||
ST_FUNC void gen_addrpc32(TCCState *S, int r, Sym *sym, int c);
|
||||
ST_FUNC void gen_cvt_csti(TCCState *S, int t);
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv);
|
||||
#endif
|
||||
|
||||
/* ------------ x86_64-gen.c ------------ */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_addr64(TCCState* S, int r, Sym *sym, int64_t c);
|
||||
ST_FUNC void gen_opl(TCCState* S, int op);
|
||||
ST_FUNC void gen_addr64(TCCState *S, int r, Sym *sym, int64_t c);
|
||||
ST_FUNC void gen_opl(TCCState *S, int op);
|
||||
#ifdef TCC_TARGET_PE
|
||||
ST_FUNC void gen_vla_result(TCCState* S, int addr);
|
||||
ST_FUNC void gen_vla_result(TCCState *S, int addr);
|
||||
#endif
|
||||
ST_FUNC void gen_cvt_sxtw(TCCState *S);
|
||||
ST_FUNC void gen_cvt_csti(TCCState* S, int t);
|
||||
ST_FUNC void gen_cvt_csti(TCCState *S, int t);
|
||||
#endif
|
||||
|
||||
/* ------------ arm-gen.c ------------ */
|
||||
|
@ -1814,29 +1813,29 @@ ST_FUNC void gen_cvt_csti(TCCState* S, int t);
|
|||
PUB_FUNC const char *default_elfinterp(TCCState *S);
|
||||
#endif
|
||||
ST_FUNC void arm_init(TCCState *S);
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv);
|
||||
#endif
|
||||
|
||||
/* ------------ arm64-gen.c ------------ */
|
||||
#ifdef TCC_TARGET_ARM64
|
||||
ST_FUNC void gen_opl(TCCState* S, int op);
|
||||
ST_FUNC void gen_opl(TCCState *S, int op);
|
||||
ST_FUNC void gfunc_return(TCCState *S, CType *func_type);
|
||||
ST_FUNC void gen_va_start(TCCState *S);
|
||||
ST_FUNC void gen_va_arg(TCCState *S, CType *t);
|
||||
ST_FUNC void gen_clear_cache(TCCState *S);
|
||||
ST_FUNC void gen_cvt_sxtw(TCCState *S);
|
||||
ST_FUNC void gen_cvt_csti(TCCState *S, int t);
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv);
|
||||
#endif
|
||||
|
||||
/* ------------ riscv64-gen.c ------------ */
|
||||
#ifdef TCC_TARGET_RISCV64
|
||||
ST_FUNC void gen_opl(TCCState* S, int op);
|
||||
ST_FUNC void gen_opl(TCCState *S, int op);
|
||||
//ST_FUNC void gfunc_return(TCCState *S, CType *func_type);
|
||||
ST_FUNC void gen_va_start(TCCState *S);
|
||||
ST_FUNC void arch_transfer_ret_regs(TCCState* S, int);
|
||||
ST_FUNC void arch_transfer_ret_regs(TCCState *S, int);
|
||||
ST_FUNC void gen_cvt_sxtw(TCCState *S);
|
||||
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||
ST_FUNC void gen_increment_tcov (TCCState *S, SValue *sv);
|
||||
#endif
|
||||
|
||||
/* ------------ c67-gen.c ------------ */
|
||||
|
@ -1851,25 +1850,25 @@ ST_FUNC int tcc_load_coff(TCCState *S, int fd);
|
|||
#endif
|
||||
|
||||
/* ------------ tccasm.c ------------ */
|
||||
ST_FUNC void asm_instr(TCCState* S);
|
||||
ST_FUNC void asm_global_instr(TCCState* S);
|
||||
ST_FUNC void asm_instr(TCCState *S);
|
||||
ST_FUNC void asm_global_instr(TCCState *S);
|
||||
ST_FUNC int tcc_assemble(TCCState *S, int do_preprocess);
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
ST_FUNC int find_constraint(TCCState* S, ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
||||
ST_FUNC Sym* get_asm_sym(TCCState* S, int name, Sym *csym);
|
||||
ST_FUNC int find_constraint(TCCState *S, ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
||||
ST_FUNC Sym* get_asm_sym(TCCState *S, int name, Sym *csym);
|
||||
ST_FUNC void asm_expr(TCCState *S, ExprValue *pe);
|
||||
ST_FUNC int asm_int_expr(TCCState *S);
|
||||
/* ------------ i386-asm.c ------------ */
|
||||
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe);
|
||||
ST_FUNC void gen_expr32(TCCState *S, ExprValue *pe);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe);
|
||||
ST_FUNC void gen_expr64(TCCState *S, ExprValue *pe);
|
||||
#endif
|
||||
ST_FUNC void asm_opcode(TCCState *S, int opcode);
|
||||
ST_FUNC int asm_parse_regvar(TCCState* S, int t);
|
||||
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
||||
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, SValue *sv, int modifier);
|
||||
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
||||
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str);
|
||||
ST_FUNC int asm_parse_regvar(TCCState *S, int t);
|
||||
ST_FUNC void asm_compute_constraints(TCCState *S, ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
||||
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str, SValue *sv, int modifier);
|
||||
ST_FUNC void asm_gen_code(TCCState *S, ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
||||
ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str);
|
||||
#endif
|
||||
|
||||
/* ------------ tccpe.c -------------- */
|
||||
|
@ -1881,9 +1880,9 @@ ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t val
|
|||
ST_FUNC SValue *pe_getimport(TCCState * S, SValue *sv, SValue *v2);
|
||||
#endif
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void pe_add_unwind_data(TCCState* S, unsigned start, unsigned end, unsigned stack);
|
||||
ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsigned stack);
|
||||
#endif
|
||||
PUB_FUNC int tcc_get_dllexports(TCCState* S, const char *filename, char **pp);
|
||||
PUB_FUNC int tcc_get_dllexports(TCCState *S, const char *filename, char **pp);
|
||||
/* symbol properties stored in Elf32_Sym->st_other */
|
||||
# define ST_PE_EXPORT 0x10
|
||||
# define ST_PE_IMPORT 0x20
|
||||
|
@ -1897,7 +1896,7 @@ ST_FUNC int macho_output_file(TCCState * S, const char *filename);
|
|||
ST_FUNC int macho_load_dll(TCCState *S, int fd, const char *filename, int lev);
|
||||
ST_FUNC int macho_load_tbd(TCCState *S, int fd, const char *filename, int lev);
|
||||
#ifdef TCC_IS_NATIVE
|
||||
ST_FUNC void tcc_add_macos_sdkpath(TCCState* S);
|
||||
ST_FUNC void tcc_add_macos_sdkpath(TCCState *S);
|
||||
ST_FUNC const char* macho_tbd_soname(const char* filename);
|
||||
#endif
|
||||
#endif
|
||||
|
|
246
tccasm.c
246
tccasm.c
|
@ -39,7 +39,7 @@ static Sym* asm_new_label1(TCCState *S, int label, int is_local, int sh_num, int
|
|||
the global C symbol table to track ASM names as well, so we need to
|
||||
transform those into ones that don't conflict with a C name,
|
||||
so prepend a '.' for them, but force the ELF asm name to be set. */
|
||||
static int asm2cname(TCCState* S, int v, int *addeddot)
|
||||
static int asm2cname(TCCState *S, int v, int *addeddot)
|
||||
{
|
||||
const char *name;
|
||||
*addeddot = 0;
|
||||
|
@ -59,7 +59,7 @@ static int asm2cname(TCCState* S, int v, int *addeddot)
|
|||
return v;
|
||||
}
|
||||
|
||||
static Sym *asm_label_find(TCCState* S, int v)
|
||||
static Sym *asm_label_find(TCCState *S, int v)
|
||||
{
|
||||
Sym *sym;
|
||||
int addeddot;
|
||||
|
@ -70,7 +70,7 @@ static Sym *asm_label_find(TCCState* S, int v)
|
|||
return sym;
|
||||
}
|
||||
|
||||
static Sym *asm_label_push(TCCState* S, int v)
|
||||
static Sym *asm_label_push(TCCState *S, int v)
|
||||
{
|
||||
int addeddot, v2 = asm2cname(S, v, &addeddot);
|
||||
/* We always add VT_EXTERN, for sym definition that's tentative
|
||||
|
@ -92,7 +92,7 @@ static Sym *asm_label_push(TCCState* S, int v)
|
|||
are anonymous in C, in this case CSYM can be used to transfer
|
||||
all information from that symbol to the (possibly newly created)
|
||||
asm symbol. */
|
||||
ST_FUNC Sym* get_asm_sym(TCCState* S, int name, Sym *csym)
|
||||
ST_FUNC Sym* get_asm_sym(TCCState *S, int name, Sym *csym)
|
||||
{
|
||||
Sym *sym = asm_label_find(S, name);
|
||||
if (!sym) {
|
||||
|
@ -122,9 +122,9 @@ static void asm_expr_unary(TCCState *S, ExprValue *pe)
|
|||
uint64_t n;
|
||||
const char *p;
|
||||
|
||||
switch(S->tccpp_tok) {
|
||||
switch(S->tok) {
|
||||
case TOK_PPNUM:
|
||||
p = S->tccpp_tokc.str.data;
|
||||
p = S->tokc.str.data;
|
||||
n = strtoull(p, (char **)&p, 0);
|
||||
if (*p == 'b' || *p == 'f') {
|
||||
/* backward or forward label */
|
||||
|
@ -161,7 +161,7 @@ static void asm_expr_unary(TCCState *S, ExprValue *pe)
|
|||
break;
|
||||
case '-':
|
||||
case '~':
|
||||
op = S->tccpp_tok;
|
||||
op = S->tok;
|
||||
next(S);
|
||||
asm_expr_unary(S, pe);
|
||||
if (pe->sym)
|
||||
|
@ -173,7 +173,7 @@ static void asm_expr_unary(TCCState *S, ExprValue *pe)
|
|||
break;
|
||||
case TOK_CCHAR:
|
||||
case TOK_LCHAR:
|
||||
pe->v = S->tccpp_tokc.i;
|
||||
pe->v = S->tokc.i;
|
||||
pe->sym = NULL;
|
||||
pe->pcrel = 0;
|
||||
next(S);
|
||||
|
@ -184,16 +184,16 @@ static void asm_expr_unary(TCCState *S, ExprValue *pe)
|
|||
skip(S, ')');
|
||||
break;
|
||||
case '.':
|
||||
pe->v = S->tccgen_ind;
|
||||
pe->v = S->ind;
|
||||
pe->sym = asm_section_sym(S, cur_text_section);
|
||||
pe->pcrel = 0;
|
||||
next(S);
|
||||
break;
|
||||
default:
|
||||
if (S->tccpp_tok >= TOK_IDENT) {
|
||||
if (S->tok >= TOK_IDENT) {
|
||||
ElfSym *esym;
|
||||
/* label case : if the label was not found, add one */
|
||||
sym = get_asm_sym(S, S->tccpp_tok, NULL);
|
||||
sym = get_asm_sym(S, S->tok, NULL);
|
||||
esym = elfsym(S, sym);
|
||||
if (esym && esym->st_shndx == SHN_ABS) {
|
||||
/* if absolute symbol, no need to put a symbol value */
|
||||
|
@ -207,7 +207,7 @@ static void asm_expr_unary(TCCState *S, ExprValue *pe)
|
|||
}
|
||||
next(S);
|
||||
} else {
|
||||
tcc_error(S, "bad expression syntax [%s]", get_tok_str(S, S->tccpp_tok, &S->tccpp_tokc));
|
||||
tcc_error(S, "bad expression syntax [%s]", get_tok_str(S, S->tok, &S->tokc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ static void asm_expr_prod(TCCState *S, ExprValue *pe)
|
|||
|
||||
asm_expr_unary(S, pe);
|
||||
for(;;) {
|
||||
op = S->tccpp_tok;
|
||||
op = S->tok;
|
||||
if (op != '*' && op != '/' && op != '%' &&
|
||||
op != TOK_SHL && op != TOK_SAR)
|
||||
break;
|
||||
|
@ -262,7 +262,7 @@ static void asm_expr_logic(TCCState *S, ExprValue *pe)
|
|||
|
||||
asm_expr_prod(S, pe);
|
||||
for(;;) {
|
||||
op = S->tccpp_tok;
|
||||
op = S->tok;
|
||||
if (op != '&' && op != '|' && op != '^')
|
||||
break;
|
||||
next(S);
|
||||
|
@ -291,7 +291,7 @@ static inline void asm_expr_sum(TCCState *S, ExprValue *pe)
|
|||
|
||||
asm_expr_logic(S, pe);
|
||||
for(;;) {
|
||||
op = S->tccpp_tok;
|
||||
op = S->tok;
|
||||
if (op != '+' && op != '-')
|
||||
break;
|
||||
next(S);
|
||||
|
@ -323,7 +323,7 @@ static inline void asm_expr_sum(TCCState *S, ExprValue *pe)
|
|||
} else if (esym2->st_shndx == cur_text_section->sh_num) {
|
||||
/* When subtracting a defined symbol in current section
|
||||
this actually makes the value PC-relative. */
|
||||
pe->v -= esym2->st_value - S->tccgen_ind - 4;
|
||||
pe->v -= esym2->st_value - S->ind - 4;
|
||||
pe->pcrel = 1;
|
||||
e2.sym = NULL;
|
||||
} else {
|
||||
|
@ -342,7 +342,7 @@ static inline void asm_expr_cmp(TCCState *S, ExprValue *pe)
|
|||
|
||||
asm_expr_sum(S, pe);
|
||||
for(;;) {
|
||||
op = S->tccpp_tok;
|
||||
op = S->tok;
|
||||
if (op != TOK_EQ && op != TOK_NE
|
||||
&& (op > TOK_GT || op < TOK_ULE))
|
||||
break;
|
||||
|
@ -428,7 +428,7 @@ static Sym* asm_new_label1(TCCState *S, int label, int is_local,
|
|||
|
||||
static Sym* asm_new_label(TCCState *S, int label, int is_local)
|
||||
{
|
||||
return asm_new_label1(S, label, is_local, cur_text_section->sh_num, S->tccgen_ind);
|
||||
return asm_new_label1(S, label, is_local, cur_text_section->sh_num, S->ind);
|
||||
}
|
||||
|
||||
/* Set the value of LABEL to that of some expression (possibly
|
||||
|
@ -452,9 +452,9 @@ static Sym* set_symbol(TCCState *S, int label)
|
|||
|
||||
static void use_section1(TCCState *S, Section *sec)
|
||||
{
|
||||
cur_text_section->data_offset = S->tccgen_ind;
|
||||
cur_text_section->data_offset = S->ind;
|
||||
cur_text_section = sec;
|
||||
S->tccgen_ind = cur_text_section->data_offset;
|
||||
S->ind = cur_text_section->data_offset;
|
||||
}
|
||||
|
||||
static void use_section(TCCState *S, const char *name)
|
||||
|
@ -488,13 +488,13 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
|
||||
/* assembler directive */
|
||||
sec = cur_text_section;
|
||||
switch(S->tccpp_tok) {
|
||||
switch(S->tok) {
|
||||
case TOK_ASMDIR_align:
|
||||
case TOK_ASMDIR_balign:
|
||||
case TOK_ASMDIR_p2align:
|
||||
case TOK_ASMDIR_skip:
|
||||
case TOK_ASMDIR_space:
|
||||
tok1 = S->tccpp_tok;
|
||||
tok1 = S->tok;
|
||||
next(S);
|
||||
n = asm_int_expr(S);
|
||||
if (tok1 == TOK_ASMDIR_p2align)
|
||||
|
@ -507,8 +507,8 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) {
|
||||
if (n < 0 || (n & (n-1)) != 0)
|
||||
tcc_error(S, "alignment must be a positive power of two");
|
||||
offset = (S->tccgen_ind + n - 1) & -n;
|
||||
size = offset - S->tccgen_ind;
|
||||
offset = (S->ind + n - 1) & -n;
|
||||
size = offset - S->ind;
|
||||
/* the section must have a compatible alignment */
|
||||
if (sec->sh_addralign < n)
|
||||
sec->sh_addralign = n;
|
||||
|
@ -518,17 +518,17 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
size = n;
|
||||
}
|
||||
v = 0;
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
v = asm_int_expr(S);
|
||||
}
|
||||
zero_pad:
|
||||
if (sec->sh_type != SHT_NOBITS) {
|
||||
sec->data_offset = S->tccgen_ind;
|
||||
sec->data_offset = S->ind;
|
||||
ptr = section_ptr_add(S, sec, size);
|
||||
memset(ptr, v, size);
|
||||
}
|
||||
S->tccgen_ind += size;
|
||||
S->ind += size;
|
||||
break;
|
||||
case TOK_ASMDIR_quad:
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
|
@ -540,8 +540,8 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
uint64_t vl;
|
||||
const char *p;
|
||||
|
||||
p = S->tccpp_tokc.str.data;
|
||||
if (S->tccpp_tok != TOK_PPNUM) {
|
||||
p = S->tokc.str.data;
|
||||
if (S->tok != TOK_PPNUM) {
|
||||
error_constant:
|
||||
tcc_error(S, "64 bit constant");
|
||||
}
|
||||
|
@ -554,9 +554,9 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
gen_le32(S, vl);
|
||||
gen_le32(S, vl >> 32);
|
||||
} else {
|
||||
S->tccgen_ind += 8;
|
||||
S->ind += 8;
|
||||
}
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
break;
|
||||
next(S);
|
||||
}
|
||||
|
@ -593,9 +593,9 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
gen_le16(S, e.v);
|
||||
}
|
||||
} else {
|
||||
S->tccgen_ind += size;
|
||||
S->ind += size;
|
||||
}
|
||||
if (S->tccpp_tok != ',')
|
||||
if (S->tok != ',')
|
||||
break;
|
||||
next(S);
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
}
|
||||
size = 1;
|
||||
val = 0;
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
size = asm_int_expr(S);
|
||||
if (size < 0) {
|
||||
|
@ -621,7 +621,7 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
}
|
||||
if (size > 8)
|
||||
size = 8;
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
val = asm_int_expr(S);
|
||||
}
|
||||
|
@ -649,8 +649,8 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
next(S);
|
||||
repeat = asm_int_expr(S);
|
||||
init_str = tok_str_alloc(S);
|
||||
while (next(S), S->tccpp_tok != TOK_ASMDIR_endr) {
|
||||
if (S->tccpp_tok == CH_EOF)
|
||||
while (next(S), S->tok != TOK_ASMDIR_endr) {
|
||||
if (S->tok == CH_EOF)
|
||||
tcc_error(S, "we at end of file, .endr not found");
|
||||
tok_str_add_tok(S, init_str);
|
||||
}
|
||||
|
@ -680,31 +680,31 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
expect(S, "constant or same-section symbol");
|
||||
n += esym->st_value;
|
||||
}
|
||||
if (n < S->tccgen_ind)
|
||||
if (n < S->ind)
|
||||
tcc_error(S, "attempt to .org backwards");
|
||||
v = 0;
|
||||
size = n - S->tccgen_ind;
|
||||
size = n - S->ind;
|
||||
goto zero_pad;
|
||||
}
|
||||
break;
|
||||
case TOK_ASMDIR_set:
|
||||
next(S);
|
||||
tok1 = S->tccpp_tok;
|
||||
tok1 = S->tok;
|
||||
next(S);
|
||||
/* Also accept '.set stuff', but don't do anything with this.
|
||||
It's used in GAS to set various features like '.set mips16'. */
|
||||
if (S->tccpp_tok == ',')
|
||||
if (S->tok == ',')
|
||||
set_symbol(S, tok1);
|
||||
break;
|
||||
case TOK_ASMDIR_globl:
|
||||
case TOK_ASMDIR_global:
|
||||
case TOK_ASMDIR_weak:
|
||||
case TOK_ASMDIR_hidden:
|
||||
tok1 = S->tccpp_tok;
|
||||
tok1 = S->tok;
|
||||
do {
|
||||
Sym *sym;
|
||||
next(S);
|
||||
sym = get_asm_sym(S, S->tccpp_tok, NULL);
|
||||
sym = get_asm_sym(S, S->tok, NULL);
|
||||
if (tok1 != TOK_ASMDIR_hidden)
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
if (tok1 == TOK_ASMDIR_weak)
|
||||
|
@ -713,7 +713,7 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
sym->a.visibility = STV_HIDDEN;
|
||||
update_storage(S, sym);
|
||||
next(S);
|
||||
} while (S->tccpp_tok == ',');
|
||||
} while (S->tok == ',');
|
||||
break;
|
||||
case TOK_ASMDIR_string:
|
||||
case TOK_ASMDIR_ascii:
|
||||
|
@ -722,21 +722,21 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
const uint8_t *p;
|
||||
int i, size, t;
|
||||
|
||||
t = S->tccpp_tok;
|
||||
t = S->tok;
|
||||
next(S);
|
||||
for(;;) {
|
||||
if (S->tccpp_tok != TOK_STR)
|
||||
if (S->tok != TOK_STR)
|
||||
expect(S, "string constant");
|
||||
p = S->tccpp_tokc.str.data;
|
||||
size = S->tccpp_tokc.str.size;
|
||||
p = S->tokc.str.data;
|
||||
size = S->tokc.str.size;
|
||||
if (t == TOK_ASMDIR_ascii && size > 0)
|
||||
size--;
|
||||
for(i = 0; i < size; i++)
|
||||
g(S, p[i]);
|
||||
next(S);
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
} else if (S->tccpp_tok != TOK_STR) {
|
||||
} else if (S->tok != TOK_STR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -747,10 +747,10 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
case TOK_ASMDIR_bss:
|
||||
{
|
||||
char sname[64];
|
||||
tok1 = S->tccpp_tok;
|
||||
tok1 = S->tok;
|
||||
n = 0;
|
||||
next(S);
|
||||
if (S->tccpp_tok != ';' && S->tccpp_tok != TOK_LINEFEED) {
|
||||
if (S->tok != ';' && S->tok != TOK_LINEFEED) {
|
||||
n = asm_int_expr(S);
|
||||
next(S);
|
||||
}
|
||||
|
@ -767,10 +767,10 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
|
||||
filename[0] = '\0';
|
||||
next(S);
|
||||
if (S->tccpp_tok == TOK_STR)
|
||||
pstrcat(filename, sizeof(filename), S->tccpp_tokc.str.data);
|
||||
if (S->tok == TOK_STR)
|
||||
pstrcat(filename, sizeof(filename), S->tokc.str.data);
|
||||
else
|
||||
pstrcat(filename, sizeof(filename), get_tok_str(S, S->tccpp_tok, NULL));
|
||||
pstrcat(filename, sizeof(filename), get_tok_str(S, S->tok, NULL));
|
||||
tcc_warning_c(warn_unsupported)(S, "ignoring .file %s", filename);
|
||||
next(S);
|
||||
}
|
||||
|
@ -781,10 +781,10 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
|
||||
ident[0] = '\0';
|
||||
next(S);
|
||||
if (S->tccpp_tok == TOK_STR)
|
||||
pstrcat(ident, sizeof(ident), S->tccpp_tokc.str.data);
|
||||
if (S->tok == TOK_STR)
|
||||
pstrcat(ident, sizeof(ident), S->tokc.str.data);
|
||||
else
|
||||
pstrcat(ident, sizeof(ident), get_tok_str(S, S->tccpp_tok, NULL));
|
||||
pstrcat(ident, sizeof(ident), get_tok_str(S, S->tok, NULL));
|
||||
tcc_warning_c(warn_unsupported)(S, "ignoring .ident %s", ident);
|
||||
next(S);
|
||||
}
|
||||
|
@ -794,15 +794,15 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
Sym *sym;
|
||||
|
||||
next(S);
|
||||
sym = asm_label_find(S, S->tccpp_tok);
|
||||
sym = asm_label_find(S, S->tok);
|
||||
if (!sym) {
|
||||
tcc_error(S, "label not found: %s", get_tok_str(S, S->tccpp_tok, NULL));
|
||||
tcc_error(S, "label not found: %s", get_tok_str(S, S->tok, NULL));
|
||||
}
|
||||
/* XXX .size name,label2-label1 */
|
||||
tcc_warning_c(warn_unsupported)(S, "ignoring .size %s,*", get_tok_str(S, S->tccpp_tok, NULL));
|
||||
tcc_warning_c(warn_unsupported)(S, "ignoring .size %s,*", get_tok_str(S, S->tok, NULL));
|
||||
next(S);
|
||||
skip(S, ',');
|
||||
while (S->tccpp_tok != TOK_LINEFEED && S->tccpp_tok != ';' && S->tccpp_tok != CH_EOF) {
|
||||
while (S->tok != TOK_LINEFEED && S->tok != ';' && S->tok != CH_EOF) {
|
||||
next(S);
|
||||
}
|
||||
}
|
||||
|
@ -813,15 +813,15 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
const char *newtype;
|
||||
|
||||
next(S);
|
||||
sym = get_asm_sym(S, S->tccpp_tok, NULL);
|
||||
sym = get_asm_sym(S, S->tok, NULL);
|
||||
next(S);
|
||||
skip(S, ',');
|
||||
if (S->tccpp_tok == TOK_STR) {
|
||||
newtype = S->tccpp_tokc.str.data;
|
||||
if (S->tok == TOK_STR) {
|
||||
newtype = S->tokc.str.data;
|
||||
} else {
|
||||
if (S->tccpp_tok == '@' || S->tccpp_tok == '%')
|
||||
if (S->tok == '@' || S->tok == '%')
|
||||
next(S);
|
||||
newtype = get_tok_str(S, S->tccpp_tok, NULL);
|
||||
newtype = get_tok_str(S, S->tok, NULL);
|
||||
}
|
||||
|
||||
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
||||
|
@ -839,26 +839,26 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
char sname[256];
|
||||
int old_nb_section = S->nb_sections;
|
||||
|
||||
tok1 = S->tccpp_tok;
|
||||
tok1 = S->tok;
|
||||
/* XXX: support more options */
|
||||
next(S);
|
||||
sname[0] = '\0';
|
||||
while (S->tccpp_tok != ';' && S->tccpp_tok != TOK_LINEFEED && S->tccpp_tok != ',') {
|
||||
if (S->tccpp_tok == TOK_STR)
|
||||
pstrcat(sname, sizeof(sname), S->tccpp_tokc.str.data);
|
||||
while (S->tok != ';' && S->tok != TOK_LINEFEED && S->tok != ',') {
|
||||
if (S->tok == TOK_STR)
|
||||
pstrcat(sname, sizeof(sname), S->tokc.str.data);
|
||||
else
|
||||
pstrcat(sname, sizeof(sname), get_tok_str(S, S->tccpp_tok, NULL));
|
||||
pstrcat(sname, sizeof(sname), get_tok_str(S, S->tok, NULL));
|
||||
next(S);
|
||||
}
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
/* skip section options */
|
||||
next(S);
|
||||
if (S->tccpp_tok != TOK_STR)
|
||||
if (S->tok != TOK_STR)
|
||||
expect(S, "string constant");
|
||||
next(S);
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
if (S->tccpp_tok == '@' || S->tccpp_tok == '%')
|
||||
if (S->tok == '@' || S->tok == '%')
|
||||
next(S);
|
||||
next(S);
|
||||
}
|
||||
|
@ -911,7 +911,7 @@ static void asm_parse_directive(TCCState *S, int global)
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
tcc_error(S, "unknown assembler directive '.%s'", get_tok_str(S, S->tccpp_tok, NULL));
|
||||
tcc_error(S, "unknown assembler directive '.%s'", get_tok_str(S, S->tok, NULL));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -928,20 +928,20 @@ static int tcc_assemble_internal(TCCState *S, int do_preprocess, int global)
|
|||
S->tccpp_parse_flags |= PARSE_FLAG_PREPROCESS;
|
||||
for(;;) {
|
||||
next(S);
|
||||
if (S->tccpp_tok == TOK_EOF)
|
||||
if (S->tok == TOK_EOF)
|
||||
break;
|
||||
S->tccpp_parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
||||
redo:
|
||||
if (S->tccpp_tok == '#') {
|
||||
if (S->tok == '#') {
|
||||
/* horrible gas comment */
|
||||
while (S->tccpp_tok != TOK_LINEFEED)
|
||||
while (S->tok != TOK_LINEFEED)
|
||||
next(S);
|
||||
} else if (S->tccpp_tok >= TOK_ASMDIR_FIRST && S->tccpp_tok <= TOK_ASMDIR_LAST) {
|
||||
} else if (S->tok >= TOK_ASMDIR_FIRST && S->tok <= TOK_ASMDIR_LAST) {
|
||||
asm_parse_directive(S, global);
|
||||
} else if (S->tccpp_tok == TOK_PPNUM) {
|
||||
} else if (S->tok == TOK_PPNUM) {
|
||||
const char *p;
|
||||
int n;
|
||||
p = S->tccpp_tokc.str.data;
|
||||
p = S->tokc.str.data;
|
||||
n = strtoul(p, (char **)&p, 10);
|
||||
if (*p != '\0')
|
||||
expect(S, "':'");
|
||||
|
@ -950,16 +950,16 @@ static int tcc_assemble_internal(TCCState *S, int do_preprocess, int global)
|
|||
next(S);
|
||||
skip(S, ':');
|
||||
goto redo;
|
||||
} else if (S->tccpp_tok >= TOK_IDENT) {
|
||||
} else if (S->tok >= TOK_IDENT) {
|
||||
/* instruction or label */
|
||||
opcode = S->tccpp_tok;
|
||||
opcode = S->tok;
|
||||
next(S);
|
||||
if (S->tccpp_tok == ':') {
|
||||
if (S->tok == ':') {
|
||||
/* new label */
|
||||
asm_new_label(S, opcode, 0);
|
||||
next(S);
|
||||
goto redo;
|
||||
} else if (S->tccpp_tok == '=') {
|
||||
} else if (S->tok == '=') {
|
||||
set_symbol(S, opcode);
|
||||
goto redo;
|
||||
} else {
|
||||
|
@ -967,7 +967,7 @@ static int tcc_assemble_internal(TCCState *S, int do_preprocess, int global)
|
|||
}
|
||||
}
|
||||
/* end of line */
|
||||
if (S->tccpp_tok != ';' && S->tccpp_tok != TOK_LINEFEED)
|
||||
if (S->tok != ';' && S->tok != TOK_LINEFEED)
|
||||
expect(S, "end of line");
|
||||
S->tccpp_parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
||||
}
|
||||
|
@ -983,10 +983,10 @@ ST_FUNC int tcc_assemble(TCCState *S, int do_preprocess)
|
|||
tcc_debug_start(S);
|
||||
/* default section is text */
|
||||
cur_text_section = text_section;
|
||||
S->tccgen_ind = cur_text_section->data_offset;
|
||||
S->tccgen_nocode_wanted = 0;
|
||||
S->ind = cur_text_section->data_offset;
|
||||
S->nocode_wanted = 0;
|
||||
ret = tcc_assemble_internal(S, do_preprocess, 1);
|
||||
cur_text_section->data_offset = S->tccgen_ind;
|
||||
cur_text_section->data_offset = S->ind;
|
||||
tcc_debug_end(S);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1017,7 +1017,7 @@ static void tcc_assemble_inline(TCCState *S, char *str, int len, int global)
|
|||
/* find a constraint by its number or id (gcc 3 extended
|
||||
syntax). return -1 if not found. Return in *pp in char after the
|
||||
constraint */
|
||||
ST_FUNC int find_constraint(TCCState* S, ASMOperand *operands, int nb_operands,
|
||||
ST_FUNC int find_constraint(TCCState *S, ASMOperand *operands, int nb_operands,
|
||||
const char *name, const char **pp)
|
||||
{
|
||||
int index;
|
||||
|
@ -1055,7 +1055,7 @@ ST_FUNC int find_constraint(TCCState* S, ASMOperand *operands, int nb_operands,
|
|||
return index;
|
||||
}
|
||||
|
||||
static void subst_asm_operands(TCCState* S, ASMOperand *operands, int nb_operands,
|
||||
static void subst_asm_operands(TCCState *S, ASMOperand *operands, int nb_operands,
|
||||
CString *out_str, CString *in_str)
|
||||
{
|
||||
int c, index, modifier;
|
||||
|
@ -1101,13 +1101,13 @@ static void subst_asm_operands(TCCState* S, ASMOperand *operands, int nb_operand
|
|||
}
|
||||
|
||||
|
||||
static void parse_asm_operands(TCCState* S, ASMOperand *operands, int *nb_operands_ptr,
|
||||
static void parse_asm_operands(TCCState *S, ASMOperand *operands, int *nb_operands_ptr,
|
||||
int is_output)
|
||||
{
|
||||
ASMOperand *op;
|
||||
int nb_operands;
|
||||
|
||||
if (S->tccpp_tok != ':') {
|
||||
if (S->tok != ':') {
|
||||
nb_operands = *nb_operands_ptr;
|
||||
for(;;) {
|
||||
CString astr;
|
||||
|
@ -1115,11 +1115,11 @@ static void parse_asm_operands(TCCState* S, ASMOperand *operands, int *nb_operan
|
|||
tcc_error(S, "too many asm operands");
|
||||
op = &operands[nb_operands++];
|
||||
op->id = 0;
|
||||
if (S->tccpp_tok == '[') {
|
||||
if (S->tok == '[') {
|
||||
next(S);
|
||||
if (S->tccpp_tok < TOK_IDENT)
|
||||
if (S->tok < TOK_IDENT)
|
||||
expect(S, "identifier");
|
||||
op->id = S->tccpp_tok;
|
||||
op->id = S->tok;
|
||||
next(S);
|
||||
skip(S, ']');
|
||||
}
|
||||
|
@ -1130,23 +1130,23 @@ static void parse_asm_operands(TCCState* S, ASMOperand *operands, int *nb_operan
|
|||
skip(S, '(');
|
||||
gexpr(S);
|
||||
if (is_output) {
|
||||
if (!(S->tccgen_vtop->type.t & VT_ARRAY))
|
||||
if (!(S->vtop->type.t & VT_ARRAY))
|
||||
test_lvalue(S);
|
||||
} else {
|
||||
/* we want to avoid LLOCAL case, except when the 'm'
|
||||
constraint is used. Note that it may come from
|
||||
register storage, so we need to convert (reg)
|
||||
case */
|
||||
if ((S->tccgen_vtop->r & VT_LVAL) &&
|
||||
((S->tccgen_vtop->r & VT_VALMASK) == VT_LLOCAL ||
|
||||
(S->tccgen_vtop->r & VT_VALMASK) < VT_CONST) &&
|
||||
if ((S->vtop->r & VT_LVAL) &&
|
||||
((S->vtop->r & VT_VALMASK) == VT_LLOCAL ||
|
||||
(S->vtop->r & VT_VALMASK) < VT_CONST) &&
|
||||
!strchr(op->constraint, 'm')) {
|
||||
gv(S, RC_INT);
|
||||
}
|
||||
}
|
||||
op->vt = S->tccgen_vtop;
|
||||
op->vt = S->vtop;
|
||||
skip(S, ')');
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
} else {
|
||||
break;
|
||||
|
@ -1157,7 +1157,7 @@ static void parse_asm_operands(TCCState* S, ASMOperand *operands, int *nb_operan
|
|||
}
|
||||
|
||||
/* parse the GCC asm() instruction */
|
||||
ST_FUNC void asm_instr(TCCState* S)
|
||||
ST_FUNC void asm_instr(TCCState *S)
|
||||
{
|
||||
CString astr, astr1;
|
||||
ASMOperand operands[MAX_ASM_OPERANDS];
|
||||
|
@ -1167,7 +1167,7 @@ ST_FUNC void asm_instr(TCCState* S)
|
|||
|
||||
/* since we always generate the asm() instruction, we can ignore
|
||||
volatile */
|
||||
if (S->tccpp_tok == TOK_VOLATILE1 || S->tccpp_tok == TOK_VOLATILE2 || S->tccpp_tok == TOK_VOLATILE3) {
|
||||
if (S->tok == TOK_VOLATILE1 || S->tok == TOK_VOLATILE2 || S->tok == TOK_VOLATILE3) {
|
||||
next(S);
|
||||
}
|
||||
parse_asm_str(S, &astr);
|
||||
|
@ -1175,27 +1175,27 @@ ST_FUNC void asm_instr(TCCState* S)
|
|||
nb_outputs = 0;
|
||||
must_subst = 0;
|
||||
memset(clobber_regs, 0, sizeof(clobber_regs));
|
||||
if (S->tccpp_tok == ':') {
|
||||
if (S->tok == ':') {
|
||||
next(S);
|
||||
must_subst = 1;
|
||||
/* output args */
|
||||
parse_asm_operands(S, operands, &nb_operands, 1);
|
||||
nb_outputs = nb_operands;
|
||||
if (S->tccpp_tok == ':') {
|
||||
if (S->tok == ':') {
|
||||
next(S);
|
||||
if (S->tccpp_tok != ')') {
|
||||
if (S->tok != ')') {
|
||||
/* input args */
|
||||
parse_asm_operands(S, operands, &nb_operands, 0);
|
||||
if (S->tccpp_tok == ':') {
|
||||
if (S->tok == ':') {
|
||||
/* clobber list */
|
||||
/* XXX: handle registers */
|
||||
next(S);
|
||||
for(;;) {
|
||||
if (S->tccpp_tok != TOK_STR)
|
||||
if (S->tok != TOK_STR)
|
||||
expect(S, "string constant");
|
||||
asm_clobber(S, clobber_regs, S->tccpp_tokc.str.data);
|
||||
asm_clobber(S, clobber_regs, S->tokc.str.data);
|
||||
next(S);
|
||||
if (S->tccpp_tok == ',') {
|
||||
if (S->tok == ',') {
|
||||
next(S);
|
||||
} else {
|
||||
break;
|
||||
|
@ -1208,7 +1208,7 @@ ST_FUNC void asm_instr(TCCState* S)
|
|||
skip(S, ')');
|
||||
/* NOTE: we do not eat the ';' so that we can restore the current
|
||||
token after the assembler parsing */
|
||||
if (S->tccpp_tok != ';')
|
||||
if (S->tok != ';')
|
||||
expect(S, "';'");
|
||||
|
||||
/* save all values in the memory */
|
||||
|
@ -1264,37 +1264,37 @@ ST_FUNC void asm_instr(TCCState* S)
|
|||
cstr_free(S, &astr1);
|
||||
}
|
||||
|
||||
ST_FUNC void asm_global_instr(TCCState* S)
|
||||
ST_FUNC void asm_global_instr(TCCState *S)
|
||||
{
|
||||
CString astr;
|
||||
int saved_nocode_wanted = S->tccgen_nocode_wanted;
|
||||
int saved_nocode_wanted = S->nocode_wanted;
|
||||
|
||||
/* Global asm blocks are always emitted. */
|
||||
S->tccgen_nocode_wanted = 0;
|
||||
S->nocode_wanted = 0;
|
||||
next(S);
|
||||
parse_asm_str(S, &astr);
|
||||
skip(S, ')');
|
||||
/* NOTE: we do not eat the ';' so that we can restore the current
|
||||
token after the assembler parsing */
|
||||
if (S->tccpp_tok != ';')
|
||||
if (S->tok != ';')
|
||||
expect(S, "';'");
|
||||
|
||||
#ifdef ASM_DEBUG
|
||||
printf("asm_global: \"%s\"\n", (char *)astr.data);
|
||||
#endif
|
||||
cur_text_section = text_section;
|
||||
S->tccgen_ind = cur_text_section->data_offset;
|
||||
S->ind = cur_text_section->data_offset;
|
||||
|
||||
/* assemble the string with tcc internal assembler */
|
||||
tcc_assemble_inline(S, astr.data, astr.size - 1, 1);
|
||||
|
||||
cur_text_section->data_offset = S->tccgen_ind;
|
||||
cur_text_section->data_offset = S->ind;
|
||||
|
||||
/* restore the current C token */
|
||||
next(S);
|
||||
|
||||
cstr_free(S, &astr);
|
||||
S->tccgen_nocode_wanted = saved_nocode_wanted;
|
||||
S->nocode_wanted = saved_nocode_wanted;
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
|
@ -1304,12 +1304,12 @@ ST_FUNC int tcc_assemble(TCCState *S, int do_preprocess)
|
|||
tcc_error(S, "asm not supported");
|
||||
}
|
||||
|
||||
ST_FUNC void asm_instr(S)
|
||||
ST_FUNC void asm_instr(TCCState *S)
|
||||
{
|
||||
tcc_error(S, "inline asm() not supported");
|
||||
}
|
||||
|
||||
ST_FUNC void asm_global_instr(S)
|
||||
ST_FUNC void asm_global_instr(TCCState *S)
|
||||
{
|
||||
tcc_error(S, "inline asm() not supported");
|
||||
}
|
||||
|
|
20
tccelf.c
20
tccelf.c
|
@ -107,7 +107,7 @@ ST_FUNC void tccelf_stab_new(TCCState *S)
|
|||
put_stabs(S, "", 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void free_section(TCCState* S, Section *s)
|
||||
static void free_section(TCCState *S, Section *s)
|
||||
{
|
||||
tcc_free(S, s->data);
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ ST_FUNC Section *new_symtab(TCCState *S,
|
|||
}
|
||||
|
||||
/* realloc section and set its content to zero */
|
||||
ST_FUNC void section_realloc(TCCState* S, Section *sec, unsigned long new_size)
|
||||
ST_FUNC void section_realloc(TCCState *S, Section *sec, unsigned long new_size)
|
||||
{
|
||||
unsigned long size;
|
||||
unsigned char *data;
|
||||
|
@ -302,7 +302,7 @@ ST_FUNC void section_realloc(TCCState* S, Section *sec, unsigned long new_size)
|
|||
|
||||
/* reserve at least 'size' bytes aligned per 'align' in section
|
||||
'sec' from current offset, and return the aligned offset */
|
||||
ST_FUNC size_t section_add(TCCState* S, Section *sec, addr_t size, int align)
|
||||
ST_FUNC size_t section_add(TCCState *S, Section *sec, addr_t size, int align)
|
||||
{
|
||||
size_t offset, offset1;
|
||||
|
||||
|
@ -318,7 +318,7 @@ ST_FUNC size_t section_add(TCCState* S, Section *sec, addr_t size, int align)
|
|||
|
||||
/* reserve at least 'size' bytes in section 'sec' from
|
||||
sec->data_offset. */
|
||||
ST_FUNC void *section_ptr_add(TCCState* S, Section *sec, addr_t size)
|
||||
ST_FUNC void *section_ptr_add(TCCState *S, Section *sec, addr_t size)
|
||||
{
|
||||
size_t offset = section_add(S, sec, size, 1);
|
||||
return sec->data + offset;
|
||||
|
@ -326,7 +326,7 @@ ST_FUNC void *section_ptr_add(TCCState* S, Section *sec, addr_t size)
|
|||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
/* reserve at least 'size' bytes from section start */
|
||||
static void section_reserve(TCCState* S, Section *sec, unsigned long size)
|
||||
static void section_reserve(TCCState *S, Section *sec, unsigned long size)
|
||||
{
|
||||
if (size > sec->data_allocated)
|
||||
section_realloc(S, sec, size);
|
||||
|
@ -357,7 +357,7 @@ ST_FUNC Section *find_section(TCCState *S, const char *name)
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
ST_FUNC int put_elf_str(TCCState* S, Section *s, const char *sym)
|
||||
ST_FUNC int put_elf_str(TCCState *S, Section *s, const char *sym)
|
||||
{
|
||||
int offset, len;
|
||||
char *ptr;
|
||||
|
@ -386,7 +386,7 @@ static unsigned long elf_hash(const unsigned char *name)
|
|||
|
||||
/* rebuild hash table of section s */
|
||||
/* NOTE: we do factorize the hash table code to go faster */
|
||||
static void rebuild_hash(TCCState* S, Section *s, unsigned int nb_buckets)
|
||||
static void rebuild_hash(TCCState *S, Section *s, unsigned int nb_buckets)
|
||||
{
|
||||
ElfW(Sym) *sym;
|
||||
int *ptr, *hash, nb_syms, sym_index, h;
|
||||
|
@ -422,7 +422,7 @@ static void rebuild_hash(TCCState* S, Section *s, unsigned int nb_buckets)
|
|||
}
|
||||
|
||||
/* return the symbol number */
|
||||
ST_FUNC int put_elf_sym(TCCState* S, Section *s, addr_t value, unsigned long size,
|
||||
ST_FUNC int put_elf_sym(TCCState *S, Section *s, addr_t value, unsigned long size,
|
||||
int info, int other, int shndx, const char *name)
|
||||
{
|
||||
int name_offset, sym_index;
|
||||
|
@ -2082,7 +2082,7 @@ static int layout_sections(TCCState *S, ElfW(Phdr) *phdr,
|
|||
}
|
||||
|
||||
/* put dynamic tag */
|
||||
static void put_dt(TCCState* S, Section *dynamic, int dt, addr_t val)
|
||||
static void put_dt(TCCState *S, Section *dynamic, int dt, addr_t val)
|
||||
{
|
||||
ElfW(Dyn) *dyn;
|
||||
dyn = section_ptr_add(S, dynamic, sizeof(ElfW(Dyn)));
|
||||
|
@ -2827,7 +2827,7 @@ ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) {
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void *load_data(TCCState* S, int fd, unsigned long file_offset, unsigned long size)
|
||||
ST_FUNC void *load_data(TCCState *S, int fd, unsigned long file_offset, unsigned long size)
|
||||
{
|
||||
void *data;
|
||||
|
||||
|
|
14
tccmacho.c
14
tccmacho.c
|
@ -249,7 +249,7 @@ struct macho {
|
|||
#define SHT_LINKEDIT (SHT_LOOS + 42)
|
||||
#define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */
|
||||
|
||||
static void * add_lc(TCCState* S, struct macho *mo, uint32_t cmd, uint32_t cmdsize)
|
||||
static void * add_lc(TCCState *S, struct macho *mo, uint32_t cmd, uint32_t cmdsize)
|
||||
{
|
||||
struct load_command *lc = tcc_mallocz(S, cmdsize);
|
||||
lc->cmd = cmd;
|
||||
|
@ -259,7 +259,7 @@ static void * add_lc(TCCState* S, struct macho *mo, uint32_t cmd, uint32_t cmdsi
|
|||
return lc;
|
||||
}
|
||||
|
||||
static struct segment_command_64 * add_segment(TCCState* S, struct macho *mo, const char *name)
|
||||
static struct segment_command_64 * add_segment(TCCState *S, struct macho *mo, const char *name)
|
||||
{
|
||||
struct segment_command_64 *sc = add_lc(S, mo, LC_SEGMENT_64, sizeof(*sc));
|
||||
strncpy(sc->segname, name, 16);
|
||||
|
@ -272,7 +272,7 @@ static struct segment_command_64 * get_segment(struct macho *mo, int i)
|
|||
return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]);
|
||||
}
|
||||
|
||||
static int add_section(TCCState* S, struct macho *mo, struct segment_command_64 **_seg, const char *name)
|
||||
static int add_section(TCCState *S, struct macho *mo, struct segment_command_64 **_seg, const char *name)
|
||||
{
|
||||
struct segment_command_64 *seg = *_seg;
|
||||
int ret = seg->nsects;
|
||||
|
@ -293,7 +293,7 @@ static struct section_64 *get_section(struct segment_command_64 *seg, int i)
|
|||
return (struct section_64*)((char*)seg + sizeof(*seg)) + i;
|
||||
}
|
||||
|
||||
static void * add_dylib(TCCState* S, struct macho *mo, char *name)
|
||||
static void * add_dylib(TCCState *S, struct macho *mo, char *name)
|
||||
{
|
||||
struct dylib_command *lc;
|
||||
int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8;
|
||||
|
@ -836,7 +836,7 @@ static uint32_t macho_swap32(uint32_t x)
|
|||
}
|
||||
#define SWAP(x) (swap ? macho_swap32(x) : (x))
|
||||
|
||||
ST_FUNC int macho_add_dllref(TCCState* S, int lev, const char* soname)
|
||||
ST_FUNC int macho_add_dllref(TCCState *S, int lev, const char* soname)
|
||||
{
|
||||
/* if the dll is already loaded, do not load it */
|
||||
DLLReference *dllref;
|
||||
|
@ -865,7 +865,7 @@ ST_FUNC int macho_add_dllref(TCCState* S, int lev, const char* soname)
|
|||
#ifdef TCC_IS_NATIVE
|
||||
/* Looks for the active developer SDK set by xcode-select (or the default
|
||||
one set during installation.) */
|
||||
ST_FUNC void tcc_add_macos_sdkpath(TCCState* s)
|
||||
ST_FUNC void tcc_add_macos_sdkpath(TCCState *S)
|
||||
{
|
||||
char *sdkroot = NULL, *pos = NULL;
|
||||
void* xcs = dlopen("libxcselect.dylib", RTLD_GLOBAL | RTLD_LAZY);
|
||||
|
@ -912,7 +912,7 @@ the_end:
|
|||
}
|
||||
#endif /* TCC_IS_NATIVE */
|
||||
|
||||
ST_FUNC int macho_load_tbd(TCCState* S, int fd, const char* filename, int lev)
|
||||
ST_FUNC int macho_load_tbd(TCCState *S, int fd, const char* filename, int lev)
|
||||
{
|
||||
char *soname, *data, *pos;
|
||||
int ret = -1;
|
||||
|
|
6
tccpe.c
6
tccpe.c
|
@ -1492,7 +1492,7 @@ static void pe_print_sections(TCCState *S, const char *fname)
|
|||
/* helper function for load/store to insert one more indirection */
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
ST_FUNC SValue *pe_getimport(TCCState* S, SValue *sv, SValue *v2)
|
||||
ST_FUNC SValue *pe_getimport(TCCState *S, SValue *sv, SValue *v2)
|
||||
{
|
||||
int r2;
|
||||
if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
|
||||
|
@ -1512,7 +1512,7 @@ ST_FUNC SValue *pe_getimport(TCCState* S, SValue *sv, SValue *v2)
|
|||
vpushv(S, v2);
|
||||
vpushi(S, sv->c.i);
|
||||
gen_opi(S, '+');
|
||||
*v2 = *S->tccgen_vtop--;
|
||||
*v2 = *S->vtop--;
|
||||
}
|
||||
v2->type.t = sv->type.t;
|
||||
v2->r |= sv->r & VT_LVAL;
|
||||
|
@ -1551,7 +1551,7 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static int get_dllexports(TCCState* S, int fd, char **pp)
|
||||
static int get_dllexports(TCCState *S, int fd, char **pp)
|
||||
{
|
||||
int l, i, n, n0, ret;
|
||||
char *p;
|
||||
|
|
400
x86_64-gen.c
400
x86_64-gen.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue