@@ -1696,28 +1696,15 @@ void emitter::emitIns_Call(const EmitCallParams& params)
1696
1696
id->idSetIsNoGC (params.isJump || params.noSafePoint || emitNoGChelper (params.methHnd ));
1697
1697
1698
1698
/* 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);
1703
1700
1704
1701
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:
1708
1703
// if (callType == EC_INDIR_R)
1709
- // jalr REG_R0/REG_RA , ireg, offset <---- 1-ins
1704
+ // jalr zero/ra , ireg, offset
1710
1705
// 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
1721
1708
1722
1709
/* Record the address: method, indirection, or funcptr */
1723
1710
if (params.callType == EC_INDIR_R)
@@ -1750,16 +1737,8 @@ void emitter::emitIns_Call(const EmitCallParams& params)
1750
1737
void * addr =
1751
1738
(void *)(((size_t )params.addr ) + (params.isJump ? 0 : 1 )); // NOTE: low-bit0 is used for jalr ra/r0,rd,0
1752
1739
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 ();
1763
1742
}
1764
1743
1765
1744
#ifdef DEBUG
@@ -1794,11 +1773,10 @@ void emitter::emitIns_Call(const EmitCallParams& params)
1794
1773
* Output a call instruction.
1795
1774
*/
1796
1775
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)
1798
1777
{
1799
- unsigned char callInstrSize = sizeof (code_t ); // 4 bytes
1800
- regMaskTP gcrefRegs;
1801
- regMaskTP byrefRegs;
1778
+ regMaskTP gcrefRegs;
1779
+ regMaskTP byrefRegs;
1802
1780
1803
1781
VARSET_TP GCvars (VarSetOps::UninitVal ());
1804
1782
@@ -1837,130 +1815,29 @@ unsigned emitter::emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, c
1837
1815
#endif // DEBUG
1838
1816
1839
1817
assert (id->idIns () == INS_jalr);
1818
+ BYTE* origDst = dst;
1840
1819
if (id->idIsCallRegPtr ())
1841
1820
{ // EC_INDIR_R
1842
1821
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));
1849
1823
}
1850
- else if (id-> idIsReloc ())
1824
+ else
1851
1825
{
1852
- // pc + offset_32bits
1853
- //
1854
- // auipc t2, addr-hi20
1855
- // jalr r0/1,t2,addr-lo12
1856
-
1857
- emitOutput_Instr (dst, 0x00000397 );
1858
-
1859
1826
size_t addr = (size_t )(id->idAddr ()->iiaAddr ); // get addr.
1860
1827
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;
1869
1831
assert ((addr & 1 ) == 0 );
1832
+ regNumber tempReg = (linkReg == REG_ZERO) ? REG_DEFAULT_HELPER_CALL_TARGET : REG_RA;
1870
1833
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 );
1882
1837
1883
- emitRecordRelocation (dst - 4 , (BYTE*)addr, IMAGE_REL_RISCV64_PC);
1838
+ assert (id->idIsDspReloc ());
1839
+ emitRecordRelocation (origDst, (BYTE*)addr, IMAGE_REL_RISCV64_PC);
1884
1840
}
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 ;
1964
1841
1965
1842
// If the method returns a GC ref, mark INTRET (A0) appropriately.
1966
1843
if (id->idGCref () == GCT_GCREF)
@@ -2008,25 +1885,17 @@ unsigned emitter::emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, c
2008
1885
// So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
2009
1886
// to record the call for GC info purposes. (It might be best to use an alternate call,
2010
1887
// 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 );
2012
1889
2013
1890
// Do we need to record a call location for GC purposes?
2014
1891
//
2015
1892
if (!emitFullGCinfo)
2016
1893
{
2017
- emitRecordGCcall (dst, callInstrSize );
1894
+ emitRecordGCcall (dst, sizeof ( code_t ) );
2018
1895
}
2019
1896
}
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
- }
2028
1897
2029
- return callInstrSize ;
1898
+ return dst - origDst ;
2030
1899
}
2031
1900
2032
1901
void emitter::emitJumpDistBind ()
@@ -3257,7 +3126,7 @@ BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* i
3257
3126
assert (!id->idIsLargeCns ());
3258
3127
*size = sizeof (instrDesc);
3259
3128
}
3260
- dst += emitOutputCall (ig, dst, id, 0 );
3129
+ dst += emitOutputCall (ig, dst, id);
3261
3130
return dst;
3262
3131
}
3263
3132
0 commit comments