예제 #1
0
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;
}
예제 #2
0
u4 ElfReader::getProgramOff() {
    if (!is64()) {
        return ehdr._32->e_phoff;
    } else {
        return ehdr._64->e_phoff;
    }
}
예제 #3
0
u4 ElfReader::getSectionOff() {
    if (!is64()) {
        return ehdr._32->e_shoff;
    } else {
        return ehdr._64->e_shoff;
    }
}
예제 #4
0
static void genbranchlink(void)
{
   int r31_64bit = is64((unsigned int*)&reg[31]);
   
   if (r31_64bit == 0)
     {
    int r31 = allocate_register_32_w((unsigned int *)&reg[31]);
    
    mov_reg32_imm32(r31, dst->addr+8);
     }
   else if (r31_64bit == -1)
     {
    mov_m32rel_imm32((unsigned int *)&reg[31], dst->addr + 8);
    if (dst->addr & 0x80000000)
      mov_m32rel_imm32(((unsigned int *)&reg[31])+1, 0xFFFFFFFF);
    else
      mov_m32rel_imm32(((unsigned int *)&reg[31])+1, 0);
     }
   else
     {
    int r31 = allocate_register_64_w((unsigned long long *)&reg[31]);
    
    mov_reg32_imm32(r31, dst->addr+8);
    movsxd_reg64_reg32(r31, r31);
     }
}
예제 #5
0
파일: MachO.cpp 프로젝트: CLavina/darling
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;
}
예제 #6
0
파일: gobj.c 프로젝트: funkygao/govtil
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;
	}
예제 #7
0
static void genbranchlink(void)
{
   int r31_64bit = is64((unsigned int*)&reg[31]);
   
   if (!r31_64bit)
     {
    int r31 = allocate_register_w((unsigned int *)&reg[31]);
    
    mov_reg32_imm32(r31, dst->addr+8);
     }
   else if (r31_64bit == -1)
     {
    mov_m32_imm32((unsigned int *)&reg[31], dst->addr + 8);
    if (dst->addr & 0x80000000)
      mov_m32_imm32(((unsigned int *)&reg[31])+1, 0xFFFFFFFF);
    else
      mov_m32_imm32(((unsigned int *)&reg[31])+1, 0);
     }
   else
     {
    int r311 = allocate_64_register1_w((unsigned int *)&reg[31]);
    int r312 = allocate_64_register2_w((unsigned int *)&reg[31]);
    
    mov_reg32_imm32(r311, dst->addr+8);
    if (dst->addr & 0x80000000)
      mov_reg32_imm32(r312, 0xFFFFFFFF);
    else
      mov_reg32_imm32(r312, 0);
     }
}
예제 #8
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
     }
}
예제 #9
0
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);
    }
}
예제 #10
0
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();
}
예제 #11
0
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);
    }
}
예제 #12
0
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
   }
}
예제 #13
0
static void genbranchlink(void)
{
   int r31_64bit = is64((unsigned int*)&reg[31]);

   if (r31_64bit == 0)
   {
#ifdef __x86_64__
      int r31 = allocate_register_32_w((unsigned int *)&reg[31]);

      mov_reg32_imm32(r31, dst->addr+8);
#else
      int r31 = allocate_register_w((unsigned int *)&reg[31]);

      mov_reg32_imm32(r31, dst->addr+8);
#endif
   }
   else if (r31_64bit == -1)
   {
#ifdef __x86_64__
      mov_m32rel_imm32((unsigned int *)&reg[31], dst->addr + 8);
      if (dst->addr & 0x80000000)
         mov_m32rel_imm32(((unsigned int *)&reg[31])+1, 0xFFFFFFFF);
      else
         mov_m32rel_imm32(((unsigned int *)&reg[31])+1, 0);
#else
      mov_m32_imm32((unsigned int *)&reg[31], dst->addr + 8);
      if (dst->addr & 0x80000000)
         mov_m32_imm32(((unsigned int *)&reg[31])+1, 0xFFFFFFFF);
      else
         mov_m32_imm32(((unsigned int *)&reg[31])+1, 0);
#endif
   }
   else
   {
#ifdef __x86_64__
      int r31 = allocate_register_64_w((uint64_t*)&reg[31]);

      mov_reg32_imm32(r31, dst->addr+8);
      movsxd_reg64_reg32(r31, r31);
#else
      int r311 = allocate_64_register1_w((unsigned int *)&reg[31]);
      int r312 = allocate_64_register2_w((unsigned int *)&reg[31]);

      mov_reg32_imm32(r311, dst->addr+8);
      if (dst->addr & 0x80000000)
         mov_reg32_imm32(r312, 0xFFFFFFFF);
      else
         mov_reg32_imm32(r312, 0);
#endif
   }
}
예제 #14
0
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);
    }
}
예제 #15
0
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;
	}
예제 #16
0
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);
  }
}
예제 #17
0
 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);
       }
     }
   }
 }
예제 #18
0
파일: cgen64.c 프로젝트: 8l/go-learn
/*
 * 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);
}