Improve flag shifts (MIPS)
This commit is contained in:
		
							parent
							
								
									9abb3ef934
								
							
						
					
					
						commit
						4dc706f361
					
				
					 2 changed files with 42 additions and 83 deletions
				
			
		|  | @ -53,11 +53,6 @@ void execute_store_spsr(u32 new_spsr, u32 store_mask); | ||||||
| u32 execute_spsr_restore_body(u32 address); | u32 execute_spsr_restore_body(u32 address); | ||||||
| u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address); | u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address); | ||||||
| 
 | 
 | ||||||
| u32 execute_lsl_flags_reg(u32 value, u32 shift); |  | ||||||
| u32 execute_lsr_flags_reg(u32 value, u32 shift); |  | ||||||
| u32 execute_asr_flags_reg(u32 value, u32 shift); |  | ||||||
| u32 execute_ror_flags_reg(u32 value, u32 shift); |  | ||||||
| 
 |  | ||||||
| typedef enum | typedef enum | ||||||
| { | { | ||||||
|   mips_reg_zero, |   mips_reg_zero, | ||||||
|  | @ -847,19 +842,55 @@ u32 arm_to_mips_reg[] = | ||||||
|                    reg_temp, arm_to_mips_reg[_rs])                            \ |                    reg_temp, arm_to_mips_reg[_rs])                            \ | ||||||
| 
 | 
 | ||||||
| #define generate_shift_reg_lsl_flags(_rm, _rs)                                \ | #define generate_shift_reg_lsl_flags(_rm, _rs)                                \ | ||||||
|  | {                                                                             \ | ||||||
|  |   u32 shift_reg = _rs;                                                        \ | ||||||
|  |   check_load_reg_pc(arm_reg_a1, shift_reg, 8);                                \ | ||||||
|   generate_load_reg_pc(reg_a0, _rm, 12);                                      \ |   generate_load_reg_pc(reg_a0, _rm, 12);                                      \ | ||||||
|   generate_load_reg_pc(reg_a1, _rs, 8);                                       \ |   /* Only load the result on zero, no shift */                                \ | ||||||
|   generate_function_call_swap_delay(execute_lsl_flags_reg)                    \ |   mips_emit_b(beq, arm_to_mips_reg[shift_reg], reg_zero, 7);                  \ | ||||||
|  |   generate_swap_delay();                                                      \ | ||||||
|  |   mips_emit_addiu(reg_temp, arm_to_mips_reg[shift_reg], -1);                  \ | ||||||
|  |   mips_emit_sllv(reg_a0, reg_a0, reg_temp);                                   \ | ||||||
|  |   mips_emit_srl(reg_c_cache, reg_a0, 31);                                     \ | ||||||
|  |   mips_emit_sltiu(reg_temp, arm_to_mips_reg[shift_reg], 33);                  \ | ||||||
|  |   mips_emit_sll(reg_a0, reg_a0, 1);                                           \ | ||||||
|  |   /* Result and flag to be zero if shift is 33+ */                            \ | ||||||
|  |   mips_emit_movz(reg_c_cache, reg_zero, reg_temp);                            \ | ||||||
|  |   mips_emit_movz(reg_a0, reg_zero, reg_temp);                                 \ | ||||||
|  | }                                                                             \ | ||||||
| 
 | 
 | ||||||
| #define generate_shift_reg_lsr_flags(_rm, _rs)                                \ | #define generate_shift_reg_lsr_flags(_rm, _rs)                                \ | ||||||
|  | {                                                                             \ | ||||||
|  |   u32 shift_reg = _rs;                                                        \ | ||||||
|  |   check_load_reg_pc(arm_reg_a1, shift_reg, 8);                                \ | ||||||
|   generate_load_reg_pc(reg_a0, _rm, 12);                                      \ |   generate_load_reg_pc(reg_a0, _rm, 12);                                      \ | ||||||
|   generate_load_reg_pc(reg_a1, _rs, 8)                                        \ |   /* Only load the result on zero, no shift */                                \ | ||||||
|   generate_function_call_swap_delay(execute_lsr_flags_reg)                    \ |   mips_emit_b(beq, arm_to_mips_reg[shift_reg], reg_zero, 7);                  \ | ||||||
|  |   generate_swap_delay();                                                      \ | ||||||
|  |   mips_emit_addiu(reg_temp, arm_to_mips_reg[shift_reg], -1);                  \ | ||||||
|  |   mips_emit_srlv(reg_a0, reg_a0, reg_temp);                                   \ | ||||||
|  |   mips_emit_andi(reg_c_cache, reg_a0, 1);                                     \ | ||||||
|  |   mips_emit_sltiu(reg_temp, arm_to_mips_reg[shift_reg], 33);                  \ | ||||||
|  |   mips_emit_srl(reg_a0, reg_a0, 1);                                           \ | ||||||
|  |   /* Result and flag to be zero if shift is 33+ */                            \ | ||||||
|  |   mips_emit_movz(reg_c_cache, reg_zero, reg_temp);                            \ | ||||||
|  |   mips_emit_movz(reg_a0, reg_zero, reg_temp);                                 \ | ||||||
|  | }                                                                             \ | ||||||
| 
 | 
 | ||||||
| #define generate_shift_reg_asr_flags(_rm, _rs)                                \ | #define generate_shift_reg_asr_flags(_rm, _rs)                                \ | ||||||
|  |   generate_load_reg_pc(reg_a1, _rs, 8);                                       \ | ||||||
|   generate_load_reg_pc(reg_a0, _rm, 12);                                      \ |   generate_load_reg_pc(reg_a0, _rm, 12);                                      \ | ||||||
|   generate_load_reg_pc(reg_a1, _rs, 8)                                        \ |   /* Only load the result on zero, no shift */                                \ | ||||||
|   generate_function_call_swap_delay(execute_asr_flags_reg)                    \ |   mips_emit_b(beq, reg_a1, reg_zero, 7);                                      \ | ||||||
|  |   generate_swap_delay();                                                      \ | ||||||
|  |   /* Cap shift at 32, since it's equivalent */                                \ | ||||||
|  |   mips_emit_addiu(reg_temp, reg_zero, 32);                                    \ | ||||||
|  |   mips_emit_srl(reg_rv, reg_a1, 5);                                           \ | ||||||
|  |   mips_emit_movn(reg_a1, reg_temp, reg_rv);                                   \ | ||||||
|  |   mips_emit_addiu(reg_temp, reg_a1, -1);                                      \ | ||||||
|  |   mips_emit_srav(reg_a0, reg_a0, reg_temp);                                   \ | ||||||
|  |   mips_emit_andi(reg_c_cache, reg_a0, 1);                                     \ | ||||||
|  |   mips_emit_sra(reg_a0, reg_a0, 1);                                           \ | ||||||
| 
 | 
 | ||||||
| #define generate_shift_reg_ror_flags(_rm, _rs)                                \ | #define generate_shift_reg_ror_flags(_rm, _rs)                                \ | ||||||
|   mips_emit_b(beq, arm_to_mips_reg[_rs], reg_zero, 3);                        \ |   mips_emit_b(beq, arm_to_mips_reg[_rs], reg_zero, 3);                        \ | ||||||
|  |  | ||||||
|  | @ -492,78 +492,6 @@ defsymbl(execute_store_spsr) | ||||||
|   jr $ra                          # return |   jr $ra                          # return | ||||||
|   sw $4, SPSR_BASE($1)            # spsr[cpu_mode] = $4 (delay slot) |   sw $4, SPSR_BASE($1)            # spsr[cpu_mode] = $4 (delay slot) | ||||||
| 
 | 
 | ||||||
| # $4: value |  | ||||||
| # $5: shift |  | ||||||
| 
 |  | ||||||
| defsymbl(execute_lsl_flags_reg) |  | ||||||
|   beq $5, $0, lsl_shift_zero      # is the shift zero? |  | ||||||
|   sltiu $1, $5, 32                # $1 = (shift < 32) (delay) |  | ||||||
|   beq $1, $0, lsl_shift_high      # is the shift >= 32? |  | ||||||
|   li $2, 32 |  | ||||||
| 
 |  | ||||||
|   subu $2, $2, $5                 # $2 = (32 - shift) |  | ||||||
|   srlv $2, $4, $2                 # $2 = (value >> (32 - shift)) |  | ||||||
|   andi $22, $2, 1                 # c flag = (value >> (32 - shift)) & 0x01 |  | ||||||
| 
 |  | ||||||
| lsl_shift_zero: |  | ||||||
|   jr $ra                          # return |  | ||||||
|   sllv $4, $4, $5                 # return (value << shift) (delay) |  | ||||||
| 
 |  | ||||||
| lsl_shift_high: |  | ||||||
|   sltiu $1, $5, 33                # $1 = (shift < 33) (delay) |  | ||||||
|   bne $1, $0, lsl_shift_done      # jump if shift == 32 |  | ||||||
|   andi $22, $4, 1                 # c flag = value & 0x01 (delay) |  | ||||||
| 
 |  | ||||||
|   addu $22, $0, $0                # c flag = 0 otherwise |  | ||||||
| 
 |  | ||||||
| lsl_shift_done: |  | ||||||
|   jr $ra                          # return |  | ||||||
|   addu $4, $0, $0                 # value = 0 no matter what |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| defsymbl(execute_lsr_flags_reg) |  | ||||||
|   beq $5, $0, lsr_shift_zero      # is the shift zero? |  | ||||||
|   sltiu $1, $5, 32                # $1 = (shift < 32) (delay) |  | ||||||
|   beq $1, $0, lsr_shift_high      # is the shift >= 32? |  | ||||||
|   addiu $2, $5, -1                # $2 = shift - 1 (delay) |  | ||||||
| 
 |  | ||||||
|   srlv $2, $4, $2                 # $2 = (value >> (shift - 1)) |  | ||||||
|   andi $22, $2, 1                 # c flag = (value >> (32 - shift)) & 0x01 |  | ||||||
| 
 |  | ||||||
| lsr_shift_zero: |  | ||||||
|   jr $ra                          # return |  | ||||||
|   srlv $4, $4, $5                 # return (value >> shift) (delay) |  | ||||||
| 
 |  | ||||||
| lsr_shift_high: |  | ||||||
|   sltiu $1, $5, 33                # $1 = (shift < 33) (delay) |  | ||||||
|   bne $1, $0, lsr_shift_done      # jump if shift == 32 |  | ||||||
|   srl $22, $4, 31                 # c flag = value >> 31 (delay) |  | ||||||
| 
 |  | ||||||
|   addu $22, $0, $0                # c flag = 0 otherwise |  | ||||||
| 
 |  | ||||||
| lsr_shift_done: |  | ||||||
|   jr $ra                          # return |  | ||||||
|   addu $4, $0, $0                 # value = 0 no matter what |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| defsymbl(execute_asr_flags_reg) |  | ||||||
|   beq $5, $0, asr_shift_zero      # is the shift zero? |  | ||||||
|   sltiu $1, $5, 32                # $1 = (shift < 32) (delay) |  | ||||||
|   beq $1, $0, asr_shift_high      # is the shift >= 32? |  | ||||||
|   addiu $2, $5, -1                # $2 = shift - 1 (delay) |  | ||||||
| 
 |  | ||||||
|   srlv $2, $4, $2                 # $2 = (value >> (shift - 1)) |  | ||||||
|   andi $22, $2, 1                 # c flag = (value >> (32 - shift)) & 0x01 |  | ||||||
| 
 |  | ||||||
| asr_shift_zero: |  | ||||||
|   jr $ra                          # return |  | ||||||
|   srav $4, $4, $5                 # return (value >> shift) (delay) |  | ||||||
| 
 |  | ||||||
| asr_shift_high: |  | ||||||
|   sra $4, $4, 31                  # value >>= 31 |  | ||||||
|   jr $ra                          # return |  | ||||||
|   andi $22, $4, 1                 # c flag = value & 0x01 |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| # $4: cycle counter argument | # $4: cycle counter argument | ||||||
| # $5: pointer to reg | # $5: pointer to reg | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue