Alien-TinyCC
view release on metacpan or search on metacpan
src/tccasm.c view on Meta::CPAN
/* backward or forward label */
label = asm_get_local_label_name(s1, n);
sym = label_find(label);
if (*p == 'b') {
/* backward : find the last corresponding defined label */
if (sym && sym->r == 0)
sym = sym->prev_tok;
if (!sym)
tcc_error("local label '%d' not found backward", n);
} else {
/* forward */
if (!sym || sym->r) {
/* if the last label is defined, then define a new one */
sym = label_push(&s1->asm_labels, label, 0);
sym->type.t = VT_STATIC | VT_VOID;
}
}
pe->v = 0;
pe->sym = sym;
} else if (*p == '\0') {
pe->v = n;
pe->sym = NULL;
} else {
tcc_error("invalid number syntax");
}
next();
break;
case '+':
next();
asm_expr_unary(s1, pe);
break;
case '-':
case '~':
op = tok;
next();
asm_expr_unary(s1, pe);
if (pe->sym)
tcc_error("invalid operation with label");
if (op == '-')
pe->v = -pe->v;
else
pe->v = ~pe->v;
break;
case TOK_CCHAR:
case TOK_LCHAR:
pe->v = tokc.i;
pe->sym = NULL;
next();
break;
case '(':
next();
asm_expr(s1, pe);
skip(')');
break;
default:
if (tok >= TOK_IDENT) {
/* label case : if the label was not found, add one */
sym = label_find(tok);
if (!sym) {
sym = label_push(&s1->asm_labels, tok, 0);
/* NOTE: by default, the symbol is global */
sym->type.t = VT_VOID;
}
if (sym->r == SHN_ABS) {
/* if absolute symbol, no need to put a symbol value */
pe->v = sym->jnext;
pe->sym = NULL;
} else {
pe->v = 0;
pe->sym = sym;
}
next();
} else {
tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
}
break;
}
}
static void asm_expr_prod(TCCState *s1, ExprValue *pe)
{
int op;
ExprValue e2;
asm_expr_unary(s1, pe);
for(;;) {
op = tok;
if (op != '*' && op != '/' && op != '%' &&
op != TOK_SHL && op != TOK_SAR)
break;
next();
asm_expr_unary(s1, &e2);
if (pe->sym || e2.sym)
tcc_error("invalid operation with label");
switch(op) {
case '*':
pe->v *= e2.v;
break;
case '/':
if (e2.v == 0) {
div_error:
tcc_error("division by zero");
}
pe->v /= e2.v;
break;
case '%':
if (e2.v == 0)
goto div_error;
pe->v %= e2.v;
break;
case TOK_SHL:
pe->v <<= e2.v;
break;
default:
case TOK_SAR:
pe->v >>= e2.v;
break;
}
}
}
src/tccasm.c view on Meta::CPAN
if (tok != ',')
break;
next();
}
break;
case TOK_ASM_fill:
{
int repeat, size, val, i, j;
uint8_t repeat_buf[8];
next();
repeat = asm_int_expr(s1);
if (repeat < 0) {
tcc_error("repeat < 0; .fill ignored");
break;
}
size = 1;
val = 0;
if (tok == ',') {
next();
size = asm_int_expr(s1);
if (size < 0) {
tcc_error("size < 0; .fill ignored");
break;
}
if (size > 8)
size = 8;
if (tok == ',') {
next();
val = asm_int_expr(s1);
}
}
/* XXX: endianness */
repeat_buf[0] = val;
repeat_buf[1] = val >> 8;
repeat_buf[2] = val >> 16;
repeat_buf[3] = val >> 24;
repeat_buf[4] = 0;
repeat_buf[5] = 0;
repeat_buf[6] = 0;
repeat_buf[7] = 0;
for(i = 0; i < repeat; i++) {
for(j = 0; j < size; j++) {
g(repeat_buf[j]);
}
}
}
break;
case TOK_ASM_org:
{
unsigned long n;
next();
/* XXX: handle section symbols too */
n = asm_int_expr(s1);
if (n < ind)
tcc_error("attempt to .org backwards");
v = 0;
size = n - ind;
goto zero_pad;
}
break;
case TOK_ASM_globl:
case TOK_ASM_global:
case TOK_ASM_weak:
tok1 = tok;
do {
Sym *sym;
next();
sym = label_find(tok);
if (!sym) {
sym = label_push(&s1->asm_labels, tok, 0);
sym->type.t = VT_VOID;
}
sym->type.t &= ~VT_STATIC;
if (tok1 == TOK_ASM_weak)
sym->type.t |= VT_WEAK;
next();
} while (tok == ',');
break;
case TOK_ASM_string:
case TOK_ASM_ascii:
case TOK_ASM_asciz:
{
const uint8_t *p;
int i, size, t;
t = tok;
next();
for(;;) {
if (tok != TOK_STR)
expect("string constant");
p = tokc.cstr->data;
size = tokc.cstr->size;
if (t == TOK_ASM_ascii && size > 0)
size--;
for(i = 0; i < size; i++)
g(p[i]);
next();
if (tok == ',') {
next();
} else if (tok != TOK_STR) {
break;
}
}
}
break;
case TOK_ASM_text:
case TOK_ASM_data:
case TOK_ASM_bss:
{
char sname[64];
tok1 = tok;
n = 0;
next();
if (tok != ';' && tok != TOK_LINEFEED) {
n = asm_int_expr(s1);
next();
}
sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
use_section(s1, sname);
}
break;
src/tccasm.c view on Meta::CPAN
} else {
break;
}
}
}
}
}
}
skip(')');
/* NOTE: we do not eat the ';' so that we can restore the current
token after the assembler parsing */
if (tok != ';')
expect("';'");
/* save all values in the memory */
save_regs(0);
/* compute constraints */
asm_compute_constraints(operands, nb_operands, nb_outputs,
clobber_regs, &out_reg);
/* substitute the operands in the asm string. No substitution is
done if no operands (GCC behaviour) */
#ifdef ASM_DEBUG
printf("asm: \"%s\"\n", (char *)astr.data);
#endif
if (must_subst) {
subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
cstr_free(&astr);
} else {
astr1 = astr;
}
#ifdef ASM_DEBUG
printf("subst_asm: \"%s\"\n", (char *)astr1.data);
#endif
/* generate loads */
asm_gen_code(operands, nb_operands, nb_outputs, 0,
clobber_regs, out_reg);
/* assemble the string with tcc internal assembler */
tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
/* restore the current C token */
next();
/* store the output values if needed */
asm_gen_code(operands, nb_operands, nb_outputs, 1,
clobber_regs, out_reg);
/* free everything */
for(i=0;i<nb_operands;i++) {
ASMOperand *op;
op = &operands[i];
tcc_free(op->constraint);
vpop();
}
cstr_free(&astr1);
}
ST_FUNC void asm_global_instr(void)
{
CString astr;
next();
parse_asm_str(&astr);
skip(')');
/* NOTE: we do not eat the ';' so that we can restore the current
token after the assembler parsing */
if (tok != ';')
expect("';'");
#ifdef ASM_DEBUG
printf("asm_global: \"%s\"\n", (char *)astr.data);
#endif
cur_text_section = text_section;
ind = cur_text_section->data_offset;
/* assemble the string with tcc internal assembler */
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
cur_text_section->data_offset = ind;
/* restore the current C token */
next();
cstr_free(&astr);
}
#endif /* CONFIG_TCC_ASM */
( run in 0.897 second using v1.01-cache-2.11-cpan-ceb78f64989 )