📄 em86real.s
字号:
li r3,SP lhbrx r4,state,r3 addi r4,r4,-4 sthbrx r4,state,r3 clrlwi r4,r4,16 stwbrx r0,r4,ssb NEXT /* pop is an exception with 32 bit addressing modes, it is possibleto calculate wrongly the address when esp is used as base. But 16 bitaddressing modes are safe */ popw_sp_a16: cmpw cr1,opreg,0 # first check the opcode li r3,SP lhbrx r4,state,r3 bne- cr1,ud lhzx r0,ssb,r4 addi r4,r4,2 sthx r0,MEM sthbrx r4,state,r3 NEXT popl_sp_a16: cmpw cr1,opreg,0 li r3,SP lhbrx r4,state,r3 bne- cr1,ud lwzx r0,ssb,r4 addi r4,r4,2 stwx r0,MEM sthbrx r4,state,r3 NEXT/* 32 bit addressing modes for pop not implemented for now. */ .equ popw_sp_a32,unimpl .equ popl_sp_a32,unimpl/* pusha/popa */pushaw_sp: li r3,SP li r0,8 lhbrx r4,r3,state mtctr r0 addi r5,state,-41: addi r4,r4,-2 lhzu r6,4(r5) clrlwi r4,r4,16 sthx r6,ssb,r4 bdnz 1b sthbrx r4,r3,state # new sp NEXTpushal_sp: li r3,SP li r0,8 lhbrx r4,r3,state mtctr r0 addi r5,state,-41: addi r4,r4,-4 lwzu r6,4(r5) clrlwi r4,r4,16 stwx r6,ssb,r4 bdnz 1b sthbrx r4,r3,state # new sp NEXTpopaw_sp: li r3,SP li r0,8 lhbrx r4,state,r3 mtctr r0 addi r5,state,321: lhzx r6,ssb,r4 addi r4,r4,2 sthu r6,-4(r5) clrlwi r4,r4,16 bdnz 1b sthbrx r4,r3,state # updated sp NEXT popal_sp: li r3,SP lis r0,0xef00 # mask to skip esp lhbrx r4,state,r3 addi r5,state,321: add. r0,r0,r0 lwzx r6,ssb,r4 addi r4,r4,4 stwu r6,-4(r5) clrlwi r4,r4,16 blt 1b addi r6,r6,-4 beq 2f addi r4,r4,4 clrlwi r4,r4,16 b 1b2: sthbrx r4,state,r3 # updated sp NEXT/* Moves with zero or sign extension: first the special cases */ cbw: lbz r3,AL(state) extsb r3,r3 sthbrx r3,AX,state NEXT cwde: lhbrx r3,AX,state extsh r3,r3 stwbrx r3,EAX,state NEXTcwd: lbz r3,AH(state) extsb r3,r3 srwi r3,r3,8 # get sign bits sth r3,DX(state) NEXTcdq: lwbrx r3,EAX,state srawi r3,r3,31 stw r3,EDX(state) # byte order unimportant ! NEXT/* The move with zero or sign extension are special since the sourceand destination are not the same size. The register describing the destinationis modified to take this into account. */movsbw: lbzx r3,MEM rlwimi opreg,opreg,4,0x10 extsb r3,r3 rlwinm opreg,opreg,0,0x1c sthbrx r3,REG NEXTmovsbl: lbzx r3,MEM rlwimi opreg,opreg,4,0x10 extsb r3,r3 rlwinm opreg,opreg,0,0x1c stwbrx r3,REG NEXT .equ movsww, movw_mem_reg movswl: lhbrx r3,MEM extsh r3,r3 stwbrx r3,REG NEXT movzbw: lbzx r3,MEM rlwimi opreg,opreg,4,0x10 rlwinm opreg,opreg,0,0x1c sthbrx r3,REG NEXTmovzbl: lbzx r3,MEM rlwimi opreg,opreg,4,0x10 rlwinm opreg,opreg,0,0x1c stwbrx r3,REG NEXT .equ movzww, movw_mem_regmovzwl: lhbrx r3,MEM stwbrx r3,REG NEXT/* Byte swapping */ bswap: clrlslwi opreg,opcode,29,2 # extract reg from opcode lwbrx r0,REG stwx r0,REG NEXT /* Input/output */inb_port_al: NEXTBYTE(r4) b 1finb_dx_al: li r4,DX lhbrx r4,r4,state1: li r3,code_inb bl _check_port lwz r3,iobase(state) lbzx r5,r4,r3 eieio stb r5,AL(state) NEXT inw_port_ax: NEXTBYTE(r4) b 1finw_dx_ax: li r4,DX lhbrx r4,r4,state1: li r3,code_inw bl _check_port lwz r3,iobase(state) lhzx r5,r4,r3 eieio sth r5,AX(state) NEXT inl_port_eax: NEXTBYTE(r4) b 1finl_dx_eax: li r4,DX lhbrx r4,r4,state1: li r3,code_inl bl _check_port lwz r3,iobase(state) lwzx r5,r4,r3 eieio stw r5,EAX(state) NEXT outb_al_port: NEXTBYTE(r4) b 1foutb_al_dx: li r4,DX lhbrx r4,r4,state1: li r3,code_outb bl _check_port lwz r3,iobase(state) lbz r5,AL(state) stbx r5,r4,r3 eieio NEXT outw_ax_port: NEXTBYTE(r4) b 1foutw_ax_dx: li r4,DX lhbrx r4,r4,state1: li r3,code_outw bl _check_port lwz r3,iobase(state) lhz r5,AX(state) sthx r5,r4,r3 eieio NEXT outl_eax_port: NEXTBYTE(r4) b 1foutl_eax_dx: li r4,DX lhbrx r4,r4,state1: li r3,code_outl bl _check_port lwz r4,iobase(state) lwz r5,EAX(state) stwx r5,r4,r3 eieio NEXT/* Macro used for add and sub */#define ARITH(op,fl) \op##b_reg_mem: lbzx op1,MEM; SET_FLAGS(fl(B)); lbzx op2,REG; \ op result,op1,op2; \ stbx result,MEM; NEXT; \op##w_reg_mem: lhbrx op1,MEM; SET_FLAGS(fl(W)); lhbrx op2,REG; \ op result,op1,op2; \ sthbrx result,MEM; NEXT; \op##l_reg_mem: lwbrx op1,MEM; SET_FLAGS(fl(L)); lwbrx op2,REG; \ op result,op1,op2; \ stwbrx result,MEM; NEXT; \op##b_mem_reg: lbzx op2,MEM; SET_FLAGS(fl(B)); lbzx op1,REG; \ op result,op1,op2; \ stbx result,REG; NEXT; \op##w_mem_reg: lhbrx op2,MEM; SET_FLAGS(fl(W)); lhbrx op1,REG; \ op result,op1,op2; \ sthbrx result,REG; NEXT; \op##l_mem_reg: lwbrx op2,MEM; SET_FLAGS(fl(L)); lwbrx op1,REG; \ op result,op1,op2; \ stwbrx result,REG; NEXT; \op##b_imm_al: addi base,state,0; li offset,AL; \op##b_imm: lbzx op1,MEM; SET_FLAGS(fl(B)); lbz op2,1(eip); \ op result,op1,op2; \ lbzu opcode,2(eip); \ stbx result,MEM; GOTNEXT; \op##w_imm_ax: addi base,state,0; li offset,AX; \op##w_imm: lhbrx op1,MEM; SET_FLAGS(fl(W)); lhbrx op2,eip,one; \ op result,op1,op2; \ lbzu opcode,3(eip); \ sthbrx result,MEM; GOTNEXT; \op##w_imm8: lbz op2,1(eip); SET_FLAGS(fl(W)); lhbrx op1,MEM; \ extsb op2,op2; clrlwi op2,op2,16; \ op result,op1,op2; \ lbzu opcode,2(eip); \ sthbrx result,MEM; GOTNEXT; \op##l_imm_eax: addi base,state,0; li offset,EAX; \op##l_imm: lwbrx op1,MEM; SET_FLAGS(fl(L)); lwbrx op2,eip,one; \ op result,op1,op2; lbzu opcode,5(eip); \ stwbrx result,MEM; GOTNEXT; \op##l_imm8: lbz op2,1(eip); SET_FLAGS(fl(L)); lwbrx op1,MEM; \ extsb op2,op2; lbzu opcode,2(eip); \ op result,op1,op2; \ stwbrx result,MEM; GOTNEXT ARITH(add, FLAGS_ADD) ARITH(sub, FLAGS_SUB)#define adc(result, op1, op2) adde result,op1,op2#define sbb(result, op1, op2) subfe result,op2,op1#define ARITH_WITH_CARRY(op, fl) \op##b_reg_mem: lbzx op1,MEM; bl carryfor##op; lbzx op2,REG; \ ADD_FLAGS(fl(B)); op(result, op1, op2); \ stbx result,MEM; NEXT; \op##w_reg_mem: lhbrx op1,MEM; bl carryfor##op; lhbrx op2,REG; \ ADD_FLAGS(fl(W)); op(result, op1, op2); \ sthbrx result,MEM; NEXT; \op##l_reg_mem: lwbrx op1,MEM; bl carryfor##op; lwbrx op2,REG; \ ADD_FLAGS(fl(L)); op(result, op1, op2); \ stwbrx result,MEM; NEXT; \op##b_mem_reg: lbzx op1,MEM; bl carryfor##op; lbzx op2,REG; \ ADD_FLAGS(fl(B)); op(result, op1, op2); \ stbx result,REG; NEXT; \op##w_mem_reg: lhbrx op1,MEM; bl carryfor##op; lhbrx op2,REG; \ ADD_FLAGS(fl(W)); op(result, op1, op2); \ sthbrx result,REG; NEXT; \op##l_mem_reg: lwbrx op1,MEM; bl carryfor##op; lwbrx op2,REG; \ ADD_FLAGS(fl(L)); op(result, op1, op2); \ stwbrx result,REG; NEXT; \op##b_imm_al: addi base,state,0; li offset,AL; \op##b_imm: lbzx op1,MEM; bl carryfor##op; lbz op2,1(eip); \ ADD_FLAGS(fl(B)); lbzu opcode,2(eip); op(result, op1, op2); \ stbx result,MEM; GOTNEXT; \op##w_imm_ax: addi base,state,0; li offset,AX; \op##w_imm: lhbrx op1,MEM; bl carryfor##op; lhbrx op2,eip,one; \ ADD_FLAGS(fl(W)); lbzu opcode,3(eip); op(result, op1, op2); \ sthbrx result,MEM; GOTNEXT; \op##w_imm8: lbz op2,1(eip); bl carryfor##op; lhbrx op1,MEM; \ extsb op2,op2; ADD_FLAGS(fl(W)); clrlwi op2,op2,16; \ lbzu opcode,2(eip); op(result, op1, op2); \ sthbrx result,MEM; GOTNEXT; \op##l_imm_eax: addi base,state,0; li offset,EAX; \op##l_imm: lwbrx op1,MEM; bl carryfor##op; lwbrx op2,eip,one; \ ADD_FLAGS(fl(L)); lbzu opcode,5(eip); op(result, op1, op2); \ stwbrx result,MEM; GOTNEXT; \op##l_imm8: lbz op2,1(eip); SET_FLAGS(fl(L)); lwbrx op1,MEM; \ extsb op2,op2; lbzu opcode,2(eip); \ op(result, op1, op2); \ stwbrx result,MEM; GOTNEXTcarryforadc: addc r3,flags,flags # CF_IN to xer[ca] RES2CF(r4) # get 8 or 16 bit carry subfe r3,result,op1 # generate PPC carry for CF_ROTCNT(r5) # preceding operation addze r3,r4 # 32 bit carry in LSB CF_POL(r4,23) # polarity rlwnm r3,r3,r5,0x100 # shift carry there xor flags,r4,r3 # CF86 ? 0x100 : 0 addic r4,r3,0xffffff00 # set xer[ca] rlwinm flags,r3,23,CF_IN blr ARITH_WITH_CARRY(adc, FLAGS_ADD) /* for sbb the input carry must be the complement of the x86 carry */carryforsbb: addc r3,flags,flags # CF_IN to xer[ca] RES2CF(r4) # 8/16 bit carry from result subfe r3,result,op1 CF_ROTCNT(r5) addze r3,r4 CF_POL(r4,23) rlwnm r3,r3,r5,0x100 eqv flags,r4,r3 # CF86 ? 0xfffffeff:0xffffffff addic r4,r3,1 # set xer[ca] rlwinm flags,r3,23,CF_IN # keep only the carry blr ARITH_WITH_CARRY(sbb, FLAGS_SBB)cmpb_reg_mem: lbzx op1,MEM SET_FLAGS(FLAGS_CMP(B)) lbzx op2,REG extsb r3,op1 cmplw cr4,op1,op2 extsb r4,op2 sub result,op1,op2 cmpw cr6,r3,r4 NEXTcmpw_reg_mem: lhbrx op1,MEM SET_FLAGS(FLAGS_CMP(W)) lhbrx op2,REG extsh r3,op1 cmplw cr4,op1,op2 extsh r4,op2 sub result,op1,op2 cmpw cr6,r3,r4 NEXTcmpl_reg_mem: lwbrx op1,MEM SET_FLAGS(FLAGS_CMP(L)) lwbrx op2,REG cmplw cr4,op1,op2 sub result,op1,op2 cmpw cr6,op1,op2 NEXTcmpb_mem_reg: lbzx op2,MEM SET_FLAGS(FLAGS_CMP(B)) lbzx op1,REG extsb r4,op2 cmplw cr4,op1,op2 extsb r3,op1 sub result,op1,op2 cmpw cr6,r3,r4 NEXTcmpw_mem_reg: lhbrx op2,MEM SET_FLAGS(FLAGS_CMP(W)) lhbrx op1,REG extsh r4,op2 cmplw cr4,op1,op2 extsh r3,op1 sub result,op1,op2 cmpw cr6,r3,r4 NEXTcmpl_mem_reg: lwbrx op2,MEM SET_FLAGS(FLAGS_CMP(L)) lwbrx op1,REG cmpw cr6,op1,op2 sub result,op1,op2 cmplw cr4,op1,op2 NEXTcmpb_imm_al: addi base,state,0 li offset,ALcmpb_imm: lbzx op1,MEM SET_FLAGS(FLAGS_CMP(B)) lbz op2,1(eip) extsb r3,op1 cmplw cr4,op1,op2 lbzu opcode,2(eip) extsb r4,op2 sub result,op1,op2 cmpw cr6,r3,r4 GOTNEXTcmpw_imm_ax: addi base,state,0 li offset,AXcmpw_imm: lhbrx op1,MEM SET_FLAGS(FLAGS_CMP(W)) lhbrx op2,eip,one extsh r3,op1 cmplw cr4,op1,op2 lbzu opcode,3(eip) extsh r4,op2 sub result,op1,op2 cmpw cr6,r3,r4 GOTNEXTcmpw_imm8: lbz op2,1(eip) SET_FLAGS(FLAGS_CMP(W)) lhbrx op1,MEM extsb r4,op2 extsh r3,op1 lbzu opcode,2(eip) clrlwi op2,r4,16 cmpw cr6,r3,r4 sub result,op1,op2 cmplw cr4,op1,op2 GOTNEXT cmpl_imm_eax: addi base,state,0 li offset,EAXcmpl_imm: lwbrx op1,MEM SET_FLAGS(FLAGS_CMP(L)) lwbrx op2,eip,one cmpw cr6,op1,op2 lbzu opcode,5(eip) sub result,op1,op2 cmplw cr4,op1,op2 GOTNEXTcmpl_imm8: lbz op2,1(eip) SET_FLAGS(FLAGS_CMP(L)) lwbrx op1,MEM extsb op2,op2 lbzu opcode,2(eip) cmpw cr6,op1,op2 sub result,op1,op2 cmplw cr4,op1,op2 GOTNEXT/* Increment and decrement */incb: lbzx op2,MEM INC_FLAGS(B) addi op2,op2,1 stbx op2,MEM NEXTincw_reg: clrlslwi opreg,opcode,29,2 # extract reg from opcode lhbrx op2,REG INC_FLAGS(W) addi op2,op2,1 sthbrx op2,REG NEXTincw: lhbrx op2,MEM INC_FLAGS(W) addi op2,op2,1 sthbrx op2,MEM NEXTincl_reg: clrlslwi opreg,opcode,29,2 lwbrx op2,REG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -