Path: blob/master/libmupen64plus/mupen64plus-core/src/r4300/x86/gspecial.c
2 views
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *1* Mupen64plus - gspecial.c *2* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *3* Copyright (C) 2002 Hacktarux *4* *5* This program is free software; you can redistribute it and/or modify *6* it under the terms of the GNU General Public License as published by *7* the Free Software Foundation; either version 2 of the License, or *8* (at your option) any later version. *9* *10* This program is distributed in the hope that it will be useful, *11* but WITHOUT ANY WARRANTY; without even the implied warranty of *12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *13* GNU General Public License for more details. *14* *15* You should have received a copy of the GNU General Public License *16* along with this program; if not, write to the *17* Free Software Foundation, Inc., *18* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *19* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */2021#include <stdio.h>2223#include "assemble.h"24#include "interpret.h"2526#include "r4300/recomph.h"27#include "r4300/recomp.h"28#include "r4300/r4300.h"29#include "r4300/ops.h"30#include "r4300/macros.h"31#include "r4300/exception.h"3233void gensll(void)34{35#ifdef INTERPRET_SLL36gencallinterp((unsigned int)cached_interpreter_table.SLL, 0);37#else38int rt = allocate_register((unsigned int *)dst->f.r.rt);39int rd = allocate_register_w((unsigned int *)dst->f.r.rd);4041mov_reg32_reg32(rd, rt);42shl_reg32_imm8(rd, dst->f.r.sa);43#endif44}4546void gensrl(void)47{48#ifdef INTERPRET_SRL49gencallinterp((unsigned int)cached_interpreter_table.SRL, 0);50#else51int rt = allocate_register((unsigned int *)dst->f.r.rt);52int rd = allocate_register_w((unsigned int *)dst->f.r.rd);5354mov_reg32_reg32(rd, rt);55shr_reg32_imm8(rd, dst->f.r.sa);56#endif57}5859void gensra(void)60{61#ifdef INTERPRET_SRA62gencallinterp((unsigned int)cached_interpreter_table.SRA, 0);63#else64int rt = allocate_register((unsigned int *)dst->f.r.rt);65int rd = allocate_register_w((unsigned int *)dst->f.r.rd);6667mov_reg32_reg32(rd, rt);68sar_reg32_imm8(rd, dst->f.r.sa);69#endif70}7172void gensllv(void)73{74#ifdef INTERPRET_SLLV75gencallinterp((unsigned int)cached_interpreter_table.SLLV, 0);76#else77int rt, rd;78allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);7980rt = allocate_register((unsigned int *)dst->f.r.rt);81rd = allocate_register_w((unsigned int *)dst->f.r.rd);8283if (rd != ECX)84{85mov_reg32_reg32(rd, rt);86shl_reg32_cl(rd);87}88else89{90int temp = lru_register();91free_register(temp);92mov_reg32_reg32(temp, rt);93shl_reg32_cl(temp);94mov_reg32_reg32(rd, temp);95}96#endif97}9899void gensrlv(void)100{101#ifdef INTERPRET_SRLV102gencallinterp((unsigned int)cached_interpreter_table.SRLV, 0);103#else104int rt, rd;105allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);106107rt = allocate_register((unsigned int *)dst->f.r.rt);108rd = allocate_register_w((unsigned int *)dst->f.r.rd);109110if (rd != ECX)111{112mov_reg32_reg32(rd, rt);113shr_reg32_cl(rd);114}115else116{117int temp = lru_register();118free_register(temp);119mov_reg32_reg32(temp, rt);120shr_reg32_cl(temp);121mov_reg32_reg32(rd, temp);122}123#endif124}125126void gensrav(void)127{128#ifdef INTERPRET_SRAV129gencallinterp((unsigned int)cached_interpreter_table.SRAV, 0);130#else131int rt, rd;132allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);133134rt = allocate_register((unsigned int *)dst->f.r.rt);135rd = allocate_register_w((unsigned int *)dst->f.r.rd);136137if (rd != ECX)138{139mov_reg32_reg32(rd, rt);140sar_reg32_cl(rd);141}142else143{144int temp = lru_register();145free_register(temp);146mov_reg32_reg32(temp, rt);147sar_reg32_cl(temp);148mov_reg32_reg32(rd, temp);149}150#endif151}152153void genjr(void)154{155#ifdef INTERPRET_JR156gencallinterp((unsigned int)cached_interpreter_table.JR, 1);157#else158static unsigned int precomp_instr_size = sizeof(precomp_instr);159unsigned int diff =160(unsigned int)(&dst->local_addr) - (unsigned int)(dst);161unsigned int diff_need =162(unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst);163unsigned int diff_wrap =164(unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst);165166if (((dst->addr & 0xFFF) == 0xFFC &&167(dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)168{169gencallinterp((unsigned int)cached_interpreter_table.JR, 1);170return;171}172173free_all_registers();174simplify_access();175mov_eax_memoffs32((unsigned int *)dst->f.i.rs);176mov_memoffs32_eax((unsigned int *)&local_rs);177178gendelayslot();179180mov_eax_memoffs32((unsigned int *)&local_rs);181mov_memoffs32_eax((unsigned int *)&last_addr);182183gencheck_interupt_reg();184185mov_eax_memoffs32((unsigned int *)&local_rs);186mov_reg32_reg32(EBX, EAX);187and_eax_imm32(0xFFFFF000);188cmp_eax_imm32(dst_block->start & 0xFFFFF000);189je_near_rj(0);190191jump_start_rel32();192193mov_m32_reg32(&jump_to_address, EBX);194mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1));195mov_reg32_imm32(EAX, (unsigned int)jump_to_func);196call_reg32(EAX);197198jump_end_rel32();199200mov_reg32_reg32(EAX, EBX);201sub_eax_imm32(dst_block->start);202shr_reg32_imm8(EAX, 2);203mul_m32((unsigned int *)(&precomp_instr_size));204205mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need);206cmp_reg32_imm32(EBX, 1);207jne_rj(7);208209add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5210jmp_reg32(EAX); // 2211212mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff);213add_reg32_m32(EAX, (unsigned int *)(&dst_block->code));214215jmp_reg32(EAX);216#endif217}218219void genjalr(void)220{221#ifdef INTERPRET_JALR222gencallinterp((unsigned int)cached_interpreter_table.JALR, 0);223#else224static unsigned int precomp_instr_size = sizeof(precomp_instr);225unsigned int diff =226(unsigned int)(&dst->local_addr) - (unsigned int)(dst);227unsigned int diff_need =228(unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst);229unsigned int diff_wrap =230(unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst);231232if (((dst->addr & 0xFFF) == 0xFFC &&233(dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)234{235gencallinterp((unsigned int)cached_interpreter_table.JALR, 1);236return;237}238239free_all_registers();240simplify_access();241mov_eax_memoffs32((unsigned int *)dst->f.r.rs);242mov_memoffs32_eax((unsigned int *)&local_rs);243244gendelayslot();245246mov_m32_imm32((unsigned int *)(dst-1)->f.r.rd, dst->addr+4);247if ((dst->addr+4) & 0x80000000)248mov_m32_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0xFFFFFFFF);249else250mov_m32_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0);251252mov_eax_memoffs32((unsigned int *)&local_rs);253mov_memoffs32_eax((unsigned int *)&last_addr);254255gencheck_interupt_reg();256257mov_eax_memoffs32((unsigned int *)&local_rs);258mov_reg32_reg32(EBX, EAX);259and_eax_imm32(0xFFFFF000);260cmp_eax_imm32(dst_block->start & 0xFFFFF000);261je_near_rj(0);262263jump_start_rel32();264265mov_m32_reg32(&jump_to_address, EBX);266mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1));267mov_reg32_imm32(EAX, (unsigned int)jump_to_func);268call_reg32(EAX);269270jump_end_rel32();271272mov_reg32_reg32(EAX, EBX);273sub_eax_imm32(dst_block->start);274shr_reg32_imm8(EAX, 2);275mul_m32((unsigned int *)(&precomp_instr_size));276277mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need);278cmp_reg32_imm32(EBX, 1);279jne_rj(7);280281add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5282jmp_reg32(EAX); // 2283284mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff);285add_reg32_m32(EAX, (unsigned int *)(&dst_block->code));286287jmp_reg32(EAX);288#endif289}290291void gensyscall(void)292{293#ifdef INTERPRET_SYSCALL294gencallinterp((unsigned int)cached_interpreter_table.SYSCALL, 0);295#else296free_all_registers();297simplify_access();298mov_m32_imm32(&Cause, 8 << 2);299gencallinterp((unsigned int)exception_general, 0);300#endif301}302303void gensync(void)304{305}306307void genmfhi(void)308{309#ifdef INTERPRET_MFHI310gencallinterp((unsigned int)cached_interpreter_table.MFHI, 0);311#else312int rd1 = allocate_64_register1_w((unsigned int*)dst->f.r.rd);313int rd2 = allocate_64_register2_w((unsigned int*)dst->f.r.rd);314int hi1 = allocate_64_register1((unsigned int*)&hi);315int hi2 = allocate_64_register2((unsigned int*)&hi);316317mov_reg32_reg32(rd1, hi1);318mov_reg32_reg32(rd2, hi2);319#endif320}321322void genmthi(void)323{324#ifdef INTERPRET_MTHI325gencallinterp((unsigned int)cached_interpreter_table.MTHI, 0);326#else327int hi1 = allocate_64_register1_w((unsigned int*)&hi);328int hi2 = allocate_64_register2_w((unsigned int*)&hi);329int rs1 = allocate_64_register1((unsigned int*)dst->f.r.rs);330int rs2 = allocate_64_register2((unsigned int*)dst->f.r.rs);331332mov_reg32_reg32(hi1, rs1);333mov_reg32_reg32(hi2, rs2);334#endif335}336337void genmflo(void)338{339#ifdef INTERPRET_MFLO340gencallinterp((unsigned int)cached_interpreter_table.MFLO, 0);341#else342int rd1 = allocate_64_register1_w((unsigned int*)dst->f.r.rd);343int rd2 = allocate_64_register2_w((unsigned int*)dst->f.r.rd);344int lo1 = allocate_64_register1((unsigned int*)&lo);345int lo2 = allocate_64_register2((unsigned int*)&lo);346347mov_reg32_reg32(rd1, lo1);348mov_reg32_reg32(rd2, lo2);349#endif350}351352void genmtlo(void)353{354#ifdef INTERPRET_MTLO355gencallinterp((unsigned int)cached_interpreter_table.MTLO, 0);356#else357int lo1 = allocate_64_register1_w((unsigned int*)&lo);358int lo2 = allocate_64_register2_w((unsigned int*)&lo);359int rs1 = allocate_64_register1((unsigned int*)dst->f.r.rs);360int rs2 = allocate_64_register2((unsigned int*)dst->f.r.rs);361362mov_reg32_reg32(lo1, rs1);363mov_reg32_reg32(lo2, rs2);364#endif365}366367void gendsllv(void)368{369#ifdef INTERPRET_DSLLV370gencallinterp((unsigned int)cached_interpreter_table.DSLLV, 0);371#else372int rt1, rt2, rd1, rd2;373allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);374375rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);376rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);377rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);378rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);379380if (rd1 != ECX && rd2 != ECX)381{382mov_reg32_reg32(rd1, rt1);383mov_reg32_reg32(rd2, rt2);384shld_reg32_reg32_cl(rd2,rd1);385shl_reg32_cl(rd1);386test_reg32_imm32(ECX, 0x20);387je_rj(4);388mov_reg32_reg32(rd2, rd1); // 2389xor_reg32_reg32(rd1, rd1); // 2390}391else392{393int temp1, temp2;394force_32(ECX);395temp1 = lru_register();396temp2 = lru_register_exc1(temp1);397free_register(temp1);398free_register(temp2);399400mov_reg32_reg32(temp1, rt1);401mov_reg32_reg32(temp2, rt2);402shld_reg32_reg32_cl(temp2, temp1);403shl_reg32_cl(temp1);404test_reg32_imm32(ECX, 0x20);405je_rj(4);406mov_reg32_reg32(temp2, temp1); // 2407xor_reg32_reg32(temp1, temp1); // 2408409mov_reg32_reg32(rd1, temp1);410mov_reg32_reg32(rd2, temp2);411}412#endif413}414415void gendsrlv(void)416{417#ifdef INTERPRET_DSRLV418gencallinterp((unsigned int)cached_interpreter_table.DSRLV, 0);419#else420int rt1, rt2, rd1, rd2;421allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);422423rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);424rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);425rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);426rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);427428if (rd1 != ECX && rd2 != ECX)429{430mov_reg32_reg32(rd1, rt1);431mov_reg32_reg32(rd2, rt2);432shrd_reg32_reg32_cl(rd1,rd2);433shr_reg32_cl(rd2);434test_reg32_imm32(ECX, 0x20);435je_rj(4);436mov_reg32_reg32(rd1, rd2); // 2437xor_reg32_reg32(rd2, rd2); // 2438}439else440{441int temp1, temp2;442force_32(ECX);443temp1 = lru_register();444temp2 = lru_register_exc1(temp1);445free_register(temp1);446free_register(temp2);447448mov_reg32_reg32(temp1, rt1);449mov_reg32_reg32(temp2, rt2);450shrd_reg32_reg32_cl(temp1, temp2);451shr_reg32_cl(temp2);452test_reg32_imm32(ECX, 0x20);453je_rj(4);454mov_reg32_reg32(temp1, temp2); // 2455xor_reg32_reg32(temp2, temp2); // 2456457mov_reg32_reg32(rd1, temp1);458mov_reg32_reg32(rd2, temp2);459}460#endif461}462463void gendsrav(void)464{465#ifdef INTERPRET_DSRAV466gencallinterp((unsigned int)cached_interpreter_table.DSRAV, 0);467#else468int rt1, rt2, rd1, rd2;469allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);470471rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);472rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);473rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);474rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);475476if (rd1 != ECX && rd2 != ECX)477{478mov_reg32_reg32(rd1, rt1);479mov_reg32_reg32(rd2, rt2);480shrd_reg32_reg32_cl(rd1,rd2);481sar_reg32_cl(rd2);482test_reg32_imm32(ECX, 0x20);483je_rj(5);484mov_reg32_reg32(rd1, rd2); // 2485sar_reg32_imm8(rd2, 31); // 3486}487else488{489int temp1, temp2;490force_32(ECX);491temp1 = lru_register();492temp2 = lru_register_exc1(temp1);493free_register(temp1);494free_register(temp2);495496mov_reg32_reg32(temp1, rt1);497mov_reg32_reg32(temp2, rt2);498shrd_reg32_reg32_cl(temp1, temp2);499sar_reg32_cl(temp2);500test_reg32_imm32(ECX, 0x20);501je_rj(5);502mov_reg32_reg32(temp1, temp2); // 2503sar_reg32_imm8(temp2, 31); // 3504505mov_reg32_reg32(rd1, temp1);506mov_reg32_reg32(rd2, temp2);507}508#endif509}510511void genmult(void)512{513#ifdef INTERPRET_MULT514gencallinterp((unsigned int)cached_interpreter_table.MULT, 0);515#else516int rs, rt;517allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);518allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);519rs = allocate_register((unsigned int*)dst->f.r.rs);520rt = allocate_register((unsigned int*)dst->f.r.rt);521mov_reg32_reg32(EAX, rs);522imul_reg32(rt);523#endif524}525526void genmultu(void)527{528#ifdef INTERPRET_MULTU529gencallinterp((unsigned int)cached_interpreter_table.MULTU, 0);530#else531int rs, rt;532allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);533allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);534rs = allocate_register((unsigned int*)dst->f.r.rs);535rt = allocate_register((unsigned int*)dst->f.r.rt);536mov_reg32_reg32(EAX, rs);537mul_reg32(rt);538#endif539}540541void gendiv(void)542{543#ifdef INTERPRET_DIV544gencallinterp((unsigned int)cached_interpreter_table.DIV, 0);545#else546int rs, rt;547allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);548allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);549rs = allocate_register((unsigned int*)dst->f.r.rs);550rt = allocate_register((unsigned int*)dst->f.r.rt);551cmp_reg32_imm32(rt, 0);552je_rj((rs == EAX ? 0 : 2) + 1 + 2);553mov_reg32_reg32(EAX, rs); // 0 or 2554cdq(); // 1555idiv_reg32(rt); // 2556#endif557}558559void gendivu(void)560{561#ifdef INTERPRET_DIVU562gencallinterp((unsigned int)cached_interpreter_table.DIVU, 0);563#else564int rs, rt;565allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);566allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);567rs = allocate_register((unsigned int*)dst->f.r.rs);568rt = allocate_register((unsigned int*)dst->f.r.rt);569cmp_reg32_imm32(rt, 0);570je_rj((rs == EAX ? 0 : 2) + 2 + 2);571mov_reg32_reg32(EAX, rs); // 0 or 2572xor_reg32_reg32(EDX, EDX); // 2573div_reg32(rt); // 2574#endif575}576577void gendmult(void)578{579gencallinterp((unsigned int)cached_interpreter_table.DMULT, 0);580}581582void gendmultu(void)583{584#ifdef INTERPRET_DMULTU585gencallinterp((unsigned int)cached_interpreter_table.DMULTU, 0);586#else587free_all_registers();588simplify_access();589590mov_eax_memoffs32((unsigned int *)dst->f.r.rs);591mul_m32((unsigned int *)dst->f.r.rt); // EDX:EAX = temp1592mov_memoffs32_eax((unsigned int *)(&lo));593594mov_reg32_reg32(EBX, EDX); // EBX = temp1>>32595mov_eax_memoffs32((unsigned int *)dst->f.r.rs);596mul_m32((unsigned int *)(dst->f.r.rt)+1);597add_reg32_reg32(EBX, EAX);598adc_reg32_imm32(EDX, 0);599mov_reg32_reg32(ECX, EDX); // ECX:EBX = temp2600601mov_eax_memoffs32((unsigned int *)(dst->f.r.rs)+1);602mul_m32((unsigned int *)dst->f.r.rt); // EDX:EAX = temp3603604add_reg32_reg32(EBX, EAX);605adc_reg32_imm32(ECX, 0); // ECX:EBX = result2606mov_m32_reg32((unsigned int*)(&lo)+1, EBX);607608mov_reg32_reg32(ESI, EDX); // ESI = temp3>>32609mov_eax_memoffs32((unsigned int *)(dst->f.r.rs)+1);610mul_m32((unsigned int *)(dst->f.r.rt)+1);611add_reg32_reg32(EAX, ESI);612adc_reg32_imm32(EDX, 0); // EDX:EAX = temp4613614add_reg32_reg32(EAX, ECX);615adc_reg32_imm32(EDX, 0); // EDX:EAX = result3616mov_memoffs32_eax((unsigned int *)(&hi));617mov_m32_reg32((unsigned int *)(&hi)+1, EDX);618#endif619}620621void genddiv(void)622{623gencallinterp((unsigned int)cached_interpreter_table.DDIV, 0);624}625626void genddivu(void)627{628gencallinterp((unsigned int)cached_interpreter_table.DDIVU, 0);629}630631void genadd(void)632{633#ifdef INTERPRET_ADD634gencallinterp((unsigned int)cached_interpreter_table.ADD, 0);635#else636int rs = allocate_register((unsigned int *)dst->f.r.rs);637int rt = allocate_register((unsigned int *)dst->f.r.rt);638int rd = allocate_register_w((unsigned int *)dst->f.r.rd);639640if (rt != rd && rs != rd)641{642mov_reg32_reg32(rd, rs);643add_reg32_reg32(rd, rt);644}645else646{647int temp = lru_register();648free_register(temp);649mov_reg32_reg32(temp, rs);650add_reg32_reg32(temp, rt);651mov_reg32_reg32(rd, temp);652}653#endif654}655656void genaddu(void)657{658#ifdef INTERPRET_ADDU659gencallinterp((unsigned int)cached_interpreter_table.ADDU, 0);660#else661int rs = allocate_register((unsigned int *)dst->f.r.rs);662int rt = allocate_register((unsigned int *)dst->f.r.rt);663int rd = allocate_register_w((unsigned int *)dst->f.r.rd);664665if (rt != rd && rs != rd)666{667mov_reg32_reg32(rd, rs);668add_reg32_reg32(rd, rt);669}670else671{672int temp = lru_register();673free_register(temp);674mov_reg32_reg32(temp, rs);675add_reg32_reg32(temp, rt);676mov_reg32_reg32(rd, temp);677}678#endif679}680681void gensub(void)682{683#ifdef INTERPRET_SUB684gencallinterp((unsigned int)cached_interpreter_table.SUB, 0);685#else686int rs = allocate_register((unsigned int *)dst->f.r.rs);687int rt = allocate_register((unsigned int *)dst->f.r.rt);688int rd = allocate_register_w((unsigned int *)dst->f.r.rd);689690if (rt != rd && rs != rd)691{692mov_reg32_reg32(rd, rs);693sub_reg32_reg32(rd, rt);694}695else696{697int temp = lru_register();698free_register(temp);699mov_reg32_reg32(temp, rs);700sub_reg32_reg32(temp, rt);701mov_reg32_reg32(rd, temp);702}703#endif704}705706void gensubu(void)707{708#ifdef INTERPRET_SUBU709gencallinterp((unsigned int)cached_interpreter_table.SUBU, 0);710#else711int rs = allocate_register((unsigned int *)dst->f.r.rs);712int rt = allocate_register((unsigned int *)dst->f.r.rt);713int rd = allocate_register_w((unsigned int *)dst->f.r.rd);714715if (rt != rd && rs != rd)716{717mov_reg32_reg32(rd, rs);718sub_reg32_reg32(rd, rt);719}720else721{722int temp = lru_register();723free_register(temp);724mov_reg32_reg32(temp, rs);725sub_reg32_reg32(temp, rt);726mov_reg32_reg32(rd, temp);727}728#endif729}730731void genand(void)732{733#ifdef INTERPRET_AND734gencallinterp((unsigned int)cached_interpreter_table.AND, 0);735#else736int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);737int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);738int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);739int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);740int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);741int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);742743if (rt1 != rd1 && rs1 != rd1)744{745mov_reg32_reg32(rd1, rs1);746mov_reg32_reg32(rd2, rs2);747and_reg32_reg32(rd1, rt1);748and_reg32_reg32(rd2, rt2);749}750else751{752int temp = lru_register();753free_register(temp);754mov_reg32_reg32(temp, rs1);755and_reg32_reg32(temp, rt1);756mov_reg32_reg32(rd1, temp);757mov_reg32_reg32(temp, rs2);758and_reg32_reg32(temp, rt2);759mov_reg32_reg32(rd2, temp);760}761#endif762}763764void genor(void)765{766#ifdef INTERPRET_OR767gencallinterp((unsigned int)cached_interpreter_table.OR, 0);768#else769int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);770int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);771int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);772int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);773int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);774int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);775776if (rt1 != rd1 && rs1 != rd1)777{778mov_reg32_reg32(rd1, rs1);779mov_reg32_reg32(rd2, rs2);780or_reg32_reg32(rd1, rt1);781or_reg32_reg32(rd2, rt2);782}783else784{785int temp = lru_register();786free_register(temp);787mov_reg32_reg32(temp, rs1);788or_reg32_reg32(temp, rt1);789mov_reg32_reg32(rd1, temp);790mov_reg32_reg32(temp, rs2);791or_reg32_reg32(temp, rt2);792mov_reg32_reg32(rd2, temp);793}794#endif795}796797void genxor(void)798{799#ifdef INTERPRET_XOR800gencallinterp((unsigned int)cached_interpreter_table.XOR, 0);801#else802int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);803int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);804int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);805int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);806int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);807int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);808809if (rt1 != rd1 && rs1 != rd1)810{811mov_reg32_reg32(rd1, rs1);812mov_reg32_reg32(rd2, rs2);813xor_reg32_reg32(rd1, rt1);814xor_reg32_reg32(rd2, rt2);815}816else817{818int temp = lru_register();819free_register(temp);820mov_reg32_reg32(temp, rs1);821xor_reg32_reg32(temp, rt1);822mov_reg32_reg32(rd1, temp);823mov_reg32_reg32(temp, rs2);824xor_reg32_reg32(temp, rt2);825mov_reg32_reg32(rd2, temp);826}827#endif828}829830void gennor(void)831{832#ifdef INTERPRET_NOR833gencallinterp((unsigned int)cached_interpreter_table.NOR, 0);834#else835int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);836int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);837int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);838int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);839int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);840int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);841842if (rt1 != rd1 && rs1 != rd1)843{844mov_reg32_reg32(rd1, rs1);845mov_reg32_reg32(rd2, rs2);846or_reg32_reg32(rd1, rt1);847or_reg32_reg32(rd2, rt2);848not_reg32(rd1);849not_reg32(rd2);850}851else852{853int temp = lru_register();854free_register(temp);855mov_reg32_reg32(temp, rs1);856or_reg32_reg32(temp, rt1);857mov_reg32_reg32(rd1, temp);858mov_reg32_reg32(temp, rs2);859or_reg32_reg32(temp, rt2);860mov_reg32_reg32(rd2, temp);861not_reg32(rd1);862not_reg32(rd2);863}864#endif865}866867void genslt(void)868{869#ifdef INTERPRET_SLT870gencallinterp((unsigned int)cached_interpreter_table.SLT, 0);871#else872int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);873int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);874int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);875int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);876int rd = allocate_register_w((unsigned int *)dst->f.r.rd);877878cmp_reg32_reg32(rs2, rt2);879jl_rj(13);880jne_rj(4); // 2881cmp_reg32_reg32(rs1, rt1); // 2882jl_rj(7); // 2883mov_reg32_imm32(rd, 0); // 5884jmp_imm_short(5); // 2885mov_reg32_imm32(rd, 1); // 5886#endif887}888889void gensltu(void)890{891#ifdef INTERPRET_SLTU892gencallinterp((unsigned int)cached_interpreter_table.SLTU, 0);893#else894int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);895int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);896int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);897int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);898int rd = allocate_register_w((unsigned int *)dst->f.r.rd);899900cmp_reg32_reg32(rs2, rt2);901jb_rj(13);902jne_rj(4); // 2903cmp_reg32_reg32(rs1, rt1); // 2904jb_rj(7); // 2905mov_reg32_imm32(rd, 0); // 5906jmp_imm_short(5); // 2907mov_reg32_imm32(rd, 1); // 5908#endif909}910911void gendadd(void)912{913#ifdef INTERPRET_DADD914gencallinterp((unsigned int)cached_interpreter_table.DADD, 0);915#else916int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);917int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);918int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);919int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);920int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);921int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);922923if (rt1 != rd1 && rs1 != rd1)924{925mov_reg32_reg32(rd1, rs1);926mov_reg32_reg32(rd2, rs2);927add_reg32_reg32(rd1, rt1);928adc_reg32_reg32(rd2, rt2);929}930else931{932int temp = lru_register();933free_register(temp);934mov_reg32_reg32(temp, rs1);935add_reg32_reg32(temp, rt1);936mov_reg32_reg32(rd1, temp);937mov_reg32_reg32(temp, rs2);938adc_reg32_reg32(temp, rt2);939mov_reg32_reg32(rd2, temp);940}941#endif942}943944void gendaddu(void)945{946#ifdef INTERPRET_DADDU947gencallinterp((unsigned int)cached_interpreter_table.DADDU, 0);948#else949int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);950int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);951int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);952int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);953int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);954int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);955956if (rt1 != rd1 && rs1 != rd1)957{958mov_reg32_reg32(rd1, rs1);959mov_reg32_reg32(rd2, rs2);960add_reg32_reg32(rd1, rt1);961adc_reg32_reg32(rd2, rt2);962}963else964{965int temp = lru_register();966free_register(temp);967mov_reg32_reg32(temp, rs1);968add_reg32_reg32(temp, rt1);969mov_reg32_reg32(rd1, temp);970mov_reg32_reg32(temp, rs2);971adc_reg32_reg32(temp, rt2);972mov_reg32_reg32(rd2, temp);973}974#endif975}976977void gendsub(void)978{979#ifdef INTERPRET_DSUB980gencallinterp((unsigned int)cached_interpreter_table.DSUB, 0);981#else982int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);983int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);984int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);985int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);986int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);987int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);988989if (rt1 != rd1 && rs1 != rd1)990{991mov_reg32_reg32(rd1, rs1);992mov_reg32_reg32(rd2, rs2);993sub_reg32_reg32(rd1, rt1);994sbb_reg32_reg32(rd2, rt2);995}996else997{998int temp = lru_register();999free_register(temp);1000mov_reg32_reg32(temp, rs1);1001sub_reg32_reg32(temp, rt1);1002mov_reg32_reg32(rd1, temp);1003mov_reg32_reg32(temp, rs2);1004sbb_reg32_reg32(temp, rt2);1005mov_reg32_reg32(rd2, temp);1006}1007#endif1008}10091010void gendsubu(void)1011{1012#ifdef INTERPRET_DSUBU1013gencallinterp((unsigned int)cached_interpreter_table.DSUBU, 0);1014#else1015int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);1016int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);1017int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);1018int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);1019int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);1020int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);10211022if (rt1 != rd1 && rs1 != rd1)1023{1024mov_reg32_reg32(rd1, rs1);1025mov_reg32_reg32(rd2, rs2);1026sub_reg32_reg32(rd1, rt1);1027sbb_reg32_reg32(rd2, rt2);1028}1029else1030{1031int temp = lru_register();1032free_register(temp);1033mov_reg32_reg32(temp, rs1);1034sub_reg32_reg32(temp, rt1);1035mov_reg32_reg32(rd1, temp);1036mov_reg32_reg32(temp, rs2);1037sbb_reg32_reg32(temp, rt2);1038mov_reg32_reg32(rd2, temp);1039}1040#endif1041}10421043void genteq(void)1044{1045gencallinterp((unsigned int)cached_interpreter_table.TEQ, 0);1046}10471048void gendsll(void)1049{1050#ifdef INTERPRET_DSLL1051gencallinterp((unsigned int)cached_interpreter_table.DSLL, 0);1052#else1053int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);1054int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);1055int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);1056int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);10571058mov_reg32_reg32(rd1, rt1);1059mov_reg32_reg32(rd2, rt2);1060shld_reg32_reg32_imm8(rd2, rd1, dst->f.r.sa);1061shl_reg32_imm8(rd1, dst->f.r.sa);1062if (dst->f.r.sa & 0x20)1063{1064mov_reg32_reg32(rd2, rd1);1065xor_reg32_reg32(rd1, rd1);1066}1067#endif1068}10691070void gendsrl(void)1071{1072#ifdef INTERPRET_DSRL1073gencallinterp((unsigned int)cached_interpreter_table.DSRL, 0);1074#else1075int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);1076int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);1077int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);1078int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);10791080mov_reg32_reg32(rd1, rt1);1081mov_reg32_reg32(rd2, rt2);1082shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa);1083shr_reg32_imm8(rd2, dst->f.r.sa);1084if (dst->f.r.sa & 0x20)1085{1086mov_reg32_reg32(rd1, rd2);1087xor_reg32_reg32(rd2, rd2);1088}1089#endif1090}10911092void gendsra(void)1093{1094#ifdef INTERPRET_DSRA1095gencallinterp((unsigned int)cached_interpreter_table.DSRA, 0);1096#else1097int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);1098int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);1099int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);1100int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);11011102mov_reg32_reg32(rd1, rt1);1103mov_reg32_reg32(rd2, rt2);1104shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa);1105sar_reg32_imm8(rd2, dst->f.r.sa);1106if (dst->f.r.sa & 0x20)1107{1108mov_reg32_reg32(rd1, rd2);1109sar_reg32_imm8(rd2, 31);1110}1111#endif1112}11131114void gendsll32(void)1115{1116#ifdef INTERPRET_DSLL321117gencallinterp((unsigned int)cached_interpreter_table.DSLL32, 0);1118#else1119int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);1120int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);1121int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);11221123mov_reg32_reg32(rd2, rt1);1124shl_reg32_imm8(rd2, dst->f.r.sa);1125xor_reg32_reg32(rd1, rd1);1126#endif1127}11281129void gendsrl32(void)1130{1131#ifdef INTERPRET_DSRL321132gencallinterp((unsigned int)cached_interpreter_table.DSRL32, 0);1133#else1134int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);1135int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);1136int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);11371138mov_reg32_reg32(rd1, rt2);1139shr_reg32_imm8(rd1, dst->f.r.sa);1140xor_reg32_reg32(rd2, rd2);1141#endif1142}11431144void gendsra32(void)1145{1146#ifdef INTERPRET_DSRA321147gencallinterp((unsigned int)cached_interpreter_table.DSRA32, 0);1148#else1149int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);1150int rd = allocate_register_w((unsigned int *)dst->f.r.rd);11511152mov_reg32_reg32(rd, rt2);1153sar_reg32_imm8(rd, dst->f.r.sa);1154#endif1155}1156115711581159