;; arm7.asm ;; arm7 chip for gba ;; ;; Copyripht 2019 moecmks (agalis01@outlook.com) ;; This file is part of ArchBoyAdvance. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software Foundation, ;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ;; TODO: ;; GamePak Prfetch Timing Problem. .686 .mmx .xmm .model flat, c option casemap :none ;; mmu read/write ;; internal will set arm7tdmi::waitState extrn agb_mbus_rw_seq@8:proc extrn agb_mbus_ww_seq@12:proc extrn agb_code_rhw_seq@8:proc extrn agb_code_rw_seq@8:proc extrn agb_mbus_rb_noseq@8:proc extrn agb_mbus_rhw_noseq@8:proc extrn agb_mbus_rw_noseq@8:proc extrn agb_mbus_wb_noseq@12:proc extrn agb_mbus_whw_noseq@12:proc extrn agb_mbus_ww_noseq@12:proc extrn agb_code_rhw_noseq@8:proc extrn agb_code_rw_noseq@8:proc extrn agb_gamepak_prefetch@12:proc extrn agb_irq_hook@4:proc extrn agb_stack_ww_seq@20:proc extrn agb_stack_ww_noseq@20:proc extrn agb_stack_rw_seq@8:proc extrn agb_stack_rw_noseq@8:proc STACK_PUSH_STATUS_INIT equ 0 STACK_PUSH_STATUS_PUSH equ 1 StackWriteSeq equ agb_stack_ww_seq@20 StackWriteNoSeq equ agb_stack_ww_noseq@20 StackReadSeq equ agb_stack_rw_seq@8 StackReadNoSeq equ agb_stack_rw_noseq@8 MmuReadWordSeq equ agb_mbus_rw_seq@8 MmuWriteWordSeq equ agb_mbus_ww_seq@12 MmuReadByteNoSeq equ agb_mbus_rb_noseq@8 MmuReadHalfWordNoSeq equ agb_mbus_rhw_noseq@8 MmuReadWordNoSeq equ agb_mbus_rw_noseq@8 MmuWriteByteNoSeq equ agb_mbus_wb_noseq@12 MmuWriteHalfWordNoSeq equ agb_mbus_whw_noseq@12 MmuWriteWordNoSeq equ agb_mbus_ww_noseq@12 tb_FetchSeq equ agb_code_rhw_seq@8 tb_FetchNoSeq equ agb_code_rhw_noseq@8 ARM7_FetchSeq equ agb_code_rw_seq@8 ARM7_FetchNoSeq equ agb_code_rw_noseq@8 AGB_GamePakPrefetch equ agb_gamepak_prefetch@12 AGB_IRQ_Hook equ agb_irq_hook@4 ;; XXX:memory order indep arm7tdmi struct SZ_STACK equ 13 SZ_LRLINK equ 14 SZ_PC equ 15 SZ_CPSR equ 16 Regs dd 17 dup (?) R812_T dd 10 dup (?) R1314_T dd 12 dup (?) SPSR_T dd 6 dup (?) Opcode dd 2 dup (?) IME dd ? IFS dw ? IE dw ? waitState dd ? nextNoSeqFetch dd ? agb dd ? calc dd ? arm7tdmi ends ;;================================================================================== ;; My CPSR IRQ-I FIQ-I THUMB-F MODE-MASK, PSW. for ARM. same as X86's PSW. ARM7_DEBUG equ 0 GBA_IE_IF_MASK equ 003FFFh ARM7_MODE_CLR_MASK equ 0E0FFFFFFh ARM7_MODE_IRQ_MASK equ 012000000h ARM7_MODE_MGR_MASK equ 013000000h ARM7_MODE_USER_MASK equ 010000000h ARM7_MODE_MSB_BIT_MASK equ 010000000h ARM7_MODE_FIQ_MASK equ 011000000h ARM7_MODE_UNDEF_MASK equ 01B000000h ARM7_MODE_SYS_MASK equ 01F000000h ARM7_MODE_ABT_MASK equ 017000000h ARM7_MODE_GET_MASK equ 01F000000h ARM7_PSR_FLAG_MASK equ 00000C101H ARM7_PSR_MODE4BIT_MASK equ 00F000000H ARM7_PSR_MODE8BIT_MASK equ 0DF000000H ARM7_PSR_STATE_MASK equ 020000000H ARM7_THUMB_BIT equ 29 ARM7_MODE_BLOCK_SUB_TOF equ 16 ARM7_MODE_SFT_BIT equ 24 ARM7_VECTOR_RESET equ 000h ARM7_VECTOR_UNDEF equ 004h ARM7_VECTOR_SOFTWARE equ 008h ARM7_VECTOR_PREFETCH_ABORT equ 00Ch ARM7_VECTOR_DATA_ABORT equ 010h ARM7_VECTOR_IRQ equ 018h ARM7_VECTOR_FIQ equ 01Ch ARM7_STD_FLAGS_N equ 080000000h ARM7_STD_FLAGS_Z equ 040000000h ARM7_STD_FLAGS_C equ 020000000h ARM7_STD_FLAGS_V equ 010000000h ERRORS_ASSERT equ MOECMKS_DONE @ALIGN_Z equ align 16 PTR32 equ dword ptr IRQ_INHIBI_MASK equ 080000000h IRQ_INHIBI_MASK_BIT equ 31 FIQ_INHIBI_MASK equ 040000000h MODE_SYS equ 001Fh MODE_USER equ 00010h MODE_SFT_BASE_PSR equ 24 FLAG_THUMB equ 020000000H FLAG_CZ equ (FLAG_C or FLAG_Z) FLAG_NZ equ (FLAG_N or FLAG_Z) FLAG_C equ 000100H FLAG_V equ 000001H FLAG_N equ 008000H FLAG_Z equ 004000H FLAG_N_TOLSB_BIT equ 15 FLAG_N_TO_V_ALIGN_BIT equ 15 FLAG_N_TO_V_ALIGN_SHIFT equ shr FLAG_V_TOLSB_BIT equ 0 FLAG_Z_TOLSB_BIT equ 14 FLAG_C_TOLSB_BIT equ 8 FLAG_CHECK_C_X86_BT equ 8 FLAG_MSR_FLAGS equ 00080000h FLAG_MSR_CTL equ 00010000h R812b_BLOCK equ 20 R812b_EXCEPT_FIQ equ R812b_BLOCK*0 R812b_FIQ equ R812b_BLOCK*1 R1314b_BLOCK equ 8 R1314b_SYSUSER equ R1314b_BLOCK*0 R1314b_MGR equ R1314b_BLOCK*1 R1314b_IRQ equ R1314b_BLOCK*2 R1314b_FIQ equ R1314b_BLOCK*3 R1314b_ABT equ R1314b_BLOCK*4 R1314b_UDEF equ R1314b_BLOCK*5 SPSRb_BLOCK equ 4 SPSRb_SYSUSER equ SPSRb_BLOCK*0 SPSRb_MGR equ SPSRb_BLOCK*1 SPSRb_IRQ equ SPSRb_BLOCK*2 SPSRb_FIQ equ SPSRb_BLOCK*3 SPSRb_ABT equ SPSRb_BLOCK*4 SPSRb_UDEF equ SPSRb_BLOCK*5 SC_CPSR8 equ bl SC_CPSR16 equ bx SC_CPSR16H equ bh SC_CPSR equ ebx SC_ARM7 equ esi SC_INVOL equ edi SC_WAIT equ ebp ARM7_bba1 macro OUTd " #%08X (IMM8:%02X, ROR:%d)", "SC_INVOL & 255 ?~ SC_INVOL}8 & 15 { 1", "SC_INVOL & 255", "SC_INVOL}8 & 15 { 1" endm ARM7_ALU_BASE_OUTd1 macro OPID IF OPID eq AND_OP OUTd "AND R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq EOR_OP OUTd "EOR R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq ORR_OP OUTd "ORR R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq SUB_OP OUTd "SUB R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq ADD_OP OUTd "ADD R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq MOV_OP OUTd "MOV R%d", "SC_INVOL}12 & 15" ARM7_bba1 ELSEIF OPID eq MVN_OP OUTd "MVN R%d", "SC_INVOL}12 & 15" ARM7_bba1 ELSEIF OPID eq BIC_OP OUTd "BIC R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq RSB_OP OUTd "RSB R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq SBC_OP OUTd "SBC R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq RSC_OP OUTd "RSC R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq ADC_OP OUTd "ADC R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq TST_OP ELSEIF OPID eq TEQ_OP ELSEIF OPID eq CMP_OP ELSEIF OPID eq CMN_OP ELSE ERRORS_ASSERT ENDIF endm ARM7_ALU_SIGN_BASE_OUTd1 macro OPID IF OPID eq AND_OP OUTd "ANDS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq EOR_OP OUTd "EORS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq ORR_OP OUTd "ORRS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq SUB_OP OUTd "SUBS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq ADD_OP OUTd "ADDS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq MOV_OP OUTd "MOVS R%d", "SC_INVOL}12 & 15" ARM7_bba1 ELSEIF OPID eq MVN_OP OUTd "MVNS R%d", "SC_INVOL}12 & 15" ARM7_bba1 ELSEIF OPID eq BIC_OP OUTd "BICS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq RSB_OP OUTd "RSBS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq SBC_OP OUTd "SBCS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq RSC_OP OUTd "RSCS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq ADC_OP OUTd "ADCS R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq TST_OP OUTd "TST R%d", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq TEQ_OP OUTd "TEQ R%d", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq CMP_OP OUTd "CMP R%d", "SC_INVOL}16 & 15" ARM7_bba1 ELSEIF OPID eq CMN_OP OUTd "CMN R%d", "SC_INVOL}16 & 15" ARM7_bba1 ELSE ERRORS_ASSERT ENDIF endm ARM7_ALU_BASE_OUTd2 macro OPID IF OPID eq AND_OP ;; LSL #2 OUTd "AND R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq EOR_OP OUTd "EOR R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq ORR_OP OUTd "ORR R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq SUB_OP OUTd "SUB R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq ADD_OP OUTd "ADD R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq MOV_OP OUTd "MOV R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL & 15" ELSEIF OPID eq MVN_OP OUTd "MVN R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL & 15" ELSEIF OPID eq BIC_OP OUTd "BIC R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq RSB_OP OUTd "RSB R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq SBC_OP OUTd "SBC R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq RSC_OP OUTd "RSC R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq ADC_OP OUTd "ADC R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq TST_OP OUTd "TST R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq TEQ_OP OUTd "TEQ R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq CMP_OP OUTd "CMP R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq CMN_OP OUTd "CMN R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSE ERRORS_ASSERT ENDIF endm ARM7_ALU_SIGN_BASE_OUTd2 macro OPID IF OPID eq AND_OP ;; LSL #2 OUTd "ANDS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq EOR_OP OUTd "EORS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq ORR_OP OUTd "ORRS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq SUB_OP OUTd "SUBS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq ADD_OP OUTd "ADDS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq MOV_OP OUTd "MOVS R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL & 15" ELSEIF OPID eq MVN_OP OUTd "MVNS R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL & 15" ELSEIF OPID eq BIC_OP OUTd "BICS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq RSB_OP OUTd "RSBS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq SBC_OP OUTd "SBCS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq RSC_OP OUTd "RSCS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq ADC_OP OUTd "ADCS R%d, R%d, R%d, ", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq TST_OP OUTd "TST R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq TEQ_OP OUTd "TEQ R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq CMP_OP OUTd "CMP R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSEIF OPID eq CMN_OP OUTd "CMN R%d, R%d, ", "SC_INVOL}16 & 15", "SC_INVOL & 15" ELSE ERRORS_ASSERT ENDIF endm .data ;; TODO: Bad Code . ;; ;; Macros assembled by MASM are difficult to debug in VS2012's embedded environment, ;; especially because ehco macros do not work. @ModeUser@ db 'MODE:USER', 0 @ModeSys@ db 'MODE:SYS', 0 @ModeUdef@ db 'MODE:Undef', 0 @ModeABT@ db 'MODE:Abort', 0 @ModeIRQ@ db 'MODE:IRQ', 0 @ModeFIQ@ db 'MODE:FIQ', 0 @ModeMGR@ db 'MODE:MGR', 0 @ModeTabs dd @ModeUser@, @ModeFIQ@, @ModeIRQ@, @ModeMGR@ dd @ModeUser@, @ModeUser@, @ModeUser@, @ModeABT@ dd @ModeUser@, @ModeUser@, @ModeUser@, @ModeUdef@ dd @ModeUser@, @ModeUser@, @ModeUser@, @ModeSys@ printf PROTO C :DWORD,:VARARG DEBUG_OUT equ printf ;; input : "content" rdata_mak macro format LOCAL mID ;; loop's iterator LOCAL mLEN LOCAL mCHSET ; eg. "Hello World", 00Ah, "Goddbyte word", 0 LOCAL mN ;; Pos init left. LOCAL mTAIL_COMP ;; :BOOL init tail comp , LOCAL mT1 ;; fro calc temp LOCAL mT2 ;; fro calc temp mN = 1 mID = 0 mTAIL_COMP = 0 mLEN = @SizeStr (format) mCHSET TEXTEQU <> ;; mCHSET CATSTR mCHSET, ;; echo format FORC CHS, IFIDN , <\> IF mID ne (mLEN-2) CHR_N TEXTEQU @SubStr (format, mID+2, 1) %FORC CHS_N, CHR_N IFIDN , IF mID eq (mLEN-3) mTAIL_COMP = 1 ENDIF IF mID ne 1 IF (mID-mN) ne 0 mT1 = mN+1 mT2 = mID - mN mCHSET CATSTR mCHSET, , @SubStr (format, mT1, mT2), ENDIF ENDIF mN = mID + 2 mCHSET CATSTR mCHSET, <00Ah>, ENDIF ENDM ENDIF ENDIF mID = mID + 1 ENDM ;; add tail IF mTAIL_COMP ne 1 ;; echo mLEN = mLEN - mN - 1 mN = mN + 1 mCHSET CATSTR mCHSET, , @SubStr (format, mN, mLEN), ELSEIF mTAIL_COMP eq 1 ;; echo mCHSET CATSTR mCHSET, <0> ENDIF ;; %echo mCHSET EXITM endm tem_rev_arg macro arg1, arglist:vararg LOCAL mCHSET mCHSET TEXTEQU FOR ARG, mCHSET CATSTR , , mCHSET ENDM EXITM endm tem_alphatoint macro arg IFIDNI , <0> EXITM <0> ELSEIFIDNI , <1> EXITM <1> ELSEIFIDNI , <2> EXITM <2> ELSEIFIDNI , <3> EXITM <3> ELSEIFIDNI , <4> EXITM <4> ELSEIFIDNI , <5> EXITM <5> ELSEIFIDNI , <6> EXITM <6> ELSEIFIDNI , <7> EXITM <7> ELSEIFIDNI , <8> EXITM <8> ELSEIFIDNI , <9> EXITM <9> ELSEIFIDNI , EXITM <10> ELSEIFIDNI , EXITM <11> ELSEIFIDNI , EXITM <12> ELSEIFIDNI , EXITM <13> ELSEIFIDNI , EXITM <14> ELSEIFIDNI , EXITM <15> ELSE ERRORS_ASSERT ENDIF endm tem_push_arg macro arglist0:vararg ;; e.g. "eax>7&00Ah", "ecx<5&ecx" ;; op } shift right 0 ;; op { shift left 1 ;; op + add 2 ;; op - sub 3 ;; op & and 4 ;; op ^ xor 5 ;; op | or 6 ;; op ~ ror right 7 ;; op ? 8 LhsOut rhs link sym, after ?, must offer a op symbol ;; src/dst : reg or imm (e.g. 0A00h, 1, 2, 3) ;; ;; Z0-ZF Mapper register 0-15 (current) ;; U0-UF Mapper register 0-15 (sys/user) ;; Q0-QF Mapper register 0-15 (irq) F:=SPSR ;; M0-MF Mapper register 0-15 (mgr) F:=SPSR ;; O0-O1 pipeline opcode ;; ;; $alu, get value register index, outval LOCAL mRSC_POS ;; LhsOut's end pos LOCAL mLEN LOCAL mID LOCAL mOP LOCAL mT LOCAL mT2 LOCAL mT3 LOCAL mSET_TYPE ;; LOCAL mTEMP LOCAL mID2 LOCAL mTEMP2 LOCAL mSIGJ LOCAL mACRG LOCAL mCC LOCAL mDIS LOCAL mLINK LOCAL mAGQ FOR arg, mRSC_POS = 1 mLEN = @SizeStr (arg) mID = 0 mOP = -1 mSIGJ = 0 mACRG = 0 mDIS = 0 mLINK = 0 mAGQ TEXTEQU FORC CHS, IFIDN , mDIS =1 ENDIF ENDM IF mDIS eq 1 GOTO IBGS ENDIF ;; %echo arg FORC CHS, ; echo CHS mSET_TYPE = -1 mT = 0 mT2 = 0 mACRG = 0 IF mLINK ne 0 mLINK = mLINK - 1 ;; skip n. GOTO IBGA ENDIF IFIDN , IF mID eq (mLEN-1) mSET_TYPE = 0 ENDIF ELSEIFIDN , < > ;; Skip it. ELSEIFIDN , ;; adjust pos, to rhs mT = mID + 2 mAGQ SUBSTR , mT, 1 mACRG = 1 mSET_TYPE = 0 ELSEIFIDN , ;; set reg mSIGJ = 1 mRSC_POS = mRSC_POS + 1 ELSEIFIDN , mSET_TYPE = 0 ELSEIFIDN , mSET_TYPE = 1 ELSEIFIDN , mSET_TYPE = 2 ELSEIFIDN , mSET_TYPE = 3 ELSEIFIDN , mSET_TYPE = 4 ELSEIFIDN , mSET_TYPE = 5 ELSEIFIDN , mSET_TYPE = 6 ELSEIFIDN , mSET_TYPE = 7 ENDIF IF mSET_TYPE ne -1 ;; Check MAPPER mT = mRSC_POS + 1 mT2 = mID - 1 - mRSC_POS + 1 mTEMP TEXTEQU @SubStr (, mT, mT2) mT = 0 mT2= 1 mID2 = 0 %FORC CHS_N, mTEMP IFIDNI , mT = mID2+2 mCC SubStr mTEMP, mT, 1 mTEMP2 CATSTR , mCC, mT2 = 0 ELSEIFIDNI , mT = mID2+2 mCC SubStr mTEMP, mT, 1 mTEMP2 CATSTR , <0>, mCC, mT2 = 0 ELSEIFIDNI , ;;sys/user mT = mID2+2 mCC SubStr mTEMP, mT, 1 mT3 = tem_alphatoint (%mCC) mT2 = 0 mT3 = mT3 + 1 mT3 = mT3 and 15 mTEMP2 CATSTR , <0>, mCC, IF mT3 GE 14 mTEMP2 TEXTEQU <> mTEMP2 CATSTR , , mCC, ENDIF ELSEIFIDNI , ;;IRQ mT = mID2+2 mCC SubStr mTEMP, mT, 1 mT3 = tem_alphatoint (%mCC) mT3 = mT3 + 1 mT3 = mT3 and 15 mT2 = 0 mTEMP2 CATSTR , <0>, mCC, IF mT3 GE 14 mTEMP2 CATSTR , , mCC, ELSEIF mT3 EQ 0 mTEMP2 TEXTEQU <> mTEMP2 CATSTR ENDIF ELSEIFIDNI , ;;MGR mT = mID2+2 mCC SubStr mTEMP, mT, 1 mT3 = tem_alphatoint (%mCC) mT3 = mT3 + 1 mT2 = 0 mT3 = mT3 and 15 mTEMP2 CATSTR , <0>, mCC, IF mT3 GE 14 mTEMP2 TEXTEQU <> mTEMP2 CATSTR , , mCC, ELSEIF mT3 EQ 0 mTEMP2 TEXTEQU <> mTEMP2 CATSTR ENDIF ENDIF mID2 = mID2 +1 ENDM IF mT2 eq 0 mTEMP TEXTEQU mTEMP2 ENDIF ;; Compile code movd xmm7, eax mov eax, mTEMP movd xmm1, eax movd eax, xmm7 IF mOP eq -1 ;; mem/imm/reg. movdqa xmm0, xmm1 ELSEIF mOP eq 0 movd xmm7, eax movd xmm6, ecx movd ecx, xmm1 movd eax, xmm0 shl eax, cl movd xmm0, eax movd eax, xmm7 movd ecx, xmm6 ELSEIF mOP eq 1 movd xmm7, eax movd xmm6, ecx movd ecx, xmm1 movd eax, xmm0 shr eax, cl movd xmm0, eax movd eax, xmm7 movd ecx, xmm6 ELSEIF mOP eq 2 ;; + mem/imm/reg. paddd xmm0, xmm1 ELSEIF mOP eq 3 psubd xmm0, xmm1 ELSEIF mOP eq 4 ;; & pand xmm0, xmm1 ELSEIF mOP eq 5 pxor xmm0, xmm1 ELSEIF mOP eq 6 por xmm0, xmm1 ELSEIF mOP eq 7 ;; ror it. movd xmm7, eax movd xmm6, ecx movd ecx, xmm1 movd eax, xmm0 ror eax, cl movd xmm0, eax movd eax, xmm7 movd ecx, xmm6 ELSE ERRORS_ASSERT ENDIF mOP = mSET_TYPE mRSC_POS = mID+1 IF mACRG ne 0 mACRG = 0 mLINK = 1 mOP = -1 mRSC_POS = mID + 2 mSIGJ = 0 movdqa xmm5, xmm0 ENDIF ENDIF :IBGA mID = mID + 1 ENDM %FORC CHS_N, mAGQ IFIDNI , IF mSIGJ eq 1 movd xmm1, eax movd eax, xmm0 and eax, 15 push PTR32[SC_ARM7].Regs[eax*4] movd eax, xmm1 ELSE movd xmm1, eax movd eax, xmm0 push eax movd eax, xmm1 ENDIF ELSE IFIDN , movd xmm7, eax movd xmm6, ecx movd ecx, xmm0 movd eax, xmm5 shl eax, cl movd xmm5, eax movd eax, xmm7 movd ecx, xmm6 ELSEIFIDN , movd xmm7, eax movd xmm6, ecx movd ecx, xmm0 movd eax, xmm5 shr eax, cl movd xmm5, eax movd eax, xmm7 movd ecx, xmm6 ELSEIFIDN , paddd xmm5, xmm0 ELSEIFIDN , psubd xmm5, xmm0 ELSEIFIDN , pand xmm5, xmm0 ELSEIFIDN , pxor xmm5, xmm0 ELSEIFIDN , por xmm5, xmm0 ELSEIFIDN , movd xmm7, eax movd xmm6, ecx movd ecx, xmm0 movd eax, xmm5 ror eax, cl movd xmm5, eax movd eax, xmm7 movd ecx, xmm6 ELSE ENDIF movd xmm7, eax movd eax, xmm5 push eax movd eax, xmm7 ENDIF ENDM :IBGS IF mDIS eq 1 ;; MAKE DISPLAY. movd xmm0, eax movd xmm1, ebx mov eax, SC_CPSR shr eax, ARM7_MODE_SFT_BIT and eax, 01Fh sub eax, 16 push PTR32 [@ModeTabs+eax*4] movd eax, xmm0 movd ebx, xmm1 .code ENDIF :IBGC ENDM endm tem_print macro format, arglist:vararg LOCAL cstr ARGLIST_EMPTY = 0 FOR ARG, ARGLIST_EMPTY = ARGLIST_EMPTY + 4 ENDM .data cstr db rdata_mak (format) .code push eax push edx push ecx %tem_push_arg tem_rev_arg (arglist) push offset cstr CALLIt DEBUG_OUT add esp, 4 add esp, ARGLIST_EMPTY pop ecx pop edx pop eax endm IF ARM7_DEBUG ne 0 OUTd equ tem_print ELSE ;; non-debug mode OUTd macro arglist:vararg endm ENDIF OUTc equ tem_print DEBUG_BREAK equ int 3 ;; GBA Mmu Operate IF 1 CALLIt macro Symbol call Symbol endm ELSE CALLIt macro Symbol call PTR32[Symbol] endm ENDIF CallMemOrIO macro Symbol push [SC_ARM7].agb CALLIt Symbol endm CallMemOrIOAddWaitState macro Symbol push [SC_ARM7].agb CALLIt Symbol add SC_WAIT, [SC_ARM7].waitState endm CallMemOrIOAddWaitState2 macro Symbol, Addr2 push Addr2 push [SC_ARM7].agb CALLIt Symbol add SC_WAIT, [SC_ARM7].waitState endm Call_IRQ_Hook macro push eax push ecx push edx push [SC_ARM7].agb CALLIt AGB_IRQ_Hook pop edx pop ecx pop eax endm Add_WaitStateClks equ add SC_WAIT, [SC_ARM7].waitState GamePAK_Prefetch macro InternalCycle:REQ push InternalCycle push ZRS (SZ_PC) push [SC_ARM7].agb CALLIt AGB_GamePakPrefetch endm STA macro offsets EXITM endm ZRS macro offsets EXITM endm SetNZCV_A macro sub_bit:REQ ;; 1 indicate sub otherwise 0 lahf seto al xor ah, sub_bit mov SC_CPSR16, ax endm SetNZC_A macro sub_bit ;; 1 indicate sub otherwise 0 lahf mov SC_CPSR16H, ah endm SetC_A macro lahf and SC_CPSR, not FLAG_C ;; c clear and eax, FLAG_C ;; save c or SC_CPSR, eax ;;c reset endm SetNZ_A macro lahf and SC_CPSR, not (FLAG_N or FLAG_Z) ;; nz clear and eax, FLAG_NZ ;; save nz or SC_CPSR, eax ;;nz reset endm Set_NZmul32 macro out_reg and out_reg, out_reg SetNZ_A endm Set_NZmul64 macro out_lo, out_hi LOCAL SkipN LOCAL SkipZ and SC_CPSR, not (FLAG_N or FLAG_Z) ;; nz clear bt out_hi, 31 jnc SkipN or SC_CPSR, FLAG_N jmp SkipZ SkipN: or out_hi, out_lo jne SkipZ or SC_CPSR, FLAG_Z SkipZ: endm ;; ToStandPSR ;; destroy : ecx, eax ToStandPSR macro Post, REC, epx, emx LOCAL @setZ LOCAL @setC LOCAL @setV LOCAL @setOver mov epx, Post mov emx, Post rol epx, 8 and epx, 0000000FFh test emx, FLAG_N je @setZ or epx, ARM7_STD_FLAGS_N @setZ: test emx, FLAG_Z je @setC or epx, ARM7_STD_FLAGS_Z @setC: test emx, FLAG_C je @setV or epx, ARM7_STD_FLAGS_C @setV: test emx, FLAG_V je @setOver or epx, ARM7_STD_FLAGS_V @setOver: mov REC, epx endm ;; ToFastPSR ;; destroy : ecx, eax ToFastPSR macro Post, REC, epx, emx LOCAL @setZ LOCAL @setC LOCAL @setV LOCAL @setOver mov epx, Post mov emx, Post ror epx, 8 and epx, 0FF000000h test emx, ARM7_STD_FLAGS_N je @setZ or epx, FLAG_N @setZ: test emx, ARM7_STD_FLAGS_Z je @setC or epx, FLAG_Z @setC: test emx, ARM7_STD_FLAGS_C je @setV or epx, FLAG_C @setV: test emx, ARM7_STD_FLAGS_V je @setOver or epx, FLAG_V @setOver: mov REC, epx endm ;; destroy eax, ecx Imm8BitmapSft_AC macro Sft4Imm8, REC mov eax, Sft4Imm8 mov ecx, Sft4Imm8 and eax, 0FFh and ecx, 0F00h shr ecx, 7 ror eax, cl mov REC, eax endm Imm8BitmapSft_AC_SetC macro Sft4Imm8, REC LOCAL @Skip mov eax, Sft4Imm8 mov ecx, Sft4Imm8 and eax, 0FFh and ecx, 0F00h shr ecx, 7 je @Skip ror eax, cl mov ecx, eax SetC_A mov eax, ecx @Skip: mov REC, eax endm C_op_Care equ 0 C_op_NOCare equ 1 ;; XXX: better case ShiftRegImm5 macro Post, REC, tr1c, tr2, C_op LOCAL @END LOCAL @HASH LOCAL @LSL LOCAL @LSR LOCAL @ASR LOCAL @ROR LOCAL @LSL_0 LOCAL @LSR_0 LOCAL @ASR_0 LOCAL @ROR_0 mov tr1c, Post mov tr2, Post shr tr1c, 5 and tr1c, 3 jmp @HASH[tr1c*4] Si5SftOp macro X86Sft, lSym mov tr1c, tr2 and tr2, 15 mov tr2, ZRS (tr2) ;; Get Rm. shr tr1c, 7 and tr1c, 31 je lSym and SC_CPSR, not FLAG_C X86Sft tr2, cl ;; check c sbb tr1c, tr1c and tr1c, FLAG_C or SC_CPSR, tr1c mov REC, tr2 jmp @END endm @LSR: OUTd "LSR #%d ", "SC_INVOL}7 & 31" Si5SftOp shr, @LSR_0 @LSR_0: and SC_CPSR, not FLAG_C xor tr1c, tr1c bt tr2, 31 ;; check c[31] sbb tr2, tr2 and tr2, FLAG_C or SC_CPSR, tr2 mov REC, tr1c jmp @END @ASR: OUTd "ASR #%d ", "SC_INVOL}7 & 31" Si5SftOp sar, @ASR_0 @ASR_0: and SC_CPSR, not FLAG_C bt tr2, 31 sbb tr1c, tr1c mov tr2, tr1c and tr1c, FLAG_C or SC_CPSR, tr1c mov REC, tr2 jmp @END @ROR: OUTd "ROR #%d ", "SC_INVOL}7 & 31" Si5SftOp ror, @ROR_0 @ROR_0: ;; RRX OUTd "...RRX " btr SC_CPSR, FLAG_CHECK_C_X86_BT rcr tr2, 1 ;; check c sbb tr1c, tr1c and tr1c, FLAG_C or SC_CPSR, tr1c mov REC, tr2 jmp @END @ALIGN_Z @HASH dd @LSL, @LSR, @ASR, @ROR @LSL: OUTd "LSL #%d ", "SC_INVOL}7 & 31" Si5SftOp shl, @LSL_0 @LSL_0: mov REC, tr2 @END: OUTd "Sft Result:%08X ", "&REC&" endm ;; XXX: better case ShiftRegImm5_WithOutC macro Post, REC, tr1c, tr2 LOCAL @END LOCAL @HASH LOCAL @LSL LOCAL @LSR LOCAL @ASR LOCAL @ROR LOCAL @LSL_0 LOCAL @LSR_0 LOCAL @ASR_0 LOCAL @ROR_0 mov tr1c, Post mov tr2, Post shr tr1c, 5 and tr2, 15 mov tr2, ZRS (tr2) ;; Get Rm. and tr1c, 3 jmp @HASH[tr1c*4] Si5SftOp_WithOutC macro X86Sft, lSym mov tr1c, Post shr tr1c, 7 and tr1c, 31 je lSym X86Sft tr2, cl ;; check c mov REC, tr2 jmp @END endm @LSR: OUTd "LSR #%d ", "SC_INVOL}7 & 31" Si5SftOp_WithOutC shr, @LSR_0 @LSR_0: xor REC, REC jmp @END @ASR: OUTd "ASR #%d ", "SC_INVOL}7 & 31" Si5SftOp_WithOutC sar, @ASR_0 @ASR_0: bt tr2, 31 sbb REC, REC jmp @END @ROR: OUTd "ROR #%d ", "SC_INVOL}7 & 31" Si5SftOp_WithOutC ror, @ROR_0 @ROR_0: ;; RRX OUTd "...RRX " bt SC_CPSR, FLAG_CHECK_C_X86_BT rcr tr2, 1 ;; check c mov REC, tr2 jmp @END @ALIGN_Z @HASH dd @LSL, @LSR, @ASR, @ROR @LSL: OUTd "LSL #%d ", "SC_INVOL}7 & 31" Si5SftOp_WithOutC shl, @LSL_0 @LSL_0: mov REC, tr2 @END: OUTd "Sft Result:%08X ", "&REC&" endm ;; XXX: better case, use inline label. ShiftRegRs macro Post, REC, tr1c, tr2, C_op LOCAL @END LOCAL @HASH LOCAL @LSL LOCAL @LSR LOCAL @ASR LOCAL @ROR LOCAL @ROR_ep mov tr1c, Post mov tr2, Post shr tr1c, 5 and tr1c, 3 IF C_op eq C_op_NOCare mov [esp-8], SC_CPSR IF ARM7_DEBUG ne 0 sub esp, 32 ENDIF ENDIF jmp @HASH[tr1c*4] Rs_SftOp macro X86Sft and SC_CPSR, not FLAG_C X86Sft tr2, cl ;; check c sbb tr1c, tr1c and tr1c, FLAG_C or SC_CPSR, tr1c mov REC, tr2 jmp @END endm Rs_Stiff macro LOCAL locSym mov tr1c, tr2 and tr2, 15 cmp tr2, SZ_PC mov tr2, ZRS (tr2) ;; Get Rm. jne locSym add tr2, 4 ;; PC + 12, if rm in rorate shift. locSym: shr tr1c, 8 and tr1c, 15 mov tr1c, ZRS (tr1c) ;; Get Rs and tr1c, 255 ;; TODO:better case ? cmp tr1c, 32 jl @F endm @LSL: OUTd "LSL R%d ", "SC_INVOL}8 & 15" Rs_Stiff ;; Rs >= 32 ;; ;; DEBUG_BREAK sete cl and ecx, 1 and SC_CPSR, not FLAG_C and tr1c, tr2 shl tr1c, FLAG_CHECK_C_X86_BT or SC_CPSR, tr1c xor REC, REC jmp @END @@: test tr1c, tr1c jne @F ;; Rs := 0 mov REC, tr2 jmp @END @@: Rs_SftOp shl @LSR: OUTd "LSR R%d ", "SC_INVOL}8 & 15" Rs_Stiff ;; Rs >= 32 ;; DEBUG_BREAK sete cl and ecx, 1 and SC_CPSR, not FLAG_C bt tr2, 31 sbb tr2, tr2 and tr1c, tr2 shl tr1c, FLAG_CHECK_C_X86_BT or SC_CPSR, tr1c xor REC, REC jmp @END @@: test tr1c, tr1c jne @F ;; Rs := 0 mov REC, tr2 jmp @END @@: Rs_SftOp shr @ASR: OUTd "ASR R%d ", "SC_INVOL}8 & 15" Rs_Stiff ;; Rs >= 32 ;; DEBUG_BREAK and SC_CPSR, not FLAG_C shl tr2, 1 sbb tr2, tr2 mov tr1c, tr2 and tr2, 1 shl tr2, FLAG_CHECK_C_X86_BT or SC_CPSR, tr2 mov REC, tr1c jmp @END @@: test tr1c, tr1c jne @F ;; Rs := 0 mov REC, tr2 jmp @END @@: Rs_SftOp sar @ROR: OUTd "ROR R%d ", "SC_INVOL}8 & 15" mov tr1c, tr2 and tr2, 15 cmp tr2, SZ_PC mov tr2, ZRS (tr2) ;; Get Rm. jne @ROR_ep add tr2, 4 @ROR_ep: shr tr1c, 8 and tr1c, 15 mov tr1c, ZRS (tr1c) ;; Get Rs and tr1c, 255 jne @F ;; Rs := 0 mov REC, tr2 jmp @END @@: and tr1c, 31 jne @F and SC_CPSR, not FLAG_C bt tr2, 31 sbb tr1c, tr1c and tr1c, FLAG_C or SC_CPSR, tr1c mov REC, tr2 jmp @END @@: Rs_SftOp ror @HASH dd @LSL, @LSR, @ASR, @ROR @END: IF C_op eq C_op_NOCare IF ARM7_DEBUG ne 0 add esp, 32 ENDIF mov SC_CPSR, [esp-8] ENDIF OUTd "Sft Result:%08X ", "&REC&" endm ;; XXX: better case, use inline label. ShiftRegRs_WithOutC macro Post, REC, tr1c, tr2, C_op LOCAL @END LOCAL @HASH LOCAL @LSL LOCAL @LSR LOCAL @ASR LOCAL @ROR LOCAL @ZERO mov tr1c, Post mov tr2, Post shr tr1c, 5 and tr1c, 3 jmp @HASH[tr1c*4] Rs_SftOp macro X86Sft X86Sft tr2, cl ;; check c mov REC, tr2 jmp @END endm Rs_Stiff macro mov tr1c, tr2 and tr2, 15 mov tr2, ZRS (tr2) ;; Get Rm. shr tr1c, 8 and tr1c, 15 mov tr1c, ZRS (tr1c) ;; Get Rs and tr1c, 255 ;; TODO:better case ? cmp tr1c, 32 jl @F endm @LSR: OUTd "LSR R%d ", "SC_INVOL}8 & 15" Rs_Stiff ;; Rs >= 32 ;; ;; DEBUG_BREAK xor REC, REC jmp @END @@: test tr1c, tr1c je @ZERO Rs_SftOp shr @ASR: OUTd "ASR R%d ", "SC_INVOL}8 & 15" Rs_Stiff ;; Rs >= 32 ;; DEBUG_BREAK shl tr2, 1 sbb REC, REC jmp @END @@: test tr1c, tr1c je @ZERO Rs_SftOp sar @ROR: OUTd "ROR R%d ", "SC_INVOL}8 & 15" mov tr1c, Post shr tr1c, 8 and tr1c, 15 mov tr1c, ZRS (tr1c) and tr1c, 31 je @ZERO Rs_SftOp ror @HASH dd @LSL, @LSR, @ASR, @ROR @LSL: OUTd "LSL R%d ", "SC_INVOL}8 & 15" Rs_Stiff ;; Rs >= 32 ;; DEBUG_BREAK xor REC, REC jmp @END @@: test tr1c, tr1c je @ZERO shl tr2, cl ;; check c @ZERO: mov REC, tr2 @END: OUTd "Sft Result:%08X ", "&REC&" endm ;; Resume CPSR from current mode's SPSR. ;; destroy: eax, ecx, edx SPSRToCPSR macro tr ;; Copy SPSR to CPSR. GetCurSPSRP tr mov tr, [tr] ;; Switch CPU mode. SwitchMode tr, 1 endm SC_CPSR8 equ bl SC_CPSR16 equ bx SC_CPSR16H equ bh SC_CPSR equ ebx SC_ARM7 equ esi SC_INVOL equ edi SC_WAIT equ ebp ;; FETCH --------------------------------------------------------------- ARM7_ExitAddPC macro Clks:REQ mov ecx, ZRS (SZ_PC) mov ZRS (SZ_CPSR), SC_CPSR add ecx, 4 and ecx,-4 lea eax, [SC_WAIT+Clks] mov ZRS (SZ_PC), ecx pop ebx pop ebp pop esi pop edi ret endm tb_ExitAddPC macro Clks:REQ mov ecx, ZRS (SZ_PC) mov ZRS (SZ_CPSR), SC_CPSR add ecx, 2 and ecx,-2 lea eax, [SC_WAIT+Clks] mov ZRS (SZ_PC), ecx pop ebx pop ebp pop esi pop edi ret endm arm7_FlushPipeline macro Clks:REQ mov SC_INVOL, ZRS (SZ_PC) push SC_INVOL CallMemOrIOAddWaitState ARM7_FetchNoSeq add SC_INVOL, 4 ;; ++PC mov [SC_ARM7].Opcode[0], eax push SC_INVOL CallMemOrIOAddWaitState ARM7_FetchSeq add SC_INVOL, 4 ;; ++PC and SC_INVOL, -4 mov [SC_ARM7].Opcode[4], eax mov ZRS (SZ_PC), SC_INVOL mov ZRS (SZ_CPSR), SC_CPSR lea eax, [SC_WAIT+Clks] pop ebx pop ebp pop esi pop edi ret endm tb_FlushPipeline macro Clks:REQ mov SC_INVOL, ZRS (SZ_PC) push SC_INVOL CallMemOrIOAddWaitState tb_FetchNoSeq add SC_INVOL, 2 ;; ++PC mov [SC_ARM7].Opcode[0], eax push SC_INVOL CallMemOrIOAddWaitState tb_FetchSeq add SC_INVOL, 2 ;; ++PC and SC_INVOL, -2 mov [SC_ARM7].Opcode[4], eax mov ZRS (SZ_PC), SC_INVOL mov ZRS (SZ_CPSR), SC_CPSR lea eax, [SC_WAIT+Clks] pop ebx pop ebp pop esi pop edi ret endm GetRFI macro Post, BitScanStart, REC mov REC, Post shr REC, BitScanStart and REC, 15 endm GetRFIV macro Post, BitScanStart, REC GetRFI Post, BitScanStart, REC mov REC, ZRS (REC) endm GetRFI_T macro Post, BitScanStart, REC mov REC, Post shr REC, BitScanStart and REC, 7 endm GetRFIV_T macro Post, BitScanStart, REC GetRFI_T Post, BitScanStart, REC mov REC, ZRS (REC) endm GetCurSPSRP macro REC LOCAL @FIQ LOCAL @IRQ LOCAL @UDEF LOCAL @USYS LOCAL @UNUSED LOCAL @SVC LOCAL @ABT LOCAL @END LOCAL @HASH mov REC, SC_CPSR and REC, 00F000000h shr REC, 24 jmp PTR32 @HASH [REC*4] ;; --------------------------------------------------------------------------------- @USYS: lea REC, [SC_ARM7].SPSR_T[SPSRb_SYSUSER] jmp @END @IRQ: lea REC, [SC_ARM7].SPSR_T[SPSRb_IRQ] jmp @END .data @ALIGN_Z @HASH dd @USYS, @FIQ, @IRQ, @SVC dd @UNUSED, @UNUSED, @UNUSED, @ABT dd @UNUSED, @UNUSED, @UNUSED, @UDEF dd @UNUSED, @UNUSED, @UNUSED, @USYS .code @FIQ: lea REC, [SC_ARM7].SPSR_T[SPSRb_FIQ] jmp @END @UDEF: @ABT: @UNUSED: int 3 @SVC: lea REC, [SC_ARM7].SPSR_T[SPSRb_MGR] @END: endm ;; switch ARM7 mode ;; destroy: eax, ecx, edx SwitchMode macro SG_PSR, CPSR_Copy_dis:=<0> LOCAL @FIQ LOCAL @IRQ LOCAL @UDEF LOCAL @USER LOCAL @SVC LOCAL @ABT LOCAL @UNUSED LOCAL @SPSR_TABLE LOCAL @FIQ2 LOCAL @IRQ2 LOCAL @UDEF2 LOCAL @USER2 LOCAL @SVC2 LOCAL @ABT2 LOCAL @UNUSED2 LOCAL @SPSR2_TABLE LOCAL @END push SC_WAIT mov eax, SG_PSR mov edx, SC_CPSR xor ecx, ecx mov [SC_ARM7].calc, SC_CPSR ;; save old CPSR mov SC_CPSR, eax and eax, ARM7_MODE_GET_MASK and edx, ARM7_MODE_GET_MASK ;; Check FIQ r8_r12 bank store cmp eax, ARM7_MODE_FIQ_MASK sete cl cmp edx, ARM7_MODE_FIQ_MASK sete ch or cl, ch movzx SC_WAIT, cl xor ecx, ecx cmp eax, ARM7_MODE_USER_MASK sete ch cmp eax, ARM7_MODE_SYS_MASK sete cl or cl, ch shl ecx, 24 cmp edx, ARM7_MODE_USER_MASK sete ch cmp edx, ARM7_MODE_SYS_MASK sete cl or cl, ch rol ecx, 8 and ch, cl jne @END mov ecx, [SC_ARM7].calc shr eax, ARM7_MODE_SFT_BIT shr edx, ARM7_MODE_SFT_BIT sub eax, ARM7_MODE_BLOCK_SUB_TOF sub edx, ARM7_MODE_BLOCK_SUB_TOF jmp PTR32 @SPSR_TABLE[edx*4] saveR8_12 macro R812Bank, Post mov Post, ZRS (8) mov [SC_ARM7].R812_T[R812Bank], Post mov Post, ZRS (9) mov [SC_ARM7].R812_T[R812Bank+4], Post mov Post, ZRS (10) mov [SC_ARM7].R812_T[R812Bank+8], Post mov Post, ZRS (11) mov [SC_ARM7].R812_T[R812Bank+12], Post mov Post, ZRS (12) mov [SC_ARM7].R812_T[R812Bank+16], Post endm loadR8_12 macro R812Bank, Post mov Post, [SC_ARM7].R812_T[R812Bank] mov ZRS (8), Post mov Post, [SC_ARM7].R812_T[R812Bank+4] mov ZRS (9), Post mov Post, [SC_ARM7].R812_T[R812Bank+8] mov ZRS (10), Post mov Post, [SC_ARM7].R812_T[R812Bank+12] mov ZRS (11), Post mov Post, [SC_ARM7].R812_T[R812Bank+16] mov ZRS (12), Post endm saveR13_14 macro R1314Bank, Post mov Post, ZRS (13) mov [SC_ARM7].R1314_T[R1314Bank], Post mov Post, ZRS (14) mov [SC_ARM7].R1314_T[R1314Bank+4], Post endm loadR13_14 macro R1314Bank, Post mov Post, [SC_ARM7].R1314_T[R1314Bank] mov ZRS (13), Post mov Post, [SC_ARM7].R1314_T[R1314Bank+4] mov ZRS (14), Post endm markBankSave macro lSym, R812Bank, R1314Bank LOCAL locSym lSym: test SC_WAIT, SC_WAIT je locSym saveR8_12 R812Bank, edx locSym: saveR13_14 R1314Bank, edx jmp PTR32 @SPSR2_TABLE[eax*4] endm ;; -------- Mode Current Check Save to bank -------- markBankSave @USER, R812b_EXCEPT_FIQ, R1314b_SYSUSER markBankSave @FIQ, R812b_FIQ, R1314b_FIQ markBankSave @IRQ, R812b_EXCEPT_FIQ, R1314b_IRQ markBankSave @SVC, R812b_EXCEPT_FIQ, R1314b_MGR markBankSave @ABT, R812b_EXCEPT_FIQ, R1314b_ABT markBankSave @UDEF, R812b_EXCEPT_FIQ, R1314b_UDEF markBankLoad macro lSym, R812Bank, R1314Bank, SPSRBank LOCAL locSym lSym: test SC_WAIT, SC_WAIT je locSym loadR8_12 R812Bank, eax locSym: loadR13_14 R1314Bank, eax IF R1314Bank ne R1314b_SYSUSER IF CPSR_Copy_dis eq 0 mov [SC_ARM7].SPSR_T[SPSRBank], ecx ENDIF ENDIF jmp @END endm ;; -------- Mode New Check Store to runtime regs group -------- markBankLoad @USER2, R812b_EXCEPT_FIQ, R1314b_SYSUSER, SPSRb_SYSUSER markBankLoad @FIQ2, R812b_FIQ, R1314b_FIQ, SPSRb_FIQ markBankLoad @IRQ2, R812b_EXCEPT_FIQ, R1314b_IRQ, SPSRb_IRQ markBankLoad @SVC2, R812b_EXCEPT_FIQ, R1314b_MGR, SPSRb_MGR markBankLoad @ABT2, R812b_EXCEPT_FIQ, R1314b_ABT, SPSRb_ABT markBankLoad @UDEF2, R812b_EXCEPT_FIQ, R1314b_UDEF, SPSRb_UDEF @UNUSED: @UNUSED2: int 3 .data @ALIGN_Z @SPSR_TABLE dd @USER, @FIQ, @IRQ, @SVC dd @UNUSED, @UNUSED, @UNUSED, @ABT dd @UNUSED, @UNUSED, @UNUSED, @UDEF dd @UNUSED, @UNUSED, @UNUSED, @USER @SPSR2_TABLE dd @USER2, @FIQ2, @IRQ2, @SVC2 dd @UNUSED2, @UNUSED2, @UNUSED2, @ABT2 dd @UNUSED2, @UNUSED2, @UNUSED2, @UDEF2 dd @UNUSED2, @UNUSED2, @UNUSED2, @USER2 .code @END: pop SC_WAIT endm .code ;;===================================================================================== ;; arm7tdmi_ticks c prototype ;; uint16_t arm7tdmi_ticks (struct arm7tdmi *arm7) ;; ret: real exec ticks. arm7tdmi_ticks proc c option prologue:none, epilogue:none push edi push esi push ebp push ebx STACK_PUSH equ 16 assume SC_ARM7:ptr arm7tdmi xor SC_WAIT, SC_WAIT mov SC_ARM7, STA (4+STACK_PUSH) mov SC_CPSR, ZRS (SZ_CPSR) ;; prefetcht0 [SC_ARM7] mov ax, [SC_ARM7].IFS and ax, [SC_ARM7].IE and eax, GBA_IE_IF_MASK bt dword ptr[SC_ARM7].IME, 0 sbb edx, edx and eax, edx ;; GBA_IE_IF_MASK. bt SC_CPSR, IRQ_INHIBI_MASK_BIT sbb edx, edx not edx and eax, edx je e_step IF 0 Call_IRQ_Hook ENDIF mov eax, ZRS (SZ_PC) mov ecx, SC_CPSR and ecx, ARM7_MODE_CLR_MASK or ecx, ARM7_MODE_IRQ_MASK ;; Set IRQ mode. and ecx, not FLAG_THUMB ;; Clear Thumb exec flag or ecx, IRQ_INHIBI_MASK ;; Set IRQ inhibit mask ;; PC to IRQ's LR, LR:= Current Instruction +4 bt SC_CPSR, ARM7_THUMB_BIT sbb edx, edx xor edx, -1 and edx, -4 add edx, eax mov [SC_ARM7].R1314_T[R1314b_IRQ +4], edx ;; Adjust PC Pointer to IRQ Interrupt vector address mov ZRS (SZ_PC), ARM7_VECTOR_IRQ mov SC_INVOL, SC_CPSR and SC_INVOL, ARM7_MODE_GET_MASK cmp SC_INVOL, ARM7_MODE_IRQ_MASK je @Nest_IRQ ;; switch Mode SwitchMode ecx, 0 ;; Prefetch Opcode pipeline arm7_FlushPipeline 5 ;; minimum interrupt cycle delay @Nest_IRQ: mov ZRS (SZ_LRLINK), edx mov [SC_ARM7].SPSR_T[SPSRb_IRQ], SC_CPSR mov eax, ZRS (SZ_STACK) mov [SC_ARM7].R1314_T[R1314b_IRQ], eax mov eax, ZRS (SZ_LRLINK) mov [SC_ARM7].R1314_T[R1314b_IRQ+4], eax mov SC_CPSR, ecx ;; Prefetch Opcode pipeline arm7_FlushPipeline 5 ;; CPU simulation. ;; According to the order section of the official manual DDI0210B.pdf of ARM7TDMI, ;; Because of the pipeline relationship, the PC pointer always points to the two instructions ;; after the current execution address before each instruction is executed by SC_ARM7. ;; This implicitly points out the following points. ;; ;; (1) Instruction execution is always in pipeline cycle >= 2 execution, which means ;; (2) Previous and at least two Fetch scripts (this operation may be included with specific implementation instructions) ;; (3) The first instruction code has been decoded, the second instruction code has been pushed to the first instruction code @ALIGN_Z DEBUG_TICK macro Address local dm push eax mov eax, ZRS(SZ_PC) cmp eax, Address+8 jne dm int 3 dm: pop eax endm DEBUG_TICK2 macro Address local dm push eax mov eax, ZRS(SZ_PC) cmp eax, Address+4 jne dm int 3 dm: pop eax endm e_step: xor SC_WAIT, SC_WAIT mov eax, [SC_ARM7].nextNoSeqFetch mov [SC_ARM7].nextNoSeqFetch, SC_WAIT test SC_CPSR, FLAG_THUMB jne @F ;; ARM7 Code, do next instruction's first seq/noseq read cycle push ZRS (SZ_PC) test eax, eax je aaf7 CallMemOrIOAddWaitState ARM7_FetchNoSeq jmp nn aaf7: CallMemOrIOAddWaitState ARM7_FetchSeq nn: mov SC_INVOL, [SC_ARM7].Opcode[0] mov ecx, [SC_ARM7].Opcode[4] mov [SC_ARM7].Opcode[4], eax mov [SC_ARM7].Opcode[0], ecx mov eax, SC_INVOL OUTd "\n\nPC:%08X-OP:%08X-SP:%08X LR:%08X -M:%s-\n", "ZF-8", "SC_INVOL", "ZD", "ZE", "#" OUTd "R0:%08X R1:%08X R2:%08X R3:%08X \n", "Z0", "Z1", "Z2", "Z3" OUTd "R4:%08X R5:%08X R6:%08X R7:%08X \n", "Z4", "Z5", "Z6", "Z7" OUTd "R8:%08X R9:%08X R10:%08X R11:%08X R12:%08X \n", "Z8", "Z9", "ZA", "ZB", "ZC" OUTd "IRQ:%d N:%d Z:%d C:%d V:%d\n", "SC_CPSR}31 & 1", "SC_CPSR}15 & 1", "SC_CPSR}14 & 1", "SC_CPSR}8 & 1", "SC_CPSR & 1" shr eax, 28 jmp fTAB[eax*4] @@: ;; Thumb Code, do next instruction's first seq/noseq read cycle push ZRS (SZ_PC) test eax, eax je uaf7 CallMemOrIOAddWaitState tb_FetchNoSeq jmp cc uaf7: CallMemOrIOAddWaitState tb_FetchSeq cc: mov SC_INVOL, [SC_ARM7].Opcode[0] mov ecx, [SC_ARM7].Opcode[4] mov [SC_ARM7].Opcode[4], eax mov [SC_ARM7].Opcode[0], ecx OUTd "\n\nPC:%08X-OP:%04X-SP:%08X LR:%08X -M:%s-\n", "ZF-4", "SC_INVOL & 0FFFFh","ZD", "ZE" , "#" OUTd "R0:%08X R1:%08X R2:%08X R3:%08X \n", "Z0", "Z1", "Z2", "Z3" OUTd "R4:%08X R5:%08X R6:%08X R7:%08X \n", "Z4", "Z5", "Z6", "Z7" OUTd "R8:%08X R9:%08X R10:%08X R11:%08X R12:%08X \n", "Z8", "Z9", "ZA", "ZB", "ZC" OUTd "IRQ:%d N:%d Z:%d C:%d V:%d\n", "SC_CPSR}31 & 1", "SC_CPSR}15 & 1", "SC_CPSR}14 & 1", "SC_CPSR}8 & 1", "SC_CPSR & 1" and SC_INVOL, 0FFFFh mov eax, SC_INVOL mov edx, SC_INVOL mov ecx, SC_INVOL shr ecx, 8 and ecx, 255 jmp sTAB[ecx*4] ;; ARM7 Instruction Entry ----------------------------------------------------------------------------------- AS_I8: OUTd "I:AS_I8;;*** " mov eax, edx and eax, 001F00000h shr eax, 20 jmp i8r4TAB[eax*4] SF_RS: OUTd "I:SF_RS;;*** " mov eax, edx and eax, 001F00000h shr eax, 20 jmp rsTAB[eax*4] SF_I5: OUTd "I:SF_I5;;*** " mov eax, edx and eax, 001F00000h shr eax, 20 jmp si5TAB[eax*4] A7MUL: OUTd "I:A7MUL;;*** " mov eax, edx and eax, 000F00000h shr eax, 20 jmp ARM7_MUL_TAB[eax*4] LDI12: OUTd "I:LDI12;;*** " mov eax, edx and eax, 001F00000h shr eax, 20 jmp nTAB[eax*4] LDIRS: OUTd "I:LDIRS;;*** " mov eax, edx and eax, 001F00000h shr eax, 20 jmp eTAB[eax*4] LDRHW: ;; FIXME OUTd "I:LDRHW;;*** " mov eax, edx mov ecx, edx and ecx, 060h and eax, 0100000h shr eax, 18 shr ecx, 5 or ecx, eax ;; and ecx, 7 mov eax, SC_INVOL and eax, 01a00000h shr eax, 20 or eax, pcMTAB[ecx*4] test edx, 0400000h je @F jmp cTAB[eax*4] @@:jmp pTAB[eax*4] RGSET: OUTd "I:RGSET;;*** " mov eax, SC_INVOL shr eax, 20 and eax, 31 jmp zTAB[eax*4] ;; ARM7 Instruction Entry ----------------------------------------------------------------------------------- fEQ: OUTd "Cond:EQ " test SC_CPSR, FLAG_Z jne fAL fNV: OUTd ":Skip " ARM7_ExitAddPC 1 fNE: OUTd "Cond:NE " test SC_CPSR, FLAG_Z je fAL ARM7_ExitAddPC 1 fCS: OUTd "Cond:CS " test SC_CPSR, FLAG_C jne fAL jmp fNV fCC: OUTd "Cond:CC " test SC_CPSR, FLAG_C je fAL jmp fNV fMI: OUTd "Cond:MI " test SC_CPSR, FLAG_N jne fAL jmp fNV fPL: OUTd "Cond:PL " test SC_CPSR, FLAG_N je fAL jmp fNV fVS: OUTd "Cond:VS " test SC_CPSR, FLAG_V jne fAL jmp fNV fVC: OUTd "Cond:VC " test SC_CPSR, FLAG_V je fAL jmp fNV fHI: ;; C = 1 && Z = 0 OUTd "Cond:HI " mov ecx, SC_CPSR and ecx, FLAG_CZ cmp ecx, FLAG_C je fAL jmp fNV fLS: ;; C = 0 || Z = 1 OUTd "Cond:LS " mov ecx, SC_CPSR and ecx, FLAG_CZ ;; C0Z1 ^ C1Z0 -> C1Z1 ;; C1Z1 ^ C1Z0 -> C0Z1 ;; C0Z0 ^ C1Z0 -> C1Z0 ;; C1Z0 ^ C1Z0 -> ZERO. xor ecx, FLAG_C jne fAL jmp fNV fGE: ;; N = V OUTd "Cond:GE " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx je fAL jmp fNV fLT: ;; N != V OUTd "Cond:LT " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx jne fAL jmp fNV fGT: ;; N = V && Z= 0 OUTd "Cond:GT " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx mov ecx, SC_CPSR shr ecx, FLAG_Z_TOLSB_BIT and ecx, 1 or eax, ecx je fAL jmp fNV fLE: ;; Z = 1 || N!=V OUTd "Cond:LE " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx mov ecx, SC_CPSR shr ecx, FLAG_Z_TOLSB_BIT and ecx, 1 or eax, ecx je fNV fAL: ;; 1110 mov ecx, SC_INVOL mov eax, SC_INVOL mov edx, SC_INVOL and edx, -1 rol ecx, 8 nop rol cx, 4 nop and ecx, 0FFh nop jmp jTAB[ecx*4] AND_OP equ 0 EOR_OP equ 1 SUB_OP equ 2 ;; With C RSB_OP equ 3 ;; With C ADD_OP equ 4 ;; With C ADC_OP equ 5 ;; With C SBC_OP equ 6 ;; With C RSC_OP equ 7 ;; With C TST_OP equ 8 ;; NORMAL SET- TEQ_OP equ 9 ;; NORMAL SET- CMP_OP equ 10 ;; With C CMN_OP equ 11 ;; With C ORR_OP equ 12 MOV_OP equ 13 BIC_OP equ 14 MVN_OP equ 15 ARM7_ALU_BASE macro OPID, LhsOut, Rhs IF OPID eq AND_OP and LhsOut, Rhs ELSEIF OPID eq EOR_OP xor LhsOut, Rhs ELSEIF OPID eq ORR_OP or LhsOut, Rhs ELSEIF OPID eq SUB_OP sub LhsOut, Rhs ELSEIF OPID eq ADD_OP add LhsOut, Rhs ELSEIF OPID eq MOV_OP mov LhsOut, Rhs ELSEIF OPID eq MVN_OP not Rhs mov LhsOut, Rhs ELSEIF OPID eq BIC_OP not Rhs and LhsOut, Rhs ELSEIF OPID eq RSB_OP sub Rhs, LhsOut mov LhsOut, Rhs ELSEIF OPID eq SBC_OP xor SC_CPSR, FLAG_C btc SC_CPSR, FLAG_CHECK_C_X86_BT sbb LhsOut, Rhs ELSEIF OPID eq RSC_OP xor SC_CPSR, FLAG_C btc SC_CPSR, FLAG_CHECK_C_X86_BT sbb Rhs, LhsOut mov LhsOut, Rhs ELSEIF OPID eq ADC_OP bt SC_CPSR, FLAG_CHECK_C_X86_BT adc LhsOut, Rhs ELSEIF OPID eq TST_OP and LhsOut, Rhs SetNZ_A ELSEIF OPID eq TEQ_OP xor LhsOut, Rhs SetNZ_A ELSEIF OPID eq CMP_OP cmp LhsOut, Rhs SetNZCV_A 1 ELSEIF OPID eq CMN_OP add LhsOut, Rhs SetNZCV_A 0 ELSE ;; never reach here, make a simple syntax errors ERRORS_ASSERT ENDIF endm ARM7_ALU_SIGN_BASE macro OPID, LhsOut, Rhs ;; LhsOut Must not eax! IF OPID eq AND_OP and LhsOut, Rhs SetNZ_A ELSEIF OPID eq EOR_OP xor LhsOut, Rhs SetNZ_A ELSEIF OPID eq ORR_OP or LhsOut, Rhs SetNZ_A ELSEIF OPID eq SUB_OP sub LhsOut, Rhs SetNZCV_A 1 ELSEIF OPID eq ADD_OP add LhsOut, Rhs SetNZCV_A 0 ELSEIF OPID eq MOV_OP mov LhsOut, Rhs test LhsOut, LhsOut SetNZ_A ELSEIF OPID eq MVN_OP not Rhs mov LhsOut, Rhs test LhsOut, LhsOut SetNZ_A ELSEIF OPID eq BIC_OP not Rhs and LhsOut, Rhs SetNZ_A ELSEIF OPID eq RSB_OP sub Rhs, LhsOut mov LhsOut, Rhs SetNZCV_A 1 ELSEIF OPID eq SBC_OP xor SC_CPSR, FLAG_C bt SC_CPSR, FLAG_CHECK_C_X86_BT sbb LhsOut, Rhs SetNZCV_A 1 ELSEIF OPID eq RSC_OP xor SC_CPSR, FLAG_C bt SC_CPSR, FLAG_CHECK_C_X86_BT sbb Rhs, LhsOut mov LhsOut, Rhs SetNZCV_A 1 ELSEIF OPID eq ADC_OP bt SC_CPSR, FLAG_CHECK_C_X86_BT adc LhsOut, Rhs SetNZCV_A 0 ELSE ;; never reach here, make a simple syntax errors ERRORS_ASSERT ENDIF endm i8r4_ALU macro lSym, OPID @ALIGN_Z i8r4&lSym: ;; Clks 1: ALU Operate, and MemAccess Seq Read Next Opcode, indicate next mREQ:0 Seq:0 IF (OPID and 1100b) ne 1000b Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSEIF (OPID and 1100b) eq 1000b Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ENDIF GetRFIV SC_INVOL, 16, ecx ;; Rn GetRFI SC_INVOL, 12, edx ;; RdIs ARM7_ALU_BASE_OUTd1 OPID ARM7_ALU_BASE OPID, ecx, eax IF (OPID and 1100b) ne 1000b ;; Write Back, Check R15. mov ZRS (edx), ecx cmp edx, 15 jne @F ;; dest := pc ;; Clks 2: MemAccess, NoSeq Read. (because current is new pc read first), indicate next mREQ:0 Seq:1 ;; Clks 3: MemAccess (new pc read, second), Seq Read. arm7_FlushPipeline 3 @@: ENDIF ARM7_ExitAddPC 1 IF (OPID and 1100b) ne 1000b @ALIGN_Z i8r4&lSym&S: ;; Save Old CPSR mov [SC_ARM7].calc, SC_CPSR IF OPID eq AND_OP Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ELSEIF OPID eq EOR_OP Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ELSEIF OPID eq ORR_OP Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ELSEIF OPID eq SUB_OP ;; with C Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSEIF OPID eq ADD_OP ;; with C Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSEIF OPID eq MOV_OP Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ELSEIF OPID eq MVN_OP Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ELSEIF OPID eq BIC_OP Imm8BitmapSft_AC_SetC SC_INVOL, eax ;; Rm ELSEIF OPID eq RSB_OP ;; with C Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSEIF OPID eq SBC_OP ;; with C Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSEIF OPID eq RSC_OP ;; with C Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSEIF OPID eq ADC_OP ;; with C Imm8BitmapSft_AC SC_INVOL, eax ;; Rm ELSE ;; never reach here, make a simple syntax errors ERRORS_ASSERT ENDIF GetRFIV SC_INVOL, 16, ecx ;; Rn GetRFI SC_INVOL, 12, edx ;; RdIs ARM7_ALU_SIGN_BASE_OUTd1 OPID ARM7_ALU_SIGN_BASE OPID, ecx, eax mov ZRS (edx), ecx cmp edx, 15 je @F ARM7_ExitAddPC 1 @@: ;; R15 resume old CPSR. mov SC_CPSR, [SC_ARM7].calc SPSRToCPSR edx test SC_CPSR, FLAG_THUMB je @F tb_FlushPipeline 3 @@: arm7_FlushPipeline 3 ENDIF endm si5_ALU macro lSym, OPID si5&lSym: ARM7_ALU_BASE_OUTd2 OPID IF (OPID and 1100b) ne 1000b ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ELSEIF (OPID and 1100b) eq 1000b ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ENDIF GetRFIV edx, 16, ecx ;; Rn GetRFI edx, 12, edx ;; RdIs ARM7_ALU_BASE OPID, ecx, eax IF (OPID and 1100b) ne 1000b ;; Write Back, Check R15. mov ZRS (edx), ecx cmp edx, 15 jne @F arm7_FlushPipeline 3;; +1S +1N @@: ENDIF ARM7_ExitAddPC 1 IF (OPID and 1100b) ne 1000b si5&lSym&S: ;; Save Old CPSR mov [SC_ARM7].calc, SC_CPSR IF OPID eq AND_OP ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ;; Rm ELSEIF OPID eq EOR_OP ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ;; Rm ELSEIF OPID eq ORR_OP ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ;; Rm ELSEIF OPID eq SUB_OP ;; with C ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ;; Rm ELSEIF OPID eq ADD_OP ;; with C ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ;; Rm ELSEIF OPID eq MOV_OP ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ;; Rm ELSEIF OPID eq MVN_OP ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ;; Rm ELSEIF OPID eq BIC_OP ShiftRegImm5 SC_INVOL, eax, ecx, eax, C_op_Care ;; Rm ELSEIF OPID eq RSB_OP ;; with C ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ;; Rm ELSEIF OPID eq SBC_OP ;; with C ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ;; Rm ELSEIF OPID eq RSC_OP ;; with C ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ;; Rm ELSEIF OPID eq ADC_OP ;; with C ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, eax ;; Rm ELSE ;; never reach here, make a simple syntax errors ERRORS_ASSERT ENDIF ARM7_ALU_SIGN_BASE_OUTd2 OPID GetRFIV SC_INVOL, 16, ecx ;; Rn GetRFI SC_INVOL, 12, edx ;; RdIs ARM7_ALU_SIGN_BASE OPID, ecx, eax mov ZRS (edx), ecx cmp edx, 15 je @F ARM7_ExitAddPC 1 @@: ;; R15 resume old CPSR. mov SC_CPSR, [SC_ARM7].calc SPSRToCPSR edx test SC_CPSR, FLAG_THUMB je @F tb_FlushPipeline 3 @@: arm7_FlushPipeline 3 ENDIF endm rs_ALU macro lSym, OPID LOCAL locSym LOCAL locSym_S rs&lSym: GamePAK_Prefetch 1 IF (OPID and 1100b) ne 1000b ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ELSEIF (OPID and 1100b) eq 1000b ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ENDIF GetRFI SC_INVOL, 16, ecx ;; RnI cmp ecx, SZ_PC mov ecx, ZRS (ecx) jne locSym add ecx, 4 locSym: GetRFI SC_INVOL, 12, edx ;; RdIs ARM7_ALU_BASE_OUTd2 OPID ARM7_ALU_BASE OPID, ecx, eax ;; In Rs Shift. Add I (Internal) Clk ;; In AGB, I Clk can access GamePAK Cache. (I cycle does not access memory) IF (OPID and 1100b) ne 1000b ;; Write Back, Check R15. mov ZRS (edx), ecx cmp edx, 15 jne @F arm7_FlushPipeline 4 @@: ENDIF ARM7_ExitAddPC 2 IF (OPID and 1100b) ne 1000b rs&lSym&S: GamePAK_Prefetch 1 mov [SC_ARM7].calc, SC_CPSR IF OPID eq AND_OP ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ;; Rm ELSEIF OPID eq EOR_OP ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ;; Rm ELSEIF OPID eq ORR_OP ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ;; Rm ELSEIF OPID eq SUB_OP ;; with C ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ;; Rm ELSEIF OPID eq ADD_OP ;; with C ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ;; Rm ELSEIF OPID eq MOV_OP ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ;; Rm ELSEIF OPID eq MVN_OP ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ;; Rm ELSEIF OPID eq BIC_OP ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_Care ;; Rm ELSEIF OPID eq RSB_OP ;; with C ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ;; Rm ELSEIF OPID eq SBC_OP ;; with C ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ;; Rm ELSEIF OPID eq RSC_OP ;; with C ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ;; Rm ELSEIF OPID eq ADC_OP ;; with C ShiftRegRs SC_INVOL, eax, ecx, edx, C_op_NOCare ;; Rm ELSE ;; never reach here, make a simple syntax errors ERRORS_ASSERT ENDIF GetRFI SC_INVOL, 16, ecx ;; RnI cmp ecx, SZ_PC mov ecx, ZRS (ecx) jne locSym_S add ecx, 4 locSym_S: GetRFI SC_INVOL, 12, edx ;; RdIs ARM7_ALU_SIGN_BASE_OUTd2 OPID ARM7_ALU_SIGN_BASE OPID, ecx, eax mov ZRS (edx), ecx cmp edx, 15 je @F ARM7_ExitAddPC 2 @@: ;; R15 resume old CPSR. mov SC_CPSR, [SC_ARM7].calc SPSRToCPSR edx test SC_CPSR, FLAG_THUMB je @F tb_FlushPipeline 4 @@: arm7_FlushPipeline 4 ENDIF endm ;; ------------------------- ALU+Imm8+Sft ;; 27 26 25 24 23 22 21 20 19 - 16 15 - 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 0 0 1 Opcode S Rn Rd Imm8+Sft ;; 0 0 1 1 0 R 1 0 fmask SBO Imm8+Sft i8r4_ALU AND, AND_OP i8r4_ALU EOR, EOR_OP i8r4_ALU SUB, SUB_OP i8r4_ALU RSB, RSB_OP i8r4_ALU ADD, ADD_OP i8r4_ALU ADC, ADC_OP i8r4_ALU SBC, SBC_OP i8r4_ALU RSC, RSC_OP i8r4_ALU TST, TST_OP i8r4_ALU TEQ, TEQ_OP i8r4_ALU CMP, CMP_OP i8r4_ALU CMN, CMN_OP i8r4_ALU ORR, ORR_OP i8r4_ALU MOV, MOV_OP i8r4_ALU BIC, BIC_OP i8r4_ALU MVN, MVN_OP mUB: i8r4UB: int 3 ;; ------------------------- ALU+Imm5 ;; 27 26 25 24 23 22 21 20 19 - 16 15 - 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 0 0 0 Opcode S Rn Rd Imm5 T T 0 Rm ;; 0 0 0 1 0 R 1 0 fmask SBO SBZ 0 0 0 0 Rm MSR PSR, Rm si5_ALU AND, AND_OP si5_ALU EOR, EOR_OP si5_ALU SUB, SUB_OP si5_ALU RSB, RSB_OP si5_ALU ADD, ADD_OP si5_ALU ADC, ADC_OP si5_ALU SBC, SBC_OP si5_ALU RSC, RSC_OP si5_ALU TST, TST_OP si5_ALU TEQ, TEQ_OP si5_ALU CMP, CMP_OP si5_ALU CMN, CMN_OP si5_ALU ORR, ORR_OP si5_ALU MOV, MOV_OP si5_ALU BIC, BIC_OP si5_ALU MVN, MVN_OP ;; ------------------------- ALU+RegSft ;; 27 26 25 24 23 22 21 20 19 - 16 15 - 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 0 0 0 Opcode S Rn Rd Rs 0 T T 1 Rm rs_ALU AND, AND_OP rs_ALU EOR, EOR_OP rs_ALU SUB, SUB_OP rs_ALU RSB, RSB_OP rs_ALU ADD, ADD_OP rs_ALU ADC, ADC_OP rs_ALU SBC, SBC_OP rs_ALU RSC, RSC_OP rs_ALU TST, TST_OP rs_ALU TEQ, TEQ_OP rs_ALU CMP, CMP_OP rs_ALU CMN, CMN_OP rs_ALU ORR, ORR_OP rs_ALU MOV, MOV_OP rs_ALU BIC, BIC_OP rs_ALU MVN, MVN_OP ;; --------------------------------------------------------------------------------------------- ;; 27 26 25 24 23 22 21 20 19 - 16 15 - 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 Rn branch exchange @ALIGN_Z rsBX: ;; BX Rn GetRFIV SC_INVOL, 0, eax OUTd "BX R%d:%08X- PC:%08X \n", "SC_INVOL & 15", "eax","ZF-8" test eax, 1 jne @F and eax, -4 mov ZRS (SZ_PC), eax arm7_FlushPipeline 3 @@: and eax, -2 or SC_CPSR, FLAG_THUMB ;; set thumb flag and eax, -2 mov ZRS (SZ_PC), eax tb_FlushPipeline 3 rsUB: int 3 ;; ------------------------- branch clks:3 2Seq + 1N Cycles ;; 27 26 25 24 23 22 21 20 19 - 16 15 - 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 1 0 1 L Sign Offset 24 JMP24: ;; without LR and edx, 0FFFFFFh bt edx, 23 sbb ecx, ecx and ecx, 03F000000h ;; save 30 bit or ecx, edx shl ecx, 2 ;; shift 2 OUTd "B %06X- PC:%08X LR:%08X \n", "ZF+ecx", "ZF-8" , "ZE" add ZRS (SZ_PC), ecx arm7_FlushPipeline 3 JMPLR: ;; with LR mov SC_INVOL, ZRS (SZ_PC) and edx, 0FFFFFFh bt edx, 23 sbb ecx, ecx and ecx, 03F000000h ;; save 30 bit or ecx, edx shl ecx, 2 ;; shift 2 OUTd "BL %06X- PC:%08X LR:%08X ", "ZF+ecx", "ZF-8" , "ZE" add ZRS (SZ_PC), ecx lea eax, [SC_INVOL-4] OUTd "NEW-LR:%08X \n", "eax" mov ZRS (SZ_LRLINK), eax ;; next pc save to LR. arm7_FlushPipeline 3 LDR_SET macro ldrtype, pre, link LDR_L equ 1 LDR_W equ 2 LDR_B equ 4 LDR_U equ 8 LDR_P equ 16 LDR_STD_IMM12 equ 0 ;;-> LDR_STD_SCALED equ 1 ;;-> LDR_EXT_LOHI8BIT equ 2 ;;-> LDR_EXT_RNMD equ 3 ;; :: ldrtype pre&link: IF ldrtype eq LDR_STD_IMM12 or (ldrtype eq LDR_STD_SCALED) IF (link and LDR_L) eq 0 OUTd "STR" ELSEIF (link and LDR_L) ne 0 OUTd "LDR" ENDIF IF (link and LDR_B) ne 0 OUTd "B" ENDIF IF ((link and LDR_W) ne 0) and ((link and LDR_P) eq 0) OUTd "T" ENDIF ELSEIF ldrtype eq LDR_EXT_LOHI8BIT or (ldrtype eq LDR_EXT_RNMD) IF (link and 5) eq 4 OUTd "STRH" ELSEIF (link and 5) ne 4 OUTd "LDR" IF (link and 5) eq 0 OUTd "H" ELSEIF (link and 5) eq 1 OUTd "SB" ELSEIF (link and 5) eq 5 OUTd "SH" ELSE ERRORS_ASSERT ENDIF ELSE ERRORS_ASSERT ENDIF ELSE ERRORS_ASSERT ENDIF IF (link and LDR_P) ne 0 OUTd " R%d, [R%d, ", "SC_INVOL } 12 & 15", "SC_INVOL } 16 & 15" ELSEIF (link and LDR_P) eq 0 OUTd " R%d, [R%d], ", "SC_INVOL } 12 & 15", "SC_INVOL } 16 & 15" ENDIF IF (link and LDR_U) eq 0 OUTd "-" ENDIF ;; Fetch Source . ;; P U X1 W X2 ;; X1 X2 3:= LDRSH (7) ;; 2:= STRHW (1) ;; 1:= LDRSB (6) ;; 0:= LDRUH (5) ;; eax:temp value, ecx:rn IF ldrtype eq LDR_STD_IMM12 mov eax, SC_INVOL and eax, 0FFFh ;; GetImm12 OUTd "#%03X", "eax" ELSEIF ldrtype eq LDR_STD_SCALED OUTd "R%d, ", "SC_INVOL & 15" ShiftRegImm5_WithOutC SC_INVOL, eax, ecx, edx ;; Rm Sft. ELSEIF ldrtype eq LDR_EXT_LOHI8BIT mov eax, SC_INVOL shl al, 4 shr eax, 4 and eax, 255 ;; LO|HI OUTd "#%02X", "eax" ELSEIF ldrtype eq LDR_EXT_RNMD GetRFIV SC_INVOL, 0, eax ;; GetRm OUTd "R%d", "SC_INVOL & 15" ELSE ERRORS_ASSERT ENDIF IF (link and LDR_P) ne 0 OUTd "]" IF (link and LDR_W) ne 0 OUTd "!" ENDIF ENDIF GetRFI SC_INVOL, 16, ecx ;; GetRn GetRFI SC_INVOL, 12, SC_INVOL ;; GetRd IF (link and LDR_U) eq 0 neg eax ENDIF ;; Post-Index?? IF (link and LDR_P) eq 0 mov edx, ZRS (ecx) add eax, edx ELSEIF (link and LDR_P) ne 0 mov edx, eax add edx, ZRS (ecx) mov eax, edx ENDIF IF (((link and LDR_P) eq 0) or ((link and LDR_W) ne 0)) mov ZRS (ecx), eax ENDIF ;; Check Access type IF ldrtype eq LDR_STD_IMM12 or (ldrtype eq LDR_STD_SCALED) IF (link and LDR_L) eq 0 ;; STR. STRB push ZRS (SC_INVOL) push edx push [SC_ARM7].agb IF (link and LDR_B) ne 0 CALLIt MmuWriteByteNoSeq ELSEIF (link and LDR_B) eq 0 ;; Is R15?? + PCSTOREOFFSET - 8 cmp SC_INVOL, 15 jne @F add PTR32[esp+8], 4 @@: CALLIt MmuWriteWordNoSeq ENDIF mov [SC_ARM7].nextNoSeqFetch, 1 Add_WaitStateClks ARM7_ExitAddPC 2 ;; 2 noSEQ clks. ELSEIF (link and LDR_L) ne 0 ;; LDR. LDRB GamePAK_Prefetch 1 push edx push [SC_ARM7].agb IF (link and LDR_B) ne 0 CALLIt MmuReadByteNoSeq movzx eax, al ELSEIF (link and LDR_B) eq 0 mov [SC_ARM7].calc, edx CALLIt MmuReadWordNoSeq mov ecx, [SC_ARM7].calc and ecx, 3 shl ecx, 3 ror eax, cl ENDIF Add_WaitStateClks mov ZRS (SC_INVOL), eax cmp SC_INVOL, 15 je @F ARM7_ExitAddPC 3 ;; S+N+1 3Clks. @@: and ZRS (SC_INVOL), -4 arm7_FlushPipeline 5 ENDIF ELSEIF ldrtype eq LDR_EXT_LOHI8BIT or (ldrtype eq LDR_EXT_RNMD) IF (link and 5) eq 4 push ZRS (SC_INVOL) push edx CallMemOrIOAddWaitState MmuWriteHalfWordNoSeq mov [SC_ARM7].nextNoSeqFetch, 1 ARM7_ExitAddPC 2 ;; 2 noSEQ clks. ELSEIF (link and 5) ne 4 push edx push [SC_ARM7].agb GamePAK_Prefetch 1 IF (link and 5) eq 0 mov [SC_ARM7].calc, edx CALLIt MmuReadHalfWordNoSeq mov ecx, [SC_ARM7].calc and eax, 0FFFFh and ecx, 1 shl ecx, 3 ror eax, cl ELSEIF (link and 5) eq 1 CALLIt MmuReadByteNoSeq movsx eax, al ELSEIF (link and 5) eq 5 mov [SC_ARM7].calc, edx CALLIt MmuReadHalfWordNoSeq mov ecx, [SC_ARM7].calc mov edx, eax movsx eax, ax and ecx, 1 je @F movsx eax, dh @@: ELSE ERRORS_ASSERT ENDIF Add_WaitStateClks mov ZRS (SC_INVOL), eax cmp SC_INVOL, 15 je @F ARM7_ExitAddPC 3 ;; S+N+1 3Clks. @@: and ZRS (SC_INVOL), -4 arm7_FlushPipeline 5 ENDIF ELSE ERRORS_ASSERT ENDIF endm SWINT: ;; ARM7 Software Interrupt OUTd "SWI-ARM7 FUNC:%02X R0 %08X R1 %08X R2 %08X\n", "SC_INVOL & 0FFFFFFh", "Z0", "Z1", "Z2" mov eax, ZRS (SZ_PC) mov ecx, SC_CPSR and ecx, ARM7_MODE_CLR_MASK or ecx, ARM7_MODE_MGR_MASK ;; Set SVC mode. and ecx, not FLAG_THUMB ;; Clear Thumb exec flag or ecx, IRQ_INHIBI_MASK ;; Set IRQ inhibit mask ;; PC to SVC's LR, LR:= Current Instruction +4 lea edx, [eax-4] mov [SC_ARM7].R1314_T[R1314b_MGR+4], edx ;; Adjust PC Pointer to IRQ Interrupt vector address mov ZRS (SZ_PC), ARM7_VECTOR_SOFTWARE mov SC_INVOL, SC_CPSR and SC_INVOL, ARM7_MODE_GET_MASK cmp SC_INVOL, ARM7_MODE_MGR_MASK je @NestSwi_ARM7 ;; switch Mode SwitchMode ecx, 0 ;; Prefetch Opcode pipeline arm7_FlushPipeline 3 @NestSwi_ARM7: mov ZRS (SZ_LRLINK), edx mov [SC_ARM7].SPSR_T[SPSRb_MGR], SC_CPSR mov eax, ZRS (SZ_STACK) mov [SC_ARM7].R1314_T[R1314b_MGR], eax mov eax, ZRS (SZ_LRLINK) mov [SC_ARM7].R1314_T[R1314b_MGR+4], eax mov SC_CPSR, ecx ;; Prefetch Opcode pipeline arm7_FlushPipeline 3 ;; PSR MASK In V4T Version , UseMask 0xF0000000, PrivMask 0x0000000F, State Mask 0x00000020 ;; This means that in any case you can't control the interrupt shielding bit field through MSR. ;; That sounds really incredible! ;; Many books and software examples show that it can be controlled by MSR. ;; I really don't know who to trust. ;; See ARM Architecture Reference Manual::A4.1.39 MSR IFDEF STRICT_MODE_PSR ARM7_PSR_CTL_MASK equ ARM7_PSR_MODE4BIT_MASK ELSE ARM7_PSR_CTL_MASK equ ARM7_PSR_MODE8BIT_MASK ENDIF i8r4ToCPSR: Imm8BitmapSft_AC SC_INVOL, eax OUTd "MSR #%08X(org)", "eax" jmp @F si5ToCPSR: ;; 0 1 MSR Rs CPSR TODO:Check d4-d7 := 0 OUTd "MSR R%d to cpsr_", "SC_INVOL & 15" GetRFIV edx, 0, eax @@: ToFastPSR eax, eax, eax, ecx ;; Limit MASK, in fact write will only affect flag and cpu mode's low 4bit in std arm7. OUTd " #%08X(fast) to spsr_", "eax" mov [SC_ARM7].calc, SC_CPSR ;;;; FIXME: mov ecx, SC_CPSR and ecx, ARM7_MODE_GET_MASK cmp ecx, ARM7_MODE_USER_MASK jne @Privilege_MSR ;; USER Mode MSR. ;; Only Affect Flag Bit. @ChkSetFLags: test edx, FLAG_MSR_FLAGS je @F and SC_CPSR, not ARM7_PSR_FLAG_MASK and eax, ARM7_PSR_FLAG_MASK or SC_CPSR, eax @@: test SC_CPSR, FLAG_THUMB je @F int 3 @@: ARM7_ExitAddPC 1 @Privilege_MSR: test edx, FLAG_MSR_CTL je @ChkSetFLags IF 1 ;; PriMode MSR. test edx, FLAG_MSR_FLAGS jne @F mov edx, SC_CPSR and edx, not ARM7_PSR_CTL_MASK and eax, ARM7_PSR_CTL_MASK or eax, edx or eax, ARM7_MODE_MSB_BIT_MASK SwitchMode eax, 1 test SC_CPSR, FLAG_THUMB je @Skip int 3 @Skip: ARM7_ExitAddPC 1 @@: mov SC_INVOL, eax mov edx, SC_CPSR and edx, not ARM7_PSR_CTL_MASK and eax, ARM7_PSR_CTL_MASK or eax, edx or eax, ARM7_MODE_MSB_BIT_MASK SwitchMode eax, 1 and SC_CPSR, not ARM7_PSR_FLAG_MASK and SC_INVOL, ARM7_PSR_FLAG_MASK or SC_CPSR, SC_INVOL test SC_CPSR, FLAG_THUMB je @F int 3 @@: ARM7_ExitAddPC 1 ELSE ENDIF ;; TODO: assert mode, flags si5PSR4: ;; 1 1 MSR Rs SPSR OUTd "MSR R%d to spsr_", "SC_INVOL & 15" GetRFIV edx, 0, eax ToFastPSR eax, eax, eax, ecx jmp toSPSR_main i8r4ToSPSR: Imm8BitmapSft_AC SC_INVOL, eax OUTd "MSR #%08X(org)", "eax" ToFastPSR eax, eax, eax, ecx OUTd " #%08X(fast) to spsr_", "eax" toSPSR_main: GetCurSPSRP ecx test edx, FLAG_MSR_FLAGS je @F mov SC_INVOL, eax and PTR32[ecx], not ARM7_PSR_FLAG_MASK and SC_INVOL, ARM7_PSR_FLAG_MASK or [ecx], SC_INVOL OUTd "f" @@: test edx, FLAG_MSR_CTL je @F OUTd "c" and PTR32[ecx], not (ARM7_PSR_CTL_MASK or ARM7_PSR_STATE_MASK) and eax, (ARM7_PSR_CTL_MASK or ARM7_PSR_STATE_MASK) or [ecx], eax or PTR32[ecx], ARM7_MODE_MSB_BIT_MASK @@: ARM7_ExitAddPC 1 si5PSR1: ;; 0 0 MRS Rs CPSR OUTd "MRS R%d, CPSR", "SC_INVOL}12 & 15" ToStandPSR SC_CPSR, ecx, eax, ecx jmp @F si5PSR3: ;; 1 0 MRS Rs SPSR, TODO: Check SBO/SBZ OUTd "MRS R%d, SPSR", "SC_INVOL}12 & 15" GetCurSPSRP eax mov eax, [eax] ToStandPSR eax, ecx, eax, ecx @@: GetRFI edx, 12, eax and ecx, 00F00000FFh or ecx, 010h mov ZRS (eax), ecx ARM7_ExitAddPC 1 ;; XXX: This macro branch is actually terrible to write. REGS_SET_OP macro link LOCAL stdPush LOCAL fiqPush LOCAL usrPush LOCAL usrPushFiq LOCAL usrPushFiq_R8_12 LOCAL usrPushFiq_R13_14 LOCAL usrPushFiq_next LOCAL usrPushFiq_next2 LOCAL stdPush_Q LOCAL usrPush_Q LOCAL stdPush_Q2 LOCAL usrPush_Q2 LOCAL outPush LOCAL stdPop LOCAL fiqPop LOCAL usrPop LOCAL usrPopFiq LOCAL usrPopFiq_R8_12 LOCAL usrPopFiq_R13_14 LOCAL usrPopFiq_next LOCAL usrPopFiq_next2 LOCAL usrPopFiqFirst LOCAL stdPop_Q LOCAL usrPop_Q LOCAL stdPop_Q2 LOCAL stdPop_HitR15 LOCAL usrPop_Q2 LOCAL outPop LOCAL stdPushFirst LOCAL usrPushFirst LOCAL usrPushFiqFirst LOCAL stdPopFirst LOCAL usrPopFirst LOCAL usrPopFiqFirst LOCAL LDM_empty LOCAL STM_empty z&link: ;; have to use variables. LDM_STACK_REQUIRE equ 128 RSO_L equ 1 RSO_W equ 2 RSO_S equ 4 RSO_U equ 8 RSO_P equ 16 RnAddress equ 16 RnIndex equ 20 RnCount equ 28 Reglist equ 32 RnWriteBack equ 36 RnAdjust equ 40 RnFirst equ 44 RnTemp equ 52 RnTempi equ 56 IF (link and RSO_L) eq 0 OUTd "STM" ELSEIF (link and RSO_L) ne 0 OUTd "LDM" GamePAK_Prefetch 1 ;; I cycle before fetch new opcode. ENDIF IF (link and RSO_U) eq 0 OUTd "D" ELSEIF (link and RSO_U) ne 0 OUTd "I" ENDIF IF (link and RSO_P) eq 0 OUTd "A" ELSEIF (link and RSO_P) ne 0 OUTd "B" ENDIF OUTd " R%d", "SC_INVOL } 16 & 15" IF (link and RSO_W) ne 0 OUTd "!" ENDIF OUTd ", " OUTd "[ R15-R12:%01X, R11-R8:%01X ", "SC_INVOL } 12 & 15", "SC_INVOL } 8 & 15" OUTd " R7-R4:%01X, R3-R0:%01X ]", "SC_INVOL } 4 & 15", "SC_INVOL & 15" IF (link and RSO_S) ne 0 OUTd "^" ENDIF sub esp, LDM_STACK_REQUIRE xor eax, eax mov STA (RnAddress), eax mov STA (RnIndex), eax mov STA (RnAdjust), eax mov STA (RnFirst), eax mov STA (RnCount), eax GetRFI SC_INVOL, 16, eax ;;Rn. mov ecx, SC_INVOL mov edx, ZRS (eax) ;;GetRn and ecx, 0FFFFh mov STA (RnIndex), eax mov STA (RnAddress), edx IF (link and RSO_U) ne 0 mov SC_INVOL, 4 ELSEIF (link and RSO_U) eq 0 mov SC_INVOL, -4 ENDIF mov STA (Reglist), ecx mov eax, ecx xor ecx, ecx mov edx, 16 @@: shr ax, 1 adc cx, 0 dec dx jne @B ;; TODO: assert 0 shl ecx, 2 mov edx, STA (RnAddress) IF (link and RSO_U) ne 0 add edx, ecx ELSEIF (link and RSO_U) eq 0 sub edx, ecx lea eax, [edx+4] mov STA (RnAddress), eax ENDIF mov STA (RnWriteBack), edx IF (link and RSO_P) ne 0 add STA (RnAddress), SC_INVOL ENDIF mov SC_INVOL, STA (RnAddress) ;; STM------------------------------------------------------- ;; STM------------------------------------------------------- ;; STM------------------------------------------------------- IF (link and RSO_L) eq 0 test STA (Reglist), 0FFFFh je STM_empty IF (link and RSO_W) ne 0 ;; Check Rn's adjust mov ecx, STA (RnIndex) bt STA (Reglist), ecx jnc @F sbb edx, edx ;; Check is First Vailed bit mov eax, edx shl eax, cl xor eax, edx test STA (Reglist), eax je @F ;; TODO: error. ;; Dirty register, write directly mov eax, STA (RnIndex) mov ecx, STA (RnWriteBack) mov ZRS (eax), ecx @@: ENDIF IF (link and RSO_S) ne 0 ;; In User mode, Check Current is user/sys mode ;; If hit, use std copy . (Because the user-mode cache register may not have been updated) mov eax, SC_CPSR and eax, ARM7_MODE_GET_MASK cmp eax, ARM7_MODE_SYS_MASK je stdPush cmp eax, ARM7_MODE_USER_MASK je stdPush cmp eax, ARM7_MODE_FIQ_MASK je usrPushFiq jmp usrPush ELSEIF (link and RSO_S) eq 0 jmp stdPush ENDIF ;; STM empty ------------------------------------------------------- STM_empty: mov edx, STA (RnIndex) push STACK_PUSH_STATUS_PUSH push SZ_PC mov eax, ZRS (SZ_PC) add eax, 4 push eax push ZRS (edx) IF (link and RSO_W) ne 0 IF (link and RSO_U) ne 0 add ZRS (edx), 64 ELSE sub ZRS (edx), 64 ENDIF ENDIF and ZRS (edx), -4 CallMemOrIOAddWaitState StackWriteNoSeq add esp, LDM_STACK_REQUIRE mov [SC_ARM7].nextNoSeqFetch, 1 ARM7_ExitAddPC 2 ;; STM User Mode ------------------------------------------------------- usrPush: shr STA (Reglist), 1 jnc @F inc SC_WAIT ;; + 1 S or N cycle mov eax, STA (RnCount) mov ecx, ZRS (eax) add eax, 1 and eax, 15 push STACK_PUSH_STATUS_PUSH push eax cmp eax, 14 jb usrPush_Q sub eax, 14 mov ecx, [SC_ARM7].R1314_T[R1314b_SYSUSER+ eax*4] usrPush_Q: test eax, eax jne usrPush_Q2 add ecx, 4 usrPush_Q2: push ecx mov eax, SC_INVOL add SC_INVOL, 4 ;;and eax, -4 push eax cmp STA (RnFirst+16), 0 mov STA (RnFirst+16), 1 je usrPushFirst CallMemOrIOAddWaitState StackWriteSeq jmp @F usrPushFirst: CallMemOrIOAddWaitState StackWriteNoSeq @@: add STA (RnCount), 1 cmp STA (RnCount), 16 jb usrPush jmp outPush ;; STM User Mode FIQ ----------------Will this happen to GBA?--------------------------------------- usrPushFiq: shr STA (Reglist), 1 jnc @F inc SC_WAIT ;; + 1 S or N cycle mov eax, STA (RnCount) mov ecx, ZRS (eax) add eax, 1 and eax, 15 push STACK_PUSH_STATUS_PUSH push eax cmp eax, 9 jb usrPushFiq_next cmp eax, 14 jb usrPushFiq_R8_12 usrPushFiq_R8_12: sub eax, 9 mov ecx, [SC_ARM7].R812_T[R812b_EXCEPT_FIQ+ eax*4] jmp usrPushFiq_next2 usrPushFiq_R13_14: sub eax, 14 mov ecx, [SC_ARM7].R1314_T[R1314b_SYSUSER+ eax*4] jmp usrPushFiq_next2 usrPushFiq_next: test eax, eax jne usrPushFiq_next2 add ecx, 4 usrPushFiq_next2: push ecx mov eax, SC_INVOL add SC_INVOL, 4 ;;and eax, -4 push eax cmp STA (RnFirst+16), 0 mov STA (RnFirst+16), 1 je usrPushFiqFirst CallMemOrIOAddWaitState StackWriteSeq jmp @F usrPushFiqFirst: CallMemOrIOAddWaitState StackWriteNoSeq @@: add STA (RnCount), 1 cmp STA (RnCount), 16 jb usrPushFiq jmp outPush ;; STM Std Mode -------------------------------------------------------- stdPush: shr STA (Reglist), 1 jnc @F inc SC_WAIT ;; + 1 S or N cycle mov eax, STA (RnCount) push STACK_PUSH_STATUS_PUSH push eax push ZRS (eax) cmp eax, 15 jne stdPush_Q2 add PTR32[esp], 4 stdPush_Q2: mov eax, SC_INVOL ;;and eax, -4 push eax add SC_INVOL, 4 cmp STA (RnFirst+16), 0 mov STA (RnFirst+16), 1 je stdPushFirst CallMemOrIOAddWaitState StackWriteSeq jmp @F stdPushFirst: CallMemOrIOAddWaitState StackWriteNoSeq @@: add STA (RnCount), 1 cmp STA (RnCount), 16 jb stdPush outPush: IF (link and RSO_W) ne 0 mov eax, STA (RnIndex) mov ecx, STA (RnWriteBack) mov ZRS (eax), ecx ;; TODO: RnCheck with Reglist ENDIF mov [SC_ARM7].nextNoSeqFetch, 1 add esp, LDM_STACK_REQUIRE ARM7_ExitAddPC 1 ELSEIF (link and RSO_L) ne 0 ;; LDM ---------------------------------------------------------------------- ;; LDM ---------------------------------------------------------------------- ;; LDM ---------------------------------------------------------------------- test STA (Reglist), 0FFFFh je LDM_empty ;; Check Rn's adjust mov ecx, STA (RnIndex) bt STA (Reglist), ecx jnc @F mov STA (RnAdjust), 1 @@: IF (link and RSO_S) ne 0 test STA (Reglist), 08000h jne stdPop mov eax, SC_CPSR and eax, ARM7_MODE_GET_MASK cmp eax, ARM7_MODE_SYS_MASK je stdPop cmp eax, ARM7_MODE_USER_MASK je stdPop cmp eax, ARM7_MODE_FIQ_MASK je usrPopFiq jmp usrPop ELSEIF (link and RSO_S) eq 0 jmp stdPop ENDIF ;; LDM reglist empty ------------------------------------------------------- LDM_empty: mov ecx, STA (RnIndex) push ZRS(ecx) IF (link and RSO_W) ne 0 IF (link and RSO_U) ne 0 add ZRS(ecx), 64 ELSE sub ZRS(ecx), 64 ENDIF ENDIF and ZRS(ecx), -4 CallMemOrIOAddWaitState StackReadNoSeq mov ZRS (SZ_PC), eax add esp, LDM_STACK_REQUIRE arm7_FlushPipeline 3 ;; LDM User Mode ------------------------------------------------------- usrPop: shr STA (Reglist), 1 jnc @F inc SC_WAIT ;; + 1 S or N cycle mov eax, STA (RnCount) lea SC_INVOL, ZRS (eax) add eax, 1 and eax, 15 cmp eax, 14 jb @F sub eax, 14 lea SC_INVOL, [SC_ARM7].R1314_T[R1314b_SYSUSER+ eax*4] @@: mov eax, STA (RnAddress) add STA (RnAddress), 4 ;;and eax, -4 push eax cmp STA (RnFirst+4), 0 mov STA (RnFirst+4), 1 je usrPopFirst CallMemOrIOAddWaitState StackReadSeq mov [SC_INVOL], eax jmp @F usrPopFirst: CallMemOrIOAddWaitState StackReadNoSeq mov [SC_INVOL], eax @@: add STA (RnCount), 1 cmp STA (RnCount), 16 jb usrPop jmp outPop ;; LDM FIQ Mode ----------------Will this happen to GBA?--------------------------------------- usrPopFiq: shr STA (Reglist), 1 jnc @F inc SC_WAIT ;; + 1 S or N cycle mov eax, STA (RnCount) lea SC_INVOL, ZRS (eax) add eax, 1 and eax, 15 cmp eax, 14 jb usrPopFiq_next sub eax, 14 lea SC_INVOL, [SC_ARM7].R1314_T[R1314b_SYSUSER+ eax*4] jmp usrPopFiq_next2 usrPopFiq_next: cmp eax, 9 jb usrPopFiq_next2 sub eax, 9 lea SC_INVOL, [SC_ARM7].R812_T[R812b_EXCEPT_FIQ+ eax*4] usrPopFiq_next2: mov eax, STA (RnAddress) add STA (RnAddress), 4 ;;and eax, -4 push eax cmp STA (RnFirst+4), 0 mov STA (RnFirst+4), 1 je usrPopFiqFirst CallMemOrIOAddWaitState StackReadSeq mov [SC_INVOL], eax jmp @F usrPopFiqFirst: CallMemOrIOAddWaitState StackReadNoSeq mov [SC_INVOL], eax @@: add STA (RnCount), 1 cmp STA (RnCount), 16 jb usrPopFiq jmp outPop ;; LDM Std Mode -------------------------------------------------------- stdPop: shr STA (Reglist), 1 jnc @F inc SC_WAIT ;; + 1 S or N cycle mov eax, STA (RnCount) lea SC_INVOL, ZRS (eax) mov eax, STA (RnAddress) add STA (RnAddress), 4 ;;and eax, -4 push eax cmp STA (RnFirst+4), 0 mov STA (RnFirst+4), 1 je stdPopFirst CallMemOrIOAddWaitState StackReadSeq mov [SC_INVOL], eax ;; Check is finial?? cmp STA (RnCount), 15 jne @F jmp stdPop_HitR15 stdPopFirst: CallMemOrIOAddWaitState StackReadNoSeq mov [SC_INVOL], eax ;; Check is finial?? cmp STA (RnCount), 15 jne @F stdPop_HitR15: IF (link and RSO_W) ne 0 cmp STA (RnAdjust), 1 je stdPop_Q mov eax, STA (RnIndex) mov ecx, STA (RnWriteBack) mov ZRS (eax), ecx stdPop_Q: ENDIF IF (link and RSO_S) ne 0 SPSRToCPSR eax ENDIF add esp, LDM_STACK_REQUIRE test SC_CPSR, FLAG_THUMB jne stdPop_Q2 arm7_FlushPipeline 4 stdPop_Q2: tb_FlushPipeline 4 @@: add STA (RnCount), 1 cmp STA (RnCount), 16 jb stdPop outPop: IF (link and RSO_W) ne 0 cmp STA (RnAdjust), 1 je @F mov eax, STA (RnIndex) mov ecx, STA (RnWriteBack) mov ZRS (eax), ecx @@: ENDIF add esp, LDM_STACK_REQUIRE ARM7_ExitAddPC 2 ENDIF endm ;; TODO: one unit for LDM/STM ;; TODO: other Bank Rn!^ ? ;; TODO: empty load/ store A7SWP: ;; SWAP. S+2N+I GetRFIV SC_INVOL, 16, eax ;; Rn:= Address GetRFIV SC_INVOL, 0, ecx ;; Rm: mov [SC_ARM7].calc, eax push ecx push eax push [SC_ARM7].agb push eax push [SC_ARM7].agb test SC_INVOL, 00400000h je @F A7SWP_INLINE macro rd, wr, msk CALLIt rd add SC_WAIT, [SC_ARM7].waitState GetRFI SC_INVOL, 12, SC_INVOL ;; Rd:= Rd. and eax, msk if msk eq 0FFFFFFFFh ;; test align rot. mov ecx, [SC_ARM7].calc and ecx, 3 shl ecx, 3 ror eax, cl endif mov ZRS (SC_INVOL), eax CALLIt wr add SC_WAIT, [SC_ARM7].waitState GamePAK_Prefetch 1 ARM7_ExitAddPC 4 endm OUTd "SWPB R%d, R%d, [R%d]", "SC_INVOL}12 & 15", "SC_INVOL & 15", "SC_INVOL}16 & 15" A7SWP_INLINE MmuReadByteNoSeq, MmuWriteByteNoSeq, 0FFh @@: OUTd "SWP R%d, R%d, [R%d]", "SC_INVOL}12 & 15", "SC_INVOL & 15", "SC_INVOL}16 & 15" A7SWP_INLINE MmuReadWordNoSeq, MmuWriteWordNoSeq, 0FFFFFFFFh MUL_OP equ 0 MLA_OP equ 1 UMUL64_OP equ 2 UMLA64_OP equ 3 SMUL64_OP equ 4 SMLA64_OP equ 5 mulClks macro Post, TReg, Recv ;; XXX: TReg ^ Post ^ Recv ;; XXX: better case ;; multiplier's clks, m ;; see ARM7TDMI Technical Reference Manual's 6.20 Instruction speed summary ;; m is: ;; 1 if bits [31:8] of the multiplier operand (Rs) are all zero or one, else ;; 2 if bits [31:16] of the multiplier operand (Rs) are all zero or one, else ;; 3 if bits [31:24] of the multiplier operand (Rs) are all zero or all one, else ;; 4. bt Post, 31 sbb TReg, TReg xor TReg, Post movd xmm0, TReg pxor xmm1, xmm1 pcmpeqb xmm1, xmm0 pmovmskb TReg, xmm1 shl TReg, 29 sbb Recv, Recv shl TReg, 1 sbb Post, Post shl TReg, 1 sbb TReg, TReg and Post, Recv and TReg, Post add Recv, TReg lea Recv, [Recv+Post+4] endm mul_interp_b macro OPID GetRFIV SC_INVOL, 0, eax ;; Rm. GetRFIV SC_INVOL, 8, ecx ;; Rs. IF OPID eq MUL_OP OUTd "MUL R%d, R%d, R%d", "SC_INVOL}16 & 15", "SC_INVOL & 15", "SC_INVOL}8 & 15" mul ecx GetRFI SC_INVOL, 16, edx ;; Rd mov ZRS (edx), eax ELSEIF OPID eq MLA_OP OUTd "MLA R%d, R%d, R%d, R%d", "SC_INVOL}16 & 15", "SC_INVOL & 15", "SC_INVOL}8 & 15", "SC_INVOL}12 & 15" mul ecx GetRFIV SC_INVOL, 12, edx ;; Rn add eax, edx GetRFI SC_INVOL, 16, edx ;; Rd mov ZRS (edx), eax ELSEIF OPID eq UMUL64_OP OUTd "UMULL R%d, R%d, R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15", "SC_INVOL}8 & 15" movd xmm0, ecx mul ecx GetRFI SC_INVOL, 12, ecx ;; RdLO GetRFI SC_INVOL, 16, SC_INVOL ;; RdHI mov ZRS (ecx), eax mov ZRS (SC_INVOL), edx movd ecx, xmm0 ELSEIF OPID eq UMLA64_OP OUTd "UMLAL R%d, R%d, R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15", "SC_INVOL}8 & 15" movd xmm0, ecx mul ecx GetRFI SC_INVOL, 12, ecx ;; RdLO GetRFI SC_INVOL, 16, SC_INVOL ;; RdHI add eax, ZRS (ecx) adc edx, ZRS (SC_INVOL) mov ZRS (ecx), eax mov ZRS (SC_INVOL), edx movd ecx, xmm0 ELSEIF OPID eq SMUL64_OP OUTd "SMULL R%d, R%d, R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15", "SC_INVOL}8 & 15" movd xmm0, ecx imul ecx GetRFI SC_INVOL, 12, ecx ;; RdLO GetRFI SC_INVOL, 16, SC_INVOL ;; RdHI mov ZRS (ecx), eax mov ZRS (SC_INVOL), edx movd ecx, xmm0 ELSEIF OPID eq SMLA64_OP OUTd "SMLAL R%d, R%d, R%d, R%d", "SC_INVOL}12 & 15", "SC_INVOL}16 & 15", "SC_INVOL & 15", "SC_INVOL}8 & 15" movd xmm0, ecx imul ecx GetRFI SC_INVOL, 12, ecx ;; RdLO GetRFI SC_INVOL, 16, SC_INVOL ;; RdHI add eax, ZRS (ecx) adc edx, ZRS (SC_INVOL) mov ZRS (ecx), eax mov ZRS (SC_INVOL), edx movd ecx, xmm0 ELSE ERRORS_ASSERT ENDIF endm mul_interp macro lSym, OPID ;;LOCAL StdLink ;;LOCAL StdLinkWithSymbol LOCAL SetMClks m&lSym: OUTd "NOSET_SIGN " mul_interp_b OPID jmp SetMClks m&lSym&S: OUTd "SET_SIGN " mul_interp_b OPID IF OPID eq MUL_OP Set_NZmul32 eax ELSEIF OPID eq MLA_OP Set_NZmul32 eax ELSEIF OPID eq UMUL64_OP Set_NZmul64 eax, edx ELSEIF OPID eq UMLA64_OP Set_NZmul64 eax, edx ELSEIF OPID eq SMUL64_OP Set_NZmul64 eax, edx ELSEIF OPID eq SMLA64_OP Set_NZmul64 eax, edx ELSE ERRORS_ASSERT ENDIF SetMClks: mulClks ecx, edx, eax IF OPID eq MUL_OP ;; MUL := M I Clks. ELSEIF OPID eq MLA_OP ;; MLA := M+1 I Clks add eax, 1 ELSEIF OPID eq UMUL64_OP ;; UMULL := M+1 I Clks add eax, 1 ELSEIF OPID eq UMLA64_OP ;; UMLAL := M+2 I Clks add eax, 2 ELSEIF OPID eq SMUL64_OP ;; SMULL := M+1 I Clks add eax, 1 ELSEIF OPID eq SMLA64_OP ;; SMLAL := M+2 I Clks add eax, 2 ELSE ERRORS_ASSERT ENDIF add SC_WAIT, eax GamePAK_Prefetch eax ARM7_ExitAddPC 1 endm @ALIGN_Z mul_interp MUL, MUL_OP mul_interp MLA, MLA_OP mul_interp UMUL64, UMUL64_OP mul_interp UMLA64, UMLA64_OP mul_interp SMUL64, SMUL64_OP mul_interp SMLA64, SMLA64_OP IRL_PUSH_b macro num LDR_SET LDR_STD_IMM12, n, num LDR_SET LDR_STD_SCALED, e, num LDR_SET LDR_EXT_LOHI8BIT, c, num LDR_SET LDR_EXT_RNMD, p, num REGS_SET_OP num endm IRL_PUSH macro ID = 0 WHILE ID ne 32 IRL_PUSH_b %ID ID = ID + 1 ENDM endm IRL_PUSH int 3 COPMO: COPDT: UDEFI: ;; undef opcode abnormal int 3 ;; Thumb Instruction Entry ----------------------------------------------------------------------------------- ALUOP: SRC_cx equ ecx DST_i equ edx DST equ ZRS (DST_i) TMPR equ eax TMPR8 equ al ;; ALU Unwind ------------------------ GetRFI_T SC_INVOL, 0, DST_i ;;Rd's Index . GetRFIV_T SC_INVOL, 3, SRC_cx ;;Rs/Rm/Rn mov TMPR, SC_INVOL shr TMPR, 6 and TMPR, 15 jmp taTAB[TMPR*4] taAND: OUTd "AND R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" and DST, SRC_cx SetNZ_A tb_ExitAddPC 1 taEOR: OUTd "EOR R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" xor DST, SRC_cx SetNZ_A tb_ExitAddPC 1 taORR: OUTd "ORR R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" or DST, SRC_cx SetNZ_A tb_ExitAddPC 1 taADC: OUTd "ADC R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" bt SC_CPSR, FLAG_CHECK_C_X86_BT adc DST, SRC_cx SetNZCV_A 0 tb_ExitAddPC 1 taSBC: OUTd "SBC R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" xor SC_CPSR, FLAG_C bt SC_CPSR, FLAG_CHECK_C_X86_BT sbb DST, SRC_cx SetNZCV_A 1 tb_ExitAddPC 1 taCMP: OUTd "CMP R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" cmp DST, SRC_cx SetNZCV_A 1 tb_ExitAddPC 1 taCMN: OUTd "CMN R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" add SRC_cx, DST SetNZCV_A 0 tb_ExitAddPC 1 taTST: OUTd "TST R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" test DST, SRC_cx SetNZ_A tb_ExitAddPC 1 taNEG: mov DST, 0 sub DST, SRC_cx SetNZCV_A 1 tb_ExitAddPC 1 taBIC: OUTd "BIC R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" not SRC_cx and DST, SRC_cx SetNZ_A tb_ExitAddPC 1 taMVN: OUTd "MVN R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" xor SRC_cx, -1 mov DST, SRC_cx SetNZ_A tb_ExitAddPC 1 taMUL: OUTd "MUL R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" movd xmm0, SRC_cx movd xmm1, DST pmuludq xmm0, xmm1 movd TMPR, xmm0 mov DST, TMPR or TMPR, TMPR SetNZ_A mulClks SRC_cx, DST_i, TMPR ;; @FIXME lea SC_INVOL, [TMPR+1] GamePAK_Prefetch TMPR tb_ExitAddPC SC_INVOL taLSL: OUTd "LSL R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" and SRC_cx, 255 jne @F ;; ZERO. mov TMPR, DST or TMPR, TMPR SetNZ_A GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: xor TMPR, TMPR cmp SRC_cx, 32 jb @F ;; >= 32 mov SRC_cx, DST mov DST, TMPR ;; Rd:= 0 sete TMPR8 ;; 32 1 and SC_CPSR, not (FLAG_C or FLAG_N) and SRC_cx, 1 and SRC_cx, TMPR ;; and it. shl SRC_cx, FLAG_CHECK_C_X86_BT or SC_CPSR, SRC_cx or SC_CPSR, FLAG_Z GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: shl DST, cl SetNZC_A GamePAK_Prefetch 1 tb_ExitAddPC 2 taLSR: OUTd "LSR R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" and SRC_cx, 255 jne @F ;; ZERO. mov TMPR, DST or TMPR, TMPR SetNZ_A GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: xor TMPR, TMPR cmp SRC_cx, 32 jb @F ;; >= 32 mov SRC_cx, DST mov DST, TMPR ;; Rd:= 0 sete TMPR8 ;; 32 1 and SC_CPSR, not (FLAG_C or FLAG_N) shr SRC_cx, 31 and SRC_cx, TMPR ;; and it. shl SRC_cx, FLAG_CHECK_C_X86_BT or SC_CPSR, SRC_cx or SC_CPSR, FLAG_Z GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: shr DST, cl SetNZC_A GamePAK_Prefetch 1 tb_ExitAddPC 2 taASR: OUTd "ASR R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" and SRC_cx, 255 jne @F ;; ZERO. mov TMPR, DST or TMPR, TMPR SetNZ_A GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: cmp SRC_cx, 32 jb @F bt DST, 31 sbb SRC_cx, SRC_cx mov DST, SRC_cx SetNZC_A GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: sar DST, cl SetNZC_A GamePAK_Prefetch 1 tb_ExitAddPC 2 taROR: OUTd "ROR R%d, R%d", "SC_INVOL & 7", "SC_INVOL } 3 & 7" and SRC_cx, 255 jne @F ;; ZERO. mov TMPR, DST or TMPR, TMPR SetNZ_A GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: test SRC_cx, 31 jne @F mov SC_INVOL, DST or SC_INVOL, SC_INVOL rol SC_INVOL, 1 SetNZC_A GamePAK_Prefetch 1 tb_ExitAddPC 2 @@: and SRC_cx, 31 ror DST, cl SetC_A mov eax, DST or eax, eax SetNZ_A GamePAK_Prefetch 1 tb_ExitAddPC 2 INLSL: OUTd "LSL R%d, R%d, #%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 31" mov ecx, SC_INVOL GetRFIV_T SC_INVOL, 3, edx ;;Rm. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . shr ecx, 6 and ecx, 31 jne @F or edx, edx mov ZRS (eax), edx SetNZ_A tb_ExitAddPC 1 @@: shl edx, cl mov ZRS (eax), edx SetNZC_A tb_ExitAddPC 1 INLSR: OUTd "LSR R%d, R%d, #%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 31" mov ecx, SC_INVOL GetRFIV_T SC_INVOL, 3, edx ;;Rm. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . shr ecx, 6 and ecx, 31 jne @F and SC_CPSR, not (FLAG_Z or FLAG_N or FLAG_C) or SC_CPSR, FLAG_Z shl edx, 1 mov ZRS (eax), 0 SetC_A tb_ExitAddPC 1 @@: shr edx, cl mov ZRS (eax), edx SetNZC_A tb_ExitAddPC 1 INASR: OUTd "ASR R%d, R%d, #%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 31" mov ecx, SC_INVOL GetRFIV_T SC_INVOL, 3, edx ;;Rm. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . shr ecx, 6 and ecx, 31 jne @F shl edx, 1 sbb ecx, ecx ;; 0 or -1 mov ZRS (eax), ecx SetNZC_A tb_ExitAddPC 1 @@: sar edx, cl mov ZRS (eax), edx SetNZC_A tb_ExitAddPC 1 ADDI3: OUTd "ADD R%d, R%d, #%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 7" GetRFIV_T SC_INVOL, 3, edx ;;Rn. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . GetRFI_T SC_INVOL, 6, ecx ;;Imm3 add edx, ecx mov ZRS (eax), edx SetNZCV_A 0 tb_ExitAddPC 1 SUBI3: OUTd "SUB R%d, R%d, #%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 7" GetRFIV_T SC_INVOL, 3, edx ;;Rn. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . GetRFI_T SC_INVOL, 6, ecx ;;Imm3 sub edx, ecx mov ZRS (eax), edx SetNZCV_A 1 tb_ExitAddPC 1 ADDRT: OUTd "ADD R%d, R%d, R%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 7" GetRFIV_T SC_INVOL, 3, edx ;;Rn. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . GetRFIV_T SC_INVOL, 6, ecx ;;Rm add edx, ecx mov ZRS (eax), edx SetNZCV_A 0 tb_ExitAddPC 1 SUBRT: OUTd "SUB R%d, R%d, R%d", "SC_INVOL & 7", "SC_INVOL }3 & 7", "SC_INVOL } 6 & 7" GetRFIV_T SC_INVOL, 3, edx ;;Rn. GetRFI_T SC_INVOL, 0, eax ;;Rd's Index . GetRFIV_T SC_INVOL, 6, ecx ;;Rm sub edx, ecx mov ZRS (eax), edx SetNZCV_A 1 tb_ExitAddPC 1 MOVI8: OUTd "MOV R%d, #%d", "SC_INVOL }8 & 7", "SC_INVOL & 255" GetRFI_T SC_INVOL, 8, ecx ;;Rd's Index . and SC_INVOL, 255 mov ZRS (ecx), SC_INVOL SetNZ_A tb_ExitAddPC 1 CMPI8: OUTd "CMP R%d, #%d", "SC_INVOL }8 & 7", "SC_INVOL & 255" GetRFIV_T SC_INVOL, 8, ecx ;;Rn's Value . and SC_INVOL, 255 cmp ecx, SC_INVOL SetNZCV_A 1 tb_ExitAddPC 1 ADDI8: OUTd "ADD R%d, #%d", "SC_INVOL }8 & 7", "SC_INVOL & 255" GetRFI_T SC_INVOL, 8, ecx ;;Rd's Index . and SC_INVOL, 255 add ZRS (ecx), SC_INVOL SetNZCV_A 0 tb_ExitAddPC 1 SUBI8: OUTd "SUB R%d, #%d", "SC_INVOL }8 & 7", "SC_INVOL & 255" GetRFI_T SC_INVOL, 8, ecx ;;Rd's Index . and SC_INVOL, 255 sub ZRS (ecx), SC_INVOL SetNZCV_A 1 tb_ExitAddPC 1 ih1h2Get macro Post, RdRev, RmRev mov RmRev, Post bt Post, 7 sbb RdRev, RdRev and RdRev, 8 and RmRev, 7 or RdRev, RmRev mov RmRev, Post and RmRev, 078h shr RmRev, 3 ;; TODO: Check LO-LO Trans UB. endm ADD16: ih1h2Get SC_INVOL, ecx, edx OUTd "ADD R%d, R%d", "ecx", "edx" mov edx, ZRS (edx) add ZRS (ecx), edx cmp ecx, 15 jne @F and ZRS (ecx), -2 tb_FlushPipeline 3 @@: tb_ExitAddPC 1 MOV16: ih1h2Get SC_INVOL, ecx, edx OUTd "MOV R%d, R%d", "ecx", "edx" mov edx, ZRS (edx) mov ZRS (ecx), edx cmp ecx, 15 jne @F and ZRS (ecx), -2 tb_FlushPipeline 3 @@: tb_ExitAddPC 1 CMP16: ih1h2Get SC_INVOL, ecx, edx OUTd "CMP R%d, R%d", "ecx", "edx" mov edx, ZRS (edx) cmp ZRS (ecx), edx SetNZCV_A 1 tb_ExitAddPC 1 SIM08 macro lSym, SZ_BODY lSym: mov eax, SC_INVOL mov ecx, SC_INVOL mov edx, ZRS (SZ_BODY) ;; edx:PC or SP and eax, 255 ;; Imm8 shr ecx, 8 and ecx, 7 ;; ecx: RdI shl eax, 2 ;; eax: address temp IF SZ_BODY eq SZ_STACK OUTd "ADD R%d, SP, %d-%03X", "ecx", "eax", "eax" ELSEIF SZ_BODY eq SZ_PC OUTd "ADD R%d, PC, %d-%03X", "ecx", "eax", "eax" ELSE ERRORS_ASSERT ENDIF endm SIM08 PCI08, SZ_PC and edx, -4 add edx, eax mov ZRS (ecx), edx tb_ExitAddPC 1 SIM08 SPI08, SZ_STACK add edx, eax mov ZRS (ecx), edx tb_ExitAddPC 1 STKS7: test SC_INVOL, 080h je @F and SC_INVOL, 07Fh shl SC_INVOL, 2 OUTd "SUB SP, #%d", "SC_INVOL" sub ZRS (SZ_STACK), SC_INVOL tb_ExitAddPC 1 @@: and SC_INVOL, 07Fh shl SC_INVOL, 2 OUTd "ADD SP, #%d", "SC_INVOL" add ZRS (SZ_STACK), SC_INVOL tb_ExitAddPC 1 SWI08: ;; Thumb Software Interrupt OUTd "SWI-THUMB FUNC:%02X R0 %08X R1 %08X R2 %08X\n", "SC_INVOL & 255", "Z0", "Z1", "Z2" mov eax, ZRS (SZ_PC) mov ecx, SC_CPSR and ecx, ARM7_MODE_CLR_MASK or ecx, ARM7_MODE_MGR_MASK ;; Set SVC mode. and ecx, not FLAG_THUMB ;; Clear Thumb exec flag or ecx, IRQ_INHIBI_MASK ;; Set IRQ inhibit mask ;; PC to SVC's LR, LR:= Current Instruction next ins lea edx, [eax-2] mov [SC_ARM7].R1314_T[R1314b_MGR+4], edx ;; Adjust PC Pointer to IRQ Interrupt vector address mov ZRS (SZ_PC), ARM7_VECTOR_SOFTWARE mov SC_INVOL, SC_CPSR and SC_INVOL, ARM7_MODE_GET_MASK cmp SC_INVOL, ARM7_MODE_MGR_MASK je @NestSwi_thumb ;; switch Mode SwitchMode ecx, 0 ;; Prefetch Opcode pipeline arm7_FlushPipeline 3 @NestSwi_thumb: mov ZRS (SZ_LRLINK), edx mov [SC_ARM7].SPSR_T[SPSRb_MGR], SC_CPSR mov eax, ZRS (SZ_STACK) mov [SC_ARM7].R1314_T[R1314b_MGR], eax mov eax, ZRS (SZ_LRLINK) mov [SC_ARM7].R1314_T[R1314b_MGR+4], eax mov SC_CPSR, ecx ;; Prefetch Opcode pipeline arm7_FlushPipeline 3 PUSHR: ;; PUSH is DB stack opreate type, if R spec, Push LRLINK to stack. OUTd "PUSH R:%d R7-R4:%01X R3-R0:%01X", "SC_INVOL } 8 & 1", "SC_INVOL } 4 & 15", "SC_INVOL & 15" sub esp, LDM_STACK_REQUIRE mov STA (RnFirst), 0 sub ZRS (SZ_STACK), 4 mov STA (RnCount), 8 shl SC_INVOL, 23 @@: shl SC_INVOL, 1 jnc PUSHR_c add SC_WAIT, 1 mov eax, STA (RnCount) bt eax, 3 ;; Check R Spec sbb ecx, ecx and ecx, SZ_LRLINK or eax, ecx ;; XXX: LRLINK must be 14 push STACK_PUSH_STATUS_PUSH push eax push ZRS (eax) push ZRS (SZ_STACK) sub ZRS (SZ_STACK), 4 cmp STA (RnFirst+16), 0 mov STA (RnFirst+16), 1 je PUSHR_first CallMemOrIOAddWaitState StackWriteSeq jmp PUSHR_c PUSHR_first: CallMemOrIOAddWaitState StackWriteNoSeq PUSHR_c: sub STA (RnCount), 1 jge @B add ZRS (SZ_STACK), 4 add esp, LDM_STACK_REQUIRE mov [SC_ARM7].nextNoSeqFetch, 1 tb_ExitAddPC 1 POPRP: ;; POP is IA stack opreate type, if R spec, Pop PC from stack. OUTd "POP R:%d R7-R4:%01X R3-R0:%01X", "SC_INVOL } 8 & 1", "SC_INVOL } 4 & 15", "SC_INVOL & 15" GamePAK_Prefetch 1 xor eax, eax sub esp, LDM_STACK_REQUIRE mov STA (RnFirst), eax mov STA (RnCount), eax @@: shr SC_INVOL, 1 jnc POPRP_c inc SC_WAIT push ZRS (SZ_STACK) cmp STA (RnFirst+4), 0 mov STA (RnFirst+4), 1 je POPRP_first CallMemOrIOAddWaitState StackReadSeq jmp POPRP_continue POPRP_first: CallMemOrIOAddWaitState StackReadNoSeq POPRP_continue: mov edx, STA (RnCount) bt edx, 3 ;; Check R Spec sbb ecx, ecx and ecx, SZ_PC or edx, ecx ;; XXX: PC must be 15 mov ZRS (edx), eax add ZRS (SZ_STACK), 4 cmp edx, SZ_PC ;; PC Flush? Flush Pipeline : nodone. je @F POPRP_c: add STA (RnCount), 1 cmp STA (RnCount), 9 jne @B add esp, LDM_STACK_REQUIRE tb_ExitAddPC 2 @@: add esp, LDM_STACK_REQUIRE tb_FlushPipeline 4 TB_LDR equ 0 TB_LDRH equ 1 TB_LDRSH equ 2 TB_RESET equ 7 STRsc macro Routine mov eax, SC_INVOL mov ecx, SC_INVOL mov edx, SC_INVOL and eax, 7 shr ecx, 3 and ecx, 7 shr edx, 6 and edx, 7 OUTd "R%d, [R%d, R%d]", "eax", "ecx", "edx" mov ecx, ZRS (ecx) mov eax, ZRS (eax) add ecx, ZRS (edx) push eax push ecx CallMemOrIOAddWaitState Routine mov [SC_ARM7].nextNoSeqFetch, 1 ;; STR always NoSeq fetch in next fetch. tb_ExitAddPC 2 endm LDRsc macro MemAccessType, Routine, MovSt, rhs, alignBlk mov eax, SC_INVOL mov ecx, SC_INVOL mov edx, SC_INVOL and eax, 7 shr ecx, 3 and ecx, 7 shr edx, 6 and edx, 7 OUTd "R%d, [R%d, R%d]", "eax", "ecx", "edx" mov ecx, ZRS (ecx) mov SC_INVOL, eax add ecx, ZRS (edx) mov [SC_ARM7].calc, ecx ;; and ecx, alignBlk push ecx CallMemOrIOAddWaitState Routine mov ecx, [SC_ARM7].calc IF MemAccessType eq TB_RESET MovSt eax, rhs ELSEIF MemAccessType eq TB_LDR and ecx, 3 shl ecx, 3 ror eax, cl ELSEIF MemAccessType eq TB_LDRH and eax, 0FFFFh and ecx, 1 shl ecx, 3 ror eax, cl ELSEIF MemAccessType eq TB_LDRSH mov edx, eax movsx eax, ax and ecx, 1 je @F movsx eax, dh @@: ELSE ERRORS_ASSERT ENDIF mov ZRS (SC_INVOL), eax GamePAK_Prefetch 1 tb_ExitAddPC 3 endm STRWD: OUTd "STR " STRsc MmuWriteWordNoSeq STRHW: OUTd "STRH " STRsc MmuWriteHalfWordNoSeq STRUB: OUTd "STRB " STRsc MmuWriteByteNoSeq LDRWD: OUTd "LDR " LDRsc TB_LDR, MmuReadWordNoSeq, mov, eax, 0FFFFFFFCh LDHW2: OUTd "LDRH " LDRsc TB_LDRH, MmuReadHalfWordNoSeq, movzx, ax, 0FFFFFFFEh LDRSW: OUTd "LDRSH " LDRsc TB_LDRSH, MmuReadHalfWordNoSeq, movsx, ax, 0FFFFFFFEh LDRUB: OUTd "LDRB " LDRsc TB_RESET, MmuReadByteNoSeq, movzx, al, 0FFFFFFFFh LDRSB: OUTd "LDRSB " LDRsc TB_RESET, MmuReadByteNoSeq, movsx, al, 0FFFFFFFFh ;; encode: d0-d2 rd, d3-d5 rn, r6-r10 imm5*sizeof(bitdepth/8) ADR5 macro SftBit ;; eax:rdi, edx:address mov eax, SC_INVOL mov ecx, SC_INVOL mov edx, SC_INVOL and eax, 7 ;; Rd shr ecx, 3 and ecx, 7 ;; Rn shr edx, 6 and edx, 31 ;; Imm5 shl edx, SftBit OUTd "R%d, [R%d, %d]", "eax", "ecx", "edx" add edx, ZRS (ecx) mov [SC_ARM7].calc, edx endm STR5 macro SftBit, CallRoutine ADR5 SftBit push ZRS (eax) push edx CallMemOrIOAddWaitState CallRoutine mov [SC_ARM7].nextNoSeqFetch, 1 tb_ExitAddPC 2 endm LDR5 macro MemAccessType, SftBit, BitLimit, CallRoutine ADR5 SftBit mov SC_INVOL, eax push edx CallMemOrIOAddWaitState CallRoutine mov ecx, [SC_ARM7].calc IF MemAccessType eq TB_LDR and ecx, 3 shl ecx, 3 ror eax, cl ELSEIF MemAccessType eq TB_LDRH and eax, 0FFFFh and ecx, 1 shl ecx, 3 ror eax, cl ELSEIF MemAccessType eq TB_RESET movzx eax, al ENDIF mov ZRS (SC_INVOL), eax GamePAK_Prefetch 1 tb_ExitAddPC 3 endm LDSTR1315 macro lSym lSym: mov eax, SC_INVOL mov ecx, SC_INVOL mov edx, SC_INVOL and eax, 255 ;; Imm8 shr ecx, 8 and ecx, 7 ;; Rd shl eax, 2 ;;;;4 address temp endm STRW5: OUTd "STR " STR5 2, MmuWriteWordNoSeq STRH5: OUTd "STRH " STR5 1, MmuWriteHalfWordNoSeq STRB5: OUTd "STRB " STR5 0, MmuWriteByteNoSeq LDRW5: ;;=======================DEBUG OUTd "LDR " LDR5 TB_LDR, 2, 0FFFFFFFFh, MmuReadWordNoSeq LDRH5: OUTd "LDRH " LDR5 TB_LDRH, 1, 0FFFFh, MmuReadHalfWordNoSeq LDRB5: OUTd "LDRB " LDR5 TB_RESET, 0, 0FFh, MmuReadByteNoSeq LDSTR1315 LDRPC OUTd "LDR R%d, [PC, #%d-%03X]", "ecx", "eax", "eax" mov edx, ZRS (SZ_PC) and edx, -4 add eax, edx mov SC_INVOL, ecx push eax mov [SC_ARM7].calc, eax CallMemOrIOAddWaitState MmuReadWordNoSeq mov ecx, [SC_ARM7].calc and ecx, 3 shl ecx, 3 ror eax, cl mov ZRS (SC_INVOL), eax GamePAK_Prefetch 1 tb_ExitAddPC 3 LDSTR1315 LDRSP OUTd "LDR R%d, [SP, #%d-%03X]", "ecx", "eax", "eax" add eax, ZRS (SZ_STACK) mov SC_INVOL, ecx push eax mov [SC_ARM7].calc, eax CallMemOrIOAddWaitState MmuReadWordNoSeq mov ecx, [SC_ARM7].calc and ecx, 3 shl ecx, 3 ror eax, cl mov ZRS (SC_INVOL), eax GamePAK_Prefetch 1 tb_ExitAddPC 3 LDSTR1315 STRSP OUTd "STR R%d, [SP, #%d-%03X]", "ecx", "eax", "eax" add eax, ZRS (SZ_STACK) push ZRS (ecx) push eax CallMemOrIOAddWaitState MmuWriteWordNoSeq mov [SC_ARM7].nextNoSeqFetch, 1 tb_ExitAddPC 2 ;; A7.1.57 - STMIA (INC, AFTER) ;; ;; Codec: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 1 1 1 0 0 Rn Reglist. ;; STMIA: OUTd "T-STMIA [R%d]!, R7-R4:%01X R3-R0:%01X ", "SC_INVOL } 8 & 7", "SC_INVOL } 4 & 15", "SC_INVOL & 15" sub esp, LDM_STACK_REQUIRE mov eax, SC_INVOL mov ecx, SC_INVOL and eax, 255 shr ecx, 8 and ecx, 7 ;; Get Rn's index and Rn's init value. mov edx, ZRS (ecx) mov STA (RnTempi), ecx mov STA (RnTemp), edx mov STA (RnFirst), 0 mov STA (RnCount), 0 ;; Check Reglist is empty ? ;; ================================= NO$GBA doc ================================= ;; Strange Effects on Invalid Rlist's ;; Empty Rlist: R15 loaded/stored (ARMv4 only), and Rb=Rb+40h (ARMv4-v5). ;; Writeback with Rb included in Rlist: Store OLD base if Rb is FIRST entry in ;; Rlist, otherwise store NEW base (STM/ARMv4), always store OLD base (STM/ARMv5), ;; no writeback (LDM/ARMv4/ARMv5; at this point, THUMB opcodes work different than ARM opcodes). test eax, eax jne @F push STACK_PUSH_STATUS_PUSH push SZ_PC mov eax, ZRS (SZ_PC) add eax, 2 push eax push edx add ZRS (ecx), 64 and ZRS (ecx), -4 CallMemOrIOAddWaitState StackWriteNoSeq add esp, LDM_STACK_REQUIRE mov [SC_ARM7].nextNoSeqFetch, 1 tb_ExitAddPC 2 ;; Check Rn with Reglist ? @@: bt eax, ecx jnc @F DEBUG_BREAK OUTd "R%d in reglist! FIRST-V:", "ecx" xor edx, edx not edx ;; Check First Vailed bit ;; IF Done, write inital value to stack ;; ELSE. write final Rn's value to stack (this is UB. but i test on AXD Debugger 1.2 is final Rn) ;; See ARM Developer Suite Assembler Guide:: Thumb Instruction Reference::5.1.5 LDMIA and STMIA ;; shl edx, cl not edx test edx, eax je STMIA_k OUTd "NO" ;; Calc write back's Rn in end. IF 1 mov ecx, 8 xor edx, edx STMIA0: shr eax, 1 adc edx, 0 dec ecx jne STMIA0 ELSE and eax, 255 popcnt edx, eax ENDIF ;; Write back Rn. lea edx, [edx*4] mov ecx, SC_INVOL shr ecx, 8 and ecx, 7 add ZRS (ecx), edx and ZRS (ecx), -4 STMIA_k: OUTd "YES" @@: shr SC_INVOL, 1 jnc STMIA_c inc SC_WAIT mov eax, STA (RnCount) push STACK_PUSH_STATUS_PUSH push eax push ZRS (eax) mov eax, STA (RnTemp+12) add STA (RnTemp+12), 4 ;; and eax, -4 push eax cmp STA (RnFirst+16), 0 mov STA (RnFirst+16), 1 je STMIA_first CallMemOrIOAddWaitState StackWriteSeq jmp STMIA_c STMIA_first: CallMemOrIOAddWaitState StackWriteNoSeq STMIA_c: add STA (RnCount), 1 cmp STA (RnCount), 8 jne @B cmp STA (RnFirst), 0 jne @F @@: mov ecx, STA (RnTemp) mov eax, STA (RnTempi) mov ZRS (eax), ecx and ZRS (eax), -4 add esp, LDM_STACK_REQUIRE mov [SC_ARM7].nextNoSeqFetch, 1 tb_ExitAddPC 1 ;; A7.1.27 LDMIA ;; ;; Codec: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ;; 1 1 1 0 1 Rn Reglist. ;; LDMIA: GamePAK_Prefetch 1 OUTd "T-LDMIA [R%d]!, R7-R4:%01X R3-R0:%01X ", "SC_INVOL } 8 & 7", "SC_INVOL } 4 & 15", "SC_INVOL & 15" sub esp, LDM_STACK_REQUIRE mov eax, SC_INVOL mov ecx, SC_INVOL and eax, 255 shr ecx, 8 and ecx, 7 ;; Get Rn's index and Rn's init value. mov edx, ZRS (ecx) mov STA (RnTempi), ecx mov STA (RnTemp), edx mov STA (RnFirst), 0 mov STA (RnCount), 0 mov STA (RnAdjust), 1 ;; Check empty reglist test eax, eax jne @F push edx add ZRS (ecx), 64 and ZRS (ecx), -4 CallMemOrIOAddWaitState StackReadNoSeq mov ZRS (SZ_PC), eax add esp, LDM_STACK_REQUIRE tb_FlushPipeline 3 @@: bt eax, ecx jnc @F ;; Rn with Reglist ;; Rn WriteBack will miss in thumb-LDMIA. ;; DEBUG_BREAK OUTd "R%d in reglist!" mov STA (RnAdjust), 0 @@: shr SC_INVOL, 1 jnc LDMIA_c inc SC_WAIT mov eax, STA (RnTemp) add STA (RnTemp), 4 ;; and eax, -4 push eax cmp STA (RnFirst+4), 0 mov STA (RnFirst+4), 1 je LDMIA_first CallMemOrIOAddWaitState StackReadSeq jmp LDMIA_a LDMIA_first: CallMemOrIOAddWaitState StackReadNoSeq LDMIA_a: mov ecx, STA (RnCount) mov ZRS (ecx), eax LDMIA_c: add STA (RnCount), 1 cmp STA (RnCount), 8 jne @B cmp STA (RnFirst), 0 jne @F ;; FIXME: No Reglist mask exist stuff.. DEBUG_BREAK @@: cmp STA (RnAdjust), 0 je @F mov ecx, STA (RnTemp) mov eax, STA (RnTempi) mov ZRS (eax), ecx and ZRS (eax), -4 @@: add esp, LDM_STACK_REQUIRE tb_ExitAddPC 2 ;; JMP Sign Offset 11bit. @!SMARK. JMP11: and SC_INVOL, 07FFh bt SC_INVOL, 10 sbb eax, eax shl eax, 10 or SC_INVOL, eax shl SC_INVOL, 1 OUTd ":JMP 11 Offset %d-%08X ", "SC_INVOL", "SC_INVOL" add ZRS (SZ_PC), SC_INVOL OUTd ":CurrentPC %d-%08X", "ZF", "ZF" tb_FlushPipeline 2 IF 0 ;; BL Ext BLEXT: ;; Fetch Ext High ;; int 3 and SC_INVOL, 07FFh bt SC_INVOL, 10 sbb eax, eax shl eax, 10 or SC_INVOL, eax shl SC_INVOL, 12 add SC_INVOL, ZRS(SZ_PC) mov ZRS (SZ_LRLINK), SC_INVOL ;; Fetch Next Opcode Must be BLSTD (TODO: Opcode Check) mov eax, [SC_ARM7].Opcode[0] and eax, 07FFh shl eax, 1 add eax, ZRS (SZ_LRLINK) OUTd ":BL Offset %d-%08X ", "ZE", "ZE" mov ecx, ZRS (SZ_PC) mov ZRS (SZ_PC), eax OUTd ":CurrentPC %d-%08X ", "ZF", "ZF" sub ecx, 0 ;; backup to next instruction base current instruction or ecx, 1 ;; With Thumb flags, for BX OUTd ":LINK %d-%08X ", "ecx", "ecx" mov ZRS (SZ_LRLINK) ,ecx ;; prefetch opcode . tb_FlushPipeline 3 BLSTD: ;;(in fact, with BLEXT). ELSE ;; BL Ext BLEXT: ;; Fetch Ext High ;; int 3 and SC_INVOL, 07FFh bt SC_INVOL, 10 sbb eax, eax shl eax, 10 or SC_INVOL, eax shl SC_INVOL, 12 add SC_INVOL, ZRS(SZ_PC) mov ZRS (SZ_LRLINK), SC_INVOL tb_ExitAddPC 1 BLSTD: ;;(in fact, with BLEXT). mov eax, SC_INVOL and eax, 07FFh shl eax, 1 add eax, ZRS (SZ_LRLINK) OUTd ":BL Offset %d-%08X ", "ZE", "ZE" mov ecx, ZRS (SZ_PC) mov ZRS (SZ_PC), eax OUTd ":CurrentPC %d-%08X ", "ZF", "ZF" sub ecx, 2 ;; backup to next instruction base current instruction or ecx, 1 ;; With Thumb flags, for BX OUTd ":LINK %d-%08X ", "ecx", "ecx" mov ZRS (SZ_LRLINK) ,ecx ;; prefetch opcode . tb_FlushPipeline 3 ENDIF UNDEF: int 3 BX_TB: mov eax, SC_INVOL and eax, 078h shr eax, 3 OUTd "BX R%d", "eax" mov ecx, ZRS (eax) test ecx, 1 je @F or SC_CPSR, FLAG_THUMB and ecx, -2 mov ZRS (SZ_PC), ecx tb_FlushPipeline 3 @@: and SC_CPSR, not FLAG_THUMB and ecx, -4 mov ZRS (SZ_PC), ecx arm7_FlushPipeline 3 ;; Thumb JCC ----------------------------------------------------------------- JCCEQ: OUTd "JCC:EQ " test SC_CPSR, FLAG_Z jne JCCAL JCCNV: OUTd ":Skip " tb_ExitAddPC 1 JCCNE: OUTd "JCC:NE " test SC_CPSR, FLAG_Z je JCCAL tb_ExitAddPC 1 JCCCS: OUTd "JCC:CS " test SC_CPSR, FLAG_C jne JCCAL jmp JCCNV JCCCC: OUTd "JCC:CC " test SC_CPSR, FLAG_C je JCCAL jmp JCCNV JCCMI: OUTd "JCC:MI " test SC_CPSR, FLAG_N jne JCCAL jmp JCCNV JCCPL: OUTd "JCC:PL " test SC_CPSR, FLAG_N je JCCAL jmp JCCNV JCCVS: OUTd "JCC:VS " test SC_CPSR, FLAG_V jne JCCAL jmp JCCNV JCCVC: OUTd "JCC:VC " test SC_CPSR, FLAG_V je JCCAL jmp JCCNV JCCHI: ;; C = 1 && Z = 0 OUTd "JCC:HI " mov ecx, SC_CPSR and ecx, FLAG_CZ cmp ecx, FLAG_C je JCCAL jmp JCCNV JCCLS: ;; C = 0 || Z = 1 OUTd "JCC:LS " mov ecx, SC_CPSR and ecx, FLAG_CZ ;; C0Z1 ^ C1Z0 -> C1Z1 ;; C1Z1 ^ C1Z0 -> C0Z1 ;; C0Z0 ^ C1Z0 -> C1Z0 ;; C1Z0 ^ C1Z0 -> ZERO. xor ecx, FLAG_C jne JCCAL jmp JCCNV JCCGE: ;; N = V OUTd "JCC:GE " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx je JCCAL jmp JCCNV JCCLT: ;; N != V OUTd "JCC:LT " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx jne JCCAL jmp JCCNV JCCGT: ;; N = V && Z= 0 OUTd "JCC:GT " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx mov ecx, SC_CPSR shr ecx, FLAG_Z_TOLSB_BIT and ecx, 1 or eax, ecx je JCCAL jmp JCCNV JCCLE: ;; Z = 1 || N!=V OUTd "JCC:LE " mov eax, SC_CPSR mov ecx, SC_CPSR shr eax, FLAG_V_TOLSB_BIT shr ecx, FLAG_N_TOLSB_BIT and eax, 1 and ecx, 1 xor eax, ecx mov ecx, SC_CPSR shr ecx, FLAG_Z_TOLSB_BIT and ecx, 1 or eax, ecx je JCCNV JCCAL: ;; 1110 OUTd "Exec It.:" mov eax, SC_INVOL and eax, 255 mov [esp-8], eax movsx eax, byte ptr [esp-8] OUTd ":Offset %d-%08X ", "eax", "eax" shl eax, 1 add ZRS (SZ_PC), eax OUTd ":CurrentPC %d-%08X", "ZF", "ZF" tb_FlushPipeline 2 ; Instruction Hash Entry ----------------------------------------------------------------------------------- .data i8r4TAB dd i8r4AND, i8r4ANDS, i8r4EOR, i8r4EORS dd i8r4SUB, i8r4SUBS, i8r4RSB, i8r4RSBS dd i8r4ADD, i8r4ADDS, i8r4ADC, i8r4ADCS dd i8r4SBC, i8r4SBCS, i8r4RSC, i8r4RSCS dd i8r4UB, i8r4TST, i8r4ToCPSR, i8r4TEQ dd i8r4UB, i8r4CMP, i8r4ToSPSR, i8r4CMN dd i8r4ORR, i8r4ORRS, i8r4MOV, i8r4MOVS dd i8r4BIC, i8r4BICS, i8r4MVN, i8r4MVNS si5TAB dd si5AND, si5ANDS, si5EOR, si5EORS dd si5SUB, si5SUBS, si5RSB, si5RSBS dd si5ADD, si5ADDS, si5ADC, si5ADCS dd si5SBC, si5SBCS, si5RSC, si5RSCS dd si5PSR1, si5TST, si5ToCPSR, si5TEQ dd si5PSR3, si5CMP, si5PSR4, si5CMN dd si5ORR, si5ORRS, si5MOV, si5MOVS dd si5BIC, si5BICS, si5MVN, si5MVNS rsTAB dd rsAND, rsANDS, rsEOR, rsEORS ;; 0 0 0 0 0 dd rsSUB, rsSUBS, rsRSB, rsRSBS ;; 0 0 1 0 0 dd rsADD, rsADDS, rsADC, rsADCS ;; 0 1 0 0 0 dd rsSBC, rsSBCS, rsRSC, rsRSCS ;; 0 1 1 0 0 dd rsUB, rsTST, rsBX, rsTEQ ;; 1 0 0 0 0 dd rsUB, rsCMP, rsUB, rsCMN ;; 1 0 1 0 0 dd rsORR, rsORRS, rsMOV, rsMOVS ;; 1 1 0 0 0 dd rsBIC, rsBICS, rsMVN, rsMVNS ;; 1 1 1 0 0 ;; LDR/STR Word/Byte Imm12 ;; P U B W L nTAB dd n0, n1, n2, n3 ;; 0 0 0 0 0 dd n4, n5, n6, n7 ;; 0 0 1 0 0 dd n8, n9, n10, n11 ;; 0 1 0 0 0 dd n12, n13, n14, n15 ;; 0 1 1 0 0 dd n16, n17, n18, n19 ;; 1 0 0 0 0 dd n20, n21, n22, n23 ;; 1 0 1 0 0 dd n24, n25, n26, n27 ;; 1 1 0 0 0 dd n28, n29, n30, n31 ;; 1 1 1 0 0 ;; LDR/STR Word/Byte Scaled ;; P U B W L eTAB dd e0, e1, e2, e3 ;; 0 0 0 0 0 dd e4, e5, e6, e7 ;; 0 0 1 0 0 dd e8, e9, e10, e11 ;; 0 1 0 0 0 dd e12, e13, e14, e15 ;; 0 1 1 0 0 dd e16, e17, e18, e19 ;; 1 0 0 0 0 dd e20, e21, e22, e23 ;; 1 0 1 0 0 dd e24, e25, e26, e27 ;; 1 1 0 0 0 dd e28, e29, e30, e31 ;; 1 1 1 0 0 ;; LDR/STR HalfWord/SByte Imm8 Hash ;; P U X1 W X2 cTAB dd c0, c1, c2, c3 ;; 0 0 0 0 0 dd c4, c5, c6, c7 ;; 0 0 1 0 0 dd c8, c9, c10, c11 ;; 0 1 0 0 0 dd c12, c13, c14, c15 ;; 0 1 1 0 0 dd c16, c17, c18, c19 ;; 1 0 0 0 0 dd c20, c21, c22, c23 ;; 1 0 1 0 0 dd c24, c25, c26, c27 ;; 1 1 0 0 0 dd c28, c29, c30, c31 ;; 1 1 1 0 0 ;; LDR/STR HalfWord/SByte Rm, Rn Hash ;; P U X1 W X2 pTAB dd p0, p1, p2, p3 ;; 0 0 0 0 0 dd p4, p5, p6, p7 ;; 0 0 1 0 0 dd p8, p9, p10, p11 ;; 0 1 0 0 0 dd p12, p13, p14, p15 ;; 0 1 1 0 0 dd p16, p17, p18, p19 ;; 1 0 0 0 0 dd p20, p21, p22, p23 ;; 1 0 1 0 0 dd p24, p25, p26, p27 ;; 1 1 0 0 0 dd p28, p29, p30, p31 ;; 1 1 1 0 0 ;; P U X1 W X2 ;; X1 X2 3:= LDRSH (7) ;; 2:= STRHW (1) ;; 1:= LDRSB (6) ;; 0:= LDRUH (5) ;; LDM/STM Hash ;; P U S W L zTAB dd z0, z1, z2, z3 ;; 0 0 0 0 0 dd z4, z5, z6, z7 ;; 0 0 1 0 0 dd z8, z9, z10, z11 ;; 0 1 0 0 0 dd z12, z13, z14, z15 ;; 0 1 1 0 0 dd z16, z17, z18, z19 ;; 1 0 0 0 0 dd z20, z21, z22, z23 ;; 1 0 1 0 0 dd z24, z25, z26, z27 ;; 1 1 0 0 0 dd z28, z29, z30, z31 ;; 1 1 1 0 0 fTAB dd fEQ, fNE, fCS, fCC dd fMI, fPL, fVS, fVC dd fHI, fLS, fGE, fLT dd fGT, fLE, fAL, fNV pcMTAB dd 000h, 100b ;; 0 0 0 dd 000b, 000b ;; 0 1 0 dd 000b, 000b ;; 0 0 0 dd 0001b, 0101b ;; 0 1 0 ARM7_MUL_TAB dd mMUL, mMULS, mMLA, mMLAS dd mUB, mUB, mUB, mUB dd mUMUL64, mUMUL64S, mUMLA64, mUMLA64S dd mSMUL64, mSMUL64S, mSMLA64, mSMLA64S ;; thumb alu taTAB dd taAND, taEOR, taLSL, taLSR dd taASR, taADC, taSBC, taROR dd taTST, taNEG, taCMP, taCMN dd taORR, taMUL, taBIC, taMVN ;; ALU Shift Imm5 / Shift Rs / MUL / MISC | | jTAB dd SF_I5, SF_RS, SF_I5, SF_RS, SF_I5, SF_RS, SF_I5, SF_RS, SF_I5, A7MUL, SF_I5, LDRHW, SF_I5, LDRHW, SF_I5, LDRHW dd SF_I5, SF_RS, SF_I5, SF_RS, SF_I5, SF_RS, SF_I5, SF_RS, SF_I5, A7SWP, SF_I5, LDRHW, SF_I5, LDRHW, SF_I5, LDRHW ;; ALU Imm8 Bitmap + 4bit Even Shift dd AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8 dd AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8, AS_I8 ;; LDR/ STR Imm dd LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12 ;;post index dd LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12, LDI12 ;;preindex or std index ;; LDR/ STR Shift Rm dd LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI dd LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI, LDIRS, UDEFI ;; Negtive --------------------|---------------------------|---------------------------|--------------------------------------------------- ;; Load/Stroe Multi dd RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET dd RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET, RGSET ;; Branch Sign Imm24 Without LRLINK dd JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24, JMP24 ;; Branch Sign Imm24 With LRLINK dd JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR, JMPLR ;; FPU, GBA doesn't have to deal with these things, For Simple, Link it to int 3 dd COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT dd COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT, COPDT dd COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO, COPMO ;; GBA Bios Software Interrupt. dd SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT, SWINT sTAB dd INLSL, INLSL, INLSL, INLSL, INLSL, INLSL, INLSL, INLSL, INLSR, INLSR, INLSR, INLSR, INLSR, INLSR, INLSR, INLSR dd INASR, INASR, INASR, INASR, INASR, INASR, INASR, INASR, ADDRT, ADDRT, SUBRT, SUBRT, ADDI3, ADDI3, SUBI3, SUBI3 dd MOVI8, MOVI8, MOVI8, MOVI8, MOVI8, MOVI8, MOVI8, MOVI8, CMPI8, CMPI8, CMPI8, CMPI8, CMPI8, CMPI8, CMPI8, CMPI8 dd ADDI8, ADDI8, ADDI8, ADDI8, ADDI8, ADDI8, ADDI8, ADDI8, SUBI8, SUBI8, SUBI8, SUBI8, SUBI8, SUBI8, SUBI8, SUBI8 dd ALUOP, ALUOP, ALUOP, ALUOP, ADD16, CMP16, MOV16, BX_TB, LDRPC, LDRPC, LDRPC, LDRPC, LDRPC, LDRPC, LDRPC, LDRPC dd STRWD, STRWD, STRHW, STRHW, STRUB, STRUB, LDRSB, LDRSB, LDRWD, LDRWD, LDHW2, LDHW2, LDRUB, LDRUB, LDRSW, LDRSW dd STRW5, STRW5, STRW5, STRW5, STRW5, STRW5, STRW5, STRW5, LDRW5, LDRW5, LDRW5, LDRW5, LDRW5, LDRW5, LDRW5, LDRW5 dd STRB5, STRB5, STRB5, STRB5, STRB5, STRB5, STRB5, STRB5, LDRB5, LDRB5, LDRB5, LDRB5, LDRB5, LDRB5, LDRB5, LDRB5 ;; Negtive -------------------------------------------------------------------------------------------------------------------------------- dd STRH5, STRH5, STRH5, STRH5, STRH5, STRH5, STRH5, STRH5, LDRH5, LDRH5, LDRH5, LDRH5, LDRH5, LDRH5, LDRH5, LDRH5 dd STRSP, STRSP, STRSP, STRSP, STRSP, STRSP, STRSP, STRSP, LDRSP, LDRSP, LDRSP, LDRSP, LDRSP, LDRSP, LDRSP, LDRSP dd PCI08, PCI08, PCI08, PCI08, PCI08, PCI08, PCI08, PCI08, SPI08, SPI08, SPI08, SPI08, SPI08, SPI08, SPI08, SPI08 dd STKS7, UNDEF, UNDEF, UNDEF, PUSHR, PUSHR, UNDEF, UNDEF, UNDEF, UNDEF, UNDEF, UNDEF, POPRP, POPRP, UNDEF, UNDEF dd STMIA, STMIA, STMIA, STMIA, STMIA, STMIA, STMIA, STMIA, LDMIA, LDMIA, LDMIA, LDMIA, LDMIA, LDMIA, LDMIA, LDMIA dd JCCEQ, JCCNE, JCCCS, JCCCC, JCCMI, JCCPL, JCCVS, JCCVC, JCCHI, JCCLS, JCCGE, JCCLT, JCCGT, JCCLE, JCCAL, SWI08 dd JMP11, JMP11, JMP11, JMP11, JMP11, JMP11, JMP11, JMP11, UNDEF, UNDEF, UNDEF, UNDEF, UNDEF, UNDEF, UNDEF, UNDEF dd BLEXT, BLEXT, BLEXT, BLEXT, BLEXT, BLEXT, BLEXT, BLEXT, BLSTD, BLSTD, BLSTD, BLSTD, BLSTD, BLSTD, BLSTD, BLSTD .code arm7tdmi_ticks endp end end