int compare_bitcounts(const void *aa, const void *bb) { int a=*(int *)aa; int b=*(int *)bb; if (bitsset(a)<bitsset(b)) return -1; if (bitsset(a)>bitsset(b)) return 1; return 0; }
// Generate a return statement. // void GenerateReturn(SYM *sym, Statement *stmt) { AMODE *ap; int nn; int lab1; int cnt; // Generate code to evaluate the return expression. if( stmt != NULL && stmt->exp != NULL ) { initstack(); ap = GenerateExpression(stmt->exp,F_ALL & ~F_BREG,8); // Force return value into register 1 if( ap->preg != 1 ) { if (ap->mode == am_immed) GenerateDiadic(op_ldi, 0, makereg(1),ap); else if (ap->mode == am_reg) GenerateDiadic(op_mov, 0, makereg(1),ap); else GenerateDiadic(op_lw,0,makereg(1),ap); } } // Generate the return code only once. Branch to the return code for all returns. if( retlab == -1 ) { retlab = nextlabel++; GenerateLabel(retlab); // Unlock any semaphores that may have been set for (nn = lastsph - 1; nn >= 0; nn--) GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn])); if (sym->IsNocall) // nothing to do for nocall convention return; // Restore registers used as register variables. if( bsave_mask != 0 ) { cnt = (bitsset(bsave_mask)-1)*8; for (nn = 15; nn >=1 ; nn--) { if (bsave_mask & (1 << nn)) { GenerateDiadic(op_ss|op_lws,0,makebreg(nn),make_indexed(cnt,SP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(popcnt(bsave_mask)*8)); } if( save_mask != 0 ) { cnt = (bitsset(save_mask)-1)*8; for (nn = 31; nn >=1 ; nn--) { if (save_mask & (1 << nn)) { GenerateDiadic(op_ss|op_lw,0,makereg(nn),make_indexed(cnt,SP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8)); } // Unlink the stack // For a leaf routine the link register and exception link register doesn't need to be saved/restored. if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_mov,0,makereg(SP),makereg(regBP)); GenerateDiadic(op_ss|op_lw,0,makereg(regBP),make_indirect(regSP)); } if (!sym->IsLeaf) { if (exceptions) GenerateDiadic(op_ss|op_lws,0,makebreg(CLR),make_indexed(8,regSP)); GenerateDiadic(op_ss|op_lws,0,makebreg(LR),make_indexed(16,regSP)); // if (sym->UsesPredicate) } GenerateDiadic(op_ss|op_lws,0,make_string("pregs"),make_indexed(24,regSP)); //if (isOscall) { // GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave")); // gen_regrestore(); //} // Generate the return instruction. For the Pascal calling convention pop the parameters // from the stack. if (sym->IsInterrupt) { //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24)); //GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE)); //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8)); GenerateMonadic(op_rti,0,(AMODE *)NULL); return; } if (sym->IsPascal) { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(32+sym->NumParms * 8)); GenerateMonadic(op_rts,0,(AMODE *)NULL); } else { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(32)); GenerateMonadic(op_rts,0,(AMODE*)NULL); } } // Just branch to the already generated stack cleanup code. else { GenerateMonadic(op_bra,0,make_clabel(retlab)); } }
// Generate function epilog code. // void GenerateEpilog(SYM *sym) { AMODE *ap; int nn; int lab1; int cnt; // Generate the return code only once. Branch to the return code for all returns. GenerateLabel(retlab); // Unlock any semaphores that may have been set for (nn = lastsph - 1; nn >= 0; nn--) GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn])); if (sym->IsNocall) // nothing to do for nocall convention return; // Restore registers used as register variables. if( bsave_mask != 0 ) { cnt = (bitsset(bsave_mask)-1)*8; for (nn = 15; nn >=1 ; nn--) { if (bsave_mask & (1 << nn)) { GenerateDiadic(op_lws,0,makebreg(nn),make_indexed(cnt,regSP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(SP),makereg(regSP),make_immed(popcnt(bsave_mask)*8)); } if( save_mask != 0 ) { cnt = (bitsset(save_mask)-1)*8; for (nn = 31; nn >=1 ; nn--) { if (save_mask & (1 << nn)) { GenerateDiadic(op_lw,0,makereg(nn),make_indexed(cnt,regSP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(popcnt(save_mask)*8)); } // Unlink the stack // For a leaf routine the link register and exception link register doesn't need to be saved/restored. if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_mov,0,makereg(regSP),makereg(regBP)); GenerateDiadic(op_lw,0,makereg(regBP),make_indirect(regSP)); } if (!sym->IsLeaf) { if (exceptions) GenerateDiadic(op_lws,0,makebreg(regXLR),make_indexed(8,regSP)); // 11=CLR GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(16,regSP)); // 1 = LR // if (sym->UsesPredicate) } GenerateDiadic(op_lws,0,make_string("pregs"),make_indexed(24,regSP)); GenerateDiadic(op_lw,0,makereg(regCLP),make_indexed(32,regSP)); if (sym->epilog) { if (optimize) opt1(sym->epilog); GenerateStatement(sym->epilog); return; } //if (isOscall) { // GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave")); // gen_regrestore(); //} // Generate the return instruction. For the Pascal calling convention pop the parameters // from the stack. if (sym->IsInterrupt) { //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24)); //GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE)); //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8)); GenerateMonadic(op_rti,0,(AMODE *)NULL); return; } if (sym->IsPascal) { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(GetReturnBlockSize()+sym->NumParms * 8)); GenerateMonadic(op_rts,0,(AMODE *)NULL); } else { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(GetReturnBlockSize())); GenerateMonadic(op_rts,0,(AMODE*)NULL); } }