bool ElfReader::readIdent() { u4 bytesLeft = reader.size(); reader.seekg(0); if (bytesLeft < sizeof(ident)) { return false; } ident = (elf_ident_t *) reader.seekg(0); if (!isValid()) { return false; } size_t ehdrsize = is64() ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr); if (bytesLeft < ehdrsize) { return false; } if (!is64()) { stdsizes.ehdr = sizeof(Elf32_Ehdr); stdsizes.phdr = sizeof(Elf32_Phdr); stdsizes.shdr = sizeof(Elf32_Shdr); stdsizes.entries.sym = sizeof(Elf32_Sym); stdsizes.entries.dyn = sizeof(Elf32_Dyn); stdsizes.entries.rel = sizeof(Elf32_Rel); stdsizes.entries.rela = sizeof(Elf32_Rela); stdsizes.types.elf_addr = 4; stdsizes.types.elf_off = 4; stdsizes.types.elf_xword = 4; stdsizes.types.elf_sxword = 4; } else { stdsizes.ehdr = sizeof(Elf64_Ehdr); stdsizes.phdr = sizeof(Elf64_Phdr); stdsizes.shdr = sizeof(Elf64_Shdr); stdsizes.entries.sym = sizeof(Elf64_Sym); stdsizes.entries.dyn = sizeof(Elf64_Dyn); stdsizes.entries.rel = sizeof(Elf64_Rel); stdsizes.entries.rela = sizeof(Elf64_Rela); stdsizes.types.elf_addr = 8; stdsizes.types.elf_off = 8; stdsizes.types.elf_xword = 8; stdsizes.types.elf_sxword = 8; } stdsizes.dyn.sym = stdsizes.entries.sym; stdsizes.dyn.rel = stdsizes.entries.rel; stdsizes.dyn.rela = stdsizes.entries.rela; return true; }
u4 ElfReader::getProgramOff() { if (!is64()) { return ehdr._32->e_phoff; } else { return ehdr._64->e_phoff; } }
u4 ElfReader::getSectionOff() { if (!is64()) { return ehdr._32->e_shoff; } else { return ehdr._64->e_shoff; } }
static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (r31_64bit == 0) { int r31 = allocate_register_32_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); } else if (r31_64bit == -1) { mov_m32rel_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32rel_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32rel_imm32(((unsigned int *)®[31])+1, 0); } else { int r31 = allocate_register_64_w((unsigned long long *)®[31]); mov_reg32_imm32(r31, dst->addr+8); movsxd_reg64_reg32(r31, r31); } }
uint64_t MachO::relocation_base() const { uint64_t addr; if (is64()) { for (segment_command_64* seg : m_segments64) { if (seg->initprot & VM_PROT_WRITE) { addr = seg->vmaddr; break; } } } else { if (m_header.flags & MH_SPLIT_SEGS) { for (segment_command* seg : m_segments) { if (seg->initprot & VM_PROT_WRITE) { addr = uint64_t(seg->vmaddr) & 0xffffffff; break; } } } else addr = uint64_t(m_segments[0]->vmaddr) & 0xffffffff; } return addr; }
void gdata(Node *nam, Node *nr, int wid) { Prog *p; vlong v; if(nr->op == OLITERAL) { switch(nr->val.ctype) { case CTCPLX: gdatacomplex(nam, nr->val.u.cval); return; case CTSTR: gdatastring(nam, nr->val.u.sval); return; } } if(wid == 8 && is64(nr->type)) { v = mpgetfix(nr->val.u.xval); p = gins(ADATA, nam, nodintconst(v)); p->reg = 4; p = gins(ADATA, nam, nodintconst(v>>32)); p->reg = 4; p->from.offset += 4; return; }
static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (!r31_64bit) { int r31 = allocate_register_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); } else if (r31_64bit == -1) { mov_m32_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned int *)®[31])+1, 0); } else { int r311 = allocate_64_register1_w((unsigned int *)®[31]); int r312 = allocate_64_register2_w((unsigned int *)®[31]); mov_reg32_imm32(r311, dst->addr+8); if (dst->addr & 0x80000000) mov_reg32_imm32(r312, 0xFFFFFFFF); else mov_reg32_imm32(r312, 0); } }
static void genbltz_test(void) { int rs_64bit = is64((unsigned int *)dst->f.i.rs); if (!rs_64bit) { int rs = allocate_register((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 } else if (rs_64bit == -1) { cmp_m32_imm32(((unsigned int *)dst->f.i.rs)+1, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 } else { int rs2 = allocate_64_register2((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs2, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 } }
bool ElfReader::readHeader() { if (!is64()) { Elf32_Ehdr *et = (Elf32_Ehdr *) reader.seekg(0); return readHeader(et); } else { Elf64_Ehdr * et = (Elf64_Ehdr *) reader.seekg(0); return readHeader(et); } }
int main(int argc, char* argv[]) { printf("------------------------------------\n"); printf("---- DCOM Registry Configurator ----\n"); printf("------------------------------------\n"); printf("\n"); printf("OS bits: %d\n", (is64() ? 64 : 32)); main3(); }
bool ElfReader::readProgramheader() { u4 sec = getProgramOff(); if (!sec) return false; if (!is64()) { Elf32_Phdr *phdrStart = (Elf32_Phdr *) reader.seekg(sec); return readProgramheader(ehdr._32, phdrStart); } else { Elf64_Phdr *phdrStart = (Elf64_Phdr *) reader.seekg(sec); return readProgramheader(ehdr._64, phdrStart); } }
static void genbltz_test(void) { int rs_64bit = is64((unsigned int *)dst->f.i.rs); if (rs_64bit == 0) { #ifdef __x86_64__ int rs = allocate_register_32((unsigned int *)dst->f.i.rs); #else int rs = allocate_register((unsigned int *)dst->f.i.rs); #endif cmp_reg32_imm32(rs, 0); #ifdef __x86_64__ setl_m8rel((unsigned char *) &branch_taken); #else jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 #endif } else if (rs_64bit == -1) { #ifdef __x86_64__ cmp_m32rel_imm32(((unsigned int *)dst->f.i.rs)+1, 0); setl_m8rel((unsigned char *) &branch_taken); #else cmp_m32_imm32(((unsigned int *)dst->f.i.rs)+1, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 #endif } else { #ifdef __x86_64__ int rs = allocate_register_64((uint64_t*)dst->f.i.rs); cmp_reg64_imm8(rs, 0); setl_m8rel((unsigned char *) &branch_taken); #else int rs2 = allocate_64_register2((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs2, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 #endif } }
static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (r31_64bit == 0) { #ifdef __x86_64__ int r31 = allocate_register_32_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); #else int r31 = allocate_register_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); #endif } else if (r31_64bit == -1) { #ifdef __x86_64__ mov_m32rel_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32rel_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32rel_imm32(((unsigned int *)®[31])+1, 0); #else mov_m32_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned int *)®[31])+1, 0); #endif } else { #ifdef __x86_64__ int r31 = allocate_register_64_w((uint64_t*)®[31]); mov_reg32_imm32(r31, dst->addr+8); movsxd_reg64_reg32(r31, r31); #else int r311 = allocate_64_register1_w((unsigned int *)®[31]); int r312 = allocate_64_register2_w((unsigned int *)®[31]); mov_reg32_imm32(r311, dst->addr+8); if (dst->addr & 0x80000000) mov_reg32_imm32(r312, 0xFFFFFFFF); else mov_reg32_imm32(r312, 0); #endif } }
bool ElfReader::readSectionHeader() { u4 sec = getSectionOff(); if (!sec) return false; assert(phdrs.get() != NULL); if (!is64()) { Elf32_Shdr *st = (Elf32_Shdr *) reader.seekg(sec); Elf32_Phdr *pt = phdrs.get()->_32; return readSectionHeader(ehdr._32, st, pt); } else { Elf64_Shdr *st = (Elf64_Shdr *) reader.seekg(sec); Elf64_Phdr *pt = phdrs.get()->_64; return readSectionHeader(ehdr._64, st, pt); } }
void gdata(Node *nam, Node *nr, int wid) { Prog *p; vlong v; if(wid == 8 && is64(nr->type)) { v = mpgetfix(nr->val.u.xval); p = gins(ADATA, nam, nodintconst(v)); p->reg = 4; p = gins(ADATA, nam, nodintconst(v>>32)); p->reg = 4; p->from.offset += 4; return; }
void genbgez_test(void) { int rs_64bit = is64((unsigned int *)dst->f.i.rs); if (rs_64bit == 0) { int rs = allocate_register_32((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs, 0); setge_m8rel((unsigned char *) &branch_taken); } else if (rs_64bit == -1) { cmp_m32rel_imm32(((unsigned int *)dst->f.i.rs)+1, 0); setge_m8rel((unsigned char *) &branch_taken); } else { int rs = allocate_register_64((unsigned long long *)dst->f.i.rs); cmp_reg64_imm8(rs, 0); setge_m8rel((unsigned char *) &branch_taken); } }
void copyTo(uint8_t *to, bool swap) { if ( swap ) { assert(0 && "non-native endianness not supported yet"); } else { if( is64() ) { // in-memory matches on-disk, so copy segment fields followed by sections ::memcpy(to, (uint8_t*)&cmd, 72); if ( nsects != 0 ) ::memcpy(&to[72], sections, sizeof(section_64)*nsects); } else { // on-disk is 32-bit struct, so copy each field ::memcpy(to, (uint8_t*)&cmd, 24); copy32(to, 24, vmaddr); copy32(to, 28, vmsize); copy32(to, 32, fileoff); copy32(to, 36, filesize); copy32(to, 40, maxprot); copy32(to, 44, initprot); copy32(to, 48, nsects); copy32(to, 52, flags); for(uint32_t i=0; i < nsects; ++i) { unsigned off = 56+i*68; ::memcpy(&to[off], sections[i].sectname, 32); copy32(to, off+32, sections[i].addr); copy32(to, off+36, sections[i].size); copy32(to, off+40, sections[i].offset); copy32(to, off+44, sections[i].align); copy32(to, off+48, sections[i].reloff); copy32(to, off+52, sections[i].nreloc); copy32(to, off+56, sections[i].flags); copy32(to, off+60, sections[i].reserved1); copy32(to, off+64, sections[i].reserved2); } } } }
/* * attempt to generate 64-bit * res = n * return 1 on success, 0 if op not handled. */ void cgen64(Node *n, Node *res) { Node t1, t2, *l, *r; Node lo1, lo2, hi1, hi2; Node al, ah, bl, bh, cl, ch, s, n1, creg; Prog *p1, *p2, *p3, *p4, *p5, *p6; uint64 v; if(res->op != OINDREG && res->op != ONAME) { dump("n", n); dump("res", res); fatal("cgen64 %O of %O", n->op, res->op); } l = n->left; if(!l->addable) { tempname(&t1, l->type); cgen(l, &t1); l = &t1; } split64(l, &lo1, &hi1); switch(n->op) { default: fatal("cgen64 %O", n->op); case OMINUS: split64(res, &lo2, &hi2); regalloc(&t1, lo1.type, N); regalloc(&al, lo1.type, N); regalloc(&ah, hi1.type, N); gins(AMOVW, &lo1, &al); gins(AMOVW, &hi1, &ah); gmove(ncon(0), &t1); p1 = gins(ASUB, &al, &t1); p1->scond |= C_SBIT; gins(AMOVW, &t1, &lo2); gmove(ncon(0), &t1); gins(ASBC, &ah, &t1); gins(AMOVW, &t1, &hi2); regfree(&t1); regfree(&al); regfree(&ah); splitclean(); splitclean(); return; case OCOM: split64(res, &lo2, &hi2); regalloc(&n1, lo1.type, N); gins(AMOVW, &lo1, &n1); gins(AMVN, &n1, &n1); gins(AMOVW, &n1, &lo2); gins(AMOVW, &hi1, &n1); gins(AMVN, &n1, &n1); gins(AMOVW, &n1, &hi2); regfree(&n1); splitclean(); splitclean(); return; case OADD: case OSUB: case OMUL: case OLSH: case ORSH: case OAND: case OOR: case OXOR: // binary operators. // common setup below. break; } // setup for binary operators r = n->right; if(r != N && !r->addable) { tempname(&t2, r->type); cgen(r, &t2); r = &t2; } if(is64(r->type)) split64(r, &lo2, &hi2); regalloc(&al, lo1.type, N); regalloc(&ah, hi1.type, N); // Do op. Leave result in ah:al. switch(n->op) { default: fatal("cgen64: not implemented: %N\n", n); case OADD: // TODO: Constants regalloc(&bl, types[TPTR32], N); regalloc(&bh, types[TPTR32], N); gins(AMOVW, &hi1, &ah); gins(AMOVW, &lo1, &al); gins(AMOVW, &hi2, &bh); gins(AMOVW, &lo2, &bl); p1 = gins(AADD, &bl, &al); p1->scond |= C_SBIT; gins(AADC, &bh, &ah); regfree(&bl); regfree(&bh); break; case OSUB: // TODO: Constants. regalloc(&bl, types[TPTR32], N); regalloc(&bh, types[TPTR32], N); gins(AMOVW, &lo1, &al); gins(AMOVW, &hi1, &ah); gins(AMOVW, &lo2, &bl); gins(AMOVW, &hi2, &bh); p1 = gins(ASUB, &bl, &al); p1->scond |= C_SBIT; gins(ASBC, &bh, &ah); regfree(&bl); regfree(&bh); break; case OMUL: // TODO(kaib): this can be done with 4 regs and does not need 6 regalloc(&bl, types[TPTR32], N); regalloc(&bh, types[TPTR32], N); regalloc(&cl, types[TPTR32], N); regalloc(&ch, types[TPTR32], N); // load args into bh:bl and bh:bl. gins(AMOVW, &hi1, &bh); gins(AMOVW, &lo1, &bl); gins(AMOVW, &hi2, &ch); gins(AMOVW, &lo2, &cl); // bl * cl p1 = gins(AMULLU, N, N); p1->from.type = D_REG; p1->from.reg = bl.val.u.reg; p1->reg = cl.val.u.reg; p1->to.type = D_REGREG; p1->to.reg = ah.val.u.reg; p1->to.offset = al.val.u.reg; //print("%P\n", p1); // bl * ch p1 = gins(AMULA, N, N); p1->from.type = D_REG; p1->from.reg = bl.val.u.reg; p1->reg = ch.val.u.reg; p1->to.type = D_REGREG; p1->to.reg = ah.val.u.reg; p1->to.offset = ah.val.u.reg; //print("%P\n", p1); // bh * cl p1 = gins(AMULA, N, N); p1->from.type = D_REG; p1->from.reg = bh.val.u.reg; p1->reg = cl.val.u.reg; p1->to.type = D_REGREG; p1->to.reg = ah.val.u.reg; p1->to.offset = ah.val.u.reg; //print("%P\n", p1); regfree(&bh); regfree(&bl); regfree(&ch); regfree(&cl); break; case OLSH: regalloc(&bl, lo1.type, N); regalloc(&bh, hi1.type, N); gins(AMOVW, &hi1, &bh); gins(AMOVW, &lo1, &bl); if(r->op == OLITERAL) { v = mpgetfix(r->val.u.xval); if(v >= 64) { // TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al) // here and below (verify it optimizes to EOR) gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); } else if(v > 32) { gins(AEOR, &al, &al); // MOVW bl<<(v-32), ah gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah); } else if(v == 32) { gins(AEOR, &al, &al); gins(AMOVW, &bl, &ah); } else if(v > 0) { // MOVW bl<<v, al gshift(AMOVW, &bl, SHIFT_LL, v, &al); // MOVW bh<<v, ah gshift(AMOVW, &bh, SHIFT_LL, v, &ah); // OR bl>>(32-v), ah gshift(AORR, &bl, SHIFT_LR, 32-v, &ah); } else { gins(AMOVW, &bl, &al); gins(AMOVW, &bh, &ah); } goto olsh_break; } regalloc(&s, types[TUINT32], N); regalloc(&creg, types[TUINT32], N); if (is64(r->type)) { // shift is >= 1<<32 split64(r, &cl, &ch); gmove(&ch, &s); p1 = gins(AMOVW, &s, &s); p1->scond |= C_SBIT; p6 = gbranch(ABNE, T); gmove(&cl, &s); splitclean(); } else { gmove(r, &s); p6 = P; } p1 = gins(AMOVW, &s, &s); p1->scond |= C_SBIT; // shift == 0 p1 = gins(AMOVW, &bl, &al); p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bh, &ah); p1->scond = C_SCOND_EQ; p2 = gbranch(ABEQ, T); // shift is < 32 nodconst(&n1, types[TUINT32], 32); gmove(&n1, &creg); gcmp(ACMP, &s, &creg); // MOVW.LO bl<<s, al p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al); p1->scond = C_SCOND_LO; // MOVW.LO bh<<s, ah p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah); p1->scond = C_SCOND_LO; // SUB.LO s, creg p1 = gins(ASUB, &s, &creg); p1->scond = C_SCOND_LO; // OR.LO bl>>creg, ah p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah); p1->scond = C_SCOND_LO; // BLO end p3 = gbranch(ABLO, T); // shift == 32 p1 = gins(AEOR, &al, &al); p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bl, &ah); p1->scond = C_SCOND_EQ; p4 = gbranch(ABEQ, T); // shift is < 64 nodconst(&n1, types[TUINT32], 64); gmove(&n1, &creg); gcmp(ACMP, &s, &creg); // EOR.LO al, al p1 = gins(AEOR, &al, &al); p1->scond = C_SCOND_LO; // MOVW.LO creg>>1, creg p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg); p1->scond = C_SCOND_LO; // SUB.LO creg, s p1 = gins(ASUB, &creg, &s); p1->scond = C_SCOND_LO; // MOVW bl<<s, ah p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah); p1->scond = C_SCOND_LO; p5 = gbranch(ABLO, T); // shift >= 64 if (p6 != P) patch(p6, pc); gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); patch(p2, pc); patch(p3, pc); patch(p4, pc); patch(p5, pc); regfree(&s); regfree(&creg); olsh_break: regfree(&bl); regfree(&bh); break; case ORSH: regalloc(&bl, lo1.type, N); regalloc(&bh, hi1.type, N); gins(AMOVW, &hi1, &bh); gins(AMOVW, &lo1, &bl); if(r->op == OLITERAL) { v = mpgetfix(r->val.u.xval); if(v >= 64) { if(bh.type->etype == TINT32) { // MOVW bh->31, al gshift(AMOVW, &bh, SHIFT_AR, 31, &al); // MOVW bh->31, ah gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); } } else if(v > 32) { if(bh.type->etype == TINT32) { // MOVW bh->(v-32), al gshift(AMOVW, &bh, SHIFT_AR, v-32, &al); // MOVW bh->31, ah gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { // MOVW bh>>(v-32), al gshift(AMOVW, &bh, SHIFT_LR, v-32, &al); gins(AEOR, &ah, &ah); } } else if(v == 32) { gins(AMOVW, &bh, &al); if(bh.type->etype == TINT32) { // MOVW bh->31, ah gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { gins(AEOR, &ah, &ah); } } else if( v > 0) { // MOVW bl>>v, al gshift(AMOVW, &bl, SHIFT_LR, v, &al); // OR bh<<(32-v), al gshift(AORR, &bh, SHIFT_LL, 32-v, &al); if(bh.type->etype == TINT32) { // MOVW bh->v, ah gshift(AMOVW, &bh, SHIFT_AR, v, &ah); } else { // MOVW bh>>v, ah gshift(AMOVW, &bh, SHIFT_LR, v, &ah); } } else { gins(AMOVW, &bl, &al); gins(AMOVW, &bh, &ah); } goto orsh_break; } regalloc(&s, types[TUINT32], N); regalloc(&creg, types[TUINT32], N); if (is64(r->type)) { // shift is >= 1<<32 split64(r, &cl, &ch); gmove(&ch, &s); p1 = gins(AMOVW, &s, &s); p1->scond |= C_SBIT; p6 = gbranch(ABNE, T); gmove(&cl, &s); splitclean(); } else { gmove(r, &s); p6 = P; } p1 = gins(AMOVW, &s, &s); p1->scond |= C_SBIT; // shift == 0 p1 = gins(AMOVW, &bl, &al); p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bh, &ah); p1->scond = C_SCOND_EQ; p2 = gbranch(ABEQ, T); // check if shift is < 32 nodconst(&n1, types[TUINT32], 32); gmove(&n1, &creg); gcmp(ACMP, &s, &creg); // MOVW.LO bl>>s, al p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al); p1->scond = C_SCOND_LO; // SUB.LO s,creg p1 = gins(ASUB, &s, &creg); p1->scond = C_SCOND_LO; // OR.LO bh<<(32-s), al p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al); p1->scond = C_SCOND_LO; if(bh.type->etype == TINT32) { // MOVW bh->s, ah p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah); } else { // MOVW bh>>s, ah p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah); } p1->scond = C_SCOND_LO; // BLO end p3 = gbranch(ABLO, T); // shift == 32 if(bh.type->etype == TINT32) p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); else p1 = gins(AEOR, &al, &al); p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bh, &al); p1->scond = C_SCOND_EQ; p4 = gbranch(ABEQ, T); // check if shift is < 64 nodconst(&n1, types[TUINT32], 64); gmove(&n1, &creg); gcmp(ACMP, &s, &creg); // MOVW.LO creg>>1, creg p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg); p1->scond = C_SCOND_LO; // SUB.LO creg, s p1 = gins(ASUB, &creg, &s); p1->scond = C_SCOND_LO; if(bh.type->etype == TINT32) { // MOVW bh->(s-32), al p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al); p1->scond = C_SCOND_LO; // MOVW bh->31, ah p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); p1->scond = C_SCOND_LO; } else { // MOVW bh>>(v-32), al p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al); p1->scond = C_SCOND_LO; p1 = gins(AEOR, &ah, &ah); p1->scond = C_SCOND_LO; } // BLO end p5 = gbranch(ABLO, T); // s >= 64 if (p6 != P) patch(p6, pc); if(bh.type->etype == TINT32) { // MOVW bh->31, al gshift(AMOVW, &bh, SHIFT_AR, 31, &al); // MOVW bh->31, ah gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); } patch(p2, pc); patch(p3, pc); patch(p4, pc); patch(p5, pc); regfree(&s); regfree(&creg); orsh_break: regfree(&bl); regfree(&bh); break; case OXOR: case OAND: case OOR: // TODO(kaib): literal optimizations // make constant the right side (it usually is anyway). // if(lo1.op == OLITERAL) { // nswap(&lo1, &lo2); // nswap(&hi1, &hi2); // } // if(lo2.op == OLITERAL) { // // special cases for constants. // lv = mpgetfix(lo2.val.u.xval); // hv = mpgetfix(hi2.val.u.xval); // splitclean(); // right side // split64(res, &lo2, &hi2); // switch(n->op) { // case OXOR: // gmove(&lo1, &lo2); // gmove(&hi1, &hi2); // switch(lv) { // case 0: // break; // case 0xffffffffu: // gins(ANOTL, N, &lo2); // break; // default: // gins(AXORL, ncon(lv), &lo2); // break; // } // switch(hv) { // case 0: // break; // case 0xffffffffu: // gins(ANOTL, N, &hi2); // break; // default: // gins(AXORL, ncon(hv), &hi2); // break; // } // break; // case OAND: // switch(lv) { // case 0: // gins(AMOVL, ncon(0), &lo2); // break; // default: // gmove(&lo1, &lo2); // if(lv != 0xffffffffu) // gins(AANDL, ncon(lv), &lo2); // break; // } // switch(hv) { // case 0: // gins(AMOVL, ncon(0), &hi2); // break; // default: // gmove(&hi1, &hi2); // if(hv != 0xffffffffu) // gins(AANDL, ncon(hv), &hi2); // break; // } // break; // case OOR: // switch(lv) { // case 0: // gmove(&lo1, &lo2); // break; // case 0xffffffffu: // gins(AMOVL, ncon(0xffffffffu), &lo2); // break; // default: // gmove(&lo1, &lo2); // gins(AORL, ncon(lv), &lo2); // break; // } // switch(hv) { // case 0: // gmove(&hi1, &hi2); // break; // case 0xffffffffu: // gins(AMOVL, ncon(0xffffffffu), &hi2); // break; // default: // gmove(&hi1, &hi2); // gins(AORL, ncon(hv), &hi2); // break; // } // break; // } // splitclean(); // splitclean(); // goto out; // } regalloc(&n1, lo1.type, N); gins(AMOVW, &lo1, &al); gins(AMOVW, &hi1, &ah); gins(AMOVW, &lo2, &n1); gins(optoas(n->op, lo1.type), &n1, &al); gins(AMOVW, &hi2, &n1); gins(optoas(n->op, lo1.type), &n1, &ah); regfree(&n1); break; } if(is64(r->type)) splitclean(); splitclean(); split64(res, &lo1, &hi1); gins(AMOVW, &al, &lo1); gins(AMOVW, &ah, &hi1); splitclean(); //out: regfree(&al); regfree(&ah); }