-static void cop2_put_dreg(u_int copr,signed char sl,signed char temp)
-{
- switch (copr) {
- case 15:
- emit_readword((int)®_cop2d[13],temp); // SXY1
- emit_writeword(sl,(int)®_cop2d[copr]);
- emit_writeword(temp,(int)®_cop2d[12]); // SXY0
- emit_readword((int)®_cop2d[14],temp); // SXY2
- emit_writeword(sl,(int)®_cop2d[14]);
- emit_writeword(temp,(int)®_cop2d[13]); // SXY1
- break;
- case 28:
- emit_andimm(sl,0x001f,temp);
- emit_shlimm(temp,7,temp);
- emit_writeword(temp,(int)®_cop2d[9]);
- emit_andimm(sl,0x03e0,temp);
- emit_shlimm(temp,2,temp);
- emit_writeword(temp,(int)®_cop2d[10]);
- emit_andimm(sl,0x7c00,temp);
- emit_shrimm(temp,3,temp);
- emit_writeword(temp,(int)®_cop2d[11]);
- emit_writeword(sl,(int)®_cop2d[28]);
- break;
- case 30:
- emit_movs(sl,temp);
- emit_mvnmi(temp,temp);
- emit_clz(temp,temp);
- emit_writeword(sl,(int)®_cop2d[30]);
- emit_writeword(temp,(int)®_cop2d[31]);
- break;
- case 31:
- break;
- default:
- emit_writeword(sl,(int)®_cop2d[copr]);
- break;
- }
-}
-
-void cop2_assemble(int i,struct regstat *i_regs)
-{
- u_int copr=(source[i]>>11)&0x1f;
- signed char temp=get_reg(i_regs->regmap,-1);
- if (opcode2[i]==0) { // MFC2
- signed char tl=get_reg(i_regs->regmap,rt1[i]);
- if(tl>=0&&rt1[i]!=0)
- cop2_get_dreg(copr,tl,temp);
- }
- else if (opcode2[i]==4) { // MTC2
- signed char sl=get_reg(i_regs->regmap,rs1[i]);
- cop2_put_dreg(copr,sl,temp);
- }
- else if (opcode2[i]==2) // CFC2
- {
- signed char tl=get_reg(i_regs->regmap,rt1[i]);
- if(tl>=0&&rt1[i]!=0)
- emit_readword((int)®_cop2c[copr],tl);
- }
- else if (opcode2[i]==6) // CTC2
- {
- signed char sl=get_reg(i_regs->regmap,rs1[i]);
- switch(copr) {
- case 4:
- case 12:
- case 20:
- case 26:
- case 27:
- case 29:
- case 30:
- emit_signextend16(sl,temp);
- break;
- case 31:
- //value = value & 0x7ffff000;
- //if (value & 0x7f87e000) value |= 0x80000000;
- emit_shrimm(sl,12,temp);
- emit_shlimm(temp,12,temp);
- emit_testimm(temp,0x7f000000);
- emit_testeqimm(temp,0x00870000);
- emit_testeqimm(temp,0x0000e000);
- emit_orrne_imm(temp,0x80000000,temp);
- break;
- default:
- temp=sl;
- break;
- }
- emit_writeword(temp,(int)®_cop2c[copr]);
- assert(sl>=0);
- }
-}
-
-void c2op_assemble(int i,struct regstat *i_regs)
-{
- signed char temp=get_reg(i_regs->regmap,-1);
- u_int c2op=source[i]&0x3f;
- u_int hr,reglist=0;
- for(hr=0;hr<HOST_REGS;hr++) {
- if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
- }
- if(i==0||itype[i-1]!=C2OP)
- save_regs(reglist);
-
- if (gte_handlers[c2op]!=NULL) {
- int cc=get_reg(i_regs->regmap,CCREG);
- emit_movimm(source[i],1); // opcode
- if (cc>=0&>e_cycletab[c2op])
- emit_addimm(cc,gte_cycletab[c2op]/2,cc); // XXX: could just adjust ccadj?
- emit_addimm(FP,(int)&psxRegs.CP2D.r[0]-(int)&dynarec_local,0); // cop2 regs
- emit_writeword(1,(int)&psxRegs.code);
- emit_call((int)gte_handlers[c2op]);
- }
-
- if(i>=slen-1||itype[i+1]!=C2OP)
- restore_regs(reglist);
-}
-
-void cop1_unusable(int i,struct regstat *i_regs)
-{
- // XXX: should just just do the exception instead
- if(!cop1_usable) {
- int jaddr=(int)out;
- emit_jmp(0);
- add_stub(FP_STUB,jaddr,(int)out,i,0,(int)i_regs,is_delayslot,0);
- cop1_usable=1;
- }
-}
-
-void cop1_assemble(int i,struct regstat *i_regs)
-{
-#ifndef DISABLE_COP1
- // Check cop1 unusable
- if(!cop1_usable) {
- signed char rs=get_reg(i_regs->regmap,CSREG);
- assert(rs>=0);
- emit_testimm(rs,0x20000000);
- int jaddr=(int)out;
- emit_jeq(0);
- add_stub(FP_STUB,jaddr,(int)out,i,rs,(int)i_regs,is_delayslot,0);
- cop1_usable=1;
- }
- if (opcode2[i]==0) { // MFC1
- signed char tl=get_reg(i_regs->regmap,rt1[i]);
- if(tl>=0) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],tl);
- emit_readword_indexed(0,tl,tl);
- }
- }
- else if (opcode2[i]==1) { // DMFC1
- signed char tl=get_reg(i_regs->regmap,rt1[i]);
- signed char th=get_reg(i_regs->regmap,rt1[i]|64);
- if(tl>=0) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],tl);
- if(th>=0) emit_readword_indexed(4,tl,th);
- emit_readword_indexed(0,tl,tl);
- }
- }
- else if (opcode2[i]==4) { // MTC1
- signed char sl=get_reg(i_regs->regmap,rs1[i]);
- signed char temp=get_reg(i_regs->regmap,-1);
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_writeword_indexed(sl,0,temp);
- }
- else if (opcode2[i]==5) { // DMTC1
- signed char sl=get_reg(i_regs->regmap,rs1[i]);
- signed char sh=rs1[i]>0?get_reg(i_regs->regmap,rs1[i]|64):sl;
- signed char temp=get_reg(i_regs->regmap,-1);
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- emit_writeword_indexed(sh,4,temp);
- emit_writeword_indexed(sl,0,temp);
- }
- else if (opcode2[i]==2) // CFC1
- {
- signed char tl=get_reg(i_regs->regmap,rt1[i]);
- if(tl>=0) {
- u_int copr=(source[i]>>11)&0x1f;
- if(copr==0) emit_readword((int)&FCR0,tl);
- if(copr==31) emit_readword((int)&FCR31,tl);
- }
- }
- else if (opcode2[i]==6) // CTC1
- {
- signed char sl=get_reg(i_regs->regmap,rs1[i]);
- u_int copr=(source[i]>>11)&0x1f;
- assert(sl>=0);
- if(copr==31)
- {
- emit_writeword(sl,(int)&FCR31);
- // Set the rounding mode
- //FIXME
- //char temp=get_reg(i_regs->regmap,-1);
- //emit_andimm(sl,3,temp);
- //emit_fldcw_indexed((int)&rounding_modes,temp);
- }
- }
-#else
- cop1_unusable(i, i_regs);
-#endif
-}
-
-void fconv_assemble_arm(int i,struct regstat *i_regs)
-{
-#ifndef DISABLE_COP1
- signed char temp=get_reg(i_regs->regmap,-1);
- assert(temp>=0);
- // Check cop1 unusable
- if(!cop1_usable) {
- signed char rs=get_reg(i_regs->regmap,CSREG);
- assert(rs>=0);
- emit_testimm(rs,0x20000000);
- int jaddr=(int)out;
- emit_jeq(0);
- add_stub(FP_STUB,jaddr,(int)out,i,rs,(int)i_regs,is_delayslot,0);
- cop1_usable=1;
- }
-
- #if(defined(__VFP_FP__) && !defined(__SOFTFP__))
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0d) { // trunc_w_s
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_flds(temp,15);
- emit_ftosizs(15,15); // float->int, truncate
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f))
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- emit_fsts(15,temp);
- return;
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0d) { // trunc_w_d
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- emit_vldr(temp,7);
- emit_ftosizd(7,13); // double->int, truncate
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- emit_fsts(13,temp);
- return;
- }
-
- if(opcode2[i]==0x14&&(source[i]&0x3f)==0x20) { // cvt_s_w
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_flds(temp,13);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f))
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- emit_fsitos(13,15);
- emit_fsts(15,temp);
- return;
- }
- if(opcode2[i]==0x14&&(source[i]&0x3f)==0x21) { // cvt_d_w
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_flds(temp,13);
- emit_readword((int)®_cop1_double[(source[i]>>6)&0x1f],temp);
- emit_fsitod(13,7);
- emit_vstr(7,temp);
- return;
- }
-
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x21) { // cvt_d_s
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_flds(temp,13);
- emit_readword((int)®_cop1_double[(source[i]>>6)&0x1f],temp);
- emit_fcvtds(13,7);
- emit_vstr(7,temp);
- return;
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x20) { // cvt_s_d
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- emit_vldr(temp,7);
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- emit_fcvtsd(7,13);
- emit_fsts(13,temp);
- return;
- }
- #endif
-
- // C emulation code
-
- u_int hr,reglist=0;
- for(hr=0;hr<HOST_REGS;hr++) {
- if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
- }
- save_regs(reglist);
-
- if(opcode2[i]==0x14&&(source[i]&0x3f)==0x20) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_s_w);
- }
- if(opcode2[i]==0x14&&(source[i]&0x3f)==0x21) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_d_w);
- }
- if(opcode2[i]==0x15&&(source[i]&0x3f)==0x20) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_s_l);
- }
- if(opcode2[i]==0x15&&(source[i]&0x3f)==0x21) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_d_l);
- }
-
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x21) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_d_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x24) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_w_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x25) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_l_s);
- }
-
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x20) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_s_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x24) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_w_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x25) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)cvt_l_d);
- }
-
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x08) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)round_l_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x09) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)trunc_l_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0a) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)ceil_l_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0b) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)floor_l_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0c) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)round_w_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0d) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)trunc_w_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0e) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)ceil_w_s);
- }
- if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0f) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)floor_w_s);
- }
-
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x08) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)round_l_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x09) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)trunc_l_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0a) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)ceil_l_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0b) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)floor_l_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0c) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)round_w_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0d) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)trunc_w_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0e) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)ceil_w_d);
- }
- if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0f) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- emit_call((int)floor_w_d);
- }
-
- restore_regs(reglist);
-#else
- cop1_unusable(i, i_regs);
-#endif
-}
-#define fconv_assemble fconv_assemble_arm
-
-void fcomp_assemble(int i,struct regstat *i_regs)
-{
-#ifndef DISABLE_COP1
- signed char fs=get_reg(i_regs->regmap,FSREG);
- signed char temp=get_reg(i_regs->regmap,-1);
- assert(temp>=0);
- // Check cop1 unusable
- if(!cop1_usable) {
- signed char cs=get_reg(i_regs->regmap,CSREG);
- assert(cs>=0);
- emit_testimm(cs,0x20000000);
- int jaddr=(int)out;
- emit_jeq(0);
- add_stub(FP_STUB,jaddr,(int)out,i,cs,(int)i_regs,is_delayslot,0);
- cop1_usable=1;
- }
-
- if((source[i]&0x3f)==0x30) {
- emit_andimm(fs,~0x800000,fs);
- return;
- }
-
- if((source[i]&0x3e)==0x38) {
- // sf/ngle - these should throw exceptions for NaNs
- emit_andimm(fs,~0x800000,fs);
- return;
- }
-
- #if(defined(__VFP_FP__) && !defined(__SOFTFP__))
- if(opcode2[i]==0x10) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_readword((int)®_cop1_simple[(source[i]>>16)&0x1f],HOST_TEMPREG);
- emit_orimm(fs,0x800000,fs);
- emit_flds(temp,14);
- emit_flds(HOST_TEMPREG,15);
- emit_fcmps(14,15);
- emit_fmstat();
- if((source[i]&0x3f)==0x31) emit_bicvc_imm(fs,0x800000,fs); // c_un_s
- if((source[i]&0x3f)==0x32) emit_bicne_imm(fs,0x800000,fs); // c_eq_s
- if((source[i]&0x3f)==0x33) {emit_bicne_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ueq_s
- if((source[i]&0x3f)==0x34) emit_biccs_imm(fs,0x800000,fs); // c_olt_s
- if((source[i]&0x3f)==0x35) {emit_biccs_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ult_s
- if((source[i]&0x3f)==0x36) emit_bichi_imm(fs,0x800000,fs); // c_ole_s
- if((source[i]&0x3f)==0x37) {emit_bichi_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ule_s
- if((source[i]&0x3f)==0x3a) emit_bicne_imm(fs,0x800000,fs); // c_seq_s
- if((source[i]&0x3f)==0x3b) emit_bicne_imm(fs,0x800000,fs); // c_ngl_s
- if((source[i]&0x3f)==0x3c) emit_biccs_imm(fs,0x800000,fs); // c_lt_s
- if((source[i]&0x3f)==0x3d) emit_biccs_imm(fs,0x800000,fs); // c_nge_s
- if((source[i]&0x3f)==0x3e) emit_bichi_imm(fs,0x800000,fs); // c_le_s
- if((source[i]&0x3f)==0x3f) emit_bichi_imm(fs,0x800000,fs); // c_ngt_s
- return;
- }
- if(opcode2[i]==0x11) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- emit_readword((int)®_cop1_double[(source[i]>>16)&0x1f],HOST_TEMPREG);
- emit_orimm(fs,0x800000,fs);
- emit_vldr(temp,6);
- emit_vldr(HOST_TEMPREG,7);
- emit_fcmpd(6,7);
- emit_fmstat();
- if((source[i]&0x3f)==0x31) emit_bicvc_imm(fs,0x800000,fs); // c_un_d
- if((source[i]&0x3f)==0x32) emit_bicne_imm(fs,0x800000,fs); // c_eq_d
- if((source[i]&0x3f)==0x33) {emit_bicne_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ueq_d
- if((source[i]&0x3f)==0x34) emit_biccs_imm(fs,0x800000,fs); // c_olt_d
- if((source[i]&0x3f)==0x35) {emit_biccs_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ult_d
- if((source[i]&0x3f)==0x36) emit_bichi_imm(fs,0x800000,fs); // c_ole_d
- if((source[i]&0x3f)==0x37) {emit_bichi_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ule_d
- if((source[i]&0x3f)==0x3a) emit_bicne_imm(fs,0x800000,fs); // c_seq_d
- if((source[i]&0x3f)==0x3b) emit_bicne_imm(fs,0x800000,fs); // c_ngl_d
- if((source[i]&0x3f)==0x3c) emit_biccs_imm(fs,0x800000,fs); // c_lt_d
- if((source[i]&0x3f)==0x3d) emit_biccs_imm(fs,0x800000,fs); // c_nge_d
- if((source[i]&0x3f)==0x3e) emit_bichi_imm(fs,0x800000,fs); // c_le_d
- if((source[i]&0x3f)==0x3f) emit_bichi_imm(fs,0x800000,fs); // c_ngt_d
- return;
- }
- #endif
-
- // C only
-
- u_int hr,reglist=0;
- for(hr=0;hr<HOST_REGS;hr++) {
- if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
- }
- reglist&=~(1<<fs);
- save_regs(reglist);
- if(opcode2[i]==0x10) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_simple[(source[i]>>16)&0x1f],ARG2_REG);
- if((source[i]&0x3f)==0x30) emit_call((int)c_f_s);
- if((source[i]&0x3f)==0x31) emit_call((int)c_un_s);
- if((source[i]&0x3f)==0x32) emit_call((int)c_eq_s);
- if((source[i]&0x3f)==0x33) emit_call((int)c_ueq_s);
- if((source[i]&0x3f)==0x34) emit_call((int)c_olt_s);
- if((source[i]&0x3f)==0x35) emit_call((int)c_ult_s);
- if((source[i]&0x3f)==0x36) emit_call((int)c_ole_s);
- if((source[i]&0x3f)==0x37) emit_call((int)c_ule_s);
- if((source[i]&0x3f)==0x38) emit_call((int)c_sf_s);
- if((source[i]&0x3f)==0x39) emit_call((int)c_ngle_s);
- if((source[i]&0x3f)==0x3a) emit_call((int)c_seq_s);
- if((source[i]&0x3f)==0x3b) emit_call((int)c_ngl_s);
- if((source[i]&0x3f)==0x3c) emit_call((int)c_lt_s);
- if((source[i]&0x3f)==0x3d) emit_call((int)c_nge_s);
- if((source[i]&0x3f)==0x3e) emit_call((int)c_le_s);
- if((source[i]&0x3f)==0x3f) emit_call((int)c_ngt_s);
- }
- if(opcode2[i]==0x11) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- emit_readword((int)®_cop1_double[(source[i]>>16)&0x1f],ARG2_REG);
- if((source[i]&0x3f)==0x30) emit_call((int)c_f_d);
- if((source[i]&0x3f)==0x31) emit_call((int)c_un_d);
- if((source[i]&0x3f)==0x32) emit_call((int)c_eq_d);
- if((source[i]&0x3f)==0x33) emit_call((int)c_ueq_d);
- if((source[i]&0x3f)==0x34) emit_call((int)c_olt_d);
- if((source[i]&0x3f)==0x35) emit_call((int)c_ult_d);
- if((source[i]&0x3f)==0x36) emit_call((int)c_ole_d);
- if((source[i]&0x3f)==0x37) emit_call((int)c_ule_d);
- if((source[i]&0x3f)==0x38) emit_call((int)c_sf_d);
- if((source[i]&0x3f)==0x39) emit_call((int)c_ngle_d);
- if((source[i]&0x3f)==0x3a) emit_call((int)c_seq_d);
- if((source[i]&0x3f)==0x3b) emit_call((int)c_ngl_d);
- if((source[i]&0x3f)==0x3c) emit_call((int)c_lt_d);
- if((source[i]&0x3f)==0x3d) emit_call((int)c_nge_d);
- if((source[i]&0x3f)==0x3e) emit_call((int)c_le_d);
- if((source[i]&0x3f)==0x3f) emit_call((int)c_ngt_d);
- }
- restore_regs(reglist);
- emit_loadreg(FSREG,fs);
-#else
- cop1_unusable(i, i_regs);
-#endif
-}
-
-void float_assemble(int i,struct regstat *i_regs)
-{
-#ifndef DISABLE_COP1
- signed char temp=get_reg(i_regs->regmap,-1);
- assert(temp>=0);
- // Check cop1 unusable
- if(!cop1_usable) {
- signed char cs=get_reg(i_regs->regmap,CSREG);
- assert(cs>=0);
- emit_testimm(cs,0x20000000);
- int jaddr=(int)out;
- emit_jeq(0);
- add_stub(FP_STUB,jaddr,(int)out,i,cs,(int)i_regs,is_delayslot,0);
- cop1_usable=1;
- }
-
- #if(defined(__VFP_FP__) && !defined(__SOFTFP__))
- if((source[i]&0x3f)==6) // mov
- {
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- if(opcode2[i]==0x10) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],HOST_TEMPREG);
- emit_readword_indexed(0,temp,temp);
- emit_writeword_indexed(temp,0,HOST_TEMPREG);
- }
- if(opcode2[i]==0x11) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- emit_readword((int)®_cop1_double[(source[i]>>6)&0x1f],HOST_TEMPREG);
- emit_vldr(temp,7);
- emit_vstr(7,HOST_TEMPREG);
- }
- }
- return;
- }
-
- if((source[i]&0x3f)>3)
- {
- if(opcode2[i]==0x10) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- emit_flds(temp,15);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- }
- if((source[i]&0x3f)==4) // sqrt
- emit_fsqrts(15,15);
- if((source[i]&0x3f)==5) // abs
- emit_fabss(15,15);
- if((source[i]&0x3f)==7) // neg
- emit_fnegs(15,15);
- emit_fsts(15,temp);
- }
- if(opcode2[i]==0x11) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- emit_vldr(temp,7);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- emit_readword((int)®_cop1_double[(source[i]>>6)&0x1f],temp);
- }
- if((source[i]&0x3f)==4) // sqrt
- emit_fsqrtd(7,7);
- if((source[i]&0x3f)==5) // abs
- emit_fabsd(7,7);
- if((source[i]&0x3f)==7) // neg
- emit_fnegd(7,7);
- emit_vstr(7,temp);
- }
- return;
- }
- if((source[i]&0x3f)<4)
- {
- if(opcode2[i]==0x10) {
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],temp);
- }
- if(opcode2[i]==0x11) {
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],temp);
- }
- if(((source[i]>>11)&0x1f)!=((source[i]>>16)&0x1f)) {
- if(opcode2[i]==0x10) {
- emit_readword((int)®_cop1_simple[(source[i]>>16)&0x1f],HOST_TEMPREG);
- emit_flds(temp,15);
- emit_flds(HOST_TEMPREG,13);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- if(((source[i]>>16)&0x1f)!=((source[i]>>6)&0x1f)) {
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- }
- }
- if((source[i]&0x3f)==0) emit_fadds(15,13,15);
- if((source[i]&0x3f)==1) emit_fsubs(15,13,15);
- if((source[i]&0x3f)==2) emit_fmuls(15,13,15);
- if((source[i]&0x3f)==3) emit_fdivs(15,13,15);
- if(((source[i]>>16)&0x1f)==((source[i]>>6)&0x1f)) {
- emit_fsts(15,HOST_TEMPREG);
- }else{
- emit_fsts(15,temp);
- }
- }
- else if(opcode2[i]==0x11) {
- emit_readword((int)®_cop1_double[(source[i]>>16)&0x1f],HOST_TEMPREG);
- emit_vldr(temp,7);
- emit_vldr(HOST_TEMPREG,6);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- if(((source[i]>>16)&0x1f)!=((source[i]>>6)&0x1f)) {
- emit_readword((int)®_cop1_double[(source[i]>>6)&0x1f],temp);
- }
- }
- if((source[i]&0x3f)==0) emit_faddd(7,6,7);
- if((source[i]&0x3f)==1) emit_fsubd(7,6,7);
- if((source[i]&0x3f)==2) emit_fmuld(7,6,7);
- if((source[i]&0x3f)==3) emit_fdivd(7,6,7);
- if(((source[i]>>16)&0x1f)==((source[i]>>6)&0x1f)) {
- emit_vstr(7,HOST_TEMPREG);
- }else{
- emit_vstr(7,temp);
- }
- }
- }
- else {
- if(opcode2[i]==0x10) {
- emit_flds(temp,15);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- emit_readword((int)®_cop1_simple[(source[i]>>6)&0x1f],temp);
- }
- if((source[i]&0x3f)==0) emit_fadds(15,15,15);
- if((source[i]&0x3f)==1) emit_fsubs(15,15,15);
- if((source[i]&0x3f)==2) emit_fmuls(15,15,15);
- if((source[i]&0x3f)==3) emit_fdivs(15,15,15);
- emit_fsts(15,temp);
- }
- else if(opcode2[i]==0x11) {
- emit_vldr(temp,7);
- if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
- emit_readword((int)®_cop1_double[(source[i]>>6)&0x1f],temp);
- }
- if((source[i]&0x3f)==0) emit_faddd(7,7,7);
- if((source[i]&0x3f)==1) emit_fsubd(7,7,7);
- if((source[i]&0x3f)==2) emit_fmuld(7,7,7);
- if((source[i]&0x3f)==3) emit_fdivd(7,7,7);
- emit_vstr(7,temp);
- }
- }
- return;
- }
- #endif
-
- u_int hr,reglist=0;
- for(hr=0;hr<HOST_REGS;hr++) {
- if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
- }
- if(opcode2[i]==0x10) { // Single precision
- save_regs(reglist);
- emit_readword((int)®_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
- if((source[i]&0x3f)<4) {
- emit_readword((int)®_cop1_simple[(source[i]>>16)&0x1f],ARG2_REG);
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG3_REG);
- }else{
- emit_readword((int)®_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
- }
- switch(source[i]&0x3f)
- {
- case 0x00: emit_call((int)add_s);break;
- case 0x01: emit_call((int)sub_s);break;
- case 0x02: emit_call((int)mul_s);break;
- case 0x03: emit_call((int)div_s);break;
- case 0x04: emit_call((int)sqrt_s);break;
- case 0x05: emit_call((int)abs_s);break;
- case 0x06: emit_call((int)mov_s);break;
- case 0x07: emit_call((int)neg_s);break;
- }
- restore_regs(reglist);
- }
- if(opcode2[i]==0x11) { // Double precision
- save_regs(reglist);
- emit_readword((int)®_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
- if((source[i]&0x3f)<4) {
- emit_readword((int)®_cop1_double[(source[i]>>16)&0x1f],ARG2_REG);
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG3_REG);
- }else{
- emit_readword((int)®_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
- }
- switch(source[i]&0x3f)
- {
- case 0x00: emit_call((int)add_d);break;
- case 0x01: emit_call((int)sub_d);break;
- case 0x02: emit_call((int)mul_d);break;
- case 0x03: emit_call((int)div_d);break;
- case 0x04: emit_call((int)sqrt_d);break;
- case 0x05: emit_call((int)abs_d);break;
- case 0x06: emit_call((int)mov_d);break;
- case 0x07: emit_call((int)neg_d);break;
- }
- restore_regs(reglist);
- }
-#else
- cop1_unusable(i, i_regs);
-#endif
-}
-
-void multdiv_assemble_arm(int i,struct regstat *i_regs)