@@ -1696,28 +1696,15 @@ void emitter::emitIns_Call(const EmitCallParams& params)
16961696 id->idSetIsNoGC (params.isJump || params.noSafePoint || emitNoGChelper (params.methHnd ));
16971697
16981698 /* Set the instruction - special case jumping a function */
1699- instruction ins;
1700-
1701- ins = INS_jalr; // jalr
1702- id->idIns (ins);
1699+ id->idIns (INS_jalr);
17031700
17041701 id->idInsOpt (INS_OPTS_C);
1705- // TODO-RISCV64: maybe optimize.
1706-
1707- // INS_OPTS_C: placeholders. 1/2/4-ins:
1702+ // INS_OPTS_C: placeholders. 1/2-ins:
17081703 // if (callType == EC_INDIR_R)
1709- // jalr REG_R0/REG_RA , ireg, offset <---- 1-ins
1704+ // jalr zero/ra , ireg, offset
17101705 // else if (callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR)
1711- // if reloc:
1712- // //pc + offset_38bits # only when reloc.
1713- // auipc t2, addr-hi20
1714- // jalr r0/1, t2, addr-lo12
1715- //
1716- // else:
1717- // lui t2, dst_offset_lo32-hi
1718- // ori t2, t2, dst_offset_lo32-lo
1719- // lui t2, dst_offset_hi32-lo
1720- // jalr REG_R0/REG_RA, t2, 0
1706+ // auipc t2/ra, offset-hi20
1707+ // jalr zero/ra, t2/ra, offset-lo12
17211708
17221709 /* Record the address: method, indirection, or funcptr */
17231710 if (params.callType == EC_INDIR_R)
@@ -1750,16 +1737,8 @@ void emitter::emitIns_Call(const EmitCallParams& params)
17501737 void * addr =
17511738 (void *)(((size_t )params.addr ) + (params.isJump ? 0 : 1 )); // NOTE: low-bit0 is used for jalr ra/r0,rd,0
17521739 id->idAddr ()->iiaAddr = (BYTE*)addr;
1753-
1754- if (emitComp->opts .compReloc )
1755- {
1756- id->idSetIsDspReloc ();
1757- id->idCodeSize (8 );
1758- }
1759- else
1760- {
1761- id->idCodeSize (32 );
1762- }
1740+ id->idCodeSize (2 * sizeof (code_t ));
1741+ id->idSetIsDspReloc ();
17631742 }
17641743
17651744#ifdef DEBUG
@@ -1794,11 +1773,10 @@ void emitter::emitIns_Call(const EmitCallParams& params)
17941773 * Output a call instruction.
17951774 */
17961775
1797- unsigned emitter::emitOutputCall (const insGroup* ig, BYTE* dst, instrDesc* id, code_t code )
1776+ unsigned emitter::emitOutputCall (const insGroup* ig, BYTE* dst, instrDesc* id)
17981777{
1799- unsigned char callInstrSize = sizeof (code_t ); // 4 bytes
1800- regMaskTP gcrefRegs;
1801- regMaskTP byrefRegs;
1778+ regMaskTP gcrefRegs;
1779+ regMaskTP byrefRegs;
18021780
18031781 VARSET_TP GCvars (VarSetOps::UninitVal ());
18041782
@@ -1837,130 +1815,29 @@ unsigned emitter::emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, c
18371815#endif // DEBUG
18381816
18391817 assert (id->idIns () == INS_jalr);
1818+ BYTE* origDst = dst;
18401819 if (id->idIsCallRegPtr ())
18411820 { // EC_INDIR_R
18421821 ssize_t offset = id->idSmallCns ();
1843- assert (isValidSimm12 (offset));
1844- code = emitInsCode (id->idIns ());
1845- code |= (code_t )id->idReg4 () << 7 ;
1846- code |= (code_t )id->idReg3 () << 15 ;
1847- code |= (code_t )offset << 20 ;
1848- emitOutput_Instr (dst, code);
1822+ dst += emitOutput_ITypeInstr (dst, INS_jalr, id->idReg4 (), id->idReg3 (), TrimSignedToImm12 (offset));
18491823 }
1850- else if (id-> idIsReloc ())
1824+ else
18511825 {
1852- // pc + offset_32bits
1853- //
1854- // auipc t2, addr-hi20
1855- // jalr r0/1,t2,addr-lo12
1856-
1857- emitOutput_Instr (dst, 0x00000397 );
1858-
18591826 size_t addr = (size_t )(id->idAddr ()->iiaAddr ); // get addr.
18601827
1861- int reg2 = (int )(addr & 1 );
1862- addr -= reg2;
1863-
1864- if (!emitComp->opts .compReloc )
1865- {
1866- assert (isValidSimm32 (addr - (ssize_t )dst));
1867- }
1868-
1828+ regNumber linkReg = (regNumber)(addr & 1 );
1829+ assert (linkReg == REG_ZERO || linkReg == REG_RA);
1830+ addr -= linkReg;
18691831 assert ((addr & 1 ) == 0 );
1832+ regNumber tempReg = (linkReg == REG_ZERO) ? REG_DEFAULT_HELPER_CALL_TARGET : REG_RA;
18701833
1871- dst += 4 ;
1872- emitGCregDeadUpd (REG_DEFAULT_HELPER_CALL_TARGET, dst);
1873-
1874- #ifdef DEBUG
1875- code = emitInsCode (INS_auipc);
1876- assert ((code | (REG_DEFAULT_HELPER_CALL_TARGET << 7 )) == 0x00000397 );
1877- assert ((int )REG_DEFAULT_HELPER_CALL_TARGET == 7 );
1878- code = emitInsCode (INS_jalr);
1879- assert (code == 0x00000067 );
1880- #endif
1881- emitOutput_Instr (dst, 0x00000067 | (REG_DEFAULT_HELPER_CALL_TARGET << 15 ) | reg2 << 7 );
1834+ dst += emitOutput_UTypeInstr (dst, INS_auipc, tempReg, 0 );
1835+ emitGCregDeadUpd (tempReg, dst);
1836+ dst += emitOutput_ITypeInstr (dst, INS_jalr, linkReg, tempReg, 0 );
18821837
1883- emitRecordRelocation (dst - 4 , (BYTE*)addr, IMAGE_REL_RISCV64_PC);
1838+ assert (id->idIsDspReloc ());
1839+ emitRecordRelocation (origDst, (BYTE*)addr, IMAGE_REL_RISCV64_PC);
18841840 }
1885- else
1886- {
1887- // lui t2, dst_offset_hi32-hi
1888- // addi t2, t2, dst_offset_hi32-lo
1889- // slli t2, t2, 11
1890- // addi t2, t2, dst_offset_low32-hi
1891- // slli t2, t2, 11
1892- // addi t2, t2, dst_offset_low32-md
1893- // slli t2, t2, 10
1894- // jalr t2
1895-
1896- ssize_t imm = (ssize_t )(id->idAddr ()->iiaAddr );
1897- assert ((uint64_t )(imm >> 32 ) <= 0x7fff ); // RISC-V Linux Kernel SV48
1898-
1899- int reg2 = (int )(imm & 1 );
1900- imm -= reg2;
1901-
1902- UINT32 high = imm >> 32 ;
1903- code = emitInsCode (INS_lui);
1904- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1905- code |= ((code_t )((high + 0x800 ) >> 12 ) & 0xfffff ) << 12 ;
1906- emitOutput_Instr (dst, code);
1907- dst += 4 ;
1908-
1909- emitGCregDeadUpd (REG_DEFAULT_HELPER_CALL_TARGET, dst);
1910-
1911- code = emitInsCode (INS_addi);
1912- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1913- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1914- code |= (code_t )(high & 0xfff ) << 20 ;
1915- emitOutput_Instr (dst, code);
1916- dst += 4 ;
1917-
1918- code = emitInsCode (INS_slli);
1919- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1920- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1921- code |= (code_t )(11 << 20 );
1922- emitOutput_Instr (dst, code);
1923- dst += 4 ;
1924-
1925- UINT32 low = imm & 0xffffffff ;
1926-
1927- code = emitInsCode (INS_addi);
1928- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1929- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1930- code |= ((low >> 21 ) & 0x7ff ) << 20 ;
1931- emitOutput_Instr (dst, code);
1932- dst += 4 ;
1933-
1934- code = emitInsCode (INS_slli);
1935- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1936- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1937- code |= (code_t )(11 << 20 );
1938- emitOutput_Instr (dst, code);
1939- dst += 4 ;
1940-
1941- code = emitInsCode (INS_addi);
1942- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1943- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1944- code |= ((low >> 10 ) & 0x7ff ) << 20 ;
1945- emitOutput_Instr (dst, code);
1946- dst += 4 ;
1947-
1948- code = emitInsCode (INS_slli);
1949- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 7 ;
1950- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1951- code |= (code_t )(10 << 20 );
1952- emitOutput_Instr (dst, code);
1953- dst += 4 ;
1954-
1955- code = emitInsCode (INS_jalr);
1956- code |= (code_t )reg2 << 7 ;
1957- code |= (code_t )REG_DEFAULT_HELPER_CALL_TARGET << 15 ;
1958- code |= (low & 0x3ff ) << 20 ;
1959- // the offset default is 0;
1960- emitOutput_Instr (dst, code);
1961- }
1962-
1963- dst += 4 ;
19641841
19651842 // If the method returns a GC ref, mark INTRET (A0) appropriately.
19661843 if (id->idGCref () == GCT_GCREF)
@@ -2008,25 +1885,17 @@ unsigned emitter::emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, c
20081885 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
20091886 // to record the call for GC info purposes. (It might be best to use an alternate call,
20101887 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
2011- emitStackPop (dst, /* isCall*/ true , callInstrSize , /* args*/ 0 );
1888+ emitStackPop (dst, /* isCall*/ true , sizeof ( code_t ) , /* args*/ 0 );
20121889
20131890 // Do we need to record a call location for GC purposes?
20141891 //
20151892 if (!emitFullGCinfo)
20161893 {
2017- emitRecordGCcall (dst, callInstrSize );
1894+ emitRecordGCcall (dst, sizeof ( code_t ) );
20181895 }
20191896 }
2020- if (id->idIsCallRegPtr ())
2021- {
2022- callInstrSize = 1 << 2 ;
2023- }
2024- else
2025- {
2026- callInstrSize = id->idIsReloc () ? (2 << 2 ) : (8 << 2 ); // INS_OPTS_C: 2/9-ins.
2027- }
20281897
2029- return callInstrSize ;
1898+ return dst - origDst ;
20301899}
20311900
20321901void emitter::emitJumpDistBind ()
@@ -3257,7 +3126,7 @@ BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* i
32573126 assert (!id->idIsLargeCns ());
32583127 *size = sizeof (instrDesc);
32593128 }
3260- dst += emitOutputCall (ig, dst, id, 0 );
3129+ dst += emitOutputCall (ig, dst, id);
32613130 return dst;
32623131}
32633132
0 commit comments