1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242 |
- /*
- * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved.
- * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef SH4Assembler_h
- #define SH4Assembler_h
- #if ENABLE(ASSEMBLER) && CPU(SH4)
- #include "AssemblerBuffer.h"
- #include "AssemblerBufferWithConstantPool.h"
- #include "JITCompilationEffort.h"
- #include <stdarg.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <wtf/Assertions.h>
- #include <wtf/DataLog.h>
- #include <wtf/Vector.h>
- #ifndef NDEBUG
- #define SH4_ASSEMBLER_TRACING
- #endif
- namespace JSC {
- typedef uint16_t SH4Word;
- enum {
- INVALID_OPCODE = 0xffff,
- ADD_OPCODE = 0x300c,
- ADDIMM_OPCODE = 0x7000,
- ADDC_OPCODE = 0x300e,
- ADDV_OPCODE = 0x300f,
- AND_OPCODE = 0x2009,
- ANDIMM_OPCODE = 0xc900,
- DIV0_OPCODE = 0x2007,
- DIV1_OPCODE = 0x3004,
- BF_OPCODE = 0x8b00,
- BFS_OPCODE = 0x8f00,
- BRA_OPCODE = 0xa000,
- BRAF_OPCODE = 0x0023,
- NOP_OPCODE = 0x0009,
- BSR_OPCODE = 0xb000,
- RTS_OPCODE = 0x000b,
- BT_OPCODE = 0x8900,
- BTS_OPCODE = 0x8d00,
- BSRF_OPCODE = 0x0003,
- BRK_OPCODE = 0x003b,
- FTRC_OPCODE = 0xf03d,
- CMPEQ_OPCODE = 0x3000,
- CMPEQIMM_OPCODE = 0x8800,
- CMPGE_OPCODE = 0x3003,
- CMPGT_OPCODE = 0x3007,
- CMPHI_OPCODE = 0x3006,
- CMPHS_OPCODE = 0x3002,
- CMPPL_OPCODE = 0x4015,
- CMPPZ_OPCODE = 0x4011,
- CMPSTR_OPCODE = 0x200c,
- DT_OPCODE = 0x4010,
- FCMPEQ_OPCODE = 0xf004,
- FCMPGT_OPCODE = 0xf005,
- FMOV_OPCODE = 0xf00c,
- FADD_OPCODE = 0xf000,
- FMUL_OPCODE = 0xf002,
- FSUB_OPCODE = 0xf001,
- FDIV_OPCODE = 0xf003,
- FNEG_OPCODE = 0xf04d,
- JMP_OPCODE = 0x402b,
- JSR_OPCODE = 0x400b,
- LDSPR_OPCODE = 0x402a,
- LDSLPR_OPCODE = 0x4026,
- MOV_OPCODE = 0x6003,
- MOVIMM_OPCODE = 0xe000,
- MOVB_WRITE_RN_OPCODE = 0x2000,
- MOVB_WRITE_RNDEC_OPCODE = 0x2004,
- MOVB_WRITE_R0RN_OPCODE = 0x0004,
- MOVB_WRITE_OFFGBR_OPCODE = 0xc000,
- MOVB_WRITE_OFFRN_OPCODE = 0x8000,
- MOVB_READ_RM_OPCODE = 0x6000,
- MOVB_READ_RMINC_OPCODE = 0x6004,
- MOVB_READ_R0RM_OPCODE = 0x000c,
- MOVB_READ_OFFGBR_OPCODE = 0xc400,
- MOVB_READ_OFFRM_OPCODE = 0x8400,
- MOVL_WRITE_RN_OPCODE = 0x2002,
- MOVL_WRITE_RNDEC_OPCODE = 0x2006,
- MOVL_WRITE_R0RN_OPCODE = 0x0006,
- MOVL_WRITE_OFFGBR_OPCODE = 0xc200,
- MOVL_WRITE_OFFRN_OPCODE = 0x1000,
- MOVL_READ_RM_OPCODE = 0x6002,
- MOVL_READ_RMINC_OPCODE = 0x6006,
- MOVL_READ_R0RM_OPCODE = 0x000e,
- MOVL_READ_OFFGBR_OPCODE = 0xc600,
- MOVL_READ_OFFPC_OPCODE = 0xd000,
- MOVL_READ_OFFRM_OPCODE = 0x5000,
- MOVW_WRITE_RN_OPCODE = 0x2001,
- MOVW_WRITE_R0RN_OPCODE = 0x0005,
- MOVW_READ_RM_OPCODE = 0x6001,
- MOVW_READ_RMINC_OPCODE = 0x6005,
- MOVW_READ_R0RM_OPCODE = 0x000d,
- MOVW_READ_OFFRM_OPCODE = 0x8500,
- MOVW_READ_OFFPC_OPCODE = 0x9000,
- MOVA_READ_OFFPC_OPCODE = 0xc700,
- MOVT_OPCODE = 0x0029,
- MULL_OPCODE = 0x0007,
- DMULL_L_OPCODE = 0x3005,
- STSMACL_OPCODE = 0x001a,
- STSMACH_OPCODE = 0x000a,
- DMULSL_OPCODE = 0x300d,
- NEG_OPCODE = 0x600b,
- NEGC_OPCODE = 0x600a,
- NOT_OPCODE = 0x6007,
- OR_OPCODE = 0x200b,
- ORIMM_OPCODE = 0xcb00,
- ORBIMM_OPCODE = 0xcf00,
- SETS_OPCODE = 0x0058,
- SETT_OPCODE = 0x0018,
- SHAD_OPCODE = 0x400c,
- SHAL_OPCODE = 0x4020,
- SHAR_OPCODE = 0x4021,
- SHLD_OPCODE = 0x400d,
- SHLL_OPCODE = 0x4000,
- SHLL2_OPCODE = 0x4008,
- SHLL8_OPCODE = 0x4018,
- SHLL16_OPCODE = 0x4028,
- SHLR_OPCODE = 0x4001,
- SHLR2_OPCODE = 0x4009,
- SHLR8_OPCODE = 0x4019,
- SHLR16_OPCODE = 0x4029,
- STSPR_OPCODE = 0x002a,
- STSLPR_OPCODE = 0x4022,
- FLOAT_OPCODE = 0xf02d,
- SUB_OPCODE = 0x3008,
- SUBC_OPCODE = 0x300a,
- SUBV_OPCODE = 0x300b,
- TST_OPCODE = 0x2008,
- TSTIMM_OPCODE = 0xc800,
- TSTB_OPCODE = 0xcc00,
- EXTUB_OPCODE = 0x600c,
- EXTUW_OPCODE = 0x600d,
- XOR_OPCODE = 0x200a,
- XORIMM_OPCODE = 0xca00,
- XORB_OPCODE = 0xce00,
- FMOVS_READ_RM_INC_OPCODE = 0xf009,
- FMOVS_READ_RM_OPCODE = 0xf008,
- FMOVS_READ_R0RM_OPCODE = 0xf006,
- FMOVS_WRITE_RN_OPCODE = 0xf00a,
- FMOVS_WRITE_RN_DEC_OPCODE = 0xf00b,
- FMOVS_WRITE_R0RN_OPCODE = 0xf007,
- FCNVDS_DRM_FPUL_OPCODE = 0xf0bd,
- FCNVSD_FPUL_DRN_OPCODE = 0xf0ad,
- LDS_RM_FPUL_OPCODE = 0x405a,
- FLDS_FRM_FPUL_OPCODE = 0xf01d,
- STS_FPUL_RN_OPCODE = 0x005a,
- FSTS_FPUL_FRN_OPCODE = 0xF00d,
- LDSFPSCR_OPCODE = 0x406a,
- STSFPSCR_OPCODE = 0x006a,
- LDSRMFPUL_OPCODE = 0x405a,
- FSTSFPULFRN_OPCODE = 0xf00d,
- FABS_OPCODE = 0xf05d,
- FSQRT_OPCODE = 0xf06d,
- FSCHG_OPCODE = 0xf3fd,
- CLRT_OPCODE = 8,
- };
- namespace SH4Registers {
- typedef enum {
- r0,
- r1,
- r2,
- r3,
- r4,
- r5,
- r6,
- r7,
- r8,
- r9,
- r10,
- r11,
- r12,
- r13,
- r14, fp = r14,
- r15, sp = r15,
- pc,
- pr,
- } RegisterID;
- typedef enum {
- fr0, dr0 = fr0,
- fr1,
- fr2, dr2 = fr2,
- fr3,
- fr4, dr4 = fr4,
- fr5,
- fr6, dr6 = fr6,
- fr7,
- fr8, dr8 = fr8,
- fr9,
- fr10, dr10 = fr10,
- fr11,
- fr12, dr12 = fr12,
- fr13,
- fr14, dr14 = fr14,
- fr15,
- } FPRegisterID;
- }
- inline uint16_t getOpcodeGroup1(uint16_t opc, int rm, int rn)
- {
- return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4));
- }
- inline uint16_t getOpcodeGroup2(uint16_t opc, int rm)
- {
- return (opc | ((rm & 0xf) << 8));
- }
- inline uint16_t getOpcodeGroup3(uint16_t opc, int rm, int rn)
- {
- return (opc | ((rm & 0xf) << 8) | (rn & 0xff));
- }
- inline uint16_t getOpcodeGroup4(uint16_t opc, int rm, int rn, int offset)
- {
- return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4) | (offset & 0xf));
- }
- inline uint16_t getOpcodeGroup5(uint16_t opc, int rm)
- {
- return (opc | (rm & 0xff));
- }
- inline uint16_t getOpcodeGroup6(uint16_t opc, int rm)
- {
- return (opc | (rm & 0xfff));
- }
- inline uint16_t getOpcodeGroup7(uint16_t opc, int rm)
- {
- return (opc | ((rm & 0x7) << 9));
- }
- inline uint16_t getOpcodeGroup8(uint16_t opc, int rm, int rn)
- {
- return (opc | ((rm & 0x7) << 9) | ((rn & 0x7) << 5));
- }
- inline uint16_t getOpcodeGroup9(uint16_t opc, int rm, int rn)
- {
- return (opc | ((rm & 0xf) << 8) | ((rn & 0x7) << 5));
- }
- inline uint16_t getOpcodeGroup10(uint16_t opc, int rm, int rn)
- {
- return (opc | ((rm & 0x7) << 9) | ((rn & 0xf) << 4));
- }
- inline uint16_t getOpcodeGroup11(uint16_t opc, int rm, int rn)
- {
- return (opc | ((rm & 0xf) << 4) | (rn & 0xf));
- }
- inline uint16_t getRn(uint16_t x)
- {
- return ((x & 0xf00) >> 8);
- }
- inline uint16_t getRm(uint16_t x)
- {
- return ((x & 0xf0) >> 4);
- }
- inline uint16_t getDisp(uint16_t x)
- {
- return (x & 0xf);
- }
- inline uint16_t getImm8(uint16_t x)
- {
- return (x & 0xff);
- }
- inline uint16_t getImm12(uint16_t x)
- {
- return (x & 0xfff);
- }
- inline uint16_t getDRn(uint16_t x)
- {
- return ((x & 0xe00) >> 9);
- }
- inline uint16_t getDRm(uint16_t x)
- {
- return ((x & 0xe0) >> 5);
- }
- class SH4Assembler {
- public:
- typedef SH4Registers::RegisterID RegisterID;
- typedef SH4Registers::FPRegisterID FPRegisterID;
- typedef AssemblerBufferWithConstantPool<512, 4, 2, SH4Assembler> SH4Buffer;
- static const RegisterID scratchReg1 = SH4Registers::r3;
- static const RegisterID scratchReg2 = SH4Registers::r11;
- static const uint32_t maxInstructionSize = 16;
- enum {
- padForAlign8 = 0x00,
- padForAlign16 = 0x0009,
- padForAlign32 = 0x00090009,
- };
- enum JumpType {
- JumpFar,
- JumpNear
- };
- SH4Assembler()
- {
- m_claimscratchReg = 0x0;
- }
- // SH4 condition codes
- typedef enum {
- EQ = 0x0, // Equal
- NE = 0x1, // Not Equal
- HS = 0x2, // Unsigned Greater Than equal
- HI = 0x3, // Unsigned Greater Than
- LS = 0x4, // Unsigned Lower or Same
- LI = 0x5, // Unsigned Lower
- GE = 0x6, // Greater or Equal
- LT = 0x7, // Less Than
- GT = 0x8, // Greater Than
- LE = 0x9, // Less or Equal
- OF = 0xa, // OverFlow
- SI = 0xb, // Signed
- NS = 0xc, // Not Signed
- EQU= 0xd, // Equal or unordered(NaN)
- NEU= 0xe,
- GTU= 0xf,
- GEU= 0x10,
- LTU= 0x11,
- LEU= 0x12,
- } Condition;
- // Opaque label types
- public:
- bool isImmediate(int constant)
- {
- return ((constant <= 127) && (constant >= -128));
- }
- RegisterID claimScratch()
- {
- ASSERT((m_claimscratchReg != 0x3));
- if (!(m_claimscratchReg & 0x1)) {
- m_claimscratchReg = (m_claimscratchReg | 0x1);
- return scratchReg1;
- }
- m_claimscratchReg = (m_claimscratchReg | 0x2);
- return scratchReg2;
- }
- void releaseScratch(RegisterID scratchR)
- {
- if (scratchR == scratchReg1)
- m_claimscratchReg = (m_claimscratchReg & 0x2);
- else
- m_claimscratchReg = (m_claimscratchReg & 0x1);
- }
- // Stack operations
- void pushReg(RegisterID reg)
- {
- if (reg == SH4Registers::pr) {
- oneShortOp(getOpcodeGroup2(STSLPR_OPCODE, SH4Registers::sp));
- return;
- }
- oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE, SH4Registers::sp, reg));
- }
- void popReg(RegisterID reg)
- {
- if (reg == SH4Registers::pr) {
- oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE, SH4Registers::sp));
- return;
- }
- oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, reg, SH4Registers::sp));
- }
- void movt(RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup2(MOVT_OPCODE, dst);
- oneShortOp(opc);
- }
- // Arithmetic operations
- void addlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(ADD_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void addclRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(ADDC_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void addvlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(ADDV_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void addlImm8r(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 127) && (imm8 >= -128));
- uint16_t opc = getOpcodeGroup3(ADDIMM_OPCODE, dst, imm8);
- oneShortOp(opc);
- }
- void andlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(AND_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void andlImm8r(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 255) && (imm8 >= 0));
- ASSERT(dst == SH4Registers::r0);
- uint16_t opc = getOpcodeGroup5(ANDIMM_OPCODE, imm8);
- oneShortOp(opc);
- }
- void div1lRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(DIV1_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void div0lRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(DIV0_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void notlReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(NOT_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void orlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(OR_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void orlImm8r(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 255) && (imm8 >= 0));
- ASSERT(dst == SH4Registers::r0);
- uint16_t opc = getOpcodeGroup5(ORIMM_OPCODE, imm8);
- oneShortOp(opc);
- }
- void sublRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(SUB_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void subvlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(SUBV_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void xorlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(XOR_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void xorlImm8r(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 255) && (imm8 >= 0));
- ASSERT(dst == SH4Registers::r0);
- uint16_t opc = getOpcodeGroup5(XORIMM_OPCODE, imm8);
- oneShortOp(opc);
- }
- void shllImm8r(int imm, RegisterID dst)
- {
- switch (imm) {
- case 1:
- oneShortOp(getOpcodeGroup2(SHLL_OPCODE, dst));
- break;
- case 2:
- oneShortOp(getOpcodeGroup2(SHLL2_OPCODE, dst));
- break;
- case 8:
- oneShortOp(getOpcodeGroup2(SHLL8_OPCODE, dst));
- break;
- case 16:
- oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void neg(RegisterID dst, RegisterID src)
- {
- uint16_t opc = getOpcodeGroup1(NEG_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void shldRegReg(RegisterID dst, RegisterID rShift)
- {
- oneShortOp(getOpcodeGroup1(SHLD_OPCODE, dst, rShift));
- }
- void shadRegReg(RegisterID dst, RegisterID rShift)
- {
- oneShortOp(getOpcodeGroup1(SHAD_OPCODE, dst, rShift));
- }
- void shlrImm8r(int imm, RegisterID dst)
- {
- switch (imm) {
- case 1:
- oneShortOp(getOpcodeGroup2(SHLR_OPCODE, dst));
- break;
- case 2:
- oneShortOp(getOpcodeGroup2(SHLR2_OPCODE, dst));
- break;
- case 8:
- oneShortOp(getOpcodeGroup2(SHLR8_OPCODE, dst));
- break;
- case 16:
- oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void shalImm8r(int imm, RegisterID dst)
- {
- switch (imm) {
- case 1:
- oneShortOp(getOpcodeGroup2(SHAL_OPCODE, dst));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void sharImm8r(int imm, RegisterID dst)
- {
- switch (imm) {
- case 1:
- oneShortOp(getOpcodeGroup2(SHAR_OPCODE, dst));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void imullRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MULL_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void dmullRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(DMULL_L_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void dmulslRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(DMULSL_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void stsmacl(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(STSMACL_OPCODE, reg);
- oneShortOp(opc);
- }
- void stsmach(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(STSMACH_OPCODE, reg);
- oneShortOp(opc);
- }
- // Comparisons
- void cmplRegReg(RegisterID left, RegisterID right, Condition cond)
- {
- switch (cond) {
- case NE:
- oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
- break;
- case GT:
- oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, right, left));
- break;
- case EQ:
- oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
- break;
- case GE:
- oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, right, left));
- break;
- case HS:
- oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, right, left));
- break;
- case HI:
- oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, right, left));
- break;
- case LI:
- oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, left, right));
- break;
- case LS:
- oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, left, right));
- break;
- case LE:
- oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, left, right));
- break;
- case LT:
- oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void cmppl(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(CMPPL_OPCODE, reg);
- oneShortOp(opc);
- }
- void cmppz(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(CMPPZ_OPCODE, reg);
- oneShortOp(opc);
- }
- void cmpEqImmR0(int imm, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup5(CMPEQIMM_OPCODE, imm);
- oneShortOp(opc);
- }
- void testlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(TST_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void testlImm8r(int imm, RegisterID dst)
- {
- ASSERT((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0));
- uint16_t opc = getOpcodeGroup5(TSTIMM_OPCODE, imm);
- oneShortOp(opc);
- }
- void nop()
- {
- oneShortOp(NOP_OPCODE, false);
- }
- void sett()
- {
- oneShortOp(SETT_OPCODE);
- }
- void clrt()
- {
- oneShortOp(CLRT_OPCODE);
- }
- void fschg()
- {
- oneShortOp(FSCHG_OPCODE);
- }
- void bkpt()
- {
- oneShortOp(BRK_OPCODE, false);
- }
- void branch(uint16_t opc, int label)
- {
- switch (opc) {
- case BT_OPCODE:
- ASSERT((label <= 127) && (label >= -128));
- oneShortOp(getOpcodeGroup5(BT_OPCODE, label));
- break;
- case BRA_OPCODE:
- ASSERT((label <= 2047) && (label >= -2048));
- oneShortOp(getOpcodeGroup6(BRA_OPCODE, label));
- break;
- case BF_OPCODE:
- ASSERT((label <= 127) && (label >= -128));
- oneShortOp(getOpcodeGroup5(BF_OPCODE, label));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void branch(uint16_t opc, RegisterID reg)
- {
- switch (opc) {
- case BRAF_OPCODE:
- oneShortOp(getOpcodeGroup2(BRAF_OPCODE, reg));
- break;
- case JMP_OPCODE:
- oneShortOp(getOpcodeGroup2(JMP_OPCODE, reg));
- break;
- case JSR_OPCODE:
- oneShortOp(getOpcodeGroup2(JSR_OPCODE, reg));
- break;
- case BSRF_OPCODE:
- oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg));
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- }
- void ldspr(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(LDSPR_OPCODE, reg);
- oneShortOp(opc);
- }
- void stspr(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(STSPR_OPCODE, reg);
- oneShortOp(opc);
- }
- void extub(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(EXTUB_OPCODE, dst, src);
- oneShortOp(opc);
- }
-
- void extuw(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
- oneShortOp(opc);
- }
- // float operations
- void ldsrmfpul(RegisterID src)
- {
- uint16_t opc = getOpcodeGroup2(LDS_RM_FPUL_OPCODE, src);
- oneShortOp(opc);
- }
- void fneg(FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup2(FNEG_OPCODE, dst);
- oneShortOp(opc, true, false);
- }
- void fsqrt(FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup2(FSQRT_OPCODE, dst);
- oneShortOp(opc, true, false);
- }
- void stsfpulReg(RegisterID src)
- {
- uint16_t opc = getOpcodeGroup2(STS_FPUL_RN_OPCODE, src);
- oneShortOp(opc);
- }
- void floatfpulfrn(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup2(FLOAT_OPCODE, src);
- oneShortOp(opc, true, false);
- }
- void fmull(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMUL_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsRegReg(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOV_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsReadrm(RegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsWriterm(FPRegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsWriter0r(FPRegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsReadr0r(RegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsReadrminc(RegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void fmovsWriterndec(FPRegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE, dst, src);
- oneShortOp(opc, true, false);
- }
- void ftrcRegfpul(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup2(FTRC_OPCODE, src);
- oneShortOp(opc, true, false);
- }
- void fldsfpul(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE, src);
- oneShortOp(opc);
- }
- void fstsfpul(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE, src);
- oneShortOp(opc);
- }
- void ldsfpscr(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(LDSFPSCR_OPCODE, reg);
- oneShortOp(opc);
- }
- void stsfpscr(RegisterID reg)
- {
- uint16_t opc = getOpcodeGroup2(STSFPSCR_OPCODE, reg);
- oneShortOp(opc);
- }
- // double operations
- void dcnvds(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE, src >> 1);
- oneShortOp(opc);
- }
- void dcnvsd(FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup7(FCNVSD_FPUL_DRN_OPCODE, dst >> 1);
- oneShortOp(opc);
- }
- void dcmppeq(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FCMPEQ_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void dcmppgt(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FCMPGT_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void dmulRegReg(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FMUL_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void dsubRegReg(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FSUB_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void daddRegReg(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FADD_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void dmovRegReg(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FMOV_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void ddivRegReg(FPRegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup8(FDIV_OPCODE, dst >> 1, src >> 1);
- oneShortOp(opc);
- }
- void dabs(FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup7(FABS_OPCODE, dst >> 1);
- oneShortOp(opc);
- }
- void dsqrt(FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1);
- oneShortOp(opc);
- }
- void dneg(FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup7(FNEG_OPCODE, dst >> 1);
- oneShortOp(opc);
- }
- void fmovReadrm(RegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_OPCODE, dst >> 1, src);
- oneShortOp(opc);
- }
- void fmovWriterm(FPRegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE, dst, src >> 1);
- oneShortOp(opc);
- }
- void fmovWriter0r(FPRegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE, dst, src >> 1);
- oneShortOp(opc);
- }
- void fmovReadr0r(RegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE, dst >> 1, src);
- oneShortOp(opc);
- }
- void fmovReadrminc(RegisterID src, FPRegisterID dst)
- {
- uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE, dst >> 1, src);
- oneShortOp(opc);
- }
- void fmovWriterndec(FPRegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE, dst, src >> 1);
- oneShortOp(opc);
- }
- void floatfpulDreg(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup7(FLOAT_OPCODE, src >> 1);
- oneShortOp(opc);
- }
- void ftrcdrmfpul(FPRegisterID src)
- {
- uint16_t opc = getOpcodeGroup7(FTRC_OPCODE, src >> 1);
- oneShortOp(opc);
- }
- // Various move ops
- void movImm8(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 127) && (imm8 >= -128));
- uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
- oneShortOp(opc);
- }
- void movlRegReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOV_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movwRegMem(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVW_WRITE_RN_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movwMemReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVW_READ_RM_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movwMemRegIn(RegisterID base, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVW_READ_RMINC_OPCODE, dst, base);
- oneShortOp(opc);
- }
- void movwPCReg(int offset, RegisterID base, RegisterID dst)
- {
- ASSERT(base == SH4Registers::pc);
- ASSERT((offset <= 255) && (offset >= 0));
- uint16_t opc = getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE, dst, offset);
- oneShortOp(opc);
- }
- void movwMemReg(int offset, RegisterID base, RegisterID dst)
- {
- ASSERT(dst == SH4Registers::r0);
- uint16_t opc = getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE, base, offset);
- oneShortOp(opc);
- }
- void movwR0mr(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVW_READ_R0RM_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movwRegMemr0(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVW_WRITE_R0RN_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movlRegMem(RegisterID src, int offset, RegisterID base)
- {
- ASSERT((offset <= 15) && (offset >= 0));
- if (!offset) {
- oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src));
- return;
- }
- oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE, base, src, offset));
- }
- void movlRegMem(RegisterID src, RegisterID base)
- {
- uint16_t opc = getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src);
- oneShortOp(opc);
- }
- void movlMemReg(int offset, RegisterID base, RegisterID dst)
- {
- if (base == SH4Registers::pc) {
- ASSERT((offset <= 255) && (offset >= 0));
- oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, dst, offset));
- return;
- }
- ASSERT((offset <= 15) && (offset >= 0));
- if (!offset) {
- oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base));
- return;
- }
- oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
- }
- void movlMemRegCompact(int offset, RegisterID base, RegisterID dst)
- {
- oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
- }
- void movbRegMem(RegisterID src, RegisterID base)
- {
- uint16_t opc = getOpcodeGroup1(MOVB_WRITE_RN_OPCODE, base, src);
- oneShortOp(opc);
- }
- void movbMemReg(int offset, RegisterID base, RegisterID dst)
- {
- ASSERT(dst == SH4Registers::r0);
- uint16_t opc = getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE, base, offset);
- oneShortOp(opc);
- }
- void movbR0mr(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVB_READ_R0RM_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movbMemReg(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVB_READ_RM_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movbMemRegIn(RegisterID base, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVB_READ_RMINC_OPCODE, dst, base);
- oneShortOp(opc);
- }
- void movbRegMemr0(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVB_WRITE_R0RN_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movlMemReg(RegisterID base, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base);
- oneShortOp(opc);
- }
- void movlMemRegIn(RegisterID base, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, dst, base);
- oneShortOp(opc);
- }
- void movlR0mr(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVL_READ_R0RM_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movlRegMemr0(RegisterID src, RegisterID dst)
- {
- uint16_t opc = getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE, dst, src);
- oneShortOp(opc);
- }
- void movlImm8r(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 127) && (imm8 >= -128));
- uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
- oneShortOp(opc);
- }
- void loadConstant(uint32_t constant, RegisterID dst)
- {
- if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) {
- movImm8(constant, dst);
- return;
- }
- uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
- m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
- printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
- m_buffer.putShortWithConstantInt(opc, constant, true);
- }
- void loadConstantUnReusable(uint32_t constant, RegisterID dst, bool ensureSpace = false)
- {
- uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
- if (ensureSpace)
- m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
- printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
- m_buffer.putShortWithConstantInt(opc, constant);
- }
- // Flow control
- AssemblerLabel call()
- {
- RegisterID scr = claimScratch();
- m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
- loadConstantUnReusable(0x0, scr);
- branch(JSR_OPCODE, scr);
- nop();
- releaseScratch(scr);
- return m_buffer.label();
- }
- AssemblerLabel call(RegisterID dst)
- {
- m_buffer.ensureSpace(maxInstructionSize + 2);
- branch(JSR_OPCODE, dst);
- nop();
- return m_buffer.label();
- }
- AssemblerLabel jmp()
- {
- RegisterID scr = claimScratch();
- m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
- AssemblerLabel label = m_buffer.label();
- loadConstantUnReusable(0x0, scr);
- branch(BRAF_OPCODE, scr);
- nop();
- releaseScratch(scr);
- return label;
- }
- void extraInstrForBranch(RegisterID dst)
- {
- loadConstantUnReusable(0x0, dst);
- nop();
- nop();
- }
- AssemblerLabel jmp(RegisterID dst)
- {
- jmpReg(dst);
- return m_buffer.label();
- }
- void jmpReg(RegisterID dst)
- {
- m_buffer.ensureSpace(maxInstructionSize + 2);
- branch(JMP_OPCODE, dst);
- nop();
- }
- AssemblerLabel jne()
- {
- AssemblerLabel label = m_buffer.label();
- branch(BF_OPCODE, 0);
- return label;
- }
- AssemblerLabel je()
- {
- AssemblerLabel label = m_buffer.label();
- branch(BT_OPCODE, 0);
- return label;
- }
- AssemblerLabel bra()
- {
- AssemblerLabel label = m_buffer.label();
- branch(BRA_OPCODE, 0);
- return label;
- }
- void ret()
- {
- m_buffer.ensureSpace(maxInstructionSize + 2);
- oneShortOp(RTS_OPCODE, false);
- }
- AssemblerLabel labelIgnoringWatchpoints()
- {
- m_buffer.ensureSpaceForAnyInstruction();
- return m_buffer.label();
- }
- AssemblerLabel label()
- {
- m_buffer.ensureSpaceForAnyInstruction();
- return m_buffer.label();
- }
- int sizeOfConstantPool()
- {
- return m_buffer.sizeOfConstantPool();
- }
- AssemblerLabel align(int alignment)
- {
- m_buffer.ensureSpace(maxInstructionSize + 2);
- while (!m_buffer.isAligned(alignment)) {
- nop();
- m_buffer.ensureSpace(maxInstructionSize + 2);
- }
- return label();
- }
- static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress)
- {
- uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
- *reinterpret_cast<uint32_t*>(address) = newAddress;
- }
- static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
- {
- uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
- return *reinterpret_cast<uint32_t*>(address);
- }
- static uint16_t* getInstructionPtr(void* code, int offset)
- {
- return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code) + offset);
- }
- static void linkJump(void* code, AssemblerLabel from, void* to)
- {
- ASSERT(from.isSet());
- uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
- uint16_t instruction = *instructionPtr;
- int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset;
- if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
- /* BT label ==> BF 2
- nop LDR reg
- nop braf @reg
- nop nop
- */
- offsetBits -= 8;
- instruction ^= 0x0202;
- *instructionPtr++ = instruction;
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
- instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
- *instructionPtr = instruction;
- printBlockInstr(instructionPtr - 2, from.m_offset, 3);
- return;
- }
- /* MOV #imm, reg => LDR reg
- braf @reg braf @reg
- nop nop
- */
- ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
- offsetBits -= 4;
- if (offsetBits >= -4096 && offsetBits <= 4094) {
- *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
- *(++instructionPtr) = NOP_OPCODE;
- printBlockInstr(instructionPtr - 1, from.m_offset, 2);
- return;
- }
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
- printInstr(*instructionPtr, from.m_offset + 2);
- }
- static void linkCall(void* code, AssemblerLabel from, void* to)
- {
- uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
- instructionPtr -= 3;
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
- }
- static void linkPointer(void* code, AssemblerLabel where, void* value)
- {
- uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset);
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value));
- }
- static unsigned getCallReturnOffset(AssemblerLabel call)
- {
- ASSERT(call.isSet());
- return call.m_offset;
- }
- static uint32_t* getLdrImmAddressOnPool(SH4Word* insn, uint32_t* constPool)
- {
- return (constPool + (*insn & 0xff));
- }
- static SH4Word patchConstantPoolLoad(SH4Word load, int value)
- {
- return ((load & ~0xff) | value);
- }
- static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset)
- {
- ASSERT(((offset >> 1) <= 2047) && ((offset >> 1) >= -2048));
- SH4Buffer::TwoShorts m_barrier;
- m_barrier.high = (BRA_OPCODE | (offset >> 1));
- m_barrier.low = NOP_OPCODE;
- printInstr(((BRA_OPCODE | (offset >> 1))), 0);
- printInstr(NOP_OPCODE, 0);
- return m_barrier;
- }
- static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
- {
- SH4Word* instructionPtr = reinterpret_cast<SH4Word*>(loadAddr);
- SH4Word instruction = *instructionPtr;
- SH4Word index = instruction & 0xff;
- if ((instruction & 0xf000) != MOVIMM_OPCODE)
- return;
- ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024);
- int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4);
- instruction &=0xf00;
- instruction |= 0xd000;
- offset &= 0x03ff;
- instruction |= (offset >> 2);
- *instructionPtr = instruction;
- printInstr(instruction, reinterpret_cast<uint32_t>(loadAddr));
- }
- static void repatchPointer(void* where, void* value)
- {
- patchPointer(where, value);
- }
- static void* readPointer(void* code)
- {
- return reinterpret_cast<void*>(readInt32(code));
- }
- static void repatchInt32(void* where, int32_t value)
- {
- uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value);
- }
- static void repatchCompact(void* where, int32_t value)
- {
- ASSERT(value >= 0);
- ASSERT(value <= 60);
- *reinterpret_cast<uint16_t*>(where) = ((*reinterpret_cast<uint16_t*>(where) & 0xfff0) | (value >> 2));
- cacheFlush(reinterpret_cast<uint16_t*>(where), sizeof(uint16_t));
- }
- static void relinkCall(void* from, void* to)
- {
- uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from);
- instructionPtr -= 3;
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
- }
- static void relinkJump(void* from, void* to)
- {
- uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from);
- uint16_t instruction = *instructionPtr;
- int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
- if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
- offsetBits -= 8;
- instructionPtr++;
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
- instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
- *instructionPtr = instruction;
- printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
- return;
- }
- ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
- offsetBits -= 4;
- if (offsetBits >= -4096 && offsetBits <= 4094) {
- *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
- *(++instructionPtr) = NOP_OPCODE;
- printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2);
- return;
- }
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
- printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
- }
- // Linking & patching
- static ptrdiff_t maxJumpReplacementSize()
- {
- return sizeof(SH4Word) * 6;
- }
- static void replaceWithJump(void *instructionStart, void *to)
- {
- SH4Word* instruction = reinterpret_cast<SH4Word*>(instructionStart);
- intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 2 * sizeof(SH4Word));
- int nbinst = 0;
- if ((difference >= -4096) && (difference <= 4094)) {
- instruction[0] = getOpcodeGroup6(BRA_OPCODE, difference >> 1);
- instruction[1] = NOP_OPCODE;
- cacheFlush(instruction, sizeof(SH4Word) * 2);
- return;
- }
- instruction[nbinst++] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, scratchReg2, 1);
- instruction[nbinst++] = getOpcodeGroup2(JMP_OPCODE, scratchReg2);
- instruction[nbinst++] = NOP_OPCODE;
- if (!(reinterpret_cast<unsigned>(instruction) & 3))
- instruction[nbinst++] = NOP_OPCODE;
- instruction[nbinst++] = reinterpret_cast<unsigned>(to) & 0xffff;
- instruction[nbinst++] = reinterpret_cast<unsigned>(to) >> 16;
- cacheFlush(instruction, sizeof(SH4Word) * nbinst);
- }
- static void revertJump(void* instructionStart, void *immptr)
- {
- SH4Word *insn = reinterpret_cast<SH4Word*>(instructionStart);
- ASSERT((insn[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
- changePCrelativeAddress(insn[0] & 0x00ff, insn, reinterpret_cast<uint32_t>(immptr));
- }
- void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar)
- {
- ASSERT(to.isSet());
- ASSERT(from.isSet());
- uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset);
- uint16_t instruction = *instructionPtr;
- int offsetBits;
- if (type == JumpNear) {
- ASSERT((instruction == BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE));
- int offset = (codeSize() - from.m_offset) - 4;
- *instructionPtr++ = instruction | (offset >> 1);
- printInstr(*instructionPtr, from.m_offset + 2);
- return;
- }
- if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
- /* BT label => BF 2
- nop LDR reg
- nop braf @reg
- nop nop
- */
- offsetBits = (to.m_offset - from.m_offset) - 8;
- instruction ^= 0x0202;
- *instructionPtr++ = instruction;
- if ((*instructionPtr & 0xf000) == 0xe000) {
- uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
- *addr = offsetBits;
- } else
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
- instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
- *instructionPtr = instruction;
- printBlockInstr(instructionPtr - 2, from.m_offset, 3);
- return;
- }
- /* MOV # imm, reg => LDR reg
- braf @reg braf @reg
- nop nop
- */
- ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
- offsetBits = (to.m_offset - from.m_offset) - 4;
- if (offsetBits >= -4096 && offsetBits <= 4094) {
- *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
- *(++instructionPtr) = NOP_OPCODE;
- printBlockInstr(instructionPtr - 1, from.m_offset, 2);
- return;
- }
- instruction = *instructionPtr;
- if ((instruction & 0xf000) == 0xe000) {
- uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
- *addr = offsetBits - 2;
- printInstr(*instructionPtr, from.m_offset + 2);
- return;
- }
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
- printInstr(*instructionPtr, from.m_offset + 2);
- }
- static void* getRelocatedAddress(void* code, AssemblerLabel label)
- {
- return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
- }
- static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
- {
- return b.m_offset - a.m_offset;
- }
- static void patchPointer(void* code, AssemblerLabel where, void* value)
- {
- patchPointer(reinterpret_cast<uint32_t*>(code) + where.m_offset, value);
- }
- static void patchPointer(void* code, void* value)
- {
- patchInt32(code, reinterpret_cast<uint32_t>(value));
- }
- static void patchInt32(void* code, uint32_t value)
- {
- changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value);
- }
- static uint32_t readInt32(void* code)
- {
- return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
- }
- static void* readCallTarget(void* from)
- {
- uint16_t* instructionPtr = static_cast<uint16_t*>(from);
- instructionPtr -= 3;
- return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr & 0xff), instructionPtr));
- }
- PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort)
- {
- return m_buffer.executableCopy(vm, ownerUID, effort);
- }
- static void cacheFlush(void* code, size_t size)
- {
- #if OS(LINUX)
- // Flush each page separately, otherwise the whole flush will fail if an uncommited page is in the area.
- unsigned currentPage = reinterpret_cast<unsigned>(code) & ~(pageSize() - 1);
- unsigned lastPage = (reinterpret_cast<unsigned>(code) + size - 1) & ~(pageSize() - 1);
- do {
- #if defined CACHEFLUSH_D_L2
- syscall(__NR_cacheflush, currentPage, pageSize(), CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2);
- #else
- syscall(__NR_cacheflush, currentPage, pageSize(), CACHEFLUSH_D_WB | CACHEFLUSH_I);
- #endif
- currentPage += pageSize();
- } while (lastPage >= currentPage);
- #else
- #error "The cacheFlush support is missing on this platform."
- #endif
- }
- void prefix(uint16_t pre)
- {
- m_buffer.putByte(pre);
- }
- void oneShortOp(uint16_t opcode, bool checksize = true, bool isDouble = true)
- {
- printInstr(opcode, m_buffer.codeSize(), isDouble);
- if (checksize)
- m_buffer.ensureSpace(maxInstructionSize);
- m_buffer.putShortUnchecked(opcode);
- }
- void ensureSpace(int space)
- {
- m_buffer.ensureSpace(space);
- }
- void ensureSpace(int insnSpace, int constSpace)
- {
- m_buffer.ensureSpace(insnSpace, constSpace);
- }
- // Administrative methods
- void* data() const { return m_buffer.data(); }
- size_t codeSize() const { return m_buffer.codeSize(); }
- #ifdef SH4_ASSEMBLER_TRACING
- static void printInstr(uint16_t opc, unsigned size, bool isdoubleInst = true)
- {
- if (!getenv("JavaScriptCoreDumpJIT"))
- return;
- const char *format = 0;
- printfStdoutInstr("offset: 0x%8.8x\t", size);
- switch (opc) {
- case BRK_OPCODE:
- format = " BRK\n";
- break;
- case NOP_OPCODE:
- format = " NOP\n";
- break;
- case RTS_OPCODE:
- format =" *RTS\n";
- break;
- case SETS_OPCODE:
- format = " SETS\n";
- break;
- case SETT_OPCODE:
- format = " SETT\n";
- break;
- case CLRT_OPCODE:
- format = " CLRT\n";
- break;
- case FSCHG_OPCODE:
- format = " FSCHG\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format);
- return;
- }
- switch (opc & 0xf0ff) {
- case BRAF_OPCODE:
- format = " *BRAF R%d\n";
- break;
- case DT_OPCODE:
- format = " DT R%d\n";
- break;
- case CMPPL_OPCODE:
- format = " CMP/PL R%d\n";
- break;
- case CMPPZ_OPCODE:
- format = " CMP/PZ R%d\n";
- break;
- case JMP_OPCODE:
- format = " *JMP @R%d\n";
- break;
- case JSR_OPCODE:
- format = " *JSR @R%d\n";
- break;
- case LDSPR_OPCODE:
- format = " LDS R%d, PR\n";
- break;
- case LDSLPR_OPCODE:
- format = " LDS.L @R%d+, PR\n";
- break;
- case MOVT_OPCODE:
- format = " MOVT R%d\n";
- break;
- case SHAL_OPCODE:
- format = " SHAL R%d\n";
- break;
- case SHAR_OPCODE:
- format = " SHAR R%d\n";
- break;
- case SHLL_OPCODE:
- format = " SHLL R%d\n";
- break;
- case SHLL2_OPCODE:
- format = " SHLL2 R%d\n";
- break;
- case SHLL8_OPCODE:
- format = " SHLL8 R%d\n";
- break;
- case SHLL16_OPCODE:
- format = " SHLL16 R%d\n";
- break;
- case SHLR_OPCODE:
- format = " SHLR R%d\n";
- break;
- case SHLR2_OPCODE:
- format = " SHLR2 R%d\n";
- break;
- case SHLR8_OPCODE:
- format = " SHLR8 R%d\n";
- break;
- case SHLR16_OPCODE:
- format = " SHLR16 R%d\n";
- break;
- case STSPR_OPCODE:
- format = " STS PR, R%d\n";
- break;
- case STSLPR_OPCODE:
- format = " STS.L PR, @-R%d\n";
- break;
- case LDS_RM_FPUL_OPCODE:
- format = " LDS R%d, FPUL\n";
- break;
- case STS_FPUL_RN_OPCODE:
- format = " STS FPUL, R%d \n";
- break;
- case FLDS_FRM_FPUL_OPCODE:
- format = " FLDS FR%d, FPUL\n";
- break;
- case FSTS_FPUL_FRN_OPCODE:
- format = " FSTS FPUL, R%d \n";
- break;
- case LDSFPSCR_OPCODE:
- format = " LDS R%d, FPSCR \n";
- break;
- case STSFPSCR_OPCODE:
- format = " STS FPSCR, R%d \n";
- break;
- case STSMACL_OPCODE:
- format = " STS MACL, R%d \n";
- break;
- case STSMACH_OPCODE:
- format = " STS MACH, R%d \n";
- break;
- case BSRF_OPCODE:
- format = " *BSRF R%d";
- break;
- case FTRC_OPCODE:
- format = " FTRC FR%d, FPUL\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format, getRn(opc));
- return;
- }
- switch (opc & 0xf0ff) {
- case FNEG_OPCODE:
- format = " FNEG DR%d\n";
- break;
- case FLOAT_OPCODE:
- format = " FLOAT DR%d\n";
- break;
- case FTRC_OPCODE:
- format = " FTRC FR%d, FPUL\n";
- break;
- case FABS_OPCODE:
- format = " FABS FR%d\n";
- break;
- case FSQRT_OPCODE:
- format = " FSQRT FR%d\n";
- break;
- case FCNVDS_DRM_FPUL_OPCODE:
- format = " FCNVDS FR%d, FPUL\n";
- break;
- case FCNVSD_FPUL_DRN_OPCODE:
- format = " FCNVSD FPUL, FR%d\n";
- break;
- }
- if (format) {
- if (isdoubleInst)
- printfStdoutInstr(format, getDRn(opc) << 1);
- else
- printfStdoutInstr(format, getRn(opc));
- return;
- }
- switch (opc & 0xf00f) {
- case ADD_OPCODE:
- format = " ADD R%d, R%d\n";
- break;
- case ADDC_OPCODE:
- format = " ADDC R%d, R%d\n";
- break;
- case ADDV_OPCODE:
- format = " ADDV R%d, R%d\n";
- break;
- case AND_OPCODE:
- format = " AND R%d, R%d\n";
- break;
- case DIV1_OPCODE:
- format = " DIV1 R%d, R%d\n";
- break;
- case CMPEQ_OPCODE:
- format = " CMP/EQ R%d, R%d\n";
- break;
- case CMPGE_OPCODE:
- format = " CMP/GE R%d, R%d\n";
- break;
- case CMPGT_OPCODE:
- format = " CMP/GT R%d, R%d\n";
- break;
- case CMPHI_OPCODE:
- format = " CMP/HI R%d, R%d\n";
- break;
- case CMPHS_OPCODE:
- format = " CMP/HS R%d, R%d\n";
- break;
- case MOV_OPCODE:
- format = " MOV R%d, R%d\n";
- break;
- case MOVB_WRITE_RN_OPCODE:
- format = " MOV.B R%d, @R%d\n";
- break;
- case MOVB_WRITE_RNDEC_OPCODE:
- format = " MOV.B R%d, @-R%d\n";
- break;
- case MOVB_WRITE_R0RN_OPCODE:
- format = " MOV.B R%d, @(R0, R%d)\n";
- break;
- case MOVB_READ_RM_OPCODE:
- format = " MOV.B @R%d, R%d\n";
- break;
- case MOVB_READ_RMINC_OPCODE:
- format = " MOV.B @R%d+, R%d\n";
- break;
- case MOVB_READ_R0RM_OPCODE:
- format = " MOV.B @(R0, R%d), R%d\n";
- break;
- case MOVL_WRITE_RN_OPCODE:
- format = " MOV.L R%d, @R%d\n";
- break;
- case MOVL_WRITE_RNDEC_OPCODE:
- format = " MOV.L R%d, @-R%d\n";
- break;
- case MOVL_WRITE_R0RN_OPCODE:
- format = " MOV.L R%d, @(R0, R%d)\n";
- break;
- case MOVL_READ_RM_OPCODE:
- format = " MOV.L @R%d, R%d\n";
- break;
- case MOVL_READ_RMINC_OPCODE:
- format = " MOV.L @R%d+, R%d\n";
- break;
- case MOVL_READ_R0RM_OPCODE:
- format = " MOV.L @(R0, R%d), R%d\n";
- break;
- case MULL_OPCODE:
- format = " MUL.L R%d, R%d\n";
- break;
- case DMULL_L_OPCODE:
- format = " DMULU.L R%d, R%d\n";
- break;
- case DMULSL_OPCODE:
- format = " DMULS.L R%d, R%d\n";
- break;
- case NEG_OPCODE:
- format = " NEG R%d, R%d\n";
- break;
- case NEGC_OPCODE:
- format = " NEGC R%d, R%d\n";
- break;
- case NOT_OPCODE:
- format = " NOT R%d, R%d\n";
- break;
- case OR_OPCODE:
- format = " OR R%d, R%d\n";
- break;
- case SHAD_OPCODE:
- format = " SHAD R%d, R%d\n";
- break;
- case SHLD_OPCODE:
- format = " SHLD R%d, R%d\n";
- break;
- case SUB_OPCODE:
- format = " SUB R%d, R%d\n";
- break;
- case SUBC_OPCODE:
- format = " SUBC R%d, R%d\n";
- break;
- case SUBV_OPCODE:
- format = " SUBV R%d, R%d\n";
- break;
- case TST_OPCODE:
- format = " TST R%d, R%d\n";
- break;
- case XOR_OPCODE:
- format = " XOR R%d, R%d\n";break;
- case MOVW_WRITE_RN_OPCODE:
- format = " MOV.W R%d, @R%d\n";
- break;
- case MOVW_READ_RM_OPCODE:
- format = " MOV.W @R%d, R%d\n";
- break;
- case MOVW_READ_RMINC_OPCODE:
- format = " MOV.W @R%d+, R%d\n";
- break;
- case MOVW_READ_R0RM_OPCODE:
- format = " MOV.W @(R0, R%d), R%d\n";
- break;
- case MOVW_WRITE_R0RN_OPCODE:
- format = " MOV.W R%d, @(R0, R%d)\n";
- break;
- case EXTUB_OPCODE:
- format = " EXTU.B R%d, R%d\n";
- break;
- case EXTUW_OPCODE:
- format = " EXTU.W R%d, R%d\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format, getRm(opc), getRn(opc));
- return;
- }
- switch (opc & 0xf00f) {
- case FSUB_OPCODE:
- format = " FSUB FR%d, FR%d\n";
- break;
- case FADD_OPCODE:
- format = " FADD FR%d, FR%d\n";
- break;
- case FDIV_OPCODE:
- format = " FDIV FR%d, FR%d\n";
- break;
- case FMUL_OPCODE:
- format = " DMULL FR%d, FR%d\n";
- break;
- case FMOV_OPCODE:
- format = " FMOV FR%d, FR%d\n";
- break;
- case FCMPEQ_OPCODE:
- format = " FCMP/EQ FR%d, FR%d\n";
- break;
- case FCMPGT_OPCODE:
- format = " FCMP/GT FR%d, FR%d\n";
- break;
- }
- if (format) {
- if (isdoubleInst)
- printfStdoutInstr(format, getDRm(opc) << 1, getDRn(opc) << 1);
- else
- printfStdoutInstr(format, getRm(opc), getRn(opc));
- return;
- }
- switch (opc & 0xf00f) {
- case FMOVS_WRITE_RN_DEC_OPCODE:
- format = " %s FR%d, @-R%d\n";
- break;
- case FMOVS_WRITE_RN_OPCODE:
- format = " %s FR%d, @R%d\n";
- break;
- case FMOVS_WRITE_R0RN_OPCODE:
- format = " %s FR%d, @(R0, R%d)\n";
- break;
- }
- if (format) {
- if (isdoubleInst)
- printfStdoutInstr(format, "FMOV", getDRm(opc) << 1, getDRn(opc));
- else
- printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
- return;
- }
- switch (opc & 0xf00f) {
- case FMOVS_READ_RM_OPCODE:
- format = " %s @R%d, FR%d\n";
- break;
- case FMOVS_READ_RM_INC_OPCODE:
- format = " %s @R%d+, FR%d\n";
- break;
- case FMOVS_READ_R0RM_OPCODE:
- format = " %s @(R0, R%d), FR%d\n";
- break;
- }
- if (format) {
- if (isdoubleInst)
- printfStdoutInstr(format, "FMOV", getDRm(opc), getDRn(opc) << 1);
- else
- printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
- return;
- }
- switch (opc & 0xff00) {
- case BF_OPCODE:
- format = " BF %d\n";
- break;
- case BFS_OPCODE:
- format = " *BF/S %d\n";
- break;
- case ANDIMM_OPCODE:
- format = " AND #%d, R0\n";
- break;
- case BT_OPCODE:
- format = " BT %d\n";
- break;
- case BTS_OPCODE:
- format = " *BT/S %d\n";
- break;
- case CMPEQIMM_OPCODE:
- format = " CMP/EQ #%d, R0\n";
- break;
- case MOVB_WRITE_OFFGBR_OPCODE:
- format = " MOV.B R0, @(%d, GBR)\n";
- break;
- case MOVB_READ_OFFGBR_OPCODE:
- format = " MOV.B @(%d, GBR), R0\n";
- break;
- case MOVL_WRITE_OFFGBR_OPCODE:
- format = " MOV.L R0, @(%d, GBR)\n";
- break;
- case MOVL_READ_OFFGBR_OPCODE:
- format = " MOV.L @(%d, GBR), R0\n";
- break;
- case MOVA_READ_OFFPC_OPCODE:
- format = " MOVA @(%d, PC), R0\n";
- break;
- case ORIMM_OPCODE:
- format = " OR #%d, R0\n";
- break;
- case ORBIMM_OPCODE:
- format = " OR.B #%d, @(R0, GBR)\n";
- break;
- case TSTIMM_OPCODE:
- format = " TST #%d, R0\n";
- break;
- case TSTB_OPCODE:
- format = " TST.B %d, @(R0, GBR)\n";
- break;
- case XORIMM_OPCODE:
- format = " XOR #%d, R0\n";
- break;
- case XORB_OPCODE:
- format = " XOR.B %d, @(R0, GBR)\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format, getImm8(opc));
- return;
- }
- switch (opc & 0xff00) {
- case MOVB_WRITE_OFFRN_OPCODE:
- format = " MOV.B R0, @(%d, R%d)\n";
- break;
- case MOVB_READ_OFFRM_OPCODE:
- format = " MOV.B @(%d, R%d), R0\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format, getDisp(opc), getRm(opc));
- return;
- }
- switch (opc & 0xf000) {
- case BRA_OPCODE:
- format = " *BRA %d\n";
- break;
- case BSR_OPCODE:
- format = " *BSR %d\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format, getImm12(opc));
- return;
- }
- switch (opc & 0xf000) {
- case MOVL_READ_OFFPC_OPCODE:
- format = " MOV.L @(%d, PC), R%d\n";
- break;
- case ADDIMM_OPCODE:
- format = " ADD #%d, R%d\n";
- break;
- case MOVIMM_OPCODE:
- format = " MOV #%d, R%d\n";
- break;
- case MOVW_READ_OFFPC_OPCODE:
- format = " MOV.W @(%d, PC), R%d\n";
- break;
- }
- if (format) {
- printfStdoutInstr(format, getImm8(opc), getRn(opc));
- return;
- }
- switch (opc & 0xf000) {
- case MOVL_WRITE_OFFRN_OPCODE:
- format = " MOV.L R%d, @(%d, R%d)\n";
- printfStdoutInstr(format, getRm(opc), getDisp(opc), getRn(opc));
- break;
- case MOVL_READ_OFFRM_OPCODE:
- format = " MOV.L @(%d, R%d), R%d\n";
- printfStdoutInstr(format, getDisp(opc), getRm(opc), getRn(opc));
- break;
- }
- }
- static void printfStdoutInstr(const char* format, ...)
- {
- if (getenv("JavaScriptCoreDumpJIT")) {
- va_list args;
- va_start(args, format);
- vprintfStdoutInstr(format, args);
- va_end(args);
- }
- }
- static void vprintfStdoutInstr(const char* format, va_list args)
- {
- if (getenv("JavaScriptCoreDumpJIT"))
- WTF::dataLogFV(format, args);
- }
- static void printBlockInstr(uint16_t* first, unsigned offset, int nbInstr)
- {
- printfStdoutInstr(">> repatch instructions after link\n");
- for (int i = 0; i <= nbInstr; i++)
- printInstr(*(first + i), offset + i);
- printfStdoutInstr(">> end repatch\n");
- }
- #else
- static void printInstr(uint16_t opc, unsigned size, bool isdoubleInst = true) { };
- static void printBlockInstr(uint16_t* first, unsigned offset, int nbInstr) { };
- #endif
- static void replaceWithLoad(void* instructionStart)
- {
- SH4Word* insPtr = reinterpret_cast<SH4Word*>(instructionStart);
- insPtr += 2; // skip MOV and ADD opcodes
- if (((*insPtr) & 0xf00f) != MOVL_READ_RM_OPCODE) {
- *insPtr = MOVL_READ_RM_OPCODE | (*insPtr & 0x0ff0);
- cacheFlush(insPtr, sizeof(SH4Word));
- }
- }
- static void replaceWithAddressComputation(void* instructionStart)
- {
- SH4Word* insPtr = reinterpret_cast<SH4Word*>(instructionStart);
- insPtr += 2; // skip MOV and ADD opcodes
- if (((*insPtr) & 0xf00f) != MOV_OPCODE) {
- *insPtr = MOV_OPCODE | (*insPtr & 0x0ff0);
- cacheFlush(insPtr, sizeof(SH4Word));
- }
- }
- private:
- SH4Buffer m_buffer;
- int m_claimscratchReg;
- };
- } // namespace JSC
- #endif // ENABLE(ASSEMBLER) && CPU(SH4)
- #endif // SH4Assembler_h
|