📄 em86real.s
字号:
INC_FLAGS(L) addi op2,op2,1 sthbrx op2,REG NEXTincl: lwbrx op2,MEM INC_FLAGS(L) addi op2,op2,1 stwbrx op2,MEM NEXTdecb: lbzx op2,MEM DEC_FLAGS(B) addi op2,op2,-1 stbx op2,MEM NEXTdecw_reg: clrlslwi opreg,opcode,29,2 # extract reg from opcode lhbrx op2,REG DEC_FLAGS(W) addi op2,op2,-1 sthbrx op2,REG NEXTdecw: lhbrx op2,MEM DEC_FLAGS(W) addi op2,op2,-1 sthbrx op2,MEM NEXTdecl_reg: clrlslwi opreg,opcode,29,2 lwbrx op2,REG DEC_FLAGS(L) addi op2,op2,-1 sthbrx op2,REG NEXTdecl: lwbrx op2,MEM DEC_FLAGS(L) addi op2,op2,-1 stwbrx op2,MEM NEXTnegb: lbzx op2,MEM SET_FLAGS(FLAGS_SUB(B)) neg result,op2 li op1,0 stbx result,MEM NEXTnegw: lhbrx op2,MEM SET_FLAGS(FLAGS_SUB(W)) neg result,op2 li op1,0 sthbrx r0,MEM NEXTnegl: lwbrx op2,MEM SET_FLAGS(FLAGS_SUB(L)) subfic result,op2,0 li op1,0 stwbrx result,MEM NEXT/* Macro used to generate code for OR/AND/XOR */#define LOGICAL(op) \op##b_reg_mem: lbzx op1,MEM; SET_FLAGS(FLAGS_LOG(B)); lbzx op2,REG; \ op result,op1,op2; \ stbx result,MEM; NEXT; \op##w_reg_mem: lhbrx op1,MEM; SET_FLAGS(FLAGS_LOG(W)); lhbrx op2,REG; \ op result,op1,op2; \ sthbrx result,MEM; NEXT; \op##l_reg_mem: lwbrx op1,MEM; SET_FLAGS(FLAGS_LOG(L)); lwbrx op2,REG; \ op result,op1,op2; \ stwbrx result,MEM; NEXT; \op##b_mem_reg: lbzx op1,MEM; SET_FLAGS(FLAGS_LOG(B)); lbzx op2,REG; \ op result,op1,op2; \ stbx result,REG; NEXT; \op##w_mem_reg: lhbrx op2,MEM; SET_FLAGS(FLAGS_LOG(W)); lhbrx op1,REG; \ op result,op1,op2; \ sthbrx result,REG; NEXT; \op##l_mem_reg: lwbrx op2,MEM; SET_FLAGS(FLAGS_LOG(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(FLAGS_LOG(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(FLAGS_LOG(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(FLAGS_LOG(W)); lhbrx op1,MEM; \ extsb op2,op2; 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; SET_FLAGS(FLAGS_LOG(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(FLAGS_LOG(L)); lwbrx op1,MEM; \ extsb op2,op2; lbzu opcode,2(eip); \ op result,op1,op2; \ stwbrx result,MEM; GOTNEXT LOGICAL(or) LOGICAL(and) LOGICAL(xor)testb_reg_mem: lbzx op1,MEM SET_FLAGS(FLAGS_TEST(B)) lbzx op2,REG and result,op1,op2 extsb r3,result cmpwi cr6,r3,0 NEXTtestw_reg_mem: lhbrx op1,MEM SET_FLAGS(FLAGS_TEST(W)) lhbrx op2,REG and result,op1,op2 extsh r3,result cmpwi cr6,r3,0 NEXTtestl_reg_mem: lwbrx r3,MEM SET_FLAGS(FLAGS_TEST(L)) lwbrx r4,REG and result,op1,op2 cmpwi cr6,result,0 NEXTtestb_imm_al: addi base,state,0 li offset,ALtestb_imm: lbzx op1,MEM SET_FLAGS(FLAGS_TEST(B)) lbz op2,1(eip) and result,op1,op2 lbzu opcode,2(eip) extsb r3,result cmpwi cr6,r3,0 GOTNEXTtestw_imm_ax: addi base,state,0 li offset,AXtestw_imm: lhbrx op1,MEM SET_FLAGS(FLAGS_TEST(W)) lhbrx op2,eip,one and result,op1,op2 lbzu opcode,3(eip) extsh r3,result cmpwi cr6,r3,0 GOTNEXTtestl_imm_eax: addi base,state,0 li offset,EAXtestl_imm: lwbrx op1,MEM SET_FLAGS(FLAGS_TEST(L)) lwbrx op2,eip,one and result,r3,r4 lbzu opcode,5(eip) cmpwi cr6,result,0 GOTNEXT/* Not does not affect flags */notb: lbzx r3,MEM xori r3,r3,255 stbx r3,MEM NEXT notw: lhzx r3,MEM xori r3,r3,65535 sthx r3,MEM NEXT notl: lwzx r3,MEM not r3,r3 stwx r3,MEM NEXT boundw: lhbrx r4,REG li r3,code_bound lhbrx r5,MEM addi offset,offset,2 extsh r4,r4 lhbrx r6,MEM extsh r5,r5 cmpw r4,r5 extsh r6,r6 blt- complex cmpw r4,r6 ble+ nop b complex boundl: lwbrx r4,REG li r3,code_bound lwbrx r5,MEM addi offset,offset,4 lwbrx r6,MEM cmpw r4,r5 blt- complex cmpw r4,r6 ble+ nop b complex/* Bit test and modify instructions */ /* Common routine: bit index in op2, returns memory value in r3, mask in op2, and of mask and value in op1. CF flag is set as with 32 bit add when bit is non zero since result (which is cleared) will be less than op1, and in cr4, all other flags are undefined from Intel doc. Here OF and SF are clearedand ZF is set as a side effect of result being cleared. */_setup_bitw: cmpw base,state SET_FLAGS(FLAGS_BTEST) extsh op2,op2 beq- 1f srawi r4,op2,4 add offset,offset,r41: clrlwi op2,op2,28 # true bit index lhbrx r3,MEM slw op2,one,op2 # build mask li result,0 # implicitly sets CF and op1,r3,op2 # if result<op1 cmplw cr4,result,op1 # sets CF in cr4 blr _setup_bitl: cmpw base,state SET_FLAGS(FLAGS_BTEST) beq- 1f srawi r4,op2,5 add offset,offset,r41: lwbrx r3,MEM rotlw op2,one,op2 # build mask li result,0 and op1,r3,op2 cmplw cr4,result,op1 blr /* Immediate forms bit tests are not frequent since logical are often faster */btw_imm: NEXTBYTE(op2) b 1fbtw_reg_mem: lhbrx op2,REG1: bl _setup_bitw NEXT btl_imm: NEXTBYTE(op2) b 1fbtl_reg_mem: lhbrx op2,REG1: bl _setup_bitl NEXTbtcw_imm: NEXTBYTE(op2) b 1fbtcw_reg_mem: lhbrx op2,REG1: bl _setup_bitw xor r3,r3,op2 sthbrx r3,MEM NEXT btcl_imm: NEXTBYTE(op2) b 1fbtcl_reg_mem: lhbrx op2,REG1: bl _setup_bitl xor r3,r3,op2 stwbrx result,MEM NEXT btrw_imm: NEXTBYTE(op2) b 1fbtrw_reg_mem: lhbrx op2,REG1: bl _setup_bitw andc r3,r3,op2 sthbrx r3,MEM NEXT btrl_imm: NEXTBYTE(op2) b 1fbtrl_reg_mem: lhbrx op2,REG1: bl _setup_bitl andc r3,r3,op2 stwbrx r3,MEM NEXT btsw_imm: NEXTBYTE(op2) b 1fbtsw_reg_mem: lhbrx op2,REG1: bl _setup_bitw or r3,r3,op2 sthbrx r3,MEM NEXT btsl_imm: NEXTBYTE(op2) b 1fbtsl_reg_mem: lhbrx op2,REG1: bl _setup_bitl or r3,r3,op2 stwbrx r3,MEM NEXT/* Bit string search instructions, only ZF is defined after these, and theresult value is not defined when the bit field is zero. */bsfw: lhbrx result,MEM SET_FLAGS(FLAGS_BSRCH(W)) neg r3,result cmpwi cr6,result,0 # sets ZF and r3,r3,result # keep only LSB cntlzw r3,r3 subfic r3,r3,31 sthbrx r3,REG NEXTbsfl: lwbrx result,MEM SET_FLAGS(FLAGS_BSRCH(L)) neg r3,result cmpwi cr6,result,0 # sets ZF and r3,r3,result # keep only LSB cntlzw r3,r3 subfic r3,r3,31 stwbrx r3,REG NEXTbsrw: lhbrx result,MEM SET_FLAGS(FLAGS_BSRCH(W)) cntlzw r3,result cmpwi cr6,result,0 subfic r3,r3,31 sthbrx r3,REG NEXTbsrl: lwbrx result,MEM SET_FLAGS(FLAGS_BSRCH(L)) cntlzw r3,result cmpwi cr6,result,0 subfic r3,r3,31 stwbrx r3,REG NEXT/* Unconditional jumps, first the indirect than relative */jmpw: lhbrx eip,MEM lbzux opcode,eip,csb GOTNEXTjmpl: lwbrx eip,MEM lbzux opcode,eip,csb GOTNEXTsjmp_w: lbz r3,1(eip) sub eip,eip,csb addi eip,eip,2 # EIP after instruction extsb r3,r3 add eip,eip,r3 clrlwi eip,eip,16 # module 64k lbzux opcode,eip,csb GOTNEXTjmp_w: lhbrx r3,eip,one # eip now off by 3 sub eip,eip,csb addi r3,r3,3 # compensate add eip,eip,r3 clrlwi eip,eip,16 lbzux opcode,eip,csb GOTNEXTsjmp_l: lbz r3,1(eip) addi eip,eip,2 extsb r3,r3 lbzux opcode,eip,r3 GOTNEXTjmp_l: lwbrx r3,eip,one # Simple addi eip,eip,5 lbzux opcode,eip,r3 GOTNEXT /* The conditional jumps: although it should not happen, byte relative jumps (sjmp) may wrap around in 16 bit mode */ #define NOTTAKEN_S lbzu opcode,2(eip); GOTNEXT#define NOTTAKEN_W lbzu opcode,3(eip); GOTNEXT#define NOTTAKEN_L lbzu opcode,5(eip); GOTNEXT#define CONDJMP(cond, eval, flag) \sj##cond##_w: EVAL_##eval; bt flag,sjmp_w; NOTTAKEN_S; \j##cond##_w: EVAL_##eval; bt flag,jmp_w; NOTTAKEN_W; \sj##cond##_l: EVAL_##eval; bt flag,sjmp_l; NOTTAKEN_S; \j##cond##_l: EVAL_##eval; bt flag,jmp_l; NOTTAKEN_L; \sjn##cond##_w: EVAL_##eval; bf flag,sjmp_w; NOTTAKEN_S; \jn##cond##_w: EVAL_##eval; bf flag,jmp_w; NOTTAKEN_W; \sjn##cond##_l: EVAL_##eval; bf flag,sjmp_l; NOTTAKEN_S; \jn##cond##_l: EVAL_##eval; bf flag,jmp_l; NOTTAKEN_L CONDJMP(o, OF, OF) CONDJMP(c, CF, CF) CONDJMP(z, ZF, ZF) CONDJMP(a, ABOVE, ABOVE) CONDJMP(s, SF, SF) CONDJMP(p, PF, PF) CONDJMP(g, SIGNED, SGT) CONDJMP(l, SIGNED, SLT)jcxz_w: lhz r3,CX(state); cmpwi r3,0; beq- sjmp_w; NOTTAKEN_Sjcxz_l: lhz r3,CX(state); cmpwi r3,0; beq- sjmp_l; NOTTAKEN_Sjecxz_w: lwz r3,ECX(state); cmpwi r3,0; beq- sjmp_w; NOTTAKEN_Sjecxz_l: lwz r3,ECX(state); cmpwi r3,0; beq- sjmp_l; NOTTAKEN_S/* Note that loop is somewhat strange, the data size attribute givesthe size of eip, and the address size whether the counter is cx or ecx.This is the same for jcxz/jecxz. */ loopw_w: li opreg,CX lhbrx r0,REG sub. r0,r0,one sthbrx r0,REG bne+ sjmp_w NOTTAKEN_S loopl_w: li opreg,ECX lwbrx r0,REG sub. r0,r0,one stwbrx r0,REG bne+ sjmp_w NOTTAKEN_S loopw_l: li opreg,CX lhbrx r0,REG sub. r0,r0,one sthbrx r0,REG bne+ sjmp_l NOTTAKEN_S loopl_l: li opreg,ECX lwbrx r0,REG sub. r0,r0,one stwbrx r0,REG bne+ sjmp_l NOTTAKEN_S loopzw_w: li opreg,CX lhbrx r0,REG EVAL_ZF sub. r0,r0,one sthbrx r0,REG bf ZF,1f bne+ sjmp_w1: NOTTAKEN_S loopzl_w: li opreg,ECX lwbrx r0,REG EVAL_ZF sub. r3,r3,one stwbrx r3,REG bf ZF,1f bne+ sjmp_w1: NOTTAKEN_S loopzw_l: li opreg,CX lhbrx r0,REG EVAL_ZF sub. r0,r0,one sthbrx r0,REG bf ZF,1f bne+ sjmp_l1: NOTTAKEN_S loopzl_l: li opreg,ECX lwbrx r0,REG EVAL_ZF sub. r0,r0,one stwbrx r0,REG bf ZF,1f bne+ sjmp_l1: NOTTAKEN_S loopnzw_w: li opreg,CX lhbrx r0,REG EVAL_ZF sub. r0,r0,one sthbrx r0,REG bt ZF,1f bne+ sjmp_w1: NOTTAKEN_S loopnzl_w: li opreg,ECX lwbrx r0,REG EVAL_ZF sub. r0,r0,one stwbrx r0,REG bt ZF,1f bne+ sjmp_w1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -