-static void shift_assemble_arm(int i,struct regstat *i_regs)
-{
- if(rt1[i]) {
- if(opcode2[i]<=0x07) // SLLV/SRLV/SRAV
- {
- signed char s,t,shift;
- t=get_reg(i_regs->regmap,rt1[i]);
- s=get_reg(i_regs->regmap,rs1[i]);
- shift=get_reg(i_regs->regmap,rs2[i]);
- if(t>=0){
- if(rs1[i]==0)
- {
- emit_zeroreg(t);
- }
- else if(rs2[i]==0)
- {
- assert(s>=0);
- if(s!=t) emit_mov(s,t);
- }
- else
- {
- emit_andimm(shift,31,HOST_TEMPREG);
- if(opcode2[i]==4) // SLLV
- {
- emit_shl(s,HOST_TEMPREG,t);
- }
- if(opcode2[i]==6) // SRLV
- {
- emit_shr(s,HOST_TEMPREG,t);
- }
- if(opcode2[i]==7) // SRAV
- {
- emit_sar(s,HOST_TEMPREG,t);
- }
- }
- }
- } else { // DSLLV/DSRLV/DSRAV
- signed char sh,sl,th,tl,shift;
- th=get_reg(i_regs->regmap,rt1[i]|64);
- tl=get_reg(i_regs->regmap,rt1[i]);
- sh=get_reg(i_regs->regmap,rs1[i]|64);
- sl=get_reg(i_regs->regmap,rs1[i]);
- shift=get_reg(i_regs->regmap,rs2[i]);
- if(tl>=0){
- if(rs1[i]==0)
- {
- emit_zeroreg(tl);
- if(th>=0) emit_zeroreg(th);
- }
- else if(rs2[i]==0)
- {
- assert(sl>=0);
- if(sl!=tl) emit_mov(sl,tl);
- if(th>=0&&sh!=th) emit_mov(sh,th);
- }
- else
- {
- // FIXME: What if shift==tl ?
- assert(shift!=tl);
- int temp=get_reg(i_regs->regmap,-1);
- int real_th=th;
- if(th<0&&opcode2[i]!=0x14) {th=temp;} // DSLLV doesn't need a temporary register
- assert(sl>=0);
- assert(sh>=0);
- emit_andimm(shift,31,HOST_TEMPREG);
- if(opcode2[i]==0x14) // DSLLV
- {
- if(th>=0) emit_shl(sh,HOST_TEMPREG,th);
- emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
- emit_orrshr(sl,HOST_TEMPREG,th);
- emit_andimm(shift,31,HOST_TEMPREG);
- emit_testimm(shift,32);
- emit_shl(sl,HOST_TEMPREG,tl);
- if(th>=0) emit_cmovne_reg(tl,th);
- emit_cmovne_imm(0,tl);
- }
- if(opcode2[i]==0x16) // DSRLV
- {
- assert(th>=0);
- emit_shr(sl,HOST_TEMPREG,tl);
- emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
- emit_orrshl(sh,HOST_TEMPREG,tl);
- emit_andimm(shift,31,HOST_TEMPREG);
- emit_testimm(shift,32);
- emit_shr(sh,HOST_TEMPREG,th);
- emit_cmovne_reg(th,tl);
- if(real_th>=0) emit_cmovne_imm(0,th);
- }
- if(opcode2[i]==0x17) // DSRAV
- {
- assert(th>=0);
- emit_shr(sl,HOST_TEMPREG,tl);
- emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
- if(real_th>=0) {
- assert(temp>=0);
- emit_sarimm(th,31,temp);
- }
- emit_orrshl(sh,HOST_TEMPREG,tl);
- emit_andimm(shift,31,HOST_TEMPREG);
- emit_testimm(shift,32);
- emit_sar(sh,HOST_TEMPREG,th);
- emit_cmovne_reg(th,tl);
- if(real_th>=0) emit_cmovne_reg(temp,th);
- }
- }
- }
- }
- }
-}
-#define shift_assemble shift_assemble_arm
-
-static void loadlr_assemble_arm(int i,struct regstat *i_regs)
-{
- int s,tl,temp,temp2,addr;
- int offset;
- void *jaddr=0;
- int memtarget=0,c=0;
- int fastio_reg_override=-1;
- u_int hr,reglist=0;
- tl=get_reg(i_regs->regmap,rt1[i]);
- s=get_reg(i_regs->regmap,rs1[i]);
- temp=get_reg(i_regs->regmap,-1);
- temp2=get_reg(i_regs->regmap,FTEMP);
- addr=get_reg(i_regs->regmap,AGEN1+(i&1));
- assert(addr<0);
- offset=imm[i];
- for(hr=0;hr<HOST_REGS;hr++) {
- if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
- }
- reglist|=1<<temp;
- if(offset||s<0||c) addr=temp2;
- else addr=s;
- if(s>=0) {
- c=(i_regs->wasconst>>s)&1;
- if(c) {
- memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
- }
- }
- if(!c) {
- emit_shlimm(addr,3,temp);
- if (opcode[i]==0x22||opcode[i]==0x26) {
- emit_andimm(addr,0xFFFFFFFC,temp2); // LWL/LWR
- }else{
- emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR
- }
- jaddr=emit_fastpath_cmp_jump(i,temp2,&fastio_reg_override);
- }
- else {
- if(ram_offset&&memtarget) {
- host_tempreg_acquire();
- emit_addimm(temp2,ram_offset,HOST_TEMPREG);
- fastio_reg_override=HOST_TEMPREG;
- }
- if (opcode[i]==0x22||opcode[i]==0x26) {
- emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
- }else{
- emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
- }
- }
- if (opcode[i]==0x22||opcode[i]==0x26) { // LWL/LWR
- if(!c||memtarget) {
- int a=temp2;
- if(fastio_reg_override>=0) a=fastio_reg_override;
- emit_readword_indexed(0,a,temp2);
- if(fastio_reg_override==HOST_TEMPREG) host_tempreg_release();
- if(jaddr) add_stub_r(LOADW_STUB,jaddr,out,i,temp2,i_regs,ccadj[i],reglist);
- }
- else
- inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj[i],reglist);
- if(rt1[i]) {
- assert(tl>=0);
- emit_andimm(temp,24,temp);
-#ifdef BIG_ENDIAN_MIPS
- if (opcode[i]==0x26) // LWR
-#else
- if (opcode[i]==0x22) // LWL
-#endif
- emit_xorimm(temp,24,temp);
- emit_movimm(-1,HOST_TEMPREG);
- if (opcode[i]==0x26) {
- emit_shr(temp2,temp,temp2);
- emit_bic_lsr(tl,HOST_TEMPREG,temp,tl);
- }else{
- emit_shl(temp2,temp,temp2);
- emit_bic_lsl(tl,HOST_TEMPREG,temp,tl);
- }
- emit_or(temp2,tl,tl);
- }
- //emit_storereg(rt1[i],tl); // DEBUG
- }
- if (opcode[i]==0x1A||opcode[i]==0x1B) { // LDL/LDR
- assert(0);
- }
-}
-#define loadlr_assemble loadlr_assemble_arm
-
-static void c2op_prologue(u_int op,u_int reglist)