arm-asm: Implement asm_gen_code
This commit is contained in:
parent
d66c155239
commit
795d7d5ce6
1 changed files with 80 additions and 3 deletions
83
arm-asm.c
83
arm-asm.c
|
@ -1247,10 +1247,87 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
|
||||||
|
|
||||||
/* generate prolog and epilog code for asm statement */
|
/* 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(ASMOperand *operands, int nb_operands,
|
||||||
int nb_outputs, int is_output,
|
int nb_outputs, int is_output,
|
||||||
uint8_t *clobber_regs,
|
uint8_t *clobber_regs,
|
||||||
int out_reg)
|
int out_reg)
|
||||||
{
|
{
|
||||||
|
uint8_t regs_allocated[NB_ASM_REGS];
|
||||||
|
ASMOperand *op;
|
||||||
|
int i, reg;
|
||||||
|
uint32_t saved_regset = 0;
|
||||||
|
|
||||||
|
// TODO: Check non-E ABI.
|
||||||
|
// Note: Technically, r13 (sp) is also callee-saved--but that does not matter yet
|
||||||
|
static uint8_t reg_saved[] = { 4, 5, 6, 7, 8, 9 /* Note: sometimes special reg "sb" */ , 10, 11 };
|
||||||
|
|
||||||
|
/* mark all used registers */
|
||||||
|
memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
|
||||||
|
for(i = 0; i < nb_operands;i++) {
|
||||||
|
op = &operands[i];
|
||||||
|
if (op->reg >= 0)
|
||||||
|
regs_allocated[op->reg] = 1;
|
||||||
|
}
|
||||||
|
for(i = 0; i < sizeof(reg_saved)/sizeof(reg_saved[0]); i++) {
|
||||||
|
reg = reg_saved[i];
|
||||||
|
if (regs_allocated[reg])
|
||||||
|
saved_regset |= 1 << reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_output) { // prolog
|
||||||
|
/* generate reg save code */
|
||||||
|
if (saved_regset)
|
||||||
|
gen_le32(0xe92d0000 | saved_regset); // push {...}
|
||||||
|
|
||||||
|
/* generate load code */
|
||||||
|
for(i = 0; i < nb_operands; i++) {
|
||||||
|
op = &operands[i];
|
||||||
|
if (op->reg >= 0) {
|
||||||
|
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
|
||||||
|
op->is_memory) {
|
||||||
|
/* memory reference case (for both input and
|
||||||
|
output cases) */
|
||||||
|
SValue sv;
|
||||||
|
sv = *op->vt;
|
||||||
|
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
|
||||||
|
sv.type.t = VT_PTR;
|
||||||
|
load(op->reg, &sv);
|
||||||
|
} else if (i >= nb_outputs || op->is_rw) { // not write-only
|
||||||
|
/* load value in register */
|
||||||
|
load(op->reg, op->vt);
|
||||||
|
if (op->is_llong)
|
||||||
|
tcc_error("long long not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // epilog
|
||||||
|
/* generate save code */
|
||||||
|
for(i = 0 ; i < nb_outputs; i++) {
|
||||||
|
op = &operands[i];
|
||||||
|
if (op->reg >= 0) {
|
||||||
|
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
|
||||||
|
if (!op->is_memory) {
|
||||||
|
SValue sv;
|
||||||
|
sv = *op->vt;
|
||||||
|
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
|
||||||
|
sv.type.t = VT_PTR;
|
||||||
|
load(out_reg, &sv);
|
||||||
|
|
||||||
|
sv = *op->vt;
|
||||||
|
sv.r = (sv.r & ~VT_VALMASK) | out_reg;
|
||||||
|
store(op->reg, &sv);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store(op->reg, op->vt);
|
||||||
|
if (op->is_llong)
|
||||||
|
tcc_error("long long not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate reg restore code */
|
||||||
|
if (saved_regset)
|
||||||
|
gen_le32(0xe8bd0000 | saved_regset); // pop {...}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||||
|
|
Loading…
Reference in a new issue