27 #define CODEGEN_HPP_ 1
36 #if defined(__ARMEL__)
38 # define SPLIT_OPEN(type, reg, tmpreg) \
39 if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==REG_SPLIT) { \
42 (reg) = PACK_REGS(GET_LOW_REG(reg), tmpreg); \
45 # define SPLIT_STORE_AND_CLOSE(type, reg, offset) \
46 if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==3) { \
48 M_STR(GET_HIGH_REG(reg), REG_SP, 4 * (offset)); \
49 (reg) = PACK_REGS(GET_LOW_REG(reg), REG_SPLIT); \
54 # define SPLIT_OPEN(type, reg, tmpreg) \
55 if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==REG_SPLIT) { \
58 (reg) = PACK_REGS(tmpreg, GET_HIGH_REG(reg)); \
61 # define SPLIT_STORE_AND_CLOSE(type, reg, offset) \
62 if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==3) { \
64 M_STR(GET_LOW_REG(reg), REG_SP, 4 * (offset)); \
65 (reg) = PACK_REGS(REG_SPLIT, GET_HIGH_REG(reg)); \
75 #define MCODECHECK(icnt) \
77 if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
78 codegen_increase(cd); \
84 #define IS_IMM(val) ( ((val) >= 0) && ((val) <= 255) )
85 #define IS_OFFSET(off,max) ((s4)(off) <= (max) && (s4)(off) >= -(max))
87 #define CHECK_INT_REG(r) assert((r)>=0 && (r)<=15)
88 #define CHECK_FLT_REG(r) assert((r)>=0 && (r)<=15)
89 #define CHECK_OFFSET(off,max) assert(IS_OFFSET(off,max))
102 #define PATCHER_CALL_SIZE 1 * 4
104 #define PATCHER_NOPS \
119 #define ASM_DEBUG_PREPARE \
120 M_STMFD(0x7fff, REG_SP)
121 #define ASM_DEBUG_EXECUTE \
122 M_LONGBRANCH(asm_debug_intern); \
123 M_LDMFD(0x7fff, REG_SP)
148 #define UNCOND COND_AL
160 #define M_DAT(cond,op,d,n,S,I,shift) \
162 *((u4 *) cd->mcodeptr) = (((cond) << 28) | ((op) << 21) | ((d) << 12) | ((n) << 16) | ((I) << 25) | ((S) << 20) | ((shift) & 0x00000fff)); \
176 #define M_MEM(cond,L,B,d,n,adr,I,P,U,W) \
178 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (1 << 26) | ((L) << 20) | ((B) << 22) | ((d) << 12) | ((n) << 16) | ((adr) & 0x0fff) | ((I) << 25) | ((P) << 24) | ((U) << 23) | ((W) << 21)); \
182 #define M_MEM_GET_Rd(mcode) (((mcode) >> 12) & 0x0f)
183 #define M_MEM_GET_Rbase(mcode) (((mcode) >> 16) & 0x0f)
196 #define M_MEM2(cond,L,H,S,d,n,adr,I,P,U,W) \
198 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (1 << 22) | (0x9 << 4) | ((L) << 20) | ((H) << 5) | ((S) << 6) | ((d) << 12) | ((n) << 16) | ((adr) & 0x0f) | (((adr) & 0xf0) << (8-4)) | ((I) << 22) | ((P) << 24) | ((U) << 23) | ((W) << 21)); \
211 #define M_MEM_MULTI(cond,L,S,regs,n,P,U,W) \
213 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (1 << 27) | ((L) << 20) | ((S) << 22) | ((n) << 16) | ((regs) & 0xffff) | ((P) << 24) | ((U) << 23) | ((W) << 21)); \
224 #define M_BRAX(cond,L,reg) \
226 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x12 << 20) | (0xfff << 8) | (L << 5) | (1 << 4) | ((reg) & 0xf)); \
237 #define M_BRA(cond,L,offset) \
239 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x5 << 25) | ((L) << 24) | ((offset) & 0x00ffffff)); \
253 #define M_MULT(cond,d,n,m,S,A,s) \
255 *((u4 *) cd->mcodeptr) = (((cond) << 28) | ((d) << 16) | ((n) << 8) | (m) | (0x09 << 4) | ((S) << 20) | ((A) << 21) | ((s) << 12)); \
264 *((u4 *) cd->mcodeptr) = (0xe1a00000); \
271 #define M_BREAKPOINT(imm) \
273 *((u4 *) cd->mcodeptr) = (0x0e12 << 20) | (0x07 << 4) | (((imm) & 0xfff0) << (8-4)) | ((imm) & 0x0f); \
280 #define M_UNDEFINED(cond,imm,n) \
282 *((u4 *) cd->mcodeptr) = ((cond) << 28) | (0x7f << 20) | (((imm) & 0x0fff) << 8) | (0x0f << 4) | (n); \
287 #if !defined(ENABLE_SOFTFLOAT)
302 #define M_CPDOS(cond,op,D,Fd,Fn,Fm) \
304 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | ((op) << 20) | ((D) << 15) | ((Fd) << 12) | ((Fn) << 16) | ((Fm) & 0x0f)); \
309 #define M_CPDOD(cond,op,D,Fd,Fn,Fm) \
311 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | ((op) << 20) | ((D) << 15) | ((Fd) << 12) | ((Fn) << 16) | ((Fm) & 0x0f) | (1 << 7)); \
316 #define M_CPDP(cond,p,q,r,s,cp_num,D,N,M,Fd,Fn,Fm) \
318 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | ((p) << 23) | ((q) << 21) | ((r) << 20) | ((s) << 6) | ((cp_num) << 8) | ((D) << 22) | ((N) << 7) | ((M) << 5) | ((Fd) << 12) | ((Fn) << 16) | ((Fm) & 0x0f)); \
322 #define M_CPDPF(cond,p,q,r,s,cp_num,Fd,Fn,Fm) \
323 M_CPDP(cond,p,q,r,s,cp_num,(Fd)>>4,(Fn)>>4,(Fm)>>4,(Fd)&0xf,(Fn)&0xf,Fm)
336 #define M_CPDT(cond,L,T1,T0,Fd,n,off,P,U,W) \
338 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0c << 24) | (1 << 8) | ((L) << 20) | ((T1) << 22) | ((T0) << 15) | ((Fd) << 12) | ((n) << 16) | ((off) & 0xff) | ((P) << 24) | ((U) << 23) | ((W) << 21)); \
342 #define M_CPLS(cond,L,P,U,W,cp_num,D,Fd,n,off) \
344 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0c << 24) | ((P) << 24) | ((U) << 23) | ((W) << 21) | ((L) << 20) | ((cp_num) << 8) | ((D) << 22) | ((Fd) << 12) | ((n) << 16) | ((off) & 0xff)); \
357 #define M_CPRT(cond,op,L,cp_num,N,Fn,n) \
359 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 4) | ((op) << 21) | ((L) << 20) | ((cp_num) << 8) | ((N) << 7) | ((Fn) << 16) | ((n) << 12)); \
363 #define M_CPRTS(cond,L,d,Fn,Fm) \
365 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | (1 << 4) | ((L) << 20) | ((d) << 12) | ((Fn) << 16) | (Fm)); \
370 #define M_CPRTD(cond,L,d,Fn,Fm) \
372 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | (1 << 4) | ((L) << 20) | ((d) << 12) | ((Fn) << 16) | (Fm) | (1 << 7)); \
377 #define M_CPRTI(cond,L,d,Fn,Fm) \
379 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | (1 << 4) | ((L) << 20) | ((d) << 12) | ((Fn) << 16) | (Fm) | (3 << 5)); \
386 #define M_CPRTX(cond,L,d,Fn,Fm) \
388 *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | (1 << 4) | ((L) << 20) | ((d) << 12) | ((Fn) << 16) | (Fm) | (1 << 23)); \
398 *((u4 *) cd->mcodeptr) = val; \
404 #define REG_LSL(reg, shift) ( (((shift) & 0x1f) << 7) | ((reg) & 0x0f) )
405 #define REG_LSR(reg, shift) ( (((shift) & 0x1f) << 7) | ((reg) & 0x0f) | (1 << 5) )
406 #define REG_ASR(reg, shift) ( (((shift) & 0x1f) << 7) | ((reg) & 0x0f) | (1 << 6) )
407 #define REG_LSL_REG(reg, s) ( (((s) & 0x0f) << 8) | ((reg) & 0x0f) | (1 << 4) )
408 #define REG_LSR_REG(reg, s) ( (((s) & 0x0f) << 8) | ((reg) & 0x0f) | (1 << 4) | (1 << 5) )
409 #define REG_ASR_REG(reg, s) ( (((s) & 0x0f) << 8) | ((reg) & 0x0f) | (1 << 4) | (1 << 6) )
413 #define IMM_ROTR(imm, rot) ( ((imm) & 0xff) | (((rot) & 0x0f) << 8) )
414 #define IMM_ROTL(imm, rot) IMM_ROTR(imm, 16-(rot))
421 #define M_ADD(d,a,b) M_DAT(UNCOND,0x04,d,a,0,0,b)
422 #define M_ADC(d,a,b) M_DAT(UNCOND,0x05,d,a,0,0,b)
423 #define M_SUB(d,a,b) M_DAT(UNCOND,0x02,d,a,0,0,b)
424 #define M_SBC(d,a,b) M_DAT(UNCOND,0x06,d,a,0,0,b)
425 #define M_AND(a,b,d) M_DAT(UNCOND,0x00,d,a,0,0,b)
426 #define M_ORR(a,b,d) M_DAT(UNCOND,0x0c,d,a,0,0,b)
427 #define M_EOR(a,b,d) M_DAT(UNCOND,0x01,d,a,0,0,b)
428 #define M_TST(a,b) M_DAT(UNCOND,0x08,0,a,1,0,b)
429 #define M_TEQ(a,b) M_DAT(UNCOND,0x09,0,a,1,0,b)
430 #define M_CMP(a,b) M_DAT(UNCOND,0x0a,0,a,1,0,b)
431 #define M_MOV(d,b) M_DAT(UNCOND,0x0d,d,0,0,0,b)
432 #define M_ADD_S(d,a,b) M_DAT(UNCOND,0x04,d,a,1,0,b)
433 #define M_SUB_S(d,a,b) M_DAT(UNCOND,0x02,d,a,1,0,b)
434 #define M_ORR_S(a,b,d) M_DAT(UNCOND,0x0c,d,a,1,0,b)
435 #define M_MOV_S(d,b) M_DAT(UNCOND,0x0d,d,0,1,0,b)
437 #define M_ADD_IMM(d,a,i) M_DAT(UNCOND,0x04,d,a,0,1,i)
438 #define M_ADC_IMM(d,a,i) M_DAT(UNCOND,0x05,d,a,0,1,i)
439 #define M_SUB_IMM(d,a,i) M_DAT(UNCOND,0x02,d,a,0,1,i)
440 #define M_SBC_IMM(d,a,i) M_DAT(UNCOND,0x06,d,a,0,1,i)
441 #define M_RSB_IMM(d,a,i) M_DAT(UNCOND,0x03,d,a,0,1,i)
442 #define M_RSC_IMM(d,a,i) M_DAT(UNCOND,0x07,d,a,0,1,i)
443 #define M_AND_IMM(a,i,d) M_DAT(UNCOND,0x00,d,a,0,1,i)
444 #define M_TST_IMM(a,i) M_DAT(UNCOND,0x08,0,a,1,1,i)
445 #define M_TEQ_IMM(a,i) M_DAT(UNCOND,0x09,0,a,1,1,i)
446 #define M_CMP_IMM(a,i) M_DAT(UNCOND,0x0a,0,a,1,1,i)
447 #define M_CMN_IMM(a,i) M_DAT(UNCOND,0x0b,0,a,1,1,i)
448 #define M_MOV_IMM(d,i) M_DAT(UNCOND,0x0d,d,0,0,1,i)
449 #define M_ADD_IMMS(d,a,i) M_DAT(UNCOND,0x04,d,a,1,1,i)
450 #define M_SUB_IMMS(d,a,i) M_DAT(UNCOND,0x02,d,a,1,1,i)
451 #define M_RSB_IMMS(d,a,i) M_DAT(UNCOND,0x03,d,a,1,1,i)
453 #define M_ADDSUB_IMM(d,a,i) if((i)>=0) M_ADD_IMM(d,a,i); else M_SUB_IMM(d,a,-(i))
454 #define M_MOVEQ(a,d) M_DAT(COND_EQ,0x0d,d,0,0,0,a)
455 #define M_EORLE(d,a,b) M_DAT(COND_LE,0x01,d,a,0,0,b)
457 #define M_MOVVS_IMM(i,d) M_DAT(COND_VS,0x0d,d,0,0,1,i)
458 #define M_MOVEQ_IMM(i,d) M_DAT(COND_EQ,0x0d,d,0,0,1,i)
459 #define M_MOVNE_IMM(i,d) M_DAT(COND_NE,0x0d,d,0,0,1,i)
460 #define M_MOVLT_IMM(i,d) M_DAT(COND_LT,0x0d,d,0,0,1,i)
461 #define M_MOVGT_IMM(i,d) M_DAT(COND_GT,0x0d,d,0,0,1,i)
462 #define M_MOVLS_IMM(i,d) M_DAT(COND_LS,0x0d,d,0,0,1,i)
464 #define M_ADDHI_IMM(d,a,i) M_DAT(COND_HI,0x04,d,a,0,1,i)
465 #define M_ADDLT_IMM(d,a,i) M_DAT(COND_LT,0x04,d,a,0,1,i)
466 #define M_ADDGT_IMM(d,a,i) M_DAT(COND_GT,0x04,d,a,0,1,i)
467 #define M_SUBLO_IMM(d,a,i) M_DAT(COND_CC,0x02,d,a,0,1,i)
468 #define M_SUBLT_IMM(d,a,i) M_DAT(COND_LT,0x02,d,a,0,1,i)
469 #define M_SUBGT_IMM(d,a,i) M_DAT(COND_GT,0x02,d,a,0,1,i)
470 #define M_RSBMI_IMM(d,a,i) M_DAT(COND_MI,0x03,d,a,0,1,i)
471 #define M_ADCMI_IMM(d,a,i) M_DAT(COND_MI,0x05,d,a,0,1,i)
473 #define M_CMPEQ(a,b) M_DAT(COND_EQ,0x0a,0,a,1,0,b)
474 #define M_CMPLE(a,b) M_DAT(COND_LE,0x0a,0,a,1,0,b)
476 #define M_CMPEQ_IMM(a,i) M_DAT(COND_EQ,0x0a,0,a,1,1,i)
478 #define M_MUL(d,a,b) M_MULT(UNCOND,d,a,b,0,0,0x0)
480 #define M_B(off) M_BRA(UNCOND,0,off)
481 #define M_BL(off) M_BRA(UNCOND,1,off)
482 #define M_BEQ(off) M_BRA(COND_EQ,0,off)
483 #define M_BNE(off) M_BRA(COND_NE,0,off)
484 #define M_BGE(off) M_BRA(COND_GE,0,off)
485 #define M_BGT(off) M_BRA(COND_GT,0,off)
486 #define M_BLT(off) M_BRA(COND_LT,0,off)
487 #define M_BLE(off) M_BRA(COND_LE,0,off)
488 #define M_BHI(off) M_BRA(COND_HI,0,off)
489 #define M_BHS(off) M_BRA(COND_CS,0,off)
490 #define M_BLO(off) M_BRA(COND_CC,0,off)
491 #define M_BLS(off) M_BRA(COND_LS,0,off)
493 #define M_BX(a) M_BRAX(COND_AL,0,a)
494 #define M_BLX(a) M_BRAX(COND_AL,1,a)
501 #define M_LDMFD(regs,base) M_MEM_MULTI(UNCOND,1,0,regs,base,0,1,1)
502 #define M_STMFD(regs,base) M_MEM_MULTI(UNCOND,0,0,regs,base,1,0,1)
504 #define M_LDR_REG(d,base,offreg) M_MEM(UNCOND,1,0,d,base,offreg,1,1,1,0)
505 #define M_STR_REG(d,base,offreg) M_MEM(UNCOND,0,0,d,base,offreg,1,1,1,0)
507 #define M_LDR_INTERN(d,base,off) \
509 CHECK_OFFSET(off, 0x0fff); \
510 M_MEM(UNCOND,1,0,d,base,(((off) < 0) ? -(off) : off),0,1,(((off) < 0) ? 0 : 1),0); \
513 #define M_STR_INTERN(d,base,off) \
515 CHECK_OFFSET(off, 0x0fff); \
516 M_MEM(UNCOND,0,0,d,base,(((off) < 0) ? -(off) : off),0,1,(((off) < 0) ? 0 : 1),0); \
519 #define M_LDR_UPDATE(d,base,off) \
521 CHECK_OFFSET(off, 0x0fff); \
522 M_MEM(UNCOND,1,0,d,base,(((off) < 0) ? -(off) : off),0,0,(((off) < 0) ? 0 : 1),0); \
525 #define M_STR_UPDATE(d,base,off) \
527 CHECK_OFFSET(off,0x0fff); \
528 M_MEM(UNCOND,0,0,d,base,(((off) < 0) ? -(off) : off),0,1,(((off) < 0) ? 0 : 1),1); \
532 #define M_LDRH(d,base,off) \
534 CHECK_OFFSET(off, 0x00ff); \
536 M_MEM2(UNCOND,1,1,0,d,base,off,1,1,1,0); \
539 #define M_LDRSH(d,base,off) \
541 CHECK_OFFSET(off, 0x00ff); \
543 M_MEM2(UNCOND,1,1,1,d,base,off,1,1,1,0); \
546 #define M_LDRSB(d,base,off) \
548 CHECK_OFFSET(off, 0x00ff); \
550 M_MEM2(UNCOND,1,0,1,d,base,off,1,1,1,0); \
553 #define M_STRH(d,base,off) \
555 CHECK_OFFSET(off, 0x00ff); \
557 M_MEM2(UNCOND,0,1,0,d,base,off,1,1,1,0); \
560 #define M_STRB(d,base,off) \
562 CHECK_OFFSET(off, 0x0fff); \
564 M_MEM(UNCOND,0,1,d,base,off,0,1,1,0); \
568 #define M_TRAP(a,i) M_UNDEFINED(UNCOND,i,a);
569 #define M_TRAPEQ(a,i) M_UNDEFINED(COND_EQ,i,a);
570 #define M_TRAPNE(a,i) M_UNDEFINED(COND_NE,i,a);
571 #define M_TRAPLT(a,i) M_UNDEFINED(COND_LT,i,a);
572 #define M_TRAPLE(a,i) M_UNDEFINED(COND_LE,i,a);
573 #define M_TRAPHI(a,i) M_UNDEFINED(COND_HI,i,a);
574 #define M_TRAPHS(a,i) M_UNDEFINED(COND_CS,i,a);
581 #if defined(__ARMEL__)
583 #define M_LDRD_INTERN(d,base,off) \
585 M_LDR_INTERN(GET_LOW_REG(d), base, off); \
586 M_LDR_INTERN(GET_HIGH_REG(d), base, (off) + 4); \
589 #define M_STRD_INTERN(d,base,off) \
591 M_STR_INTERN(GET_LOW_REG(d), base, off); \
592 M_STR_INTERN(GET_HIGH_REG(d), base, (off) + 4); \
595 #define M_LDRD_ALTERN(d,base,off) \
597 M_LDR_INTERN(GET_HIGH_REG(d), base, (off) + 4); \
598 M_LDR_INTERN(GET_LOW_REG(d), base, off); \
601 #define M_LDRD_UPDATE(d,base,off) \
603 assert((off) == +8); \
604 M_LDR_UPDATE(GET_LOW_REG(d), base, 4); \
605 M_LDR_UPDATE(GET_HIGH_REG(d), base, 4); \
608 #define M_STRD_UPDATE(d,base,off) \
610 assert((off) == -8); \
611 M_STR_UPDATE(GET_HIGH_REG(d), base, -4); \
612 M_STR_UPDATE(GET_LOW_REG(d), base, -4); \
615 #define GET_FIRST_REG(d) GET_LOW_REG(d)
616 #define GET_SECOND_REG(d) GET_HIGH_REG(d)
620 #define M_LDRD_INTERN(d,base,off) \
622 M_LDR_INTERN(GET_HIGH_REG(d), base, off); \
623 M_LDR_INTERN(GET_LOW_REG(d), base, (off) + 4); \
626 #define M_STRD_INTERN(d,base,off) \
628 M_STR_INTERN(GET_HIGH_REG(d), base, off); \
629 M_STR_INTERN(GET_LOW_REG(d), base, (off) + 4); \
632 #define M_LDRD_ALTERN(d,base,off) \
634 M_LDR_INTERN(GET_LOW_REG(d), base, (off) + 4); \
635 M_LDR_INTERN(GET_HIGH_REG(d), base, off); \
638 #define M_LDRD_UPDATE(d,base,off) \
640 assert((off) == +8); \
641 M_LDR_UPDATE(GET_HIGH_REG(d), base, 4); \
642 M_LDR_UPDATE(GET_LOW_REG(d), base, 4); \
645 #define M_STRD_UPDATE(d,base,off) \
647 assert((off) == -8); \
648 M_STR_UPDATE(GET_LOW_REG(d), base, -4); \
649 M_STR_UPDATE(GET_HIGH_REG(d) ,base, -4); \
652 #define GET_FIRST_REG(d) GET_HIGH_REG(d)
653 #define GET_SECOND_REG(d) GET_LOW_REG(d)
662 #if !defined(ENABLE_SOFTFLOAT)
664 #if defined(__VFP_FP__)
666 #define M_FADD(a,b,d) M_CPDPF(UNCOND,0,1,1,0,10,d,a,b)
667 #define M_FSUB(a,b,d) M_CPDPF(UNCOND,0,1,1,1,10,d,a,b)
668 #define M_FMUL(a,b,d) M_CPDPF(UNCOND,0,1,0,0,10,d,a,b)
669 #define M_FDIV(a,b,d) M_CPDPF(UNCOND,1,0,0,0,10,d,a,b)
670 #define M_DADD(a,b,d) M_CPDP(UNCOND,0,1,1,0,11,0,0,0,d,a,b)
671 #define M_DSUB(a,b,d) M_CPDP(UNCOND,0,1,1,1,11,0,0,0,d,a,b)
672 #define M_DMUL(a,b,d) M_CPDP(UNCOND,0,1,0,0,11,0,0,0,d,a,b)
673 #define M_DDIV(a,b,d) M_CPDP(UNCOND,1,0,0,0,11,0,0,0,d,a,b)
675 #define M_FMOV(a,d) M_CPDPF(UNCOND,1,1,1,1,10,d,0x0,a)
676 #define M_DMOV(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,0,0,d,0x0,a)
677 #define M_FNEG(a,d) M_CPDPF(UNCOND,1,1,1,1,10,d,0x1,a)
678 #define M_DNEG(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,0,0,d,0x1,a)
680 #define M_FCMP(a,b) M_CPDPF(UNCOND,1,1,1,1,10,a,0x4,b)
681 #define M_DCMP(a,b) M_CPDP(UNCOND,1,1,1,1,11,0,0,0,a,0x4,b)
683 #define M_CVTDF(a,d) M_CPDP(UNCOND,1,1,1,1,11,(d)>>4,1,0,(d)&0xf,0x7,a)
684 #define M_CVTFD(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x7,a)
685 #define M_CVTIF(a,d) M_CPDP(UNCOND,1,1,1,1,10,(d)>>4,1,0,(d)&0xf,0x8,a)
686 #define M_CVTID(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0x8,a)
687 #define M_CVTFI(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,(a)>>4,d,0xd,a) // ftosis
688 #define M_CVTDI(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0xd,a) // ftosid
690 #define M_FMSTAT M_CPRT(UNCOND,0x07,1,10,0,0x1,0xf)
692 #define M_FMSR(a,Fb) M_CPRT(UNCOND,0x00,0,10,0,Fb,a)
693 #define M_FMRS(Fa,b) M_CPRT(UNCOND,0x00,1,10,0,Fa,b)
694 #define M_FMDLR(a,Fb) M_CPRT(UNCOND,0x00,0,11,0,Fb,a)
695 #define M_FMRDL(Fa,b) M_CPRT(UNCOND,0x00,1,11,0,Fa,b)
696 #define M_FMDHR(a,Fb) M_CPRT(UNCOND,0x01,0,11,0,Fb,a)
697 #define M_FMRDH(Fa,b) M_CPRT(UNCOND,0x01,1,11,0,Fa,b)
701 #define M_FADD(a,b,d) M_CPDOS(UNCOND,0x00,0,d,a,b)
702 #define M_FSUB(a,b,d) M_CPDOS(UNCOND,0x02,0,d,a,b)
703 #define M_FMUL(a,b,d) M_CPDOS(UNCOND,0x01,0,d,a,b)
704 #define M_FDIV(a,b,d) M_CPDOS(UNCOND,0x04,0,d,a,b)
705 #define M_RMFS(d,a,b) M_CPDOS(UNCOND,0x08,0,d,a,b)
706 #define M_DADD(a,b,d) M_CPDOD(UNCOND,0x00,0,d,a,b)
707 #define M_DSUB(a,b,d) M_CPDOD(UNCOND,0x02,0,d,a,b)
708 #define M_DMUL(a,b,d) M_CPDOD(UNCOND,0x01,0,d,a,b)
709 #define M_DDIV(a,b,d) M_CPDOD(UNCOND,0x04,0,d,a,b)
710 #define M_RMFD(d,a,b) M_CPDOD(UNCOND,0x08,0,d,a,b)
712 #define M_FMOV(a,d) M_CPDOS(UNCOND,0x00,1,d,0,a)
713 #define M_DMOV(a,d) M_CPDOD(UNCOND,0x00,1,d,0,a)
714 #define M_FNEG(a,d) M_CPDOS(UNCOND,0x01,1,d,0,a)
715 #define M_DNEG(a,d) M_CPDOD(UNCOND,0x01,1,d,0,a)
717 #define M_FCMP(a,b) M_CPRTX(UNCOND,1,0x0f,a,b)
718 #define M_DCMP(a,b) M_CPRTX(UNCOND,1,0x0f,a,b)
720 #define M_CVTDF(a,b) M_FMOV(a,b)
721 #define M_CVTFD(a,b) M_DMOV(a,b)
722 #define M_CVTIF(a,d) M_CPRTS(UNCOND,0,a,d,0)
723 #define M_CVTID(a,d) M_CPRTD(UNCOND,0,a,d,0)
724 #define M_CVTFI(a,d) M_CPRTI(UNCOND,1,d,0,a)
725 #define M_CVTDI(a,d) M_CPRTI(UNCOND,1,d,0,a)
735 #if defined(__VFP_FP__)
737 #define M_CAST_I2F(a,Fb) M_FMSR(a,Fb)
739 #define M_CAST_F2I(Fa,b) M_FMRS(Fa,b)
741 #define M_CAST_L2D(a,Fb) \
743 M_FMDLR(GET_LOW_REG(a), Fb); \
744 M_FMDHR(GET_HIGH_REG(a), Fb); \
747 #define M_CAST_D2L(Fa,b) \
749 M_FMRDL(Fa, GET_LOW_REG(b)); \
750 M_FMRDH(Fa, GET_HIGH_REG(b)); \
755 #define M_CAST_I2F(a,Fb) \
759 M_STR_UPDATE(a, REG_SP, -4); \
760 M_FLD_UPDATE(Fb, REG_SP, 4); \
763 #define M_CAST_L2D(a,Fb) \
766 CHECK_INT_REG(GET_LOW_REG(a)); \
767 CHECK_INT_REG(GET_HIGH_REG(a)); \
768 M_STRD_UPDATE(a, REG_SP, -8); \
769 M_DLD_UPDATE(Fb, REG_SP, 8); \
772 #define M_CAST_F2I(Fa,b) \
776 M_FST_UPDATE(Fa, REG_SP, -4); \
777 M_LDR_UPDATE(b, REG_SP, 4); \
780 #define M_CAST_D2L(Fa,b) \
782 CHECK_INT_REG(GET_LOW_REG(b)); \
783 CHECK_INT_REG(GET_HIGH_REG(b)); \
784 M_DST_UPDATE(Fa, REG_SP, -8); \
785 M_LDRD_UPDATE(b, REG_SP, 8); \
794 #if defined(__VFP_FP__)
796 #define M_FLD_INTERN(d,base,off) \
798 CHECK_OFFSET(off, 0x03ff); \
799 M_CPLS(UNCOND,1,1,(((off) < 0) ? 0 : 1),0,10,(d)>>4,(d)&0xf,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \
802 #define M_DLD_INTERN(d,base,off) \
804 CHECK_OFFSET(off, 0x03ff); \
805 M_CPLS(UNCOND,1,1,(((off) < 0) ? 0 : 1),0,11,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \
808 #define M_FST_INTERN(d,base,off) \
810 CHECK_OFFSET(off, 0x03ff); \
811 M_CPLS(UNCOND,0,1,(((off) < 0) ? 0 : 1),0,10,(d)>>4,(d)&0xf,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \
814 #define M_DST_INTERN(d,base,off) \
816 CHECK_OFFSET(off, 0x03ff); \
817 M_CPLS(UNCOND,0,1,(((off) < 0) ? 0 : 1),0,11,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \
822 #define M_FLD_INTERN(d,base,off) \
824 CHECK_OFFSET(off, 0x03ff); \
825 M_CPDT(UNCOND,1,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \
828 #define M_DLD_INTERN(d,base,off) \
830 CHECK_OFFSET(off, 0x03ff); \
831 M_CPDT(UNCOND,1,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \
834 #define M_FST_INTERN(d,base,off) \
836 CHECK_OFFSET(off, 0x03ff); \
837 M_CPDT(UNCOND,0,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \
840 #define M_DST_INTERN(d,base,off) \
842 CHECK_OFFSET(off, 0x03ff); \
843 M_CPDT(UNCOND,0,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \
846 #define M_FLD_UPDATE(d,base,off) \
848 CHECK_OFFSET(off, 0x03ff); \
849 M_CPDT(UNCOND,1,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),0,(((off) < 0) ? 0 : 1),1); \
852 #define M_DLD_UPDATE(d,base,off) \
854 CHECK_OFFSET(off, 0x03ff); \
855 M_CPDT(UNCOND,1,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),0,(((off) < 0) ? 0 : 1),1); \
858 #define M_FST_UPDATE(d,base,off) \
860 CHECK_OFFSET(off, 0x03ff); \
861 M_CPDT(UNCOND,0,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),1); \
864 #define M_DST_UPDATE(d,base,off) \
866 CHECK_OFFSET(off, 0x03ff); \
867 M_CPDT(UNCOND,0,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),1); \
891 #define M_LDR(d, base, offset) \
893 CHECK_OFFSET(offset, 0x0fffff); \
894 if (IS_OFFSET(offset, 0x000fff)) { \
895 M_LDR_INTERN(d, base, offset); \
898 assert((d) != REG_PC); \
899 if ((offset) > 0) { \
900 M_ADD_IMM(d, base, IMM_ROTL((offset) >> 12, 6)); \
901 M_LDR_INTERN(d, d, (offset) & 0x000fff); \
903 M_SUB_IMM(d, base, IMM_ROTL((-(offset)) >> 12, 6)); \
904 M_LDR_INTERN(d, d, -(-(offset) & 0x000fff)); \
909 #define M_LDR_NEGATIVE(d, base, offset) { \
911 if (IS_OFFSET(offset, 0x000fff)) { \
912 M_LDR_INTERN(d, base, offset); \
915 assert((d) != REG_PC); \
916 M_SUB_IMM(d, base, IMM_ROTL((-(offset)) >> 12, 6)); \
917 M_LDR_INTERN(d, d, -(-(offset) & 0x000fff)); \
921 #define M_LDRD(d, base, offset) \
923 CHECK_OFFSET(offset, 0x0fffff - 4); \
924 if (IS_OFFSET(offset, 0x000fff - 4)) { \
925 if (GET_FIRST_REG(d) != (base)) { \
926 M_LDRD_INTERN(d, base, offset); \
928 M_LDRD_ALTERN(d, base, offset); \
930 } else if (IS_OFFSET(offset, 0x000fff)) { \
931 dolog("M_LDRD: this offset seems to be complicated (%d)", offset); \
934 if ((offset) > 0) { \
935 M_ADD_IMM(GET_SECOND_REG(d), base, IMM_ROTL((offset) >> 12, 6)); \
936 M_LDRD_INTERN(d, GET_SECOND_REG(d), (offset) & 0x000fff); \
938 M_SUB_IMM(GET_SECOND_REG(d), base, IMM_ROTL((-(offset)) >> 12, 6)); \
939 M_LDRD_INTERN(d, GET_SECOND_REG(d), -(-(offset) & 0x000fff)); \
944 #if !defined(ENABLE_SOFTFLOAT)
946 #define M_LDFS(d, base, offset) \
948 CHECK_OFFSET(offset, 0x03ffff); \
949 if (IS_OFFSET(offset, 0x03ff)) { \
950 M_FLD_INTERN(d, base, offset); \
952 if ((offset) > 0) { \
953 M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \
954 M_FLD_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \
956 M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \
957 M_FLD_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \
962 #define M_LDFD(d, base, offset) \
964 CHECK_OFFSET(offset, 0x03ffff); \
965 if (IS_OFFSET(offset, 0x03ff)) { \
966 M_DLD_INTERN(d, base, offset); \
968 if ((offset) > 0) { \
969 M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \
970 M_DLD_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \
972 M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \
973 M_DLD_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \
980 #define M_STR(d, base, offset) \
982 CHECK_OFFSET(offset, 0x0fffff); \
983 if (IS_OFFSET(offset, 0x000fff)) { \
984 M_STR_INTERN(d, base, offset); \
986 assert((d) != REG_ITMP3); \
987 if ((offset) > 0) { \
988 M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 12, 6)); \
989 M_STR_INTERN(d, REG_ITMP3, (offset) & 0x000fff); \
991 M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 12, 6)); \
992 M_STR_INTERN(d, REG_ITMP3, -(-(offset) & 0x000fff)); \
997 #define M_STRD(d, base, offset) \
999 CHECK_OFFSET(offset, 0x0fffff - 4); \
1000 if (IS_OFFSET(offset, 0x000fff - 4)) { \
1001 M_STRD_INTERN(d,base,offset); \
1002 } else if (IS_OFFSET(offset, 0x000fff)) { \
1003 dolog("M_STRD: this offset seems to be complicated (%d)", offset); \
1006 assert(GET_LOW_REG(d) != REG_ITMP3); \
1007 assert(GET_HIGH_REG(d) != REG_ITMP3); \
1008 if ((offset) > 0) { \
1009 M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 12, 6)); \
1010 M_STRD_INTERN(d, REG_ITMP3, (offset) & 0x000fff); \
1012 M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 12, 6)); \
1013 M_STRD_INTERN(d, REG_ITMP3, -(-(offset) & 0x000fff)); \
1018 #if !defined(ENABLE_SOFTFLOAT)
1020 #define M_STFS(d, base, offset) \
1022 CHECK_OFFSET(offset, 0x03ffff); \
1023 if (IS_OFFSET(offset, 0x03ff)) { \
1024 M_FST_INTERN(d, base, offset); \
1026 if ((offset) > 0) { \
1027 M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \
1028 M_FST_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \
1030 M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \
1031 M_FST_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \
1036 #define M_STFD(d, base, offset) \
1038 CHECK_OFFSET(offset, 0x03ffff); \
1039 if (IS_OFFSET(offset, 0x03ff)) { \
1040 M_DST_INTERN(d, base, offset); \
1042 if ((offset) > 0) { \
1043 M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \
1044 M_DST_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \
1046 M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \
1047 M_DST_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \
1064 #define M_ADD_IMM_EXT_MUL4(d,n,imm) \
1066 assert(d != REG_PC); \
1067 assert((imm) >= 0 && (imm) <= 0x00ffffff); \
1068 M_ADD_IMM(d, n, IMM_ROTL(imm, 1)); \
1069 if ((imm) > 0x000000ff) M_ADD_IMM(d, d, IMM_ROTL((imm) >> 8, 5)); \
1070 if ((imm) > 0x0000ffff) M_ADD_IMM(d, d, IMM_ROTL((imm) >> 16, 9)); \
1073 #define M_SUB_IMM_EXT_MUL4(d,n,imm) \
1075 assert(d != REG_PC); \
1076 assert((imm) >= 0 && (imm) <= 0x00ffffff); \
1077 M_SUB_IMM(d, n, IMM_ROTL(imm, 1)); \
1078 if ((imm) > 0x000000ff) M_SUB_IMM(d, d, IMM_ROTL((imm) >> 8, 5)); \
1079 if ((imm) > 0x0000ffff) M_SUB_IMM(d, d, IMM_ROTL((imm) >> 16, 9)); \
1087 #define ICONST(d,c) emit_iconst(cd, (d), (c))
1089 #define LCONST(d,c) \
1090 if (IS_IMM((c) >> 32)) { \
1091 M_MOV_IMM(GET_HIGH_REG(d), (s4) ((s8) (c) >> 32)); \
1092 ICONST(GET_LOW_REG(d), (s4) ((s8) (c) & 0xffffffff)); \
1093 } else if (IS_IMM((c) & 0xffffffff)) { \
1094 M_MOV_IMM(GET_LOW_REG(d), (s4) ((s8) (c) & 0xffffffff)); \
1095 ICONST(GET_HIGH_REG(d), (s4) ((s8) (c) >> 32)); \
1097 disp = dseg_add_s8(cd, (c)); \
1098 M_LDRD(d, REG_PV, disp); \
1102 #if !defined(ENABLE_SOFTFLOAT)
1104 #define FCONST(d,c) \
1106 disp = dseg_add_float(cd, (c)); \
1107 M_LDFS(d, REG_PV, disp); \
1110 #define DCONST(d,c) \
1112 disp = dseg_add_double(cd, (c)); \
1113 M_LDFD(d, REG_PV, disp); \
1123 #define M_LONGBRANCH(adr) \
1124 M_ADD_IMM(REG_LR, REG_PC, 4); \
1125 M_LDR_INTERN(REG_PC, REG_PC, -4); \
1133 #define M_DSEG_LOAD(reg, offset) \
1134 M_LDR_NEGATIVE(reg, REG_PV, offset)
1136 #define M_DSEG_BRANCH(offset) \
1137 if (IS_OFFSET(offset, 0x0fff)) { \
1138 M_MOV(REG_LR, REG_PC); \
1139 M_LDR_INTERN(REG_PC, REG_PV, offset); \
1142 CHECK_OFFSET(offset,0x0fffff); \
1143 M_SUB_IMM(REG_ITMP3, REG_PV, ((-(offset) >> 12) & 0xff) | (((10) & 0x0f) << 8)); \
1144 M_MOV(REG_LR, REG_PC); \
1145 M_LDR_INTERN(REG_PC, REG_ITMP3, -(-(offset) & 0x0fff)); \
1149 #define M_ILD(a,b,c) M_LDR(a,b,c)
1150 #define M_LLD(a,b,c) M_LDRD(a,b,c)
1152 #define M_ILD_INTERN(a,b,c) M_LDR_INTERN(a,b,c)
1153 #define M_LLD_INTERN(a,b,c) M_LDRD_INTERN(a,b,c)
1155 #define M_ALD(a,b,c) M_ILD(a,b,c)
1156 #define M_ALD_INTERN(a,b,c) M_ILD_INTERN(a,b,c)
1157 #define M_ALD_DSEG(a,c) M_DSEG_LOAD(a,c)
1160 #define M_IST(a,b,c) M_STR(a,b,c)
1161 #define M_LST(a,b,c) M_STRD(a,b,c)
1163 #define M_IST_INTERN(a,b,c) M_STR_INTERN(a,b,c)
1164 #define M_LST_INTERN(a,b,c) M_STRD_INTERN(a,b,c)
1166 #define M_AST(a,b,c) M_IST(a,b,c)
1167 #define M_AST_INTERN(a,b,c) M_IST_INTERN(a,b,c)
1170 #define M_ACMP(a,b) M_CMP(a,b)
1171 #define M_ICMP(a,b) M_CMP(a,b)
1174 #define M_TEST(a) M_TEQ_IMM(a, 0);
1177 #if !defined(ENABLE_SOFTFLOAT)
1179 #define M_FLD(a,b,c) M_LDFS(a,b,c)
1180 #define M_DLD(a,b,c) M_LDFD(a,b,c)
1182 #define M_FST(a,b,c) M_STFS(a,b,c)
1183 #define M_DST(a,b,c) M_STFD(a,b,c)
1187 #define M_FMOV(s,d) M_MOV((d), (s))
1188 #define M_DMOV(s,d) \
1190 M_MOV(GET_LOW_REG(d), GET_LOW_REG(s)); \
1191 M_MOV(GET_HIGH_REG(d), GET_HIGH_REG(s)); \
1197 #endif // CODEGEN_HPP_
void asm_debug(int a1, int a2, int a3, int a4)
void asm_debug_intern(int a1, int a2, int a3, int a4)