Alien-TinyCCx
view release on metacpan or search on metacpan
src/tccasm.c view on Meta::CPAN
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;
case '.':
pe->v = 0;
pe->sym = &sym_dot;
sym_dot.type.t = VT_VOID | VT_STATIC;
sym_dot.r = cur_text_section->sh_num;
sym_dot.jnext = ind;
next();
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
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_ASMDIR_rept:
{
int repeat;
TokenString *init_str;
ParseState saved_parse_state = {0};
next();
repeat = asm_int_expr(s1);
init_str = tok_str_alloc();
next();
while ((tok != TOK_ASMDIR_endr) && (tok != CH_EOF)) {
tok_str_add_tok(init_str);
next();
}
if (tok == CH_EOF) tcc_error("we at end of file, .endr not found");
next();
tok_str_add(init_str, -1);
tok_str_add(init_str, 0);
save_parse_state(&saved_parse_state);
begin_macro(init_str, 1);
while (repeat-- > 0) {
tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS));
macro_ptr = init_str->str;
}
end_macro();
restore_parse_state(&saved_parse_state);
break;
}
case TOK_ASMDIR_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_ASMDIR_globl:
case TOK_ASMDIR_global:
case TOK_ASMDIR_weak:
case TOK_ASMDIR_hidden:
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;
}
if (tok1 != TOK_ASMDIR_hidden)
sym->type.t &= ~VT_STATIC;
if (tok1 == TOK_ASMDIR_weak)
sym->type.t |= VT_WEAK;
else if (tok1 == TOK_ASMDIR_hidden)
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
next();
} while (tok == ',');
break;
case TOK_ASMDIR_string:
case TOK_ASMDIR_ascii:
case TOK_ASMDIR_asciz:
{
const uint8_t *p;
int i, size, t;
t = tok;
next();
for(;;) {
if (tok != TOK_STR)
expect("string constant");
p = tokc.str.data;
size = tokc.str.size;
if (t == TOK_ASMDIR_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_ASMDIR_text:
case TOK_ASMDIR_data:
case TOK_ASMDIR_bss:
{
char sname[64];
tok1 = tok;
n = 0;
next();
if (tok != ';' && tok != TOK_LINEFEED) {
n = asm_int_expr(s1);
next();
}
src/tccasm.c view on Meta::CPAN
memset(freq, 0, sizeof(freq));
for(pa = asm_instrs; pa->sym != 0; pa++) {
freq[pa->nb_ops]++;
for(i=0;i<pa->nb_ops;i++) {
for(j=0;j<nb_op_vals;j++) {
if (pa->op_type[i] == op_vals[j])
goto found;
}
op_vals[nb_op_vals++] = pa->op_type[i];
found: ;
}
}
for(i=0;i<nb_op_vals;i++) {
int v = op_vals[i];
if ((v & (v - 1)) != 0)
printf("%3d: %08x\n", i, v);
}
printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
freq[0], freq[1], freq[2], freq[3]);
}
#endif
/* XXX: undefine C labels */
ch = file->buf_ptr[0];
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;
if (do_preprocess)
parse_flags |= PARSE_FLAG_PREPROCESS;
next();
for(;;) {
if (tok == TOK_EOF)
break;
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
redo:
if (tok == '#') {
/* horrible gas comment */
while (tok != TOK_LINEFEED)
next();
} else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
asm_parse_directive(s1);
} else if (tok == TOK_PPNUM) {
const char *p;
int n;
p = tokc.str.data;
n = strtoul(p, (char **)&p, 10);
if (*p != '\0')
expect("':'");
/* new local label */
asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
next();
skip(':');
goto redo;
} else if (tok >= TOK_IDENT) {
/* instruction or label */
opcode = tok;
next();
if (tok == ':') {
/* handle "extern void vide(void); __asm__("vide: ret");" as
"__asm__("globl vide\nvide: ret");" */
Sym *sym = sym_find(opcode);
if (sym && (sym->type.t & VT_EXTERN) && nocode_wanted) {
sym = label_find(opcode);
if (!sym) {
sym = label_push(&s1->asm_labels, opcode, 0);
sym->type.t = VT_VOID;
}
}
/* new label */
asm_new_label(s1, opcode, 0);
next();
goto redo;
} else if (tok == '=') {
int n;
next();
n = asm_int_expr(s1);
asm_new_label1(s1, opcode, 0, SHN_ABS, n);
goto redo;
} else {
asm_opcode(s1, opcode);
}
}
/* end of line */
if (tok != ';' && tok != TOK_LINEFEED){
expect("end of line");
}
parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
next();
}
asm_free_labels(s1);
return 0;
}
/* Assemble the current file */
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
{
Sym *define_start;
int ret;
preprocess_start(s1);
/* default section is text */
cur_text_section = text_section;
ind = cur_text_section->data_offset;
define_start = define_stack;
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
symbols can be safely used */
put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
SHN_ABS, file->filename);
ret = tcc_assemble_internal(s1, do_preprocess);
cur_text_section->data_offset = ind;
free_defines(define_start);
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.350 second using v1.01-cache-2.11-cpan-13bb782fe5a )