summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaksen <laksen@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-07-20 08:21:15 +0000
committerlaksen <laksen@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-07-20 08:21:15 +0000
commitce49a20c9d88883a4f10798bcaf4d3f36f0155c8 (patch)
treec9adb5e00e610f17557f0ac90e1b037189ab069e
parenta499e2d25bba1e81c7e3ebc1853f7093cae2b764 (diff)
downloadfpc-ce49a20c9d88883a4f10798bcaf4d3f36f0155c8.tar.gz
Added RiscV32/64 target, from a cleaned up version of branches/laksen/riscv/trunk.
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/laksen@39474 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--riscv_new/compiler/aoptobj.pas14
-rw-r--r--riscv_new/compiler/cgbase.pas8
-rw-r--r--riscv_new/compiler/cgutils.pas5
-rw-r--r--riscv_new/compiler/entfile.pas8
-rw-r--r--riscv_new/compiler/fpcdefs.inc24
-rw-r--r--riscv_new/compiler/globals.pas16
-rw-r--r--riscv_new/compiler/options.pas28
-rw-r--r--riscv_new/compiler/pp.pas13
-rw-r--r--riscv_new/compiler/ppcriscv64.lpi80
-rw-r--r--riscv_new/compiler/psub.pas6
-rw-r--r--riscv_new/compiler/psystem.pas8
-rw-r--r--riscv_new/compiler/riscv/aasmcpu.pas581
-rw-r--r--riscv_new/compiler/riscv/agrvgas.pas240
-rw-r--r--riscv_new/compiler/riscv/cgrv.pas694
-rw-r--r--riscv_new/compiler/riscv/hlcgrv.pas217
-rw-r--r--riscv_new/compiler/riscv/nrvadd.pas418
-rw-r--r--riscv_new/compiler/riscv/nrvcnv.pas178
-rw-r--r--riscv_new/compiler/riscv/nrvcon.pas131
-rw-r--r--riscv_new/compiler/riscv/nrvinl.pas244
-rw-r--r--riscv_new/compiler/riscv/nrvset.pas153
-rw-r--r--riscv_new/compiler/riscv/rgcpu.pas126
-rw-r--r--riscv_new/compiler/riscv32/aoptcpu.pas77
-rw-r--r--riscv_new/compiler/riscv32/aoptcpub.pas115
-rw-r--r--riscv_new/compiler/riscv32/aoptcpuc.pas40
-rw-r--r--riscv_new/compiler/riscv32/aoptcpud.pas40
-rw-r--r--riscv_new/compiler/riscv32/cgcpu.pas641
-rw-r--r--riscv_new/compiler/riscv32/cpubase.pas426
-rw-r--r--riscv_new/compiler/riscv32/cpuinfo.pas135
-rw-r--r--riscv_new/compiler/riscv32/cpunode.pas47
-rw-r--r--riscv_new/compiler/riscv32/cpupara.pas550
-rw-r--r--riscv_new/compiler/riscv32/cpupi.pas123
-rw-r--r--riscv_new/compiler/riscv32/cputarg.pas84
-rw-r--r--riscv_new/compiler/riscv32/hlcgcpu.pas61
-rw-r--r--riscv_new/compiler/riscv32/itcpugas.pas140
-rw-r--r--riscv_new/compiler/riscv32/nrv32add.pas56
-rw-r--r--riscv_new/compiler/riscv32/nrv32cal.pas51
-rw-r--r--riscv_new/compiler/riscv32/nrv32cnv.pas151
-rw-r--r--riscv_new/compiler/riscv32/nrv32mat.pas135
-rw-r--r--riscv_new/compiler/riscv32/rarv32.pas41
-rw-r--r--riscv_new/compiler/riscv32/rarv32gas.pas771
-rw-r--r--riscv_new/compiler/riscv32/rrv32con.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32dwa.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32nor.inc2
-rw-r--r--riscv_new/compiler/riscv32/rrv32num.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32rni.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32sri.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32sta.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32std.inc67
-rw-r--r--riscv_new/compiler/riscv32/rrv32sup.inc67
-rw-r--r--riscv_new/compiler/riscv32/rv32reg.dat77
-rw-r--r--riscv_new/compiler/riscv32/symcpu.pas216
-rw-r--r--riscv_new/compiler/riscv64/aoptcpu.pas178
-rw-r--r--riscv_new/compiler/riscv64/aoptcpub.pas116
-rw-r--r--riscv_new/compiler/riscv64/aoptcpuc.pas40
-rw-r--r--riscv_new/compiler/riscv64/aoptcpud.pas40
-rw-r--r--riscv_new/compiler/riscv64/cgcpu.pas477
-rw-r--r--riscv_new/compiler/riscv64/cpubase.pas436
-rw-r--r--riscv_new/compiler/riscv64/cpuinfo.pas136
-rw-r--r--riscv_new/compiler/riscv64/cpunode.pas54
-rw-r--r--riscv_new/compiler/riscv64/cpupara.pas593
-rw-r--r--riscv_new/compiler/riscv64/cpupi.pas116
-rw-r--r--riscv_new/compiler/riscv64/cputarg.pas85
-rw-r--r--riscv_new/compiler/riscv64/hlcgcpu.pas78
-rw-r--r--riscv_new/compiler/riscv64/itcpugas.pas157
-rw-r--r--riscv_new/compiler/riscv64/nrv64add.pas98
-rw-r--r--riscv_new/compiler/riscv64/nrv64cal.pas56
-rw-r--r--riscv_new/compiler/riscv64/nrv64cnv.pas136
-rw-r--r--riscv_new/compiler/riscv64/nrv64ld.pas57
-rw-r--r--riscv_new/compiler/riscv64/nrv64mat.pas163
-rw-r--r--riscv_new/compiler/riscv64/rarv.pas42
-rw-r--r--riscv_new/compiler/riscv64/rarv64gas.pas770
-rw-r--r--riscv_new/compiler/riscv64/rrv32con.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32dwa.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32nor.inc2
-rw-r--r--riscv_new/compiler/riscv64/rrv32num.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32rni.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32sri.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32sta.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32std.inc67
-rw-r--r--riscv_new/compiler/riscv64/rrv32sup.inc67
-rw-r--r--riscv_new/compiler/riscv64/rv32reg.dat77
-rw-r--r--riscv_new/compiler/riscv64/symcpu.pas220
-rw-r--r--riscv_new/compiler/systems.inc10
-rw-r--r--riscv_new/compiler/systems.pas15
-rw-r--r--riscv_new/compiler/systems/i_linux.pas142
-rw-r--r--riscv_new/compiler/systems/t_linux.pas19
-rw-r--r--riscv_new/compiler/utils/fpc.pp8
-rw-r--r--riscv_new/compiler/utils/ppuutils/ppudump.pp10
-rw-r--r--riscv_new/compiler/version.pas6
-rw-r--r--riscv_new/rtl/inc/system.inc16
-rw-r--r--riscv_new/rtl/inc/systemh.inc45
-rw-r--r--riscv_new/rtl/linux/osdefs.inc10
-rw-r--r--riscv_new/rtl/linux/riscv32/bsyscall.inc1
-rw-r--r--riscv_new/rtl/linux/riscv32/cprt0.as139
-rw-r--r--riscv_new/rtl/linux/riscv32/dllprt0.as80
-rw-r--r--riscv_new/rtl/linux/riscv32/gprt0.as118
-rw-r--r--riscv_new/rtl/linux/riscv32/prt0.as85
-rw-r--r--riscv_new/rtl/linux/riscv32/sighnd.inc44
-rw-r--r--riscv_new/rtl/linux/riscv32/sighndh.inc47
-rw-r--r--riscv_new/rtl/linux/riscv32/stat.inc72
-rw-r--r--riscv_new/rtl/linux/riscv32/syscall.inc141
-rw-r--r--riscv_new/rtl/linux/riscv32/syscallh.inc35
-rw-r--r--riscv_new/rtl/linux/riscv32/sysnr.inc413
-rw-r--r--riscv_new/rtl/linux/riscv64/bsyscall.inc1
-rw-r--r--riscv_new/rtl/linux/riscv64/cprt0.as139
-rw-r--r--riscv_new/rtl/linux/riscv64/dllprt0.as80
-rw-r--r--riscv_new/rtl/linux/riscv64/gprt0.as162
-rw-r--r--riscv_new/rtl/linux/riscv64/prt0.as83
-rw-r--r--riscv_new/rtl/linux/riscv64/sighnd.inc44
-rw-r--r--riscv_new/rtl/linux/riscv64/sighndh.inc47
-rw-r--r--riscv_new/rtl/linux/riscv64/stat.inc72
-rw-r--r--riscv_new/rtl/linux/riscv64/syscall.inc155
-rw-r--r--riscv_new/rtl/linux/riscv64/syscallh.inc35
-rw-r--r--riscv_new/rtl/linux/riscv64/sysnr.inc1
-rw-r--r--riscv_new/rtl/linux/system.pp8
-rw-r--r--riscv_new/rtl/linux/termios.inc530
-rw-r--r--riscv_new/rtl/riscv32/int64p.inc14
-rw-r--r--riscv_new/rtl/riscv32/makefile.cpu6
-rw-r--r--riscv_new/rtl/riscv32/math.inc15
-rw-r--r--riscv_new/rtl/riscv32/riscv32.inc83
-rw-r--r--riscv_new/rtl/riscv32/set.inc15
-rw-r--r--riscv_new/rtl/riscv32/setjump.inc26
-rw-r--r--riscv_new/rtl/riscv32/setjumph.inc25
-rw-r--r--riscv_new/rtl/riscv32/strings.inc18
-rw-r--r--riscv_new/rtl/riscv32/stringss.inc18
-rw-r--r--riscv_new/rtl/riscv64/int64p.inc14
-rw-r--r--riscv_new/rtl/riscv64/makefile.cpu6
-rw-r--r--riscv_new/rtl/riscv64/math.inc15
-rw-r--r--riscv_new/rtl/riscv64/mathu.inc151
-rw-r--r--riscv_new/rtl/riscv64/riscv64.inc124
-rw-r--r--riscv_new/rtl/riscv64/set.inc15
-rw-r--r--riscv_new/rtl/riscv64/setjump.inc132
-rw-r--r--riscv_new/rtl/riscv64/setjumph.inc39
-rw-r--r--riscv_new/rtl/riscv64/strings.inc18
-rw-r--r--riscv_new/rtl/riscv64/stringss.inc18
-rw-r--r--riscv_new/utils/fpcm/fpcmmain.pp88
136 files changed, 15951 insertions, 72 deletions
diff --git a/riscv_new/compiler/aoptobj.pas b/riscv_new/compiler/aoptobj.pas
index b9aed768e1..885b9ee64c 100644
--- a/riscv_new/compiler/aoptobj.pas
+++ b/riscv_new/compiler/aoptobj.pas
@@ -383,8 +383,8 @@ Unit AoptObj;
function JumpTargetOp(ai: taicpu): poper; inline;
begin
-{$if defined(MIPS)}
- { MIPS branches can have 1,2 or 3 operands, target label is the last one. }
+{$if defined(MIPS) or defined(riscv64) or defined(riscv32)}
+ { MIPS or RiscV branches can have 1,2 or 3 operands, target label is the last one. }
result:=ai.oper[ai.ops-1];
{$elseif defined(SPARC64)}
if ai.ops=2 then
@@ -1390,7 +1390,7 @@ Unit AoptObj;
to avoid endless loops with constructs such as "l5: ; jmp l5" }
var p1: tai;
- {$if not defined(MIPS) and not defined(JVM)}
+ {$if not defined(MIPS) and not defined(riscv64) and not defined(riscv32) and not defined(JVM)}
p2: tai;
l: tasmlabel;
{$endif}
@@ -1408,7 +1408,7 @@ Unit AoptObj;
if { the next instruction after the label where the jump hp arrives}
{ is unconditional or of the same type as hp, so continue }
IsJumpToLabelUncond(taicpu(p1))
-{$if not defined(MIPS) and not defined(JVM)}
+{$if not defined(MIPS) and not defined(riscv64) and not defined(riscv32) and not defined(JVM)}
{ for MIPS, it isn't enough to check the condition; first operands must be same, too. }
or
conditions_equal(taicpu(p1).condition,hp.condition) or
@@ -1425,7 +1425,7 @@ Unit AoptObj;
(IsJumpToLabelUncond(taicpu(p2)) or
(conditions_equal(taicpu(p2).condition,hp.condition))) and
SkipLabels(p1,p1))
-{$endif not MIPS and not JVM}
+{$endif not MIPS and not RV64 and not RV32 and not JVM}
then
begin
{ quick check for loops of the form "l5: ; jmp l5 }
@@ -1446,7 +1446,7 @@ Unit AoptObj;
JumpTargetOp(hp)^.ref^.symbol:=JumpTargetOp(taicpu(p1))^.ref^.symbol;
tasmlabel(JumpTargetOp(hp)^.ref^.symbol).increfs;
end
-{$if not defined(MIPS) and not defined(JVM)}
+{$if not defined(MIPS) and not defined(riscv64) and not defined(riscv32) and not defined(JVM)}
else
if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
if not FindAnyLabel(p1,l) then
@@ -1477,7 +1477,7 @@ Unit AoptObj;
if not GetFinalDestination(hp,succ(level)) then
exit;
end;
-{$endif not MIPS and not JVM}
+{$endif not MIPS and not RV64 and not RV32 and not JVM}
end;
GetFinalDestination := true;
end;
diff --git a/riscv_new/compiler/cgbase.pas b/riscv_new/compiler/cgbase.pas
index 325e8fdfdf..e7abf39926 100644
--- a/riscv_new/compiler/cgbase.pas
+++ b/riscv_new/compiler/cgbase.pas
@@ -93,6 +93,14 @@ interface
addr_low_call, // counterpart of two above, generate call_hi16 and call_lo16 relocs
addr_high_call
{$ENDIF}
+ {$if defined(RISCV32) or defined(RISCV64)}
+ ,
+ addr_hi20,
+ addr_lo12,
+ addr_pcrel_hi20,
+ addr_pcrel_lo12,
+ addr_pcrel
+ {$endif RISCV}
{$IFDEF AVR}
,addr_lo8
,addr_lo8_gs
diff --git a/riscv_new/compiler/cgutils.pas b/riscv_new/compiler/cgutils.pas
index 0c1374b69a..3e2475ced6 100644
--- a/riscv_new/compiler/cgutils.pas
+++ b/riscv_new/compiler/cgutils.pas
@@ -74,7 +74,10 @@ unit cgutils;
base,
index : tregister;
refaddr : trefaddr;
- scalefactor : byte;
+ scalefactor : byte;
+{$if defined(riscv32) or defined(riscv64)}
+ symboldata : tlinkedlistitem;
+{$endif riscv32/64}
{$ifdef arm}
symboldata : tlinkedlistitem;
signindex : shortint;
diff --git a/riscv_new/compiler/entfile.pas b/riscv_new/compiler/entfile.pas
index 34b3bc3325..7bbbbca9b1 100644
--- a/riscv_new/compiler/entfile.pas
+++ b/riscv_new/compiler/entfile.pas
@@ -153,7 +153,9 @@ const
{ 15 } 16 {'i8086'},
{ 16 } 64 {'aarch64'},
{ 17 } 32 {'wasm'},
- { 18 } 64 {'sparc64'}
+ { 18 } 64 {'sparc64'},
+ { 19 } 32 {'riscv32'},
+ { 20 } 64 {'riscv64'}
);
CpuAluBitSize : array[tsystemcpu] of longint =
(
@@ -175,7 +177,9 @@ const
{ 15 } 16 {'i8086'},
{ 16 } 64 {'aarch64'},
{ 17 } 64 {'wasm'},
- { 18 } 64 {'sparc64'}
+ { 18 } 64 {'sparc64'},
+ { 19 } 32 {'riscv32'},
+ { 20 } 64 {'riscv64'}
);
{$endif generic_cpu}
diff --git a/riscv_new/compiler/fpcdefs.inc b/riscv_new/compiler/fpcdefs.inc
index ff3add6a38..59f48cd00a 100644
--- a/riscv_new/compiler/fpcdefs.inc
+++ b/riscv_new/compiler/fpcdefs.inc
@@ -273,6 +273,30 @@
{$define SUPPORT_GET_FRAME}
{$endif aarch64}
+{$ifdef riscv32}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define cpufpemu}
+ {$define cputargethasfixedstack}
+ {$define cpuneedsmulhelper}
+ {$define cpuneedsdivhelper}
+ {$define cpucapabilities}
+ {$define cpurequiresproperalignment}
+{$endif riscv32}
+
+{$ifdef riscv64}
+ {$define cpu64bit}
+ {$define cpu64bitaddr}
+ {$define cpu64bitalu}
+ {$define cpufpemu}
+ {$define cputargethasfixedstack}
+ {$define cpuneedsmulhelper}
+ {$define cpuneedsdivhelper}
+ {$define cpucapabilities}
+ {$define cpurequiresproperalignment}
+{$endif riscv64}
+
{$IFDEF MACOS}
{$DEFINE USE_FAKE_SYSUTILS}
{$ENDIF MACOS}
diff --git a/riscv_new/compiler/globals.pas b/riscv_new/compiler/globals.pas
index 121845ae28..d5dddbbc4d 100644
--- a/riscv_new/compiler/globals.pas
+++ b/riscv_new/compiler/globals.pas
@@ -54,8 +54,8 @@ interface
[m_delphi,m_class,m_objpas,m_result,m_string_pchar,
m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
m_out,m_default_para,m_duplicate_names,m_hintdirective,
- m_property,m_default_inline,m_except,m_advanced_records,
- m_array_operators];
+ m_property,m_default_inline,m_except,m_advanced_records,
+ m_array_operators];
delphiunicodemodeswitches = delphimodeswitches + [m_systemcodepage,m_default_unicodestring];
fpcmodeswitches =
[m_fpc,m_string_pchar,m_nested_comment,m_repeat_forward,
@@ -529,6 +529,18 @@ interface
asmcputype : cpu_none;
fputype : fpu_x87;
{$endif i8086}
+ {$ifdef riscv32}
+ cputype : cpu_rv32imafd;
+ optimizecputype : cpu_rv32imafd;
+ asmcputype : cpu_none;
+ fputype : fpu_fd;
+ {$endif riscv32}
+ {$ifdef riscv64}
+ cputype : cpu_rv64imafd;
+ optimizecputype : cpu_rv64imafd;
+ asmcputype : cpu_none;
+ fputype : fpu_fd;
+ {$endif riscv64}
{$endif not GENERIC_CPU}
asmmode : asmmode_standard;
{$ifndef jvm}
diff --git a/riscv_new/compiler/options.pas b/riscv_new/compiler/options.pas
index a5844254b5..c2c6c055a4 100644
--- a/riscv_new/compiler/options.pas
+++ b/riscv_new/compiler/options.pas
@@ -695,6 +695,12 @@ begin
{$ifdef sparc64}
's',
{$endif}
+{$ifdef riscv32}
+ 'R',
+{$endif}
+{$ifdef riscv64}
+ 'r',
+{$endif}
{$ifdef avr}
'V',
{$endif}
@@ -3581,6 +3587,23 @@ procedure read_arguments(cmd:TCmdStr);
def_system_macro('FPC_COMP_IS_INT64');
{$endif aarch64}
+ {$ifdef riscv32}
+ def_system_macro('CPURISCV');
+ def_system_macro('CPURISCV32');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
+ {$endif riscv32}
+ {$ifdef riscv64}
+ def_system_macro('CPURISCV');
+ def_system_macro('CPURISCV64');
+ def_system_macro('CPU64');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
+ {$endif riscv64}
+
{$if defined(cpu8bitalu)}
def_system_macro('CPUINT8');
{$elseif defined(cpu16bitalu)}
@@ -4012,12 +4035,13 @@ begin
if not(option.FPUSetExplicitly) and
((target_info.system in [system_arm_wince,system_arm_gba,
system_m68k_amiga,system_m68k_atari,
- system_arm_nds,system_arm_embedded])
+ system_arm_nds,system_arm_embedded,
+ system_riscv32_embedded,system_riscv64_embedded])
{$ifdef arm}
or (target_info.abi=abi_eabi)
{$endif arm}
)
-{$if defined(arm) or defined (m68k)}
+{$if defined(arm) or defined(riscv32) or defined(riscv64) or defined (m68k)}
or (init_settings.fputype=fpu_soft)
{$endif arm or m68k}
then
diff --git a/riscv_new/compiler/pp.pas b/riscv_new/compiler/pp.pas
index aec3a42891..7dd479d360 100644
--- a/riscv_new/compiler/pp.pas
+++ b/riscv_new/compiler/pp.pas
@@ -37,6 +37,7 @@ program pp;
MIPSEL generate a compiler for the MIPSEL (Littel Endian)
POWERPC generate a compiler for the PowerPC
POWERPC64 generate a compiler for the PowerPC64 architecture
+ RISCV64 generate a compiler for the RiscV64 architecture
SPARC generate a compiler for SPARC
SPARC64 generate a compiler for SPARC64
X86_64 generate a compiler for the AMD x86-64 architecture
@@ -163,6 +164,18 @@ program pp;
{$endif CPUDEFINED}
{$define CPUDEFINED}
{$endif AARCH64}
+{$ifdef RISCV32}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif RISCV32}
+{$ifdef RISCV64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif RISCV64}
{$ifndef CPUDEFINED}
{$fatal A CPU type switch must be defined}
diff --git a/riscv_new/compiler/ppcriscv64.lpi b/riscv_new/compiler/ppcriscv64.lpi
new file mode 100644
index 0000000000..479f39e551
--- /dev/null
+++ b/riscv_new/compiler/ppcriscv64.lpi
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="11"/>
+ <PathDelim Value="\"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <Title Value="ppcriscv64"/>
+ </General>
+ <BuildModes Count="1">
+ <Item1 Name="default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
+ </local>
+ <FormatVersion Value="2"/>
+ <Modes Count="1">
+ <Mode0 Name="default">
+ <local>
+ <LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </Mode0>
+ </Modes>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="sparc64\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="11"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="riscv64\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="riscv;riscv64"/>
+ <OtherUnitFiles Value="riscv;riscv64;systems"/>
+ <UnitOutputDirectory Value="riscv64\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ <UseAnsiStrings Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-driscv64"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/riscv_new/compiler/psub.pas b/riscv_new/compiler/psub.pas
index 5bad837ff9..39e9f2bdcf 100644
--- a/riscv_new/compiler/psub.pas
+++ b/riscv_new/compiler/psub.pas
@@ -990,7 +990,7 @@ implementation
end;
-{$if defined(i386) or defined(x86_64) or defined(arm)}
+{$if defined(i386) or defined(x86_64) or defined(arm) or defined(riscv32) or defined(riscv64)}
const
exception_flags: array[boolean] of tprocinfoflags = (
[],
@@ -1002,7 +1002,7 @@ implementation
begin
tg:=tgobjclass.create;
-{$if defined(i386) or defined(x86_64) or defined(arm)}
+{$if defined(i386) or defined(x86_64) or defined(arm) or defined(riscv32) or defined(riscv64)}
{$if defined(arm)}
{ frame and stack pointer must be always the same on arm thumb so it makes no
sense to fiddle with a frame pointer }
@@ -1100,7 +1100,7 @@ implementation
{$endif defined(arm)}
end;
end;
-{$endif defined(x86) or defined(arm)}
+{$endif defined(x86) or defined(arm) or defined(riscv32) or defined(riscv64)}
{ set the start offset to the start of the temp area in the stack }
set_first_temp_offset;
end;
diff --git a/riscv_new/compiler/psystem.pas b/riscv_new/compiler/psystem.pas
index 36caae6c8f..ac1b9c86da 100644
--- a/riscv_new/compiler/psystem.pas
+++ b/riscv_new/compiler/psystem.pas
@@ -346,6 +346,14 @@ implementation
create_fpu_types;
s64currencytype:=corddef.create(scurrency,low(int64),high(int64),true);
{$endif mips}
+{$ifdef riscv32}
+ create_fpu_types;
+ s64currencytype:=corddef.create(scurrency,low(int64),high(int64),true);
+{$endif riscv32}
+{$ifdef riscv64}
+ create_fpu_types;
+ s64currencytype:=corddef.create(scurrency,low(int64),high(int64),true);
+{$endif riscv64}
{$ifdef jvm}
create_fpu_types;
s64currencytype:=corddef.create(scurrency,low(int64),high(int64),true);
diff --git a/riscv_new/compiler/riscv/aasmcpu.pas b/riscv_new/compiler/riscv/aasmcpu.pas
new file mode 100644
index 0000000000..30acbaa154
--- /dev/null
+++ b/riscv_new/compiler/riscv/aasmcpu.pas
@@ -0,0 +1,581 @@
+{
+ Copyright (c) 1999-2002 by Jonas Maebe and Thomas Schatzl
+
+ Contains the assembler object for the Risc-V 32 and Risc-V 64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,verbose,
+ aasmbase,aasmtai,aasmdata,aasmsym,
+ cpubase,cgbase,cgutils;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+
+ type
+ taicpu = class(tai_cpu_abstract_sym)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : aint);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+ constructor op_const_reg(op:tasmop; _op1: aint; _op2: tregister);
+
+ constructor op_const_const(op : tasmop;_op1,_op2 : aint);
+
+ constructor op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+
+ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+ constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: aint);
+ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ constructor op_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
+ constructor op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
+ constructor op_const_const_const(op : tasmop;_op1 : aint;_op2 : aint;_op3 : aint);
+
+ constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ constructor op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
+ constructor op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
+
+ constructor op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);
+ constructor op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
+ constructor op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
+
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ constructor op_const_const_sym(op : tasmop;_op1,_op2 : aint;_op3: tasmsymbol);
+
+
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint);
+ constructor op_reg_sym(op : tasmop;_op1 : tregister;_op2:tasmsymbol);
+ constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+ constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
+
+ procedure loadbool(opidx:aint;_b:boolean);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+implementation
+
+uses cutils, cclasses;
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.loadbool(opidx:aint;_b:boolean);
+ begin
+ if opidx>=ops then
+ ops:=opidx+1;
+ with oper[opidx]^ do
+ begin
+ if typ=top_ref then
+ dispose(ref);
+ b:=_b;
+ typ:=top_bool;
+ end;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : aint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+ constructor taicpu.op_const_reg(op:tasmop; _op1: aint; _op2: tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_op1,_op2 : aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+ begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadconst(2, _op3);
+ loadconst(3, _op4);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+ constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadsymbol(2,_op3,_op3ofs);
+ end;
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+ constructor taicpu.op_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_const_const(op : tasmop;_op1 : aint;_op2 : aint;_op3 : aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+ constructor taicpu.op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadbool(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+ constructor taicpu.op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadbool(0,_op2);
+ loadreg(0,_op3);
+ loadconst(0,cardinal(_op4));
+ end;
+
+ constructor taicpu.op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);
+ begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadreg(2, _op3);
+ loadconst(3, cardinal(_op4));
+ end;
+
+ constructor taicpu.op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
+ begin
+ inherited create(op);
+ ops:=5;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadconst(3,cardinal(_op4));
+ loadconst(4,cardinal(_op5));
+ end;
+
+ constructor taicpu.op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
+ begin
+ inherited create(op);
+ ops:=5;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ loadconst(3,_op4);
+ loadconst(4,_op5);
+ end;
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+ constructor taicpu.op_const_const_sym(op : tasmop;_op1,_op2 : aint; _op3: tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ loadsymbol(2,_op3,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+ constructor taicpu.op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,0);
+ end;
+
+
+ constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,_op2ofs);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadref(1,_op2);
+ end;
+
+
+{ ****************************** newra stuff *************************** }
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ case regtype of
+ R_INTREGISTER:
+ result:=
+ (opcode=A_ADDI) and
+ (oper[0]^.reg=oper[1]^.reg) and
+ (oper[2]^.val=0);
+ R_FPUREGISTER:
+ result:=
+ (opcode in [A_FSGNJ_S,A_FSGNJ_D]) and
+ (oper[0]^.reg=oper[1]^.reg) and
+ (oper[0]^.reg=oper[2]^.reg);
+ end;
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ result := operand_read;
+ case opcode of
+ // U type
+ A_LUI,
+ A_AUIPC:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+
+ // UJ type
+ A_JAL:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+
+ // I type
+ A_JALR,
+ A_LB,A_LH,A_LW,A_LBU,A_LHU,
+ A_ADDI,A_SLTI,A_SLTIU,
+ A_XORI,A_ORI,A_ANDI,
+ A_SLLI,A_SRLI,A_SRAI,
+
+ A_FENCE,A_FENCE_I,
+ A_ECALL,A_EBREAK,
+ A_CSRRW,A_CSRRS,A_CSRRC,A_CSRRWI,A_CSRRSI,A_CSRRCI,
+
+ A_FRCSR,A_FRRM,A_FRFLAGS,A_FSCSR,A_FSRM,
+ A_FSFLAGS,A_FSRMI,A_FSFLAGSI:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+
+ A_FLW,
+ A_FLD:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+
+ // SB type
+ A_Bxx:
+ result:=operand_read;
+
+ // S type
+ A_SB,A_SH,A_SW,
+
+ A_FSW,
+ A_FSD:
+ result:=operand_read;
+
+ // R type
+ A_ADD,A_SUB,A_SLL,A_SLT,A_SLTU,
+ A_XOR,A_OR,A_AND,A_SRL,A_SRA,
+
+ A_MUL,A_MULH,A_MULHSU,A_MULHU,
+ A_DIV,A_DIVU,A_REM,A_REMU,
+
+ A_LR_W,A_SC_W,A_AMOSWAP_W,A_AMOADD_W,A_AMOXOR_W,A_AMOAND_W,
+ A_AMOOR_W,A_AMOMIN_W,A_AMOMAX_W,A_AMOMINU_W,A_AMOMAXU_W,
+
+ A_FADD_S,A_FSUB_S,A_FMUL_S,A_FDIV_S,
+ A_FSQRT_S,A_FSGNJ_S,A_FSGNJN_S,A_FSGNJX_S,
+ A_FMIN_S,A_FMAX_S,
+ A_FMV_X_S,A_FEQ_S,A_FLT_S,A_FLE_S,A_FCLASS_S,
+ A_FCVT_W_S,A_FCVT_WU_S,A_FCVT_S_W,A_FCVT_S_WU,
+ A_FMV_S_X,
+
+ A_FADD_D,A_FSUB_D,A_FMUL_D,A_FDIV_D,
+ A_FSQRT_D,A_FSGNJ_D,A_FSGNJN_D,A_FSGNJX_D,
+ A_FMIN_D,A_FMAX_D,
+ A_FEQ_D,A_FLT_D,A_FLE_D,A_FCLASS_D,
+ A_FCVT_D_S,A_FCVT_S_D,
+ A_FCVT_W_D,A_FCVT_WU_D,A_FCVT_D_W,A_FCVT_D_WU:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+
+ // R4 type
+ A_FMADD_S,A_FMSUB_S,A_FNMSUB_S,A_FNMADD_S,
+
+ A_FMADD_D,A_FMSUB_D,A_FNMSUB_D,A_FNMADD_D:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+{$ifdef RISCV64}
+ A_LR_D,A_SC_D,A_AMOSWAP_D,A_AMOADD_D,A_AMOXOR_D,A_AMOAND_D,
+ A_AMOOR_D,A_AMOMIN_D,A_AMOMAX_D,A_AMOMINU_D,A_AMOMAXU_D,
+
+ A_MULW,
+ A_DIVW,A_DIVUW,A_REMW,A_REMUW,
+
+ A_FCVT_L_S,A_FCVT_LU_S,
+ A_FCVT_S_L,A_FCVT_S_LU,
+
+ A_FCVT_L_D,A_FCVT_LU_D,A_FMV_X_D,
+ A_FCVT_D_L,A_FCVT_D_LU,A_FMV_D_X,
+
+ A_ADDIW,A_SLLIW,A_SRLIW,A_SRAIW,
+ A_ADDW,A_SLLW,A_SRLW,A_SUBW,A_SRAW,
+ A_LD,A_LWU:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+
+ A_SD:
+ result:=operand_read;
+{$endif RISCV64}
+ end;
+ end;
+
+
+ function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+ begin
+ result := operand_read;
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER:
+{$ifdef cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_LD,r,ref);
+{$else cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_LW,r,ref);
+{$endif cpu64bitalu}
+ R_FPUREGISTER:
+ result:=taicpu.op_reg_ref(A_FLD,r,ref);
+ else
+ internalerror(2005123101);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER:
+{$ifdef cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_SD,r,ref);
+{$else cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_SW,r,ref);
+{$endif cpu64bitalu}
+ R_FPUREGISTER:
+ result:=taicpu.op_reg_ref(A_FSD,r,ref);
+ else
+ internalerror(2005123102);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+begin
+ cai_align:=tai_align;
+ cai_cpu:=taicpu;
+end.
+
diff --git a/riscv_new/compiler/riscv/agrvgas.pas b/riscv_new/compiler/riscv/agrvgas.pas
new file mode 100644
index 0000000000..19b83e74fe
--- /dev/null
+++ b/riscv_new/compiler/riscv/agrvgas.pas
@@ -0,0 +1,240 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit the GAS asm writers for Risc-V32/Risc-V64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{****************************************************************************}
+{ Helper routines for Instruction Writer }
+{****************************************************************************}
+
+unit agrvgas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems,aasmbase,
+ aasmtai,aasmdata,
+ aggas,
+ assemble,
+ cpubase,cgutils,
+ globtype;
+
+ type
+ TRVInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ TRVGNUAssembler=class(TGNUassembler)
+ constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
+ function MakeCmdLine: TCmdStr; override;
+ end;
+
+ implementation
+
+ uses
+ cutils,globals,verbose,
+ cgbase,
+ itcpugas,cpuinfo,
+ aasmcpu;
+
+
+ function getreferencestring(asminfo: pasminfo; var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ if ((offset < -2048) or (offset > 2047)) and
+ (refaddr = addr_no) then
+ internalerror(2006052501);
+ case refaddr of
+ addr_no:
+ s := '';
+ addr_pic_no_got:
+ internalerror(2016060501);
+ else
+ begin
+ s :='';
+ s := s+'(';
+ if assigned(symbol) then
+ begin
+ if asminfo^.dollarsign<>'$' then
+ begin
+ s:=s+ReplaceForbiddenAsmSymbolChars(symbol.name);
+ if assigned(relsymbol) then
+ s:=s+'-'+ReplaceForbiddenAsmSymbolChars(relsymbol.name)
+ end
+ else
+ begin
+ s:=s+symbol.name;
+ if assigned(relsymbol) then
+ s:=s+'-'+relsymbol.name;
+ end;
+ end;
+ end;
+ end;
+ if offset<0 then
+ s:=s+tostr(offset)
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ s:=s+'+'+tostr(offset)
+ else
+ s:=s+tostr(offset);
+ end;
+
+ if not(refaddr in [addr_no,addr_pic_no_got]) then
+ begin
+ s := s+')';
+ end;
+{$ifdef cpu64bitaddr}
+ if (refaddr=addr_pic) then
+ s := s + '@got';
+{$endif cpu64bitaddr}
+
+ if (index=NR_NO) then
+ begin
+ if offset=0 then
+ begin
+ if not (assigned(symbol)) then
+ s:=s+'0';
+ end;
+ if (base<>NR_NO) then
+ s:=s+'('+gas_regname(base)+')'
+ else if not assigned(symbol) then
+ s:=s+'(0)';
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) then
+ begin
+ if (offset=0) then
+ s:=s+gas_regname(base)+','+gas_regname(index)
+ else
+ internalerror(2006052502);
+ end;
+
+ case refaddr of
+ addr_lo12: s:='%lo'+s;
+ addr_hi20: s:='%hi'+s;
+ addr_pcrel_lo12: s:='%pcrel_lo'+s;
+ addr_pcrel_hi20: s:='%pcrel_hi'+s;
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr(asminfo: pasminfo; const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ if asminfo^.dollarsign<>'$' then
+ hs:=ReplaceForbiddenAsmSymbolChars(hs);
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(asminfo,o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+
+ Procedure TRVInstrWriter.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ s:=#9+gas_op2str[taicpu(hp).opcode];
+
+ if taicpu(hp).condition<>C_None then
+ s:=s+cond2str[taicpu(hp).condition];
+
+ if taicpu(hp).ops<>0 then
+ begin
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ s:=s+sep+getopstr(owner.asminfo,taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+
+ owner.writer.AsmWriteLn(s);
+ end;
+
+
+{****************************************************************************}
+{ GNU RiscV Assembler writer }
+{****************************************************************************}
+
+ constructor TRVGNUAssembler.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
+ begin
+ inherited;
+ InstrWriter := TRVInstrWriter.create(self);
+ end;
+
+
+ function TRVGNUAssembler.MakeCmdLine: TCmdStr;
+ begin
+ result := inherited MakeCmdLine;
+{$ifdef cpu64bitaddr}
+ Replace(result,'$ARCH','-m64')
+{$else cpu64bitaddr}
+ Replace(result,'$ARCH','-m32');
+{$endif cpu64bitaddr}
+ end;
+
+
+ const
+ as_riscv_gas_info : tasminfo =
+ (
+ id : as_gas;
+
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $EXTRAOPT $ARCH $ASM';
+ supported_targets : [system_riscv32_linux,system_riscv64_linux];
+ flags : [af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ dollarsign: '$';
+ );
+
+begin
+ RegisterAssembler(as_riscv_gas_info,TRVGNUAssembler);
+end.
diff --git a/riscv_new/compiler/riscv/cgrv.pas b/riscv_new/compiler/riscv/cgrv.pas
new file mode 100644
index 0000000000..5fb781150b
--- /dev/null
+++ b/riscv_new/compiler/riscv/cgrv.pas
@@ -0,0 +1,694 @@
+{
+ Copyright (c) 2006 by Florian Klaempfl
+
+ This unit implements the common part of the code generator for the Risc-V
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgrv;
+
+{$i fpcdefs.inc}
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgobj,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cpubase,cpuinfo,cgutils,rgcpu,
+ parabase;
+
+ type
+ tcgrv = class(tcg)
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
+
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
+
+ procedure a_call_reg(list : TAsmList;reg: tregister); override;
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean); override;
+
+ procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize; reg: tregister; const ref: treference); override;
+ procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister); override;
+
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
+
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister; l : tasmlabel); override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+ procedure a_jmp_name(list : TAsmList;const s : string); override;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+
+ procedure g_save_registers(list: TAsmList); override;
+ procedure g_restore_registers(list: TAsmList); override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+ protected
+ function fixref(list: TAsmList; var ref: treference): boolean;
+ end;
+
+ const
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_NONE,
+ C_LT,C_GE,C_None,C_NE,C_NONE,C_LT,C_GE,C_NONE);
+
+ const
+ TOpCG2AsmConstOp: Array[topcg] of TAsmOp = (A_NONE,
+ A_NONE,A_ADDI,A_ANDI,A_NONE,A_NONE,A_NONE,A_NONE,
+ A_None,A_None,A_ORI,A_SRAI,A_SLLI,A_SRLI,A_NONE,A_XORI,A_None,A_None);
+ TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,
+ A_NONE,A_ADD,A_AND,A_DIVU,A_DIV,A_MUL,A_MUL,
+ A_None,A_None,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR,A_None,A_None);
+
+
+ implementation
+
+ uses
+ {$ifdef extdebug}sysutils,{$endif}
+ globals,verbose,systems,cutils,
+ symconst,symsym,symtable,fmodule,
+ rgobj,tgobj,cpupi,procinfo,paramgr;
+
+
+ procedure tcgrv.a_call_name(list : TAsmList;const s : string; weak: boolean);
+ var
+ tmpreg: TRegister;
+ href: treference;
+ l: TAsmLabel;
+ begin
+ if not(weak) then
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),0,0,[])
+ else
+ reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION),0,0,[]);
+
+ tmpreg:=getintregister(list,OS_ADDR);
+
+ current_asmdata.getjumplabel(l);
+
+ a_label(list,l);
+
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
+
+ reference_reset_symbol(href,l,0,0,[]);
+ href.refaddr:=addr_pcrel_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_JALR,NR_RETURN_ADDRESS_REG,tmpreg,href));
+
+ {if not(weak) then
+ list.concat(taicpu.op_reg_sym(A_JAL,NR_RETURN_ADDRESS_REG,current_asmdata.RefAsmSymbol(s,AT_FUNCTION)))
+ else
+ list.concat(taicpu.op_reg_sym(A_JAL,NR_RETURN_ADDRESS_REG,current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION)));}
+ { not assigned while generating external wrappers }
+ if assigned(current_procinfo) then
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgrv.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
+ var
+ ref: treference;
+ tmpreg: tregister;
+
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment,[]);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+
+
+ procedure tcgrv.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
+ begin
+ internalerror(2016060401);
+ end;
+
+
+ procedure tcgrv.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
+ begin
+ a_op_const_reg_reg(list,op,size,a,reg,reg);
+ end;
+
+
+ procedure tcgrv.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ begin
+ a_op_reg_reg_reg(list,op,size,src,dst,dst);
+ end;
+
+
+ procedure tcgrv.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
+ var
+ tmpreg: TRegister;
+ begin
+ optimize_op_const(size,op,a);
+
+ if op=OP_NONE then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end;
+
+ if op=OP_SUB then
+ begin
+ op:=OP_ADD;
+ a:=-a;
+ end;
+
+ if (TOpCG2AsmConstOp[op]<>A_None) and
+ is_imm12(a) then
+ list.concat(taicpu.op_reg_reg_const(TOpCG2AsmConstOp[op],dst,src,a))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
+ end;
+ end;
+
+
+ procedure tcgrv.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
+ begin
+ case op of
+ OP_NOT:
+ list.concat(taicpu.op_reg_reg_const(A_XORI,dst,src1,-1));
+ OP_NEG:
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,dst,NR_X0,src1));
+ OP_MOVE:
+ a_load_reg_reg(list,size,size,src1,dst);
+ else
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src2,src1));
+ end;
+ end;
+
+
+ procedure tcgrv.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+ var
+ href: treference;
+ b, tmpreg: TRegister;
+ l: TAsmLabel;
+ begin
+ href:=ref;
+ fixref(list,href);
+
+ if (not assigned(href.symbol)) and
+ (href.offset=0) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
+ {else if (assigned(href.symbol) or
+ (not is_imm12(href.offset))) and
+ (href.base<>NR_NO) then
+ begin
+ b:= href.base;
+
+ href.base:=NR_NO;
+ href.refaddr:=addr_hi20;
+ list.concat(taicpu.op_reg_ref(A_LUI,r,href));
+ href.refaddr:=addr_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,href));
+
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
+ end}
+ else if (assigned(href.symbol) or
+ (not is_imm12(href.offset))) and
+ (href.base<>NR_NO) then
+ begin
+ b:= href.base;
+
+ current_asmdata.getjumplabel(l);
+ a_label(list,l);
+
+ href.base:=NR_NO;
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,r,href));
+
+ reference_reset_symbol(href,l,0,0,[]);
+ href.refaddr:=addr_pcrel_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,href));
+
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
+ end
+ else if is_imm12(href.offset) and
+ (href.base<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,r,href.base,href.offset));
+ end
+ {else if (href.refaddr=addr_pcrel) then
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+
+ current_asmdata.getaddrlabel(l);
+
+ a_label(list,l);
+
+ b:=href.base;
+ href.base:=NR_NO;
+
+ href.refaddr:=addr_hi20;
+ href.relsymbol:=l;
+ list.concat(taicpu.op_reg_ref(A_LUI,tmpreg,href));
+ href.refaddr:=addr_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,tmpreg,href));
+
+ if b<>NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
+ end}
+ else if (href.refaddr=addr_pcrel) then
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+
+ b:=href.base;
+ href.base:=NR_NO;
+
+ current_asmdata.getjumplabel(l);
+ a_label(list,l);
+
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
+
+ reference_reset_symbol(href,l,0,0,[]);
+ href.refaddr:=addr_pcrel_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,tmpreg,href));
+
+ if b<>NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,b));
+ end
+ else
+ internalerror(2016060504);
+ end;
+
+
+ procedure tcgrv.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
+ var
+ reg1: TRegister;
+ ai: taicpu;
+ begin
+ if a=0 then
+ begin
+ reg1:=NR_X0;
+ if TOpCmp2AsmCond[cmp_op]=C_None then
+ begin
+ cmp_op:=swap_opcmp(cmp_op);
+ reg1:=reg;
+ reg:=NR_X0;
+ end;
+
+ ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,reg,reg1,l,0);
+ ai.is_jmp:=true;
+ ai.condition:=TOpCmp2AsmCond[cmp_op];
+ list.concat(ai);
+ end
+ else
+ inherited;
+ end;
+
+
+ procedure tcgrv.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; reg1,reg2 : tregister;l : tasmlabel);
+ var
+ tmpreg: TRegister;
+ ai: taicpu;
+ begin
+ if TOpCmp2AsmCond[cmp_op]=C_None then
+ begin
+ cmp_op:=swap_opcmp(cmp_op);
+ tmpreg:=reg1;
+ reg1:=reg2;
+ reg2:=tmpreg;
+ end;
+
+ ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,reg2,reg1,l,0);
+ ai.is_jmp:=true;
+ ai.condition:=TOpCmp2AsmCond[cmp_op];
+ list.concat(ai);
+ end;
+
+
+ procedure tcgrv.a_jmp_name(list : TAsmList;const s : string);
+ var
+ ai: taicpu;
+ href: treference;
+ tmpreg: TRegister;
+ l: TAsmLabel;
+ begin
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),0,0,[]);
+
+ tmpreg:=getintregister(list,OS_ADDR);
+
+ current_asmdata.getjumplabel(l);
+ a_label(list,l);
+
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
+ reference_reset_symbol(href,l,0,0,[]);
+ href.refaddr:=addr_pcrel_lo12;
+ ai:=taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href);
+ ai.is_jmp:=true;
+ list.concat(ai);
+
+ //ai:=taicpu.op_reg_sym(A_JAL,NR_X0,current_asmdata.RefAsmSymbol(s));
+ //ai.is_jmp:=true;
+ end;
+
+
+ procedure tcgrv.a_jmp_always(list : TAsmList;l: tasmlabel);
+ var
+ ai: taicpu;
+ {href: treference;
+ tmpreg: TRegister;}
+ begin
+ {reference_reset_symbol(href,l,0,0);
+
+ tmpreg:=getintregister(list,OS_ADDR);
+
+ current_asmdata.getjumplabel(l);
+ a_label(list,l);
+
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
+ reference_reset_symbol(href,l,0,0);
+ href.refaddr:=addr_pcrel_lo12;
+ ai:=taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href);
+ ai.is_jmp:=true;
+ list.concat(ai);}
+
+ ai:=taicpu.op_reg_sym(A_JAL,NR_X0,l);
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgrv.g_save_registers(list: TAsmList);
+ begin
+ end;
+
+
+ procedure tcgrv.g_restore_registers(list: TAsmList);
+ begin
+ end;
+
+
+ procedure tcgrv.a_call_reg(list : TAsmList;reg: tregister);
+ begin
+ list.concat(taicpu.op_reg_reg(A_JALR,NR_RETURN_ADDRESS_REG,reg));
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgrv.a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
+ reg: tregister; const ref: treference);
+
+ const
+ StoreInstr: array[OS_8..OS_INT] of TAsmOp =
+ (A_SB,A_SH,A_SW
+{$ifdef cpu64bitalu}
+ ,
+ A_SD
+{$endif cpu64bitalu}
+ );
+ var
+ ref2: TReference;
+ tmpreg: tregister;
+ op: TAsmOp;
+ begin
+ if not (fromsize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
+ internalerror(2002090904);
+ if not (tosize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
+ internalerror(2002090905);
+
+ tosize:=tcgsize2unsigned[tosize];
+
+ ref2 := ref;
+ fixref(list, ref2);
+
+ op := storeinstr[tcgsize2unsigned[tosize]];
+ list.concat(taicpu.op_reg_ref(op, reg,ref2));
+ end;
+
+
+ procedure tcgrv.a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+ var
+ href: treference;
+ op: TAsmOp;
+ tmpreg: TRegister;
+ begin
+ href:=ref;
+ fixref(list,href);
+
+ if href.refaddr=addr_pcrel then
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,href,tmpreg);
+ reference_reset_base(href,tmpreg,0,ctempposinvalid,0,[]);
+ end;
+
+ case fromsize of
+ OS_8: op:=A_LBU;
+ OS_16: op:=A_LHU;
+ OS_S8: op:=A_LB;
+ OS_S16: op:=A_LH;
+{$ifdef RISCV64}
+ OS_32: op:=A_LWU;
+ OS_S32: op:=A_LW;
+ OS_64,
+ OS_S64: op:=A_LD;
+{$else}
+ OS_32,
+ OS_S32: op:=A_LW;
+{$endif}
+ else
+ internalerror(2016060502);
+ end;
+
+ list.concat(taicpu.op_reg_ref(op,reg,href));
+ end;
+
+
+ procedure tcgrv.a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister);
+ begin
+ if a=0 then
+ a_load_reg_reg(list,size,size,NR_X0,register)
+ else
+ begin
+ if is_imm12(a) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,register,NR_X0,a))
+ else if is_lui_imm(a) then
+ list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF))
+ else
+ begin
+ if (a and $800)<>0 then
+ list.concat(taicpu.op_reg_const(A_LUI,register,((a shr 12)+1) and $FFFFF))
+ else
+ list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF));
+
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,register,register,SarSmallint(a shl 4,4)));
+ end;
+ end;
+ end;
+
+
+ procedure tcgrv.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+ var
+ op: TAsmOp;
+ ai: taicpu;
+
+ const
+ convOp: array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
+ ((A_None,A_FCVT_D_S),
+ (A_FCVT_S_D,A_None));
+
+ begin
+ if fromsize<>tosize then
+ list.concat(taicpu.op_reg_reg(convOp[fromsize,tosize],reg2,reg1))
+ else
+ begin
+ if tosize=OS_F32 then
+ op:=A_FSGNJ_S
+ else
+ op:=A_FSGNJ_D;
+
+ ai:=taicpu.op_reg_reg_reg(op,reg2,reg1,reg1);
+ list.concat(ai);
+ rg[R_FPUREGISTER].add_move_instruction(ai);
+ end;
+ end;
+
+
+ procedure tcgrv.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+ var
+ href: treference;
+ op: TAsmOp;
+ tmpreg: TRegister;
+ l: TAsmLabel;
+ begin
+ href:=ref;
+ fixref(list,href);
+
+ if href.refaddr=addr_pcrel then
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,href,tmpreg);
+ reference_reset_base(href,tmpreg,0,ctempposinvalid,0,[]);
+ end;
+
+ if fromsize=OS_F32 then
+ op:=A_FLW
+ else
+ op:=A_FLD;
+
+ list.concat(taicpu.op_reg_ref(op,reg,href));
+
+ if fromsize<>tosize then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
+ end;
+
+
+ procedure tcgrv.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+ var
+ href: treference;
+ op: TAsmOp;
+ tmpreg: TRegister;
+ begin
+ href:=ref;
+ fixref(list,href);
+
+ if href.refaddr=addr_pcrel then
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,href,tmpreg);
+ reference_reset_base(href,tmpreg,0,ctempposinvalid,0,[]);
+ end;
+
+ if fromsize<>tosize then
+ begin
+ tmpreg:=getfpuregister(list,tosize);
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
+ reg:=tmpreg;
+ end;
+
+ if tosize=OS_F32 then
+ op:=A_FSW
+ else
+ op:=A_FSD;
+
+ list.concat(taicpu.op_reg_ref(op,reg,href));
+ end;
+
+
+ function tcgrv.fixref(list: TAsmList; var ref: treference): boolean;
+ var
+ tmpreg: TRegister;
+ href: treference;
+ l: TAsmLabel;
+ begin
+ result:=true;
+
+ if ref.refaddr=addr_pcrel then
+ begin
+ exit;
+ end;
+
+ if assigned(ref.symbol) then
+ begin
+ reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment,[]);
+ ref.symbol:=nil;
+ ref.offset:=0;
+
+ tmpreg:=getintregister(list,OS_INT);
+
+ current_asmdata.getaddrlabel(l);
+ a_label(list,l);
+
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
+ reference_reset_symbol(href,l,0,0,[]);
+ href.refaddr:=addr_pcrel_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,tmpreg,tmpreg,href));
+
+ if (ref.index<>NR_NO) and
+ (ref.base<>NR_NO) then
+ begin
+ a_op_reg_reg(list,OP_ADD,OS_INT,ref.base,tmpreg);
+ ref.base:=tmpreg;
+ end
+ else if (ref.index=NR_NO) and
+ (ref.base<>NR_NO) then
+ ref.index:=tmpreg
+ else
+ ref.base:=tmpreg;
+ end
+ else if (ref.index=NR_NO) and
+ (ref.base=NR_NO) then
+ begin
+ tmpreg:=getintregister(list,OS_INT);
+
+ a_load_const_reg(list, OS_ADDR,ref.offset,tmpreg);
+
+ reference_reset_base(ref,tmpreg,0,ctempposinvalid,ref.alignment,[]);
+ end;
+
+ if (ref.index<>NR_NO) and
+ (ref.base=NR_NO) then
+ begin
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+
+ if not is_imm12(ref.offset) then
+ begin
+ tmpreg:=getintregister(list,OS_INT);
+ a_load_const_reg(list,OS_INT,ref.offset,tmpreg);
+
+ ref.offset:=0;
+
+ if (ref.index<>NR_NO) and
+ (ref.base<>NR_NO) then
+ begin
+ a_op_reg_reg(list,OP_ADD,OS_INT,ref.index,tmpreg);
+ ref.index:=tmpreg;
+ end
+ else
+ ref.index:=tmpreg;
+ end;
+
+ if (ref.index<>NR_NO) and
+ (ref.base<>NR_NO) then
+ begin
+ tmpreg:=getaddressregister(list);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end;
+
+end.
diff --git a/riscv_new/compiler/riscv/hlcgrv.pas b/riscv_new/compiler/riscv/hlcgrv.pas
new file mode 100644
index 0000000000..ece3fdd238
--- /dev/null
+++ b/riscv_new/compiler/riscv/hlcgrv.pas
@@ -0,0 +1,217 @@
+{
+ Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
+ Member of the Free Pascal development team
+
+ This unit contains routines high-level code generator support shared by
+ riscv32 and riscv64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit hlcgrv;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globals,
+ aasmdata,
+ symtype,symdef,
+ cgbase,cgutils,hlcgobj,hlcg2ll, parabase;
+
+type
+ thlcgriscv = class(thlcg2ll)
+ protected
+ procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tdef; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
+ public
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ end;
+
+implementation
+
+ uses
+ verbose,
+ systems,fmodule,
+ symconst, symsym,
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,globtype,
+ procinfo,cpupi,cgobj,cgrv,
+ defutil;
+
+{ thlcgriscv }
+
+ procedure thlcgriscv.a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tdef; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister);
+ var
+ fromsreg, tosreg: tsubsetregister;
+ restbits: byte;
+ begin
+ { the code below is only valid for big endian }
+ if target_info.endian=endian_little then
+ begin
+ inherited;
+ exit
+ end;
+ restbits:=(sref.bitlen-(loadbitsize-sref.startbit));
+ if is_signed(subsetsize) then
+ begin
+ { sign extend }
+ a_op_const_reg(list,OP_SHL,osuinttype,AIntBits-loadbitsize+sref.startbit,valuereg);
+ a_op_const_reg(list,OP_SAR,osuinttype,AIntBits-sref.bitlen,valuereg);
+ end
+ else
+ begin
+ a_op_const_reg(list,OP_SHL,osuinttype,restbits,valuereg);
+ { mask other bits }
+ if (sref.bitlen<>AIntBits) then
+ a_op_const_reg(list,OP_AND,osuinttype,(aword(1) shl sref.bitlen)-1,valuereg);
+ end;
+ { use subsetreg routine, it may have been overridden with an optimized version }
+ fromsreg.subsetreg:=extra_value_reg;
+ fromsreg.subsetregsize:=OS_INT;
+ { subsetregs always count bits from right to left }
+ fromsreg.startbit:=loadbitsize-restbits;
+ fromsreg.bitlen:=restbits;
+
+ tosreg.subsetreg:=valuereg;
+ tosreg.subsetregsize:=OS_INT;
+ tosreg.startbit:=0;
+ tosreg.bitlen:=restbits;
+
+ a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
+ end;
+
+
+ procedure thlcgriscv.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+ procedure loadvmttor12;
+ var
+ tmpref,
+ href : treference;
+ l : TAsmLabel;
+ begin
+ reference_reset_base(href,voidpointertype,NR_X10,0,ctempposinvalid,sizeof(pint),[]);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_X5);
+ end;
+
+
+ procedure op_onr12methodaddr;
+ var
+ tmpref,
+ href : treference;
+ l : TAsmLabel;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+
+ reference_reset_base(href,voidpointertype,NR_X5,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),ctempposinvalid, sizeof(pint),[]);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_X5);
+
+ list.concat(taicpu.op_reg_reg(A_JALR,NR_X0,NR_X5));
+ end;
+
+ var
+ make_global : boolean;
+ tmpref , href: treference;
+ l : TAsmLabel;
+ hsym: tsym;
+ paraloc: PCGParaLocation;
+ tmpreg: TRegister;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0,voidcodepointertype))
+ else
+ list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0,voidcodepointertype));
+
+ { the wrapper might need aktlocaldata for the additional data to
+ load the constant }
+ current_procinfo:=cprocinfo.create(nil);
+
+ { set param1 interface to self }
+ procdef.init_paraloc_info(callerside);
+ hsym:=tsym(procdef.parast.Find('self'));
+ if not(assigned(hsym) and
+ (hsym.typ=paravarsym)) then
+ internalerror(2010103101);
+ paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+ if assigned(paraloc^.next) then
+ InternalError(2013020101);
+
+ case paraloc^.loc of
+ LOC_REGISTER:
+ begin
+ if is_imm12(ioffset) then
+ cg.a_op_const_reg(list,OP_SUB, paraloc^.size,ioffset,paraloc^.register)
+ else
+ begin
+ cg.a_load_const_reg(list, paraloc^.size, ioffset, NR_X6);
+ cg.a_op_reg_reg(list, OP_SUB, paraloc^.size, NR_X6, paraloc^.register);
+ end;
+ end;
+ else
+ internalerror(2010103102);
+ end;
+
+ { case 4 }
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ loadvmttor12;
+ op_onr12methodaddr;
+ end
+ else
+ begin
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,0,[]);
+
+ tmpreg:=NR_X5;
+
+ current_asmdata.getjumplabel(l);
+
+ cg.a_label(list, l);
+
+ href.refaddr:=addr_pcrel_hi20;
+ list.concat(taicpu.op_reg_ref(A_AUIPC,tmpreg,href));
+
+ reference_reset_symbol(href,l,0,0,[]);
+ href.refaddr:=addr_pcrel_lo12;
+ list.concat(taicpu.op_reg_reg_ref(A_JALR,NR_X0,tmpreg,href));
+
+ //list.concat(taicpu.op_reg_sym(A_JAL,NR_X0,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+ end;
+ list.concatlist(current_procinfo.aktlocaldata);
+
+ current_procinfo.Free;
+ current_procinfo:=nil;
+
+ list.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+end.
+
diff --git a/riscv_new/compiler/riscv/nrvadd.pas b/riscv_new/compiler/riscv/nrvadd.pas
new file mode 100644
index 0000000000..672e9ee6f4
--- /dev/null
+++ b/riscv_new/compiler/riscv/nrvadd.pas
@@ -0,0 +1,418 @@
+{
+ Copyright (c) 2000-2006 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the Risc-V (32 and 64 bit generic)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit nrvadd;
+
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ node,nadd,ncgadd,cpubase;
+
+ type
+ trvaddnode = class(tcgaddnode)
+ function pass_1: tnode; override;
+ protected
+ procedure Cmp(signed: boolean);
+
+ procedure second_cmpsmallset;override;
+ procedure second_cmpordinal;override;
+ procedure second_cmp64bit; override;
+
+ procedure second_addordinal; override;
+
+ procedure pass_left_and_right;
+
+ function use_fma: boolean; override;
+
+ procedure second_addfloat;override;
+ procedure second_cmpfloat;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+ cgbase,cpuinfo,pass_1,pass_2,
+ cpupara,cgcpu,cgutils,procinfo,
+ ncon,nset,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,hlcgobj;
+
+ procedure trvaddnode.Cmp(signed: boolean);
+ var
+ flabel,tlabel: tasmlabel;
+ op, opi: TAsmOp;
+ begin
+ pass_left_right;
+
+ force_reg_left_right(true,true);
+
+ if nf_swapped in flags then
+ swapleftright;
+
+ location_reset(location,LOC_REGISTER,OS_INT);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+ if signed then op:=A_SLT else op:=A_SLTU;
+ if signed then opi:=A_SLTI else opi:=A_SLTIU;
+
+ case nodetype of
+ equaln:
+ begin
+ if not (left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ if (right.location.loc=LOC_CONSTANT) and
+ (not is_imm12(-right.location.value)) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+
+ if right.location.loc=LOC_CONSTANT then
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(A_ADDI,location.register,left.location.register,-right.location.value))
+ else
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_SUB,location.register,left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(A_SLTIU,location.register,location.register,1));
+ end;
+ unequaln:
+ begin
+ if not (left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ if (right.location.loc=LOC_CONSTANT) and
+ (not is_imm12(-right.location.value)) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+
+ if right.location.loc=LOC_CONSTANT then
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(A_ADDI,location.register,left.location.register,-right.location.value))
+ else
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_SUB,location.register,left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_SLTU,location.register,NR_X0,location.register));
+ end;
+ ltn:
+ begin
+ if not (left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ if (right.location.loc=LOC_CONSTANT) and
+ (not is_imm12(right.location.value)) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+
+ if right.location.loc=LOC_CONSTANT then
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(opi,location.register,left.location.register,right.location.value))
+ else
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register));
+ end;
+ gtn:
+ begin
+ if not (right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+
+ if (left.location.loc=LOC_CONSTANT) and
+ (not is_imm12(left.location.value)) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ if left.location.loc=LOC_CONSTANT then
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(opi,location.register,right.location.register,left.location.value))
+ else
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,location.register,right.location.register,left.location.register));
+ end;
+
+ lten:
+ begin
+ if not (right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+
+ if (left.location.loc=LOC_CONSTANT) and
+ (not is_imm12(left.location.value)) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ if left.location.loc=LOC_CONSTANT then
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(opi,location.register,right.location.register,left.location.value))
+ else
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,location.register,right.location.register,left.location.register));
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(A_SLTIU,location.register,location.register,1));
+ end;
+ gten:
+ begin
+ if not (left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ if (right.location.loc=LOC_CONSTANT) and
+ (not is_imm12(right.location.value)) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+
+ if right.location.loc=LOC_CONSTANT then
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(opi,location.register,left.location.register,right.location.value))
+ else
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(A_SLTIU,location.register,location.register,1));
+ end;
+ else
+ Internalerror(2016061101);
+ end;
+ end;
+
+
+ procedure trvaddnode.second_cmpsmallset;
+ begin
+ Cmp(true);
+ end;
+
+
+ procedure trvaddnode.second_cmpordinal;
+ var
+ unsigned: Boolean;
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ Cmp(not unsigned);
+ end;
+
+
+ procedure trvaddnode.second_cmp64bit;
+ var
+ unsigned: Boolean;
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ Cmp(not unsigned);
+ end;
+
+
+ procedure trvaddnode.second_addordinal;
+ var
+ unsigned: boolean;
+ begin
+ { 32x32->64 multiplication }
+ if (nodetype=muln) and
+ is_32bit(left.resultdef) and
+ is_32bit(right.resultdef) and
+ is_64bit(resultdef) then
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+ pass_left_right;
+ force_reg_left_right(true,true);
+ { force_reg_left_right can leave right as a LOC_CONSTANT (we can't
+ say "a constant register is okay, but an ordinal constant isn't) }
+ if right.location.loc=LOC_CONSTANT then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(A_MUL,location.register,left.location.register,right.location.register));
+ end
+ else
+ inherited second_addordinal;
+ end;
+
+
+ function trvaddnode.pass_1: tnode;
+ begin
+ if (nodetype=muln) and
+ (left.resultdef.typ=orddef) and (left.resultdef.typ=orddef) and
+ (CPURV_HAS_MUL in cpu_capabilities[current_settings.cputype])
+{$ifdef cpu32bitalu}
+ and (not (is_64bit(left.resultdef) or
+ is_64bit(right.resultdef)))
+{$endif cpu32bitalu}
+ then
+ begin
+ result:=nil;
+
+ firstpass(left);
+ firstpass(right);
+
+ expectloc:=LOC_REGISTER;
+ end
+ else if (nodetype=muln) and
+ (not (CPURV_HAS_MUL in cpu_capabilities[current_settings.cputype])) and
+ (is_64bit(left.resultdef) or
+ is_64bit(right.resultdef)) then
+ begin
+ result:=first_add64bitint;
+ end
+ else
+ Result:=inherited pass_1;
+
+ if expectloc=LOC_FLAGS then
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ procedure trvaddnode.pass_left_and_right;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ { in case of constant put it to the left }
+ if (left.nodetype=ordconstn) then
+ swapleftright;
+
+ secondpass(left);
+ secondpass(right);
+ end;
+
+
+ function trvaddnode.use_fma: boolean;
+ begin
+ Result:=current_settings.fputype in [fpu_fd];
+ end;
+
+
+ procedure trvaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ cmpop,
+ singleprec , inv: boolean;
+ begin
+ pass_left_and_right;
+
+ hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+ hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+
+ cmpop:=false;
+ singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+ inv:=false;
+ case nodetype of
+ addn :
+ if singleprec then
+ op:=A_FADD_S
+ else
+ op:=A_FADD_D;
+ muln :
+ if singleprec then
+ op:=A_FMUL_S
+ else
+ op:=A_FMUL_D;
+ subn :
+ if singleprec then
+ op:=A_FSUB_S
+ else
+ op:=A_FSUB_D;
+ slashn :
+ if singleprec then
+ op:=A_FDIV_S
+ else
+ op:=A_FDIV_D;
+ equaln:
+ begin
+ if singleprec then
+ op:=A_FEQ_S
+ else
+ op:=A_FEQ_D;
+ cmpop:=true;
+ end;
+ unequaln:
+ begin
+ if singleprec then
+ op:=A_FEQ_S
+ else
+ op:=A_FEQ_D;
+ inv:=true;
+ cmpop:=true;
+ end;
+ ltn:
+ begin
+ if singleprec then
+ op:=A_FLT_S
+ else
+ op:=A_FLT_D;
+ cmpop:=true;
+ end;
+ lten:
+ begin
+ if singleprec then
+ op:=A_FLE_S
+ else
+ op:=A_FLE_D;
+ cmpop:=true;
+ end;
+ gtn:
+ begin
+ if singleprec then
+ op:=A_FLT_S
+ else
+ op:=A_FLT_D;
+ swapleftright;
+ cmpop:=true;
+ end;
+ gten:
+ begin
+ if singleprec then
+ op:=A_FLE_S
+ else
+ op:=A_FLE_D;
+ swapleftright;
+ cmpop:=true;
+ end;
+ else
+ internalerror(200403182);
+ end;
+
+ // get the operands in the correct order, there are no special cases
+ // here, everything is register-based
+ if (nf_swapped in flags) and (not cmpop) then
+ swapleftright;
+
+ // put both operands in a register
+ hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+ hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+
+ // initialize de result
+ if not cmpop then
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ end
+ else
+ begin
+ location_reset(location,LOC_REGISTER,OS_8);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ end;
+
+ // emit the actual operation
+ if not cmpop then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register))
+ end
+ else
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register));
+
+ if inv then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_XORI,location.register,location.register,1));
+ end;
+ end;
+
+ procedure trvaddnode.second_cmpfloat;
+ begin
+ second_addfloat;
+ end;
+
+end.
diff --git a/riscv_new/compiler/riscv/nrvcnv.pas b/riscv_new/compiler/riscv/nrvcnv.pas
new file mode 100644
index 0000000000..54f3e91f29
--- /dev/null
+++ b/riscv_new/compiler/riscv/nrvcnv.pas
@@ -0,0 +1,178 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate Risc-V assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrvcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv;
+
+ type
+ trvtypeconvnode = class(tcgtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { function first_int_to_real: tnode; override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ { procedure second_int_to_real;override; }
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,pass_1,pass_2,
+ ncgutil,procinfo,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj,hlcgobj;
+
+
+ procedure trvtypeconvnode.second_int_to_bool;
+ var
+ hreg1, hreg2: tregister;
+ opsize: tcgsize;
+ hlabel: tasmlabel;
+ newsize : tcgsize;
+ href: treference;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
+ else
+ location.size:=newsize;
+ exit;
+ end;
+
+ location_reset(location, LOC_REGISTER, def_cgsize(resultdef));
+ opsize := def_cgsize(left.resultdef);
+
+ if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+
+ case left.location.loc of
+ LOC_CREFERENCE, LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER:
+ begin
+ if left.location.loc in [LOC_CREFERENCE, LOC_REFERENCE] then
+ begin
+ hreg2 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,left.location.reference,hreg2);
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hreg1);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hreg1,hreg2,hreg2);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList, opsize, opsize, left.location.reference, hreg2);
+ end
+ else
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,left.location.register64.reglo,hreg2);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.register,hreg2);
+ end;
+ hreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, hreg1, NR_X0, hreg2));
+ end;
+ LOC_JUMP:
+ begin
+ hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList, left.location.truelabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 1, hreg1);
+ cg.a_jmp_always(current_asmdata.CurrAsmList, hlabel);
+ cg.a_label(current_asmdata.CurrAsmList, left.location.falselabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, hreg1);
+ cg.a_label(current_asmdata.CurrAsmList, hlabel);
+ end;
+ LOC_FLAGS:
+ begin
+ Internalerror(2016060403);
+ end
+ else
+ internalerror(10062);
+ end;
+ { Now hreg1 is either 0 or 1. For C booleans it must be 0 or -1. }
+ if is_cbool(resultdef) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_SINT,hreg1,hreg1);
+
+{$ifndef cpu64bitalu}
+ if (location.size in [OS_64,OS_S64]) then
+ begin
+ location.register64.reglo:=hreg1;
+ location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if (is_cbool(resultdef)) then
+ { reglo is either 0 or -1 -> reghi has to become the same }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
+ else
+ { unsigned }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+ end
+ else
+{$endif not cpu64bitalu}
+ location.Register := hreg1;
+ end;
+
+end.
diff --git a/riscv_new/compiler/riscv/nrvcon.pas b/riscv_new/compiler/riscv/nrvcon.pas
new file mode 100644
index 0000000000..66698527b7
--- /dev/null
+++ b/riscv_new/compiler/riscv/nrvcon.pas
@@ -0,0 +1,131 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Code generation for const nodes on the Risc-V
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrvcon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ ncgcon,cpubase;
+
+ type
+ trvrealconstnode = class(tcgrealconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+
+implementation
+
+ uses
+ verbose,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,aasmtai,aasmdata,symdef,
+ defutil,
+ cgbase,cgutils,
+ procinfo,
+ ncon;
+
+{*****************************************************************************
+ TARMREALCONSTNODE
+*****************************************************************************}
+
+ procedure trvrealconstnode.pass_generate_code;
+ { I suppose the parser/pass_1 must make sure the generated real }
+ { constants are actually supported by the target processor? (JM) }
+ const
+ floattype2ait:array[tfloattype] of tairealconsttype=
+ (aitrealconst_s32bit,aitrealconst_s64bit,aitrealconst_s80bit,aitrealconst_s80bit,aitrealconst_s64comp,aitrealconst_s64comp,aitrealconst_s128bit);
+ var
+ lastlabel : tasmlabel;
+ realait : tairealconsttype;
+
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),4);
+ lastlabel:=nil;
+ realait:=floattype2ait[tfloatdef(resultdef).floattype];
+ { const already used ? }
+ if not assigned(lab_real) then
+ begin
+ current_asmdata.getjumplabel(lastlabel);
+ lab_real:=lastlabel;
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(lastlabel));
+ location.reference.symboldata:=current_procinfo.aktlocaldata.last;
+ case realait of
+ aitrealconst_s32bit :
+ begin
+ current_procinfo.aktlocaldata.concat(tai_realconst.create_s32real(ts32real(value_real)));
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_realconst(current_procinfo.aktlocaldata.last).value.s32val=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+
+ aitrealconst_s64bit :
+ begin
+ current_procinfo.aktlocaldata.concat(tai_realconst.create_s64real(ts64real(value_real)));
+
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_realconst(current_procinfo.aktlocaldata.last).value.s64val=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+
+ aitrealconst_s80bit :
+ begin
+ current_procinfo.aktlocaldata.concat(tai_realconst.create_s80real(value_real,tfloatdef(resultdef).size));
+
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_realconst(current_procinfo.aktlocaldata.last).value.s80val=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+{$ifdef cpufloat128}
+ aitrealconst_s128bit :
+ begin
+ current_procinfo.aktlocaldata.concat(tai_realconst.create_s128real(value_real));
+
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_realconst(current_procinfo.aktlocaldata.last).value.s128val=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+{$endif cpufloat128}
+
+ { the round is necessary for native compilers where comp isn't a float }
+ aitrealconst_s64comp :
+ if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
+ message(parser_e_range_check_error)
+ else
+ current_procinfo.aktlocaldata.concat(tai_realconst.create_s64compreal(round(value_real)));
+ else
+ internalerror(2005092401);
+ end;
+ end;
+ location.reference.symbol:=lab_real;
+ location.reference.refaddr:=addr_pcrel;
+ end;
+
+begin
+ crealconstnode:=trvrealconstnode;
+end.
diff --git a/riscv_new/compiler/riscv/nrvinl.pas b/riscv_new/compiler/riscv/nrvinl.pas
new file mode 100644
index 0000000000..cc6eaa211a
--- /dev/null
+++ b/riscv_new/compiler/riscv/nrvinl.pas
@@ -0,0 +1,244 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate Risc-V32/64 inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrvinl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ node,ninl,ncginl;
+
+ type
+ trvinlinenode = class(tcginlinenode)
+ { first pass override
+ so that the code generator will actually generate
+ these nodes.
+ }
+ function first_sqrt_real: tnode; override;
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+
+ function first_fma: tnode; override;
+
+ procedure second_sqrt_real; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+
+ procedure second_fma; override;
+ protected
+ procedure load_fpu_location;
+ end;
+
+implementation
+
+ uses
+ ncal,
+ cutils,globals,verbose,globtype,
+ aasmtai,aasmdata,aasmcpu,
+ symconst,symdef,
+ defutil,
+ cgbase,pass_2,
+ cpuinfo,ncgutil,
+ hlcgobj,cgutils,cgobj,rgobj,tgobj;
+
+
+{*****************************************************************************
+ trvinlinenode
+*****************************************************************************}
+
+ function trvinlinenode.first_sqrt_real : tnode;
+ begin
+ if (current_settings.fputype >= fpu_fd) then
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqrt_real := nil;
+ end
+ else
+ result:=inherited first_sqrt_real;
+ end;
+
+
+ function trvinlinenode.first_abs_real : tnode;
+ begin
+ if (current_settings.fputype >= fpu_fd) then
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_abs_real := nil;
+ end
+ else
+ result:=inherited first_abs_real;
+ end;
+
+
+ function trvinlinenode.first_sqr_real : tnode;
+ begin
+ if (current_settings.fputype >= fpu_fd) then
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqr_real := nil;
+ end
+ else
+ result:=inherited first_sqr_real;
+ end;
+
+ function trvinlinenode.first_fma: tnode;
+ begin
+ Result:=nil;
+ end;
+
+
+ { load the FPU into the an fpu register }
+ procedure trvinlinenode.load_fpu_location;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ secondpass(left);
+ hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+ location.loc := LOC_FPUREGISTER;
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+ end;
+
+
+ procedure trvinlinenode.second_sqrt_real;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ case left.location.size of
+ OS_F32:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT_S,location.register,
+ left.location.register));
+ OS_F64:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT_D,location.register,
+ left.location.register));
+ else
+ inherited;
+ end;
+ end;
+
+
+ procedure trvinlinenode.second_abs_real;
+ var
+ op: TAsmOp;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ if (left.location.size = OS_F32) then
+ op := A_FSGNJX_S
+ else
+ op := A_FSGNJX_D;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
+ end;
+
+
+ procedure trvinlinenode.second_sqr_real;
+ var
+ op: tasmop;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ if (left.location.size = OS_F32) then
+ op := A_FMUL_S
+ else
+ op := A_FMUL_D;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
+ end;
+
+ procedure trvinlinenode.second_fma;
+ const
+ op : array[os_f32..os_f64,false..true,false..true] of TAsmOp =
+ (
+ (
+ (A_FMADD_S,A_FMSUB_S),
+ (A_FNMADD_S,A_FNMSUB_S)
+ ),
+ (
+ (A_FMADD_D,A_FMSUB_D),
+ (A_FNMADD_D,A_FNMSUB_D)
+ )
+ );
+ var
+ paraarray : array[1..3] of tnode;
+ i : integer;
+ negop3,
+ negproduct : boolean;
+ begin
+ if current_settings.fputype in [fpu_fd] then
+ begin
+ negop3:=false;
+ negproduct:=false;
+ paraarray[1]:=tcallparanode(tcallparanode(tcallparanode(parameters).nextpara).nextpara).paravalue;
+ paraarray[2]:=tcallparanode(tcallparanode(parameters).nextpara).paravalue;
+ paraarray[3]:=tcallparanode(parameters).paravalue;
+
+ { check if a neg. node can be removed
+ this is possible because changing the sign of
+ a floating point number does not affect its absolute
+ value in any way
+ }
+ if paraarray[1].nodetype=unaryminusn then
+ begin
+ paraarray[1]:=tunarynode(paraarray[1]).left;
+ { do not release the unused unary minus node, it is kept and release together with the other nodes,
+ only no code is generated for it }
+ negproduct:=not(negproduct);
+ end;
+
+ if paraarray[2].nodetype=unaryminusn then
+ begin
+ paraarray[2]:=tunarynode(paraarray[2]).left;
+ { do not release the unused unary minus node, it is kept and release together with the other nodes,
+ only no code is generated for it }
+ negproduct:=not(negproduct);
+ end;
+
+ if paraarray[3].nodetype=unaryminusn then
+ begin
+ paraarray[3]:=tunarynode(paraarray[3]).left;
+ { do not release the unused unary minus node, it is kept and release together with the other nodes,
+ only no code is generated for it }
+ negop3:=true;
+ end;
+
+ for i:=1 to 3 do
+ secondpass(paraarray[i]);
+
+ { no memory operand is allowed }
+ for i:=1 to 3 do
+ begin
+ if not(paraarray[i].location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
+ hlcg.location_force_fpureg(current_asmdata.CurrAsmList,paraarray[i].location,paraarray[i].resultdef,true);
+ end;
+
+ location_reset(location,LOC_FPUREGISTER,paraarray[1].location.size);
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(op[def_cgsize(resultdef), negproduct,negop3],location.register,paraarray[1].location.register,paraarray[2].location.register,paraarray[2].location.register));
+ end
+ else
+ internalerror(2014032301);
+ end;
+
+
+begin
+ cinlinenode:=trvinlinenode;
+end.
diff --git a/riscv_new/compiler/riscv/nrvset.pas b/riscv_new/compiler/riscv/nrvset.pas
new file mode 100644
index 0000000000..e0a51771b6
--- /dev/null
+++ b/riscv_new/compiler/riscv/nrvset.pas
@@ -0,0 +1,153 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
+
+ Generate Risc-V32/64 assembler for in set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrvset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,aasmdata,globtype;
+
+ type
+ trvcasenode = class(tcgcasenode)
+ protected
+ procedure optimizevalues(var max_linear_list : aint; var max_dist : aword);override;
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,constexp,
+ symconst,symdef,defutil,
+ paramgr,
+ cpuinfo,
+ pass_2,cgcpu,
+ ncon,
+ tgobj,ncgutil,rgobj,aasmcpu,
+ procinfo,
+ cgutils;
+
+{*****************************************************************************
+ TCGCASENODE
+*****************************************************************************}
+
+
+ procedure trvcasenode.optimizevalues(var max_linear_list : aint; var max_dist : aword);
+ begin
+ max_linear_list := 3;
+ end;
+
+
+ function trvcasenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure trvcasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+
+ procedure genitem(list:TAsmList;t : pcaselabel);
+ var
+ i : TConstExprInt;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ i:=last+1;
+ while i<=t^._low-1 do
+ begin
+ list.concat(Tai_const.Create_rel_sym(aitconst_32bit,table,elselabel));
+ i:=i+1;
+ end;
+ i:=t^._low;
+ while i<=t^._high do
+ begin
+ list.concat(Tai_const.Create_rel_sym(aitconst_32bit,table,blocklabel(t^.blockid)));
+ i:=i+1;
+ end;
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ last:=min_;
+
+ {
+ .l
+ auipc x,hi(tbl-.l)
+ addi x,x,lo(tbl-.l)
+ sll idx,idx,2
+ add idx,idx,x
+ lw idx,idx,lo(tbl-.l)
+ add idx,idx,x
+ jalr x0,idx
+ }
+
+ { make it a 32bit register }
+ // allocate base and index registers register
+ indexreg:= cg.makeregsize(current_asmdata.CurrAsmList, hregister, OS_INT);
+ { indexreg := hregister; }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, def_cgsize(opsize), OS_INT, hregister, indexreg);
+ { a <= x <= b <-> unsigned(x-a) <= (b-a) }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,aint(min_),indexreg);
+ if not(jumptable_no_range) then
+ begin
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_A,aint(max_)-aint(min_),indexreg,elselabel);
+ end;
+ current_asmdata.getjumplabel(table);
+ { create reference, indexreg := indexreg * sizeof(jtentry) (= 4) }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, 4, indexreg);
+ reference_reset_symbol(href, table, 0, 4,[]);
+
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+ reference_reset_base(href,hregister,0,ctempposinvalid,4,[]);
+ href.index:=indexreg;
+ indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ { load table entry }
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,indexreg);
+ { add table base }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,hregister,indexreg);
+ { jump }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_JALR,NR_X0, indexreg));
+
+ { generate jump table }
+ current_asmdata.CurrAsmList.concat(Tai_label.Create(table));
+ genitem(current_asmdata.CurrAsmList,hp);
+ end;
+
+
+begin
+ ccasenode:=trvcasenode;
+end.
diff --git a/riscv_new/compiler/riscv/rgcpu.pas b/riscv_new/compiler/riscv/rgcpu.pas
new file mode 100644
index 0000000000..3c7047e4db
--- /dev/null
+++ b/riscv_new/compiler/riscv/rgcpu.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the Risc-V specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
+ procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
+ end;
+
+ trgintcpu = class(trgcpu)
+ end;
+
+ implementation
+
+ uses
+ verbose, cutils,globtype,
+ cgobj,
+ procinfo;
+
+
+ procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ helpins: Taicpu;
+ begin
+ if not is_imm12(spilltemp.offset) then
+ begin
+ helplist:=tasmlist.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=tempreg
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ if (spilltemp.offset and $800)<>0 then
+ helplist.concat(taicpu.op_reg_const(A_LUI,hreg,(spilltemp.offset shr 12) and $FFFFF))
+ else
+ helplist.concat(taicpu.op_reg_const(A_LUI,hreg,((spilltemp.offset shr 12)+1) and $FFFFF));
+ helplist.concat(taicpu.op_reg_reg_const(A_ADDI,hreg,hreg,SarSmallint(spilltemp.offset shl 4,4)));
+
+ helplist.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,hreg,spilltemp.base));
+
+ reference_reset_base(tmpref,hreg,0,ctempposinvalid,sizeof(aint),[]);
+
+ helpins:=spilling_create_load(tmpref,tempreg);
+ helplist.concat(helpins);
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited;
+ end;
+
+
+ procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
+ var
+ tmpref : treference;
+ helplist : tasmlist;
+ hreg : tregister;
+ begin
+ if not is_imm12(spilltemp.offset) then
+ begin
+ helplist:=tasmlist.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ if (spilltemp.offset and $800)<>0 then
+ helplist.concat(taicpu.op_reg_const(A_LUI,hreg,((spilltemp.offset shr 12)+1) and $FFFFF))
+ else
+ helplist.concat(taicpu.op_reg_const(A_LUI,hreg,(spilltemp.offset shr 12) and $FFFFF));
+ helplist.concat(taicpu.op_reg_reg_const(A_ADDI,hreg,hreg,SarSmallint(spilltemp.offset shl 4,4)));
+
+ helplist.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,hreg,spilltemp.base));
+
+ reference_reset_base(tmpref,hreg,0,ctempposinvalid,sizeof(aint),[]);
+
+ helplist.concat(spilling_create_store(tempreg,tmpref));
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited;
+ end;
+
+
+end.
diff --git a/riscv_new/compiler/riscv32/aoptcpu.pas b/riscv_new/compiler/riscv32/aoptcpu.pas
new file mode 100644
index 0000000000..eb45ee1b9d
--- /dev/null
+++ b/riscv_new/compiler/riscv32/aoptcpu.pas
@@ -0,0 +1,77 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the Risc-V32 optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+
+Unit aoptcpu;
+
+Interface
+
+{$i fpcdefs.inc}
+
+uses cpubase, aoptobj, aoptcpub, aopt, aasmtai,aasmdata, aasmcpu;
+
+Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+
+ function PostPeepHoleOptsCpu(var p: tai): boolean; override;
+ End;
+
+Implementation
+
+ uses
+ cutils, verbose, cgbase, cgcpu, cgobj;
+
+
+ function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ var
+ next1, next2: tai;
+ l1, l2, shlcount: longint;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ {case taicpu(p).opcode of
+ end;}
+ end;
+ end;
+ end;
+
+
+ function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
+ var
+ next1: tai;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ end;
+ end;
+ end;
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+End.
diff --git a/riscv_new/compiler/riscv32/aoptcpub.pas b/riscv_new/compiler/riscv32/aoptcpub.pas
new file mode 100644
index 0000000000..eb60faa451
--- /dev/null
+++ b/riscv_new/compiler/riscv32/aoptcpub.pas
@@ -0,0 +1,115 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the 80x86 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+
+{ enable the following define if memory references can have a scaled index }
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ aasmcpu,AOptBase, cpubase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 5;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 1;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 0;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+
+ aopt_uncondjmp = A_JAL;
+ aopt_condjmp = A_Bxx;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/riscv_new/compiler/riscv32/aoptcpuc.pas b/riscv_new/compiler/riscv32/aoptcpuc.pas
new file mode 100644
index 0000000000..4b82e87f4a
--- /dev/null
+++ b/riscv_new/compiler/riscv32/aoptcpuc.pas
@@ -0,0 +1,40 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcpuc;
+
+Interface
+
+{$i fpcdefs.inc}
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/riscv_new/compiler/riscv32/aoptcpud.pas b/riscv_new/compiler/riscv32/aoptcpud.pas
new file mode 100644
index 0000000000..2df7e2e49e
--- /dev/null
+++ b/riscv_new/compiler/riscv32/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ AOptDA;
+
+Type
+ TAOptDFACpu = class(TAOptDFA)
+ End;
+
+Implementation
+
+
+End.
diff --git a/riscv_new/compiler/riscv32/cgcpu.pas b/riscv_new/compiler/riscv32/cgcpu.pas
new file mode 100644
index 0000000000..b1830b938b
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cgcpu.pas
@@ -0,0 +1,641 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the Risc-V32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgobj,cgrv,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cpubase,cpuinfo,cgutils,cg64f32,rgcpu,
+ parabase;
+
+ type
+ tcgrv32 = class(tcgrv)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ { move instructions }
+ procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+
+ { 32x32 to 64 bit multiplication }
+ procedure a_mul_reg_reg_pair(list: TAsmList;size: tcgsize; src1,src2,dstlo,dsthi: tregister); override;
+
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+
+ procedure g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+
+ procedure g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef); override;
+ end;
+
+ tcg64frv = class(tcg64f32)
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ end;
+
+ procedure create_codegen;
+
+ implementation
+
+ uses
+ symtable,
+ globals,verbose,systems,cutils,
+ symconst,symsym,fmodule,
+ rgobj,tgobj,cpupi,procinfo,paramgr;
+
+
+ procedure tcgrv32.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_X10,RS_X11,RS_X12,RS_X13,RS_X14,RS_X15,RS_X16,RS_X17,
+ RS_X31,RS_X30,RS_X29,RS_X28,
+ RS_X5,RS_X6,RS_X7,
+ RS_X3,RS_X4,
+ RS_X9,RS_X27,RS_X26,RS_X25,RS_X24,RS_X23,RS_X22,
+ RS_X21,RS_X20,RS_X19,RS_X18],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,RS_F16,RS_F17,
+ RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
+ RS_F28,RS_F29,RS_F30,RS_F31,
+ RS_F8,RS_F9,
+ RS_F27,
+ RS_F26,RS_F25,RS_F24,RS_F23,RS_F22,RS_F21,RS_F20,RS_F19,RS_F18],first_fpu_imreg,[]);
+ end;
+
+
+ procedure tcgrv32.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure tcgrv32.a_load_reg_reg(list : TAsmList;fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+ var
+ ai: taicpu;
+ begin
+ if (fromsize=tosize) or
+ ((tcgsize2unsigned[fromsize]=tcgsize2unsigned[tosize]) and
+ (tcgsize2unsigned[fromsize]=OS_32)) then
+ begin
+ ai:=taicpu.op_reg_reg_const(A_ADDI,reg2,reg1,0);
+ list.concat(ai);
+ rg[R_INTREGISTER].add_move_instruction(ai);
+ end
+ else if fromsize=OS_8 then
+ begin
+ list.Concat(taicpu.op_reg_reg_const(A_AND,reg2,reg1,$FF))
+ end
+ else
+ begin
+ if tcgsize2size[tosize]<tcgsize2size[fromsize] then
+ fromsize:=tosize;
+
+ if tcgsize2unsigned[fromsize]<>OS_32 then
+ list.Concat(taicpu.op_reg_reg_const(A_SLLI,reg2,reg1,8*(4-tcgsize2size[fromsize])))
+ else
+ a_load_reg_reg(list,fromsize,fromsize,reg1,reg2);
+
+ if tcgsize2unsigned[fromsize]=fromsize then
+ list.Concat(taicpu.op_reg_reg_const(A_SRLI,reg2,reg2,8*(4-tcgsize2size[fromsize])))
+ else
+ list.Concat(taicpu.op_reg_reg_const(A_SRAI,reg2,reg2,8*(4-tcgsize2size[fromsize])));
+ end;
+ end;
+
+
+ procedure tcgrv32.a_mul_reg_reg_pair(list: TAsmList;size: tcgsize; src1,src2,dstlo,dsthi: tregister);
+ var
+ op: tasmop;
+ begin
+ case size of
+ OS_INT: op:=A_MULHU;
+ OS_SINT: op:=A_MULH;
+ else
+ InternalError(2014061501);
+ end;
+ if (dsthi<>NR_NO) then
+ list.concat(taicpu.op_reg_reg_reg(op,dsthi,src1,src2));
+ { low word is always unsigned }
+ if (dstlo<>NR_NO) then
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dstlo,src1,src2));
+ end;
+
+
+ procedure tcgrv32.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ var
+ regs, fregs: tcpuregisterset;
+ r: TSuperRegister;
+ href: treference;
+ stackcount: longint;
+ begin
+ if not(nostackframe) then
+ begin
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ a_reg_alloc(list,NR_FRAME_POINTER_REG);
+
+ reference_reset_base(href,NR_STACK_POINTER_REG,-4,0);
+
+ { Int registers }
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
+
+ if (pi_do_call in current_procinfo.flags) then
+ regs:=regs+[RS_RETURN_ADDRESS_REG];
+
+ stackcount:=0;
+ for r:=RS_X0 to RS_X31 do
+ if r in regs then
+ inc(stackcount,4);
+
+ { Float registers }
+ fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F31 do
+ if r in fregs then
+ inc(stackcount,8);
+
+ inc(localsize,stackcount);
+ if not is_imm12(-localsize) then
+ begin
+ if not (RS_RETURN_ADDRESS_REG in regs) then
+ begin
+ include(regs,RS_RETURN_ADDRESS_REG);
+ inc(localsize,4);
+ end;
+ end;
+
+ stackcount:=0;
+ for r:=RS_X0 to RS_X31 do
+ if r in regs then
+ begin
+ list.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
+ dec(href.offset,4);
+ end;
+
+ { Float registers }
+ for r:=RS_F0 to RS_F31 do
+ if r in fregs then
+ begin
+ list.concat(taicpu.op_reg_ref(A_FSD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
+ dec(href.offset,8);
+ end;
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,0));
+
+ if localsize>0 then
+ begin
+ localsize:=align(localsize,4);
+
+ if is_imm12(-localsize) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize))
+ else
+ begin
+ a_load_const_reg(list,OS_INT,localsize,NR_RETURN_ADDRESS_REG);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_RETURN_ADDRESS_REG));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcgrv32.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+ var
+ r: tsuperregister;
+ regs, fregs: tcpuregisterset;
+ stackcount, localsize: longint;
+ href: treference;
+ begin
+ if not(nostackframe) then
+ begin
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
+
+ if (pi_do_call in current_procinfo.flags) then
+ regs:=regs+[RS_RETURN_ADDRESS_REG];
+
+ stackcount:=0;
+ reference_reset_base(href,NR_STACK_POINTER_REG,-4,0);
+ for r:=RS_X31 downto RS_X0 do
+ if r in regs then
+ dec(href.offset,4);
+
+ { Float registers }
+ fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F31 do
+ if r in fregs then
+ dec(stackcount,8);
+
+ localsize:=current_procinfo.calc_stackframe_size+(-href.offset-4);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG,0))
+ else if localsize>0 then
+ begin
+ localsize:=align(localsize,4);
+
+ if is_imm12(localsize) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize))
+ else
+ begin
+ if not (RS_RETURN_ADDRESS_REG in regs) then
+ begin
+ include(regs,RS_RETURN_ADDRESS_REG);
+ dec(href.offset,4);
+ inc(localsize,4);
+ end;
+
+ a_load_const_reg(list,OS_INT,localsize,NR_RETURN_ADDRESS_REG);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_RETURN_ADDRESS_REG));
+ end;
+ end;
+
+ { Float registers }
+ for r:=RS_F31 downto RS_F0 do
+ if r in fregs then
+ begin
+ inc(href.offset,8);
+ list.concat(taicpu.op_reg_ref(A_FLD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
+ end;
+
+ for r:=RS_X31 downto RS_X0 do
+ if r in regs then
+ begin
+ inc(href.offset,4);
+ list.concat(taicpu.op_reg_ref(A_LW,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
+ inc(stackcount);
+ end;
+ end;
+
+ list.concat(taicpu.op_reg_reg(A_JALR,NR_X0,NR_RETURN_ADDRESS_REG));
+ end;
+
+
+ procedure tcgrv32.g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
+ var
+ paraloc1, paraloc2, paraloc3: TCGPara;
+ pd: tprocdef;
+ begin
+ pd:=search_system_proc('MOVE');
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(list, pd, 1, paraloc1);
+ paramanager.getintparaloc(list, pd, 2, paraloc2);
+ paramanager.getintparaloc(list, pd, 3, paraloc3);
+ a_load_const_cgpara(list, OS_SINT, len, paraloc3);
+ a_loadaddr_ref_cgpara(list, dest, paraloc2);
+ a_loadaddr_ref_cgpara(list, Source, paraloc1);
+ paramanager.freecgpara(list, paraloc3);
+ paramanager.freecgpara(list, paraloc2);
+ paramanager.freecgpara(list, paraloc1);
+ alloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
+ alloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
+ a_call_name(list, 'FPC_MOVE', false);
+ dealloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+
+ procedure tcgrv32.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
+ var
+ tmpreg1, hreg, countreg: TRegister;
+ src, dst, src2, dst2: TReference;
+ lab: tasmlabel;
+ Count, count2: aint;
+
+ function reference_is_reusable(const ref: treference): boolean;
+ begin
+ result:=(ref.base<>NR_NO) and (ref.index=NR_NO) and
+ (ref.symbol=nil) and
+ is_imm12(ref.offset);
+ end;
+
+ begin
+ src2:=source;
+ fixref(list,src2);
+
+ dst2:=dest;
+ fixref(list,dst2);
+
+ if len > high(longint) then
+ internalerror(2002072704);
+ { A call (to FPC_MOVE) requires the outgoing parameter area to be properly
+ allocated on stack. This can only be done before tmipsprocinfo.set_first_temp_offset,
+ i.e. before secondpass. Other internal procedures request correct stack frame
+ by setting pi_do_call during firstpass, but for this particular one it is impossible.
+ Therefore, if the current procedure is a leaf one, we have to leave it that way. }
+
+ { anybody wants to determine a good value here :)? }
+ if (len > 100) and
+ assigned(current_procinfo) and
+ (pi_do_call in current_procinfo.flags) then
+ g_concatcopy_move(list, src2, dst2, len)
+ else
+ begin
+ Count := len div 4;
+ if (count<=4) and reference_is_reusable(src2) then
+ src:=src2
+ else
+ begin
+ reference_reset(src,sizeof(aint));
+ { load the address of src2 into src.base }
+ src.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, src2, src.base);
+ end;
+ if (count<=4) and reference_is_reusable(dst2) then
+ dst:=dst2
+ else
+ begin
+ reference_reset(dst,sizeof(aint));
+ { load the address of dst2 into dst.base }
+ dst.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, dst2, dst.base);
+ end;
+ { generate a loop }
+ if Count > 4 then
+ begin
+ countreg := GetIntRegister(list, OS_INT);
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, Count, countreg);
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, src.base, src.base, 4));
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, dst.base, dst.base, 4));
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, countreg, countreg, -1));
+ a_cmp_reg_reg_label(list,OS_INT,OC_GT,NR_X0,countreg,lab);
+ len := len mod 4;
+ end;
+ { unrolled loop }
+ Count := len div 4;
+ if Count > 0 then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ for count2 := 1 to Count do
+ begin
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
+ Inc(src.offset, 4);
+ Inc(dst.offset, 4);
+ end;
+ len := len mod 4;
+ end;
+ if (len and 4) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_32, OS_32, src, hreg);
+ a_load_reg_ref(list, OS_32, OS_32, hreg, dst);
+ Inc(src.offset, 4);
+ Inc(dst.offset, 4);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_16, OS_16, src, hreg);
+ a_load_reg_ref(list, OS_16, OS_16, hreg, dst);
+ Inc(src.offset, 2);
+ Inc(dst.offset, 2);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_8, OS_8, src, hreg);
+ a_load_reg_ref(list, OS_8, OS_8, hreg, dst);
+ end;
+ end;
+ end;
+
+
+ procedure tcgrv32.g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef);
+ begin
+
+ end;
+
+
+ procedure tcg64frv.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ var
+ tmpreg1: TRegister;
+ begin
+ case op of
+ OP_NOT:
+ begin
+ cg.a_op_reg_reg(list,OP_NOT,OS_32,regsrc.reglo,regdst.reglo);
+ cg.a_op_reg_reg(list,OP_NOT,OS_32,regsrc.reghi,regdst.reghi);
+ end;
+ OP_NEG:
+ begin
+ tmpreg1 := cg.GetIntRegister(list, OS_INT);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reglo, NR_X0, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, NR_X0, regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reghi, NR_X0, regsrc.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reghi, regdst.reghi, tmpreg1));
+ end;
+ else
+ a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
+ end;
+ end;
+
+
+ procedure tcg64frv.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,reg,reg);
+ end;
+
+
+ procedure tcg64frv.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ signed: Boolean;
+ tmplo, carry, tmphi, hreg: TRegister;
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ signed:=(size in [OS_S64]);
+ tmplo := cg.GetIntRegister(list,OS_S32);
+ carry := cg.GetIntRegister(list,OS_S32);
+ // destreg.reglo could be regsrc1.reglo or regsrc2.reglo
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, tmplo, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, carry, tmplo, regsrc2.reglo));
+ cg.a_load_reg_reg(list,OS_INT,OS_INT,tmplo,regdst.reglo);
+ if signed then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, regdst.reghi, regdst.reghi, carry));
+ end
+ else
+ begin
+ tmphi:=cg.GetIntRegister(list,OS_INT);
+ hreg:=cg.GetIntRegister(list,OS_INT);
+ cg.a_load_const_reg(list,OS_INT,$80000000,hreg);
+ // first add carry to one of the addends
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, tmphi, regsrc2.reghi, carry));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, carry, tmphi, regsrc2.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, carry, hreg, carry));
+ // then add another addend
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, regdst.reghi, tmphi, regsrc1.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, carry, regdst.reghi, tmphi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, carry, hreg, carry));
+ end;
+ end;
+ OP_SUB:
+ begin
+ signed:=(size in [OS_S64]);
+ tmplo := cg.GetIntRegister(list,OS_S32);
+ carry := cg.GetIntRegister(list,OS_S32);
+ // destreg.reglo could be regsrc1.reglo or regsrc2.reglo
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, tmplo, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, carry, regsrc2.reglo,tmplo));
+ cg.a_load_reg_reg(list,OS_INT,OS_INT,tmplo,regdst.reglo);
+ if signed then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reghi, regdst.reghi, carry));
+ end
+ else
+ begin
+ tmphi:=cg.GetIntRegister(list,OS_INT);
+ hreg:=cg.GetIntRegister(list,OS_INT);
+ cg.a_load_const_reg(list,OS_INT,$80000000,hreg);
+ // first subtract the carry...
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, tmphi, regsrc2.reghi, carry));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, carry, regsrc2.reghi, tmphi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, carry, hreg, carry));
+ // ...then the subtrahend
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reghi, tmphi, regsrc1.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, carry, tmphi, regdst.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB, carry, hreg, carry));
+ end;
+ end;
+ else
+ internalerror(2002072801);
+ end;
+ end;
+
+
+ procedure tcg64frv.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
+ var
+ tmplo,carry: TRegister;
+ hisize: tcgsize;
+ begin
+ carry:=NR_NO;
+ if (size in [OS_S64]) then
+ hisize:=OS_S32
+ else
+ hisize:=OS_32;
+
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(lo(value)),regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(hi(value)),regsrc.reghi,regdst.reghi);
+ end;
+
+ OP_ADD:
+ begin
+ if lo(value)<>0 then
+ begin
+ tmplo:=cg.GetIntRegister(list,OS_32);
+ carry:=cg.GetIntRegister(list,OS_32);
+
+ if is_imm12(aint(lo(value))) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,tmplo,regsrc.reglo,aint(lo(value))))
+ else
+ begin
+ cg.a_load_const_reg(list,OS_INT,aint(lo(value)),tmplo);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmplo,tmplo,regsrc.reglo))
+ end;
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU,carry,tmplo,regsrc.reglo));
+ cg.a_load_reg_reg(list,OS_32,OS_32,tmplo,regdst.reglo);
+ end
+ else
+ cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
+
+ { With overflow checking and unsigned args, this generates slighly suboptimal code
+ ($80000000 constant loaded twice). Other cases are fine. Getting it perfect does not
+ look worth the effort. }
+ cg.a_op_const_reg_reg(list,OP_ADD,hisize,aint(hi(value)),regsrc.reghi,regdst.reghi);
+ if carry<>NR_NO then
+ cg.a_op_reg_reg_reg(list,OP_ADD,hisize,carry,regdst.reghi,regdst.reghi);
+ end;
+
+ OP_SUB:
+ begin
+ carry:=NR_NO;
+ if lo(value)<>0 then
+ begin
+ tmplo:=cg.GetIntRegister(list,OS_32);
+ carry:=cg.GetIntRegister(list,OS_32);
+
+ if is_imm12(-aint(lo(value))) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,tmplo,regsrc.reglo,-aint(lo(value))))
+ else
+ begin
+ cg.a_load_const_reg(list,OS_INT,aint(lo(value)),tmplo);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmplo,tmplo,regsrc.reglo))
+ end;
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU,carry,regsrc.reglo,tmplo));
+ cg.a_load_reg_reg(list,OS_32,OS_32,tmplo,regdst.reglo);
+ end
+ else
+ cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
+
+ cg.a_op_const_reg_reg(list,OP_SUB,hisize,aint(hi(value)),regsrc.reghi,regdst.reghi);
+ if carry<>NR_NO then
+ cg.a_op_reg_reg_reg(list,OP_SUB,hisize,carry,regdst.reghi,regdst.reghi);
+ end;
+ else
+ InternalError(2013050301);
+ end;
+ end;
+
+
+ procedure create_codegen;
+ begin
+ cg := tcgrv32.create;
+ cg64 :=tcg64frv.create;
+ end;
+
+end.
diff --git a/riscv_new/compiler/riscv32/cpubase.pas b/riscv_new/compiler/riscv32/cpubase.pas
new file mode 100644
index 0000000000..feb63fc5b5
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cpubase.pas
@@ -0,0 +1,426 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the Risc-V32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This Unit contains the base types for the Risc-V32
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ strings,globtype,
+ cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(A_None,
+ { normal opcodes }
+ A_LUI,A_AUIPC,A_JAL,A_JALR,
+ A_Bxx,A_LB,A_LH,A_LW,A_LBU,A_LHU,
+ A_SB,A_SH,A_SW,
+ A_ADDI,A_SLTI,A_SLTIU,
+ A_XORI,A_ORI,A_ANDI,
+ A_SLLI,A_SRLI,A_SRAI,
+ A_ADD,A_SUB,A_SLL,A_SLT,A_SLTU,
+ A_XOR,A_SRL,A_SRA,A_OR,A_AND,
+ A_FENCE,A_FENCE_I,
+ A_ECALL,A_EBREAK,
+ A_CSRRW,A_CSRRS,A_CSRRC,A_CSRRWI,A_CSRRSI,A_CSRRCI,
+
+ { M-extension }
+ A_MUL,A_MULH,A_MULHSU,A_MULHU,
+ A_DIV,A_DIVU,A_REM,A_REMU,
+
+ { A-extension }
+ A_LR_W,A_SC_W,A_AMOSWAP_W,A_AMOADD_W,A_AMOXOR_W,A_AMOAND_W,
+ A_AMOOR_W,A_AMOMIN_W,A_AMOMAX_W,A_AMOMINU_W,A_AMOMAXU_W,
+
+ { F-extension }
+ A_FLW,A_FSW,
+ A_FMADD_S,A_FMSUB_S,A_FNMSUB_S,A_FNMADD_S,
+ A_FADD_S,A_FSUB_S,A_FMUL_S,A_FDIV_S,
+ A_FSQRT_S,A_FSGNJ_S,A_FSGNJN_S,A_FSGNJX_S,
+ A_FMIN_S,A_FMAX_S,
+ A_FMV_X_S,A_FEQ_S,A_FLT_S,A_FLE_S,A_FCLASS_S,
+ A_FCVT_W_S,A_FCVT_WU_S,A_FCVT_S_W,A_FCVT_S_WU,
+ A_FMV_S_X,
+ A_FRCSR,A_FRRM,A_FRFLAGS,A_FSCSR,A_FSRM,
+ A_FSFLAGS,A_FSRMI,A_FSFLAGSI,
+
+ { D-extension }
+ A_FLD,A_FSD,
+ A_FMADD_D,A_FMSUB_D,A_FNMSUB_D,A_FNMADD_D,
+ A_FADD_D,A_FSUB_D,A_FMUL_D,A_FDIV_D,
+ A_FSQRT_D,A_FSGNJ_D,A_FSGNJN_D,A_FSGNJX_D,
+ A_FMIN_D,A_FMAX_D,
+ A_FEQ_D,A_FLT_D,A_FLE_D,A_FCLASS_D,
+ A_FCVT_D_S,A_FCVT_S_D,
+ A_FCVT_W_D,A_FCVT_WU_D,A_FCVT_D_W,A_FCVT_D_WU,
+
+ { Machine mode }
+ A_MRET,A_HRET,A_SRET,A_URET,
+ A_WFI,
+
+ { Supervisor }
+ A_SFENCE_VM
+ );
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[8];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rrv32nor.inc}-1;
+ totherregisterset = set of tregisterindex;
+
+ const
+ maxvarregs = 32-6; { 32 int registers - r0 - stackpointer - r2 - 3 scratch registers }
+ maxfpuvarregs = 28; { 32 fpuregisters - some scratch registers (minimally 2) }
+ { Available Superregisters }
+ {$i rrv32sup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE=R_SUBNONE;
+
+ { Available Registers }
+ {$i rrv32con.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_imreg = $20;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rrv32num.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rrv32sta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rrv32dwa.inc}
+ );
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond = (C_None { unconditional jumps },
+ C_LT,C_LTU,C_GE,C_GEU,C_NE,C_EQ);
+
+ const
+ cond2str: Array[TAsmCond] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'lt','ltu','ge','geu','ne','eq');
+
+ uppercond2str: Array[TAsmCond] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'LT','LTU','GE','GEU','NE','EQ');
+
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlagsEnum = (F_EQ,F_NE,F_LT,F_LTU,F_GE,F_GEU);
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 5;
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor,
+ has to match osuinttype/ossinttype as initialized in psystem }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+
+ stab_regindex : array[tregisterindex] of shortint = (
+ {$i rrv32sta.inc}
+ );
+
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_X2;
+ RS_STACK_POINTER_REG = RS_X2;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_X8;
+ RS_FRAME_POINTER_REG = RS_X8;
+
+ NR_PIC_OFFSET_REG = NR_X3;
+ { Return address of a function }
+ NR_RETURN_ADDRESS_REG = NR_X1;
+ RS_RETURN_ADDRESS_REG = RS_X1;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_X10;
+ RS_FUNCTION_RETURN_REG = RS_X10;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_X10;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_X10;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_X11;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_X11;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_F10;
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_DEFAULTFLAGS = NR_NO;
+ RS_DEFAULTFLAGS = RS_NO;
+
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..12] of tsuperregister = (
+ RS_X2,
+ RS_X8,RS_X9,
+ RS_X18,RS_X19,
+ RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27
+ );
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ maxfpuregs = 8;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_imm12(value: aint): boolean;
+ function is_lui_imm(value: aint): boolean;
+
+ function is_calljmp(o:tasmop):boolean;
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function dwarf_reg(r:tregister):shortint;
+
+ function conditions_equal(const c1,c2: TAsmCond): boolean;
+
+implementation
+
+ uses
+ rgbase,verbose;
+
+ const
+ std_regname_table : TRegNameTable = (
+ {$i rrv32std.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rrv32rni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rrv32sri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_imm12(value: aint): boolean;
+ begin
+ result:=(value >= -2048) and (value <= 2047);
+ end;
+
+
+ function is_lui_imm(value: aint): boolean;
+ begin
+ result:=SarInt64((value and $FFFFF000) shl 32, 32) = value;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp:=false;
+ case o of
+ A_JAL,A_JALR,A_Bxx:
+ is_calljmp:=true;
+ end;
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inv_condflags:array[TAsmCond] of TAsmCond=(C_None,
+ C_GE,C_GEU,C_LT,C_LTU,C_EQ,C_NE);
+ begin
+ result := inv_condflags[c];
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ result:=OS_32;
+ R_MMREGISTER:
+ result:=OS_M128;
+ R_FPUREGISTER:
+ result:=OS_F64;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean;
+ begin
+ result:=c1=c2;
+ end;
+
+end.
diff --git a/riscv_new/compiler/riscv32/cpuinfo.pas b/riscv_new/compiler/riscv32/cpuinfo.pas
new file mode 100644
index 0000000000..755da23976
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cpuinfo.pas
@@ -0,0 +1,135 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the Risc-V32
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+{$if FPC_FULLVERSION>20700}
+ bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_rv32imafd,
+ cpu_rv32ima,
+ cpu_rv32im,
+ cpu_rv32i
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_libgcc,
+ fpu_soft,
+ fpu_fd
+ );
+
+ tcontrollertype =
+ (ct_none
+ );
+
+ tcontrollerdatatype = record
+ controllertypestr, controllerunitstr: string[20];
+ cputype: tcputype; fputype: tfputype;
+ flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize, bootbase, bootsize: dword;
+ end;
+
+
+Const
+ { Is there support for dealing with multiple microcontrollers available }
+ { for this platform? }
+ ControllerSupport = false;
+
+ { We know that there are fields after sramsize
+ but we don't care about this warning }
+ {$PUSH}
+ {$WARN 3177 OFF}
+ embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
+ (
+ (controllertypestr:''; controllerunitstr:''; cputype:cpu_none; fputype:fpu_none; flashbase:0; flashsize:0; srambase:0; sramsize:0));
+ {$POP}
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { pass all const records by reference }
+ pocall_mwpascal
+ ];
+
+ cputypestr : array[tcputype] of string[10] = ('',
+ 'RV32IMAFD',
+ 'RV32IMA',
+ 'RV32IM',
+ 'RV32I'
+ );
+
+ fputypestr : array[tfputype] of string[8] = (
+ 'LIBGCC',
+ 'NONE',
+ 'SOFT',
+ 'FD'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,
+ cs_opt_tailrecursion,cs_opt_reorder_fields,cs_opt_fastmath,
+ cs_opt_stackframe];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches + [cs_opt_regvar,cs_opt_nodecse,cs_opt_tailrecursion];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+ level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [cs_opt_stackframe];
+
+ type
+ tcpuflags =
+ (CPURV_HAS_MUL,
+ CPURV_HAS_ATOMIC,
+ CPURV_HAS_COMPACT
+ );
+
+ const
+ cpu_capabilities : array[tcputype] of set of tcpuflags =
+ ( { cpu_none } [],
+ { cpu_rv32imafd } [CPURV_HAS_MUL,CPURV_HAS_ATOMIC],
+ { cpu_rv32ima } [CPURV_HAS_MUL,CPURV_HAS_ATOMIC],
+ { cpu_rv32im } [CPURV_HAS_MUL],
+ { cpu_rv32i } []
+ );
+
+Implementation
+
+end.
diff --git a/riscv_new/compiler/riscv32/cpunode.pas b/riscv_new/compiler/riscv32/cpunode.pas
new file mode 100644
index 0000000000..08190a8a57
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cpunode.pas
@@ -0,0 +1,47 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the Risc-V32 code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,
+ ncgobjc,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nrv32add,
+ nrv32cal,
+ nrvset,
+ nrvinl,
+ nrv32mat,
+ nrv32cnv,
+ nrvcon
+ ;
+
+end.
diff --git a/riscv_new/compiler/riscv32/cpupara.pas b/riscv_new/compiler/riscv32/cpupara.pas
new file mode 100644
index 0000000000..7c90ebd074
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cpupara.pas
@@ -0,0 +1,550 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Risc-V32 specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,aasmdata,
+ cpubase,
+ symconst,symtype,symdef,symsym,
+ paramgr,parabase,cgbase,cgutils;
+
+ type
+ tcpuparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+
+ procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
+ end;
+
+ implementation
+
+ uses
+ cpuinfo,globals,
+ verbose,systems,
+ defutil,symtable,
+ procinfo,cpupi;
+
+
+ function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[RS_X0..RS_X31]-[RS_X2,RS_X8..RS_X9,RS_X18..RS_X27];
+ end;
+
+
+ function tcpuparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[RS_F0..RS_F31]-[RS_F8..RS_F9,RS_F18..RS_F27];
+ end;
+
+
+ procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
+ var
+ paraloc : pcgparalocation;
+ psym : tparavarsym;
+ pdef : tdef;
+ begin
+ psym:=tparavarsym(pd.paras[nr-1]);
+ pdef:=psym.vardef;
+ if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+ pdef:=cpointerdef.getreusable_no_free(pdef);
+ cgpara.reset;
+ cgpara.size:=def_cgsize(pdef);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
+ cgpara.alignment:=get_para_align(pd.proccalloption);
+ cgpara.def:=pdef;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=def_cgsize(pdef);
+ def:=pdef;
+ if (nr<=8) then
+ begin
+ if nr=0 then
+ internalerror(200309271);
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_X10+nr,R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=sizeof(pint)*(nr);
+ end;
+ end;
+ end;
+
+
+
+ function getparaloc(p : tdef) : tcgloc;
+
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ result:=LOC_REGISTER;
+ floatdef:
+ if (cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_soft]) then
+ result := LOC_REGISTER
+ else
+ result := LOC_FPUREGISTER;
+ enumdef:
+ result:=LOC_REGISTER;
+ pointerdef:
+ result:=LOC_REGISTER;
+ formaldef:
+ result:=LOC_REGISTER;
+ classrefdef:
+ result:=LOC_REGISTER;
+ procvardef:
+ if (p.size = sizeof(pint)) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ recorddef:
+ if (p.size > 4) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ filedef:
+ result:=LOC_REGISTER;
+ arraydef:
+ if is_dynamic_array(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ variantdef:
+ result:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ variantdef,
+ formaldef :
+ result:=true;
+ { regular procvars must be passed by value, because you cannot pass
+ the address of a local stack location when calling e.g.
+ pthread_create with the address of a function (first of all it
+ expects the address of the function to execute and not the address
+ of a memory location containing that address, and secondly if you
+ first store the address on the stack and then pass the address of
+ this stack location, then this stack location may no longer be
+ valid when the newly started thread accesses it.
+
+ However, for "procedure of object" we must use the same calling
+ convention as for "8 byte record" due to the need for
+ interchangeability with the TMethod record type.
+ }
+ procvardef :
+ result:=
+ (def.size <> sizeof(pint));
+ recorddef :
+ result := (def.size > 8) or (varspez = vs_const);
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef :
+ result:=is_object(def);
+ setdef :
+ result:=not is_smallset(def);
+ stringdef :
+ result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+ end;
+ end;
+
+
+ procedure tcpuparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ cur_stack_offset:=0;
+ curintreg:=RS_X10;
+ curfloatreg:=RS_F10;
+ curmmreg:=RS_NO;
+ end;
+
+
+ function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
+ exit;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if result.def.typ=floatdef then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ paraloc^.def:=result.def;
+ end
+ else
+ { Return in register }
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ paraloc^.def:=u32inttype;
+ { high 32bits }
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc^.def:=u32inttype;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ paraloc^.size:=retcgsize;
+ paraloc^.def:=result.def;
+ end;
+ end;
+ end;
+
+
+ function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
+
+ create_funcretloc_info(p,side);
+ end;
+
+
+
+ function tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
+ var
+ stack_offset: longint;
+ paralen: aint;
+ nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
+ locdef,
+ fdef,
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ i : integer;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize: tcgsize;
+ firstparaloc: boolean;
+
+ begin
+{$ifdef extdebug}
+ if po_explicitparaloc in p.procoptions then
+ internalerror(200411141);
+{$endif extdebug}
+
+ result:=0;
+ nextintreg := curintreg;
+ nextfloatreg := curfloatreg;
+ nextmmreg := curmmreg;
+ stack_offset := cur_stack_offset;
+ maxfpureg := RS_F17;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef := hp.vardef;
+ { Syscall for Morphos can have already a paraloc set }
+ if (vo_has_explicit_paraloc in hp.varoptions) then
+ begin
+ if not(vo_is_syscall_lib in hp.varoptions) then
+ internalerror(200412153);
+ continue;
+ end;
+ hp.paraloc[side].reset;
+ { currently only support C-style array of const }
+ if (p.proccalloption in cstylearrayofconst) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc := LOC_REGISTER;
+ paraloc^.register := NR_X0;
+ paraloc^.size := OS_ADDR;
+ paraloc^.def:=voidpointertype;
+ break;
+ end;
+
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ begin
+ paradef:=cpointerdef.getreusable_no_free(paradef);
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end;
+
+ loc := getparaloc(paradef);
+
+ hp.paraloc[side].alignment:=std_param_align;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
+{$ifndef cpu64bitaddr}
+ if (is_64bit(paradef)) and
+ odd(nextintreg-RS_X10) then
+ inc(nextintreg);
+{$endif not cpu64bitaddr}
+ if (paralen = 0) then
+ if (paradef.typ = recorddef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end
+ else
+ internalerror(2005011310);
+ locdef:=paradef;
+ firstparaloc:=true;
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_X17) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc := loc;
+ { make sure we don't lose whether or not the type is signed }
+ if (paradef.typ<>orddef) then
+ begin
+ paracgsize:=int_cgsize(paralen);
+ locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
+ end;
+ if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
+ begin
+ paraloc^.size:=OS_INT;
+ paraloc^.def:=u32inttype;
+ end
+ else
+ begin
+ paraloc^.size:=paracgsize;
+ paraloc^.def:=locdef;
+ end;
+ { aix requires that record data stored in parameter
+ registers is left-aligned }
+ if (target_info.system in systems_aix) and
+ (paradef.typ = recorddef) and
+ (paralen < sizeof(aint)) then
+ begin
+ paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
+ paraloc^.size := OS_INT;
+ paraloc^.def := u32inttype;
+ end;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end
+ else if (loc = LOC_FPUREGISTER) and
+ (nextintreg <= RS_X17) then
+ begin
+ paraloc^.loc:=loc;
+ paraloc^.size := paracgsize;
+ paraloc^.def := paradef;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end
+ else { LOC_REFERENCE }
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ case loc of
+ LOC_FPUREGISTER:
+ begin
+ paraloc^.size:=int_float_cgsize(paralen);
+ case paraloc^.size of
+ OS_F32: paraloc^.def:=s32floattype;
+ OS_F64: paraloc^.def:=s64floattype;
+ else
+ internalerror(2013060124);
+ end;
+ end;
+ LOC_REGISTER,
+ LOC_REFERENCE:
+ begin
+ paraloc^.size:=int_cgsize(paralen);
+ if paraloc^.size<>OS_NO then
+ paraloc^.def:=cgsize_orddef(paraloc^.size)
+ else
+ paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
+ end;
+ else
+ internalerror(2006011101);
+ end;
+ if (side = callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ begin
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+
+ { create_paraloc_info_intern might be also called when being outside of
+ code generation so current_procinfo might be not set }
+ if assigned(current_procinfo) then
+ trv32procinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+
+ paraloc^.reference.offset:=stack_offset;
+
+ inc(stack_offset,align(paralen,4));
+ while (paralen > 0) and
+ (nextintreg < RS_X18) do
+ begin
+ inc(nextintreg);
+ dec(paralen,sizeof(pint));
+ end;
+ paralen := 0;
+ end;
+ firstparaloc:=false;
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=stack_offset;
+ end;
+
+
+ function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ parasize, l: longint;
+ curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+ i : integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ firstfloatreg:=curfloatreg;
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
+ if (p.proccalloption in cstylearrayofconst) then
+ { just continue loading the parameters in the registers }
+ begin
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
+ end
+ else
+ begin
+ parasize:=cur_stack_offset;
+ for i:=0 to varargspara.count-1 do
+ begin
+ hp:=tparavarsym(varargspara[i]);
+ hp.paraloc[callerside].alignment:=4;
+ paraloc:=hp.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=def_cgsize(hp.vardef);
+ paraloc^.def:=hp.vardef;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+ paraloc^.reference.offset:=parasize;
+ parasize:=parasize+l;
+ end;
+ result:=parasize;
+ end;
+ if curfloatreg<>firstfloatreg then
+ include(varargspara.varargsinfo,va_uses_float_reg);
+ end;
+
+begin
+ paramanager:=tcpuparamanager.create;
+end.
diff --git a/riscv_new/compiler/riscv32/cpupi.pas b/riscv_new/compiler/riscv32/cpupi.pas
new file mode 100644
index 0000000000..138d9ab915
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cpupi.pas
@@ -0,0 +1,123 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,globtype,
+ cgbase,aasmdata,
+ procinfo,cpuinfo,psub;
+
+ type
+ trv32procinfo = class(tcgprocinfo)
+ { for arm thumb, we need to know the stackframe size before
+ starting procedure compilation, so this contains the stack frame size, the compiler
+ should assume
+ if this size is too little the procedure must be compiled again with a larger value }
+ stackframesize,
+ floatregstart : aint;
+ stackpaddingreg: TSuperRegister;
+
+ needs_frame_pointer: boolean;
+ // procedure handle_body_start;override;
+ // procedure after_pass1;override;
+ constructor create(aparent: tprocinfo); override;
+ procedure set_first_temp_offset;override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+
+ implementation
+
+ uses
+ globals,systems,
+ cpubase,
+ tgobj,
+ symconst,symtype,symsym,symcpu,paramgr,
+ cgutils,
+ cgobj,
+ defutil,
+ aasmcpu;
+
+
+ constructor trv32procinfo.create(aparent: tprocinfo);
+ begin
+ inherited create(aparent);
+ maxpushedparasize := 0;
+ end;
+
+
+ procedure trv32procinfo.set_first_temp_offset;
+ begin
+ if (po_nostackframe in procdef.procoptions) then
+ begin
+ { maxpushedparasize sghould be zero,
+ if not we will get an error later. }
+ tg.setfirsttemp(maxpushedparasize);
+ exit;
+ end;
+
+ if tg.direction = -1 then
+ tg.setfirsttemp(-(1+12)*4)
+ else
+ tg.setfirsttemp(maxpushedparasize);
+ end;
+
+
+ function trv32procinfo.calc_stackframe_size:longint;
+ var
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ floatsavesize : aword;
+ regs: tcpuregisterset;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
+ floatsavesize:=0;
+ case current_settings.fputype of
+ fpu_fd:
+ begin
+ floatsavesize:=0;
+ regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F31 do
+ if r in regs then
+ inc(floatsavesize,8);
+ end;
+ end;
+ floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
+ result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
+
+ if tg.direction=1 then
+ floatregstart:=result-aint(floatsavesize)
+ else
+ floatregstart:=-result+maxpushedparasize;
+ end;
+
+
+begin
+ cprocinfo:=trv32procinfo;
+end.
+
diff --git a/riscv_new/compiler/riscv32/cputarg.pas b/riscv_new/compiler/riscv32/cputarg.pas
new file mode 100644
index 0000000000..0643083eee
--- /dev/null
+++ b/riscv_new/compiler/riscv32/cputarg.pas
@@ -0,0 +1,84 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the Risc-V32 dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETEMBEDDED}
+ ,t_embed
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGRVGAS}
+ ,agrvgas
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaRVGas}
+ ,rarv32gas
+ {$endif NoRaRVGas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgStabx}
+ ,dbgstabx
+ {$endif NoDbgStabx}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+{**************************************
+ Optimizer
+**************************************}
+
+ {$ifndef NOOPT}
+ , aoptcpu
+ {$endif NOOPT}
+ ;
+
+end.
diff --git a/riscv_new/compiler/riscv32/hlcgcpu.pas b/riscv_new/compiler/riscv32/hlcgcpu.pas
new file mode 100644
index 0000000000..e18851b3ae
--- /dev/null
+++ b/riscv_new/compiler/riscv32/hlcgcpu.pas
@@ -0,0 +1,61 @@
+{
+ Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
+ Member of the Free Pascal development team
+
+ This unit contains high-level code generator support for Risc-V32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit hlcgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmdata,
+ symtype,
+ cgbase,cgutils,hlcgobj,hlcgrv;
+
+ type
+ thlcgcpu = class(thlcgriscv)
+ end;
+
+ procedure create_hlcodegen;
+
+implementation
+
+ uses
+ verbose,
+ cpubase,aasmcpu,
+ defutil,
+ cgobj,cgcpu;
+
+
+
+ procedure create_hlcodegen;
+ begin
+ hlcg:=thlcgcpu.create;
+ create_codegen;
+ end;
+
+
+begin
+ chlcgobj:=thlcgcpu;
+end.
+
diff --git a/riscv_new/compiler/riscv32/itcpugas.pas b/riscv_new/compiler/riscv32/itcpugas.pas
new file mode 100644
index 0000000000..190b7bfbb2
--- /dev/null
+++ b/riscv_new/compiler/riscv32/itcpugas.pas
@@ -0,0 +1,140 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the Risc-V32 GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str: array[tasmop] of string[14] = ('<none>',
+ 'lui','auipc','jal','jalr',
+ 'b','lb','lh','lw','lbu','lhu',
+ 'sb','sh','sw',
+ 'addi','slti','sltiu',
+ 'xori','ori','andi',
+ 'slli','srli','srai',
+ 'add','sub','sll','slt','sltu',
+ 'xor','srl','sra','or','and',
+ 'fence','fence.i',
+ 'ecall','ebreak',
+ 'csrrw','csrrs','csrrc','csrrwi','csrrsi','csrrci',
+
+ { m-extension }
+ 'mul','mulh','mulhsu','mulhu',
+ 'div','divu','rem','remu',
+
+ { a-extension }
+ 'lr.w','sc.w','amoswap.w','amoadd.w','amoxor.w','amoand.w',
+ 'amoor.w','amomin.w','amomax.w','amominu.w','amomaxu.w',
+
+ { f-extension }
+ 'flw','fsw',
+ 'fmadd.s','fmsub.s','fnmsub.s','fnmadd.s',
+ 'fadd.s','fsub.s','fmul.s','fdiv.s',
+ 'fsqrt.s','fsgnj.s','fsgnjn.s','fsgnjx.s',
+ 'fmin.s','fmax.s',
+ 'fmv.x.s','feq.s','flt.s','fle.s','fclass.s',
+ 'fcvt.w.s','fcvt.wu.s','fcvt.s.w','fcvt.s.wu',
+ 'fmv.s.x',
+ 'frcsr','frrm','frflags','fscsr','fsrm',
+ 'fsflags','fsrmi','fsflagsi',
+
+ { d-extension }
+ 'fld','fsd',
+ 'fmadd.d','fmsub.d','fnmsub.d','fnmadd.d',
+ 'fadd.d','fsub.d','fmul.d','fdiv.d',
+ 'fsqrt.d','fsgnj.d','fsgnjn.d','fsgnjx.d',
+ 'fmin.d','fmax.d',
+ 'feq.d','flt.d','fle.d','fclass.d',
+ 'fcvt.d.s','fcvt.s.d',
+ 'fcvt.w.d','fcvt.wu.d','fcvt.d.w','fcvt.d.wu',
+
+ { Machine mode }
+ 'mret','hret','sret','uret',
+ 'wfi',
+
+ { Supervisor mode }
+ 'sfence.vm'
+ );
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ globtype,globals,aasmbase,
+ cutils,verbose, systems,
+ rgbase;
+
+ const
+ gas_regname_table : TRegNameTable = (
+ {$i rrv32std.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rrv32sri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/riscv_new/compiler/riscv32/nrv32add.pas b/riscv_new/compiler/riscv32/nrv32add.pas
new file mode 100644
index 0000000000..836663390d
--- /dev/null
+++ b/riscv_new/compiler/riscv32/nrv32add.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the Risc-V32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv32add;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ node, ncgadd, aasmbase, nrvadd, cpubase;
+
+ type
+ trv32addnode = class(trvaddnode)
+ protected
+ function use_generic_mul32to64: boolean; override;
+ end;
+
+ implementation
+
+ uses
+ systems,
+ cutils,verbose,
+ paramgr,procinfo,
+ aasmtai,aasmdata,aasmcpu,defutil,
+ cgbase,cgcpu,cgutils,nadd,
+ cpupara,
+ ncon,nset,
+ hlcgobj, ncgutil,cgobj;
+
+ function trv32addnode.use_generic_mul32to64: boolean;
+ begin
+ result:=true;
+ end;
+
+begin
+ caddnode:=trv32addnode;
+end.
diff --git a/riscv_new/compiler/riscv32/nrv32cal.pas b/riscv_new/compiler/riscv32/nrv32cal.pas
new file mode 100644
index 0000000000..4896c362c3
--- /dev/null
+++ b/riscv_new/compiler/riscv32/nrv32cal.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the Risc-V32 specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv32cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,node,ncal,ncgcal;
+
+ type
+ trv32callnode = class(tcgcallnode)
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
+ cgbase,pass_2,
+ cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ nmem,nld,ncnv,
+ ncgutil,cgutils,cgobj,tgobj,regvars,rgobj,rgcpu,
+ cg64f32,cgcpu,cpupi,procinfo;
+
+
+begin
+ ccallnode:=trv32callnode;
+end.
diff --git a/riscv_new/compiler/riscv32/nrv32cnv.pas b/riscv_new/compiler/riscv32/nrv32cnv.pas
new file mode 100644
index 0000000000..dd56a22d49
--- /dev/null
+++ b/riscv_new/compiler/riscv32/nrv32cnv.pas
@@ -0,0 +1,151 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate Risc-V32 assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv32cnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,nrvcnv;
+
+ type
+ trv32typeconvnode = class(trvtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool;override; }
+ { procedure second_set_to_set;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,symcpu,
+ cgbase,cgutils,pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,procinfo,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj,hlcgobj;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function trv32typeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ result:=inherited first_int_to_real
+ { converting a 64bit integer to a float requires a helper }
+ else
+ begin
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { hack to avoid double division by 10000, as it's }
+ { already done by typecheckpass.resultdef_int_to_real }
+ if is_currency(left.resultdef) then
+ left.resultdef := s64inttype;
+ if is_signed(left.resultdef) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+ procedure trv32typeconvnode.second_int_to_real;
+ const
+ ops: array[boolean,s32real..s64real] of TAsmOp =
+ ((A_FCVT_S_WU,A_FCVT_D_WU),
+ (A_FCVT_S_W,A_FCVT_D_W));
+ var
+ restype: tfloattype;
+ begin
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+
+ restype:=tfloatdef(resultdef).floattype;
+
+ location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, tfloat2tcgsize[restype]);
+ if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(ops[is_signed(left.resultdef),restype], location.register, left.location.register));
+ end
+ else
+ begin
+ { Load memory in fpu register }
+ hlcg.location_force_mem(current_asmdata.CurrAsmList, left.location, left.resultdef);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F32, OS_F32, left.location.reference, location.Register);
+ tg.ungetiftemp(current_asmdata.CurrAsmList, left.location.reference);
+
+ case restype of
+ s64real: cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList, OS_F32, OS_F64, location.register, location.Register);
+ end;
+ end;
+ end;
+
+begin
+ ctypeconvnode:=trv32typeconvnode;
+end.
+
diff --git a/riscv_new/compiler/riscv32/nrv32mat.pas b/riscv_new/compiler/riscv32/nrv32mat.pas
new file mode 100644
index 0000000000..ee25d85273
--- /dev/null
+++ b/riscv_new/compiler/riscv32/nrv32mat.pas
@@ -0,0 +1,135 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate Risc-V32 assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv32mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat, ncgmat,
+ cgbase;
+
+ type
+ trv32moddivnode = class(tcgmoddivnode)
+ procedure emit_div_reg_reg(signed: boolean; denum, num: tregister); override;
+ procedure emit_mod_reg_reg(signed: boolean; denum, num: tregister); override;
+ function first_moddivint: tnode; override;
+ end;
+
+ trv32shlshrnode = class(tcgshlshrnode)
+ end;
+
+ trv32unaryminusnode = class(tcgunaryminusnode)
+ end;
+
+ trv32notnode = class(tcgnotnode)
+ procedure second_boolean; override;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,symdef,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ defutil,
+ cgutils,cgobj,hlcgobj,pass_2,
+ ncon,procinfo,
+ cpubase,
+ ncgutil,cgcpu;
+
+ procedure trv32notnode.second_boolean;
+ var
+ tlabel, flabel: tasmlabel;
+ begin
+ if not handle_locjump then
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ Internalerror(2016060601);
+ //location_copy(location,left.location);
+ //inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER,
+ LOC_REFERENCE, LOC_CREFERENCE,
+ LOC_SUBSETREG, LOC_CSUBSETREG,
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ current_asmdata.getjumplabel(tlabel);
+ current_asmdata.getjumplabel(flabel);
+
+ location_reset_jump(location,tlabel,flabel);
+
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register,tlabel);
+ hlcg.a_jmp_always(current_asmdata.CurrAsmList,flabel);
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+ procedure trv32moddivnode.emit_div_reg_reg(signed: boolean; denum, num: tregister);
+ var
+ op: TAsmOp;
+ begin
+ if signed then
+ op:=A_DIV
+ else
+ op:=A_DIVU;
+
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,denum,num,denum));
+ end;
+
+ procedure trv32moddivnode.emit_mod_reg_reg(signed: boolean; denum, num: tregister);
+ var
+ op: TAsmOp;
+ begin
+ if signed then
+ op:=A_REM
+ else
+ op:=A_REMU;
+
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,denum,num,denum));
+ end;
+
+
+ function trv32moddivnode.first_moddivint: tnode;
+ begin
+ if (not is_64bitint(resultdef)) then
+ Result:=nil
+ else
+ result:=inherited;
+ end;
+
+begin
+ cmoddivnode:=trv32moddivnode;
+ cshlshrnode:=trv32shlshrnode;
+ cunaryminusnode:=trv32unaryminusnode;
+ cnotnode:=trv32notnode;
+end.
diff --git a/riscv_new/compiler/riscv32/rarv32.pas b/riscv_new/compiler/riscv32/rarv32.pas
new file mode 100644
index 0000000000..8d7d3effad
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rarv32.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common Risc-V32 assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rarv32;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ TRVOperand=class(TOperand)
+ end;
+
+ TRVInstruction=class(TInstruction)
+ end;
+
+ implementation
+
+end.
diff --git a/riscv_new/compiler/riscv32/rarv32gas.pas b/riscv_new/compiler/riscv32/rarv32gas.pas
new file mode 100644
index 0000000000..b4ca7843c6
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rarv32gas.pas
@@ -0,0 +1,771 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the Risc-V32 GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit rarv32gas;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ raatt,rarv32;
+
+ type
+ trv32attreader = class(tattreader)
+ function is_register(const s: string): boolean; override;
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : trvoperand);
+ procedure BuildOperand(oper : trvoperand);
+ procedure BuildOpCode(instr : trvinstruction);
+ procedure ReadAt(oper : trvoperand);
+ procedure ReadSym(oper : trvoperand);
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symsym,
+ { parser }
+ procinfo,
+ rabase,rautils,
+ cgbase,cgobj,cgrv
+ ;
+
+ procedure trv32attreader.ReadSym(oper : trvoperand);
+ var
+ tempstr, mangledname : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ procedure trv32attreader.ReadAt(oper : trvoperand);
+ begin
+ { check for ...@ }
+ if actasmtoken=AS_AT then
+ begin
+ if (oper.opr.ref.symbol=nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ {if upper(actasmpattern)='L' then
+ oper.opr.ref.refaddr:=addr_low
+ else if upper(actasmpattern)='HI' then
+ oper.opr.ref.refaddr:=addr_high
+ else if upper(actasmpattern)='HA' then
+ oper.opr.ref.refaddr:=addr_higha
+ else}
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+
+
+ Procedure trv32attreader.BuildReference(oper : trvoperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+ var
+ l : aint;
+ relsym: string;
+ asmsymtyp: tasmsymtype;
+ isflags: tindsymflags;
+
+ begin
+ Consume(AS_LPAREN);
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { offset(offset) is invalid }
+ If oper.opr.Ref.Offset <> 0 Then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ End
+ Else
+ Begin
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ end;
+ exit;
+ End;
+ AS_REGISTER: { (reg ... }
+ Begin
+ if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+ ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ Consume_RParen;
+ end; {end case }
+ AS_ID:
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_PLUS:
+ begin
+ { add a constant expression? }
+ l:=BuildConstExpression(true,true);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ AS_MINUS:
+ begin
+ Consume(AS_MINUS);
+ BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
+ if (relsym<>'') then
+ begin
+ if (oper.opr.typ = OPR_REFERENCE) then
+ oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end
+ end
+ else
+ begin
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ dec(oper.opr.val,l);
+ OPR_LOCAL :
+ dec(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ dec(oper.opr.ref.offset,l);
+ else
+ internalerror(2007092601);
+ end;
+ end;
+ end;
+ end;
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ End;
+ AS_COMMA: { (, ... can either be scaling, or index }
+ Begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken=AS_REGISTER) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end;
+
+
+ Procedure trv32attreader.BuildOperand(oper : trvoperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.DefineAsmSymbol(mangledname,AB_EXTERNAL,AT_FUNCTION);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ var
+ tempreg : tregister;
+ hl : tasmlabel;
+ ofs : aint;
+ refaddr: trefaddr;
+ Begin
+ expr:='';
+
+ refaddr:=addr_full;
+ if actasmtoken=AS_MOD then
+ begin
+ consume(AS_MOD);
+
+ if actasmtoken<>AS_ID then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end
+ else
+ begin
+ if lower(actasmpattern)='pcrel_hi' then
+ refaddr:=addr_pcrel_hi20
+ else if lower(actasmpattern)='pcrel_lo' then
+ refaddr:=addr_pcrel_lo12
+ else if lower(actasmpattern)='hi' then
+ refaddr:=addr_hi20
+ else if lower(actasmpattern)='lo' then
+ refaddr:=addr_lo12
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+
+ consume(AS_ID);
+ consume(AS_LPAREN);
+ end;
+ end;
+
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ ReadAt(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+
+ if refaddr<>addr_full then
+ begin
+ if oper.opr.typ<>OPR_REFERENCE then
+ oper.InitRef;
+
+ oper.opr.ref.refaddr:=refaddr;
+ Consume(AS_RPAREN);
+ end;
+ end;
+
+
+{*****************************************************************************
+ trv32attreader
+*****************************************************************************}
+
+ procedure trv32attreader.BuildOpCode(instr : trvinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ<>OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as trvoperand);
+ end; { end case }
+ until false;
+ if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
+ dec(operandnum);
+ instr.Ops:=operandnum;
+ end;
+
+
+ function trv32attreader.is_register(const s: string): boolean;
+ type
+ treg2str = record
+ name : string[3];
+ reg : tregister;
+ end;
+
+ const
+ extraregs : array[0..31] of treg2str = (
+ (name: 'A0'; reg : NR_X10),
+ (name: 'A1'; reg : NR_X11),
+ (name: 'A2'; reg : NR_X12),
+ (name: 'A3'; reg : NR_X13),
+ (name: 'A5'; reg : NR_X14),
+ (name: 'A6'; reg : NR_X15),
+ (name: 'A7'; reg : NR_X16),
+ (name: 'A8'; reg : NR_X17),
+ (name: 'RA'; reg : NR_X1),
+ (name: 'SP'; reg : NR_X2),
+ (name: 'GP'; reg : NR_X3),
+ (name: 'TP'; reg : NR_X4),
+ (name: 'T0'; reg : NR_X5),
+ (name: 'T1'; reg : NR_X6),
+ (name: 'T2'; reg : NR_X7),
+ (name: 'S0'; reg : NR_X8),
+ (name: 'FP'; reg : NR_X8),
+ (name: 'S1'; reg : NR_X9),
+ (name: 'S2'; reg : NR_X18),
+ (name: 'S3'; reg : NR_X19),
+ (name: 'S4'; reg : NR_X20),
+ (name: 'S5'; reg : NR_X21),
+ (name: 'S6'; reg : NR_X22),
+ (name: 'S7'; reg : NR_X23),
+ (name: 'S8'; reg : NR_X24),
+ (name: 'S9'; reg : NR_X25),
+ (name: 'S10';reg : NR_X26),
+ (name: 'S11';reg : NR_X27),
+ (name: 'T3'; reg : NR_X28),
+ (name: 'T4'; reg : NR_X29),
+ (name: 'T5'; reg : NR_X30),
+ (name: 'T6'; reg : NR_X31)
+ );
+
+ var
+ i : longint;
+
+ begin
+ result:=inherited is_register(s);
+ { reg found?
+ possible aliases are always 2 char
+ }
+ if result or (not (length(s) in [2,3])) then
+ exit;
+ for i:=low(extraregs) to high(extraregs) do
+ begin
+ if s=extraregs[i].name then
+ begin
+ actasmregister:=extraregs[i].reg;
+ result:=true;
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function trv32attreader.is_asmopcode(const s: string):boolean;
+ var
+ cond : tasmcond;
+ hs : string;
+
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+ { clear condition }
+ fillchar(actcondition,sizeof(actcondition),0);
+
+ { check for direction hint }
+ actopcode := tasmop(ptruint(iasmops.find(hs)));
+ if actopcode <> A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ { not found, check branch instructions }
+ if hs[1]='B' then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ actopcode := A_Bxx;
+ for cond:=low(TAsmCond) to high(TAsmCond) do
+ if copy(hs,2,length(s)-1)=uppercond2str[cond] then
+ begin
+ actcondition:=cond;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure trv32attreader.handleopcode;
+ var
+ instr : trvinstruction;
+ begin
+ instr:=trvinstruction.Create(trvoperand);
+ BuildOpcode(instr);
+ instr.condition := actcondition;
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_rv32_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : trv32attreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_rv32_standard_info);
+end.
diff --git a/riscv_new/compiler/riscv32/rrv32con.inc b/riscv_new/compiler/riscv32/rrv32con.inc
new file mode 100644
index 0000000000..94c5f42533
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32con.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+NR_NO = tregister($00000000);
+NR_X0 = tregister($01000000);
+NR_X1 = tregister($01000001);
+NR_X2 = tregister($01000002);
+NR_X3 = tregister($01000003);
+NR_X4 = tregister($01000004);
+NR_X5 = tregister($01000005);
+NR_X6 = tregister($01000006);
+NR_X7 = tregister($01000007);
+NR_X8 = tregister($01000008);
+NR_X9 = tregister($01000009);
+NR_X10 = tregister($0100000a);
+NR_X11 = tregister($0100000b);
+NR_X12 = tregister($0100000c);
+NR_X13 = tregister($0100000d);
+NR_X14 = tregister($0100000e);
+NR_X15 = tregister($0100000f);
+NR_X16 = tregister($01000010);
+NR_X17 = tregister($01000011);
+NR_X18 = tregister($01000012);
+NR_X19 = tregister($01000013);
+NR_X20 = tregister($01000014);
+NR_X21 = tregister($01000015);
+NR_X22 = tregister($01000016);
+NR_X23 = tregister($01000017);
+NR_X24 = tregister($01000018);
+NR_X25 = tregister($01000019);
+NR_X26 = tregister($0100001a);
+NR_X27 = tregister($0100001b);
+NR_X28 = tregister($0100001c);
+NR_X29 = tregister($0100001d);
+NR_X30 = tregister($0100001e);
+NR_X31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_FCSR = tregister($05000001);
diff --git a/riscv_new/compiler/riscv32/rrv32dwa.inc b/riscv_new/compiler/riscv32/rrv32dwa.inc
new file mode 100644
index 0000000000..6755ebb4c5
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32dwa.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0
diff --git a/riscv_new/compiler/riscv32/rrv32nor.inc b/riscv_new/compiler/riscv32/rrv32nor.inc
new file mode 100644
index 0000000000..a3c3b517a4
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32nor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from rv32reg.dat }
+66
diff --git a/riscv_new/compiler/riscv32/rrv32num.inc b/riscv_new/compiler/riscv32/rrv32num.inc
new file mode 100644
index 0000000000..f9553bf4fb
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32num.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($05000001)
diff --git a/riscv_new/compiler/riscv32/rrv32rni.inc b/riscv_new/compiler/riscv32/rrv32rni.inc
new file mode 100644
index 0000000000..de9f6b796b
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32rni.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65
diff --git a/riscv_new/compiler/riscv32/rrv32sri.inc b/riscv_new/compiler/riscv32/rrv32sri.inc
new file mode 100644
index 0000000000..a39dc1faa3
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32sri.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+0,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/riscv_new/compiler/riscv32/rrv32sta.inc b/riscv_new/compiler/riscv32/rrv32sta.inc
new file mode 100644
index 0000000000..6755ebb4c5
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32sta.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0
diff --git a/riscv_new/compiler/riscv32/rrv32std.inc b/riscv_new/compiler/riscv32/rrv32std.inc
new file mode 100644
index 0000000000..468a711616
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32std.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+'INVALID',
+'x0',
+'x1',
+'x2',
+'x3',
+'x4',
+'x5',
+'x6',
+'x7',
+'x8',
+'x9',
+'x10',
+'x11',
+'x12',
+'x13',
+'x14',
+'x15',
+'x16',
+'x17',
+'x18',
+'x19',
+'x20',
+'x21',
+'x22',
+'x23',
+'x24',
+'x25',
+'x26',
+'x27',
+'x28',
+'x29',
+'x30',
+'x31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'fcsr'
diff --git a/riscv_new/compiler/riscv32/rrv32sup.inc b/riscv_new/compiler/riscv32/rrv32sup.inc
new file mode 100644
index 0000000000..cb12862e9d
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rrv32sup.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+RS_NO = $00;
+RS_X0 = $00;
+RS_X1 = $01;
+RS_X2 = $02;
+RS_X3 = $03;
+RS_X4 = $04;
+RS_X5 = $05;
+RS_X6 = $06;
+RS_X7 = $07;
+RS_X8 = $08;
+RS_X9 = $09;
+RS_X10 = $0a;
+RS_X11 = $0b;
+RS_X12 = $0c;
+RS_X13 = $0d;
+RS_X14 = $0e;
+RS_X15 = $0f;
+RS_X16 = $10;
+RS_X17 = $11;
+RS_X18 = $12;
+RS_X19 = $13;
+RS_X20 = $14;
+RS_X21 = $15;
+RS_X22 = $16;
+RS_X23 = $17;
+RS_X24 = $18;
+RS_X25 = $19;
+RS_X26 = $1a;
+RS_X27 = $1b;
+RS_X28 = $1c;
+RS_X29 = $1d;
+RS_X30 = $1e;
+RS_X31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_FCSR = $01;
diff --git a/riscv_new/compiler/riscv32/rv32reg.dat b/riscv_new/compiler/riscv32/rv32reg.dat
new file mode 100644
index 0000000000..0be9f17f99
--- /dev/null
+++ b/riscv_new/compiler/riscv32/rv32reg.dat
@@ -0,0 +1,77 @@
+;
+; RiscV registers
+;
+; layout
+; <name>,<type>,<subtype>,<value>,<stdname>,<stab idx>,<dwarf idx>
+;
+NO,$00,$00,$00,INVALID,-1,-1
+; Integer registers
+X0,$01,$00,$00,x0,0,0
+X1,$01,$00,$01,x1,1,1
+X2,$01,$00,$02,x2,2,2
+X3,$01,$00,$03,x3,3,3
+X4,$01,$00,$04,x4,4,4
+X5,$01,$00,$05,x5,5,5
+X6,$01,$00,$06,x6,6,6
+X7,$01,$00,$07,x7,7,7
+X8,$01,$00,$08,x8,8,8
+X9,$01,$00,$09,x9,9,9
+X10,$01,$00,$0a,x10,10,10
+X11,$01,$00,$0b,x11,11,11
+X12,$01,$00,$0c,x12,12,12
+X13,$01,$00,$0d,x13,13,13
+X14,$01,$00,$0e,x14,14,14
+X15,$01,$00,$0f,x15,15,15
+X16,$01,$00,$10,x16,16,16
+X17,$01,$00,$11,x17,17,17
+X18,$01,$00,$12,x18,18,18
+X19,$01,$00,$13,x19,19,19
+X20,$01,$00,$14,x20,20,20
+X21,$01,$00,$15,x21,21,21
+X22,$01,$00,$16,x22,22,22
+X23,$01,$00,$17,x23,23,23
+X24,$01,$00,$18,x24,24,24
+X25,$01,$00,$19,x25,25,25
+X26,$01,$00,$1a,x26,26,26
+X27,$01,$00,$1b,x27,27,27
+X28,$01,$00,$1c,x28,28,28
+X29,$01,$00,$1d,x29,29,29
+X30,$01,$00,$1e,x30,30,30
+X31,$01,$00,$1f,x31,31,31
+
+; Float registers
+F0,$02,$00,$00,f0,0,0
+F1,$02,$00,$01,f1,1,1
+F2,$02,$00,$02,f2,2,2
+F3,$02,$00,$03,f3,3,3
+F4,$02,$00,$04,f4,4,4
+F5,$02,$00,$05,f5,5,5
+F6,$02,$00,$06,f6,6,6
+F7,$02,$00,$07,f7,7,7
+F8,$02,$00,$08,f8,8,8
+F9,$02,$00,$09,f9,9,9
+F10,$02,$00,$0a,f10,10,10
+F11,$02,$00,$0b,f11,11,11
+F12,$02,$00,$0c,f12,12,12
+F13,$02,$00,$0d,f13,13,13
+F14,$02,$00,$0e,f14,14,14
+F15,$02,$00,$0f,f15,15,15
+F16,$02,$00,$10,f16,16,16
+F17,$02,$00,$11,f17,17,17
+F18,$02,$00,$12,f18,18,18
+F19,$02,$00,$13,f19,19,19
+F20,$02,$00,$14,f20,20,20
+F21,$02,$00,$15,f21,21,21
+F22,$02,$00,$16,f22,22,22
+F23,$02,$00,$17,f23,23,23
+F24,$02,$00,$18,f24,24,24
+F25,$02,$00,$19,f25,25,25
+F26,$02,$00,$1a,f26,26,26
+F27,$02,$00,$1b,f27,27,27
+F28,$02,$00,$1c,f28,28,28
+F29,$02,$00,$1d,f29,29,29
+F30,$02,$00,$1e,f30,30,30
+F31,$02,$00,$1f,f31,31,31
+
+; Special registers
+FCSR,$05,$00,$01,fcsr,0,0
diff --git a/riscv_new/compiler/riscv32/symcpu.pas b/riscv_new/compiler/riscv32/symcpu.pas
new file mode 100644
index 0000000000..43005180e9
--- /dev/null
+++ b/riscv_new/compiler/riscv32/symcpu.pas
@@ -0,0 +1,216 @@
+{
+ Copyright (c) 2014 by Florian Klaempfl
+
+ Symbol table overrides for Risc-V32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit symcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ symconst,symtype,symdef,symsym;
+
+type
+ { defs }
+ tcpufiledef = class(tfiledef)
+ end;
+ tcpufiledefclass = class of tcpufiledef;
+
+ tcpuvariantdef = class(tvariantdef)
+ end;
+ tcpuvariantdefclass = class of tcpuvariantdef;
+
+ tcpuformaldef = class(tformaldef)
+ end;
+ tcpuformaldefclass = class of tcpuformaldef;
+
+ tcpuforwarddef = class(tforwarddef)
+ end;
+ tcpuforwarddefclass = class of tcpuforwarddef;
+
+ tcpuundefineddef = class(tundefineddef)
+ end;
+ tcpuundefineddefclass = class of tcpuundefineddef;
+
+ tcpuerrordef = class(terrordef)
+ end;
+ tcpuerrordefclass = class of tcpuerrordef;
+
+ tcpupointerdef = class(tpointerdef)
+ end;
+ tcpupointerdefclass = class of tcpupointerdef;
+
+ tcpurecorddef = class(trecorddef)
+ end;
+ tcpurecorddefclass = class of tcpurecorddef;
+
+ tcpuimplementedinterface = class(timplementedinterface)
+ end;
+ tcpuimplementedinterfaceclass = class of tcpuimplementedinterface;
+
+ tcpuobjectdef = class(tobjectdef)
+ end;
+ tcpuobjectdefclass = class of tcpuobjectdef;
+
+ tcpuclassrefdef = class(tclassrefdef)
+ end;
+ tcpuclassrefdefclass = class of tcpuclassrefdef;
+
+ tcpuarraydef = class(tarraydef)
+ end;
+ tcpuarraydefclass = class of tcpuarraydef;
+
+ tcpuorddef = class(torddef)
+ end;
+ tcpuorddefclass = class of tcpuorddef;
+
+ tcpufloatdef = class(tfloatdef)
+ end;
+ tcpufloatdefclass = class of tcpufloatdef;
+
+ tcpuprocvardef = class(tprocvardef)
+ end;
+ tcpuprocvardefclass = class of tcpuprocvardef;
+
+ tcpuprocdef = class(tprocdef)
+ end;
+ tcpuprocdefclass = class of tcpuprocdef;
+
+ tcpustringdef = class(tstringdef)
+ end;
+ tcpustringdefclass = class of tcpustringdef;
+
+ tcpuenumdef = class(tenumdef)
+ end;
+ tcpuenumdefclass = class of tcpuenumdef;
+
+ tcpusetdef = class(tsetdef)
+ end;
+ tcpusetdefclass = class of tcpusetdef;
+
+ { syms }
+ tcpulabelsym = class(tlabelsym)
+ end;
+ tcpulabelsymclass = class of tcpulabelsym;
+
+ tcpuunitsym = class(tunitsym)
+ end;
+ tcpuunitsymclass = class of tcpuunitsym;
+
+ tcpuprogramparasym = class(tprogramparasym)
+ end;
+ tcpuprogramparasymclass = class(tprogramparasym);
+
+ tcpunamespacesym = class(tnamespacesym)
+ end;
+ tcpunamespacesymclass = class of tcpunamespacesym;
+
+ tcpuprocsym = class(tprocsym)
+ end;
+ tcpuprocsymclass = class of tcpuprocsym;
+
+ tcputypesym = class(ttypesym)
+ end;
+ tcpuypesymclass = class of tcputypesym;
+
+ tcpufieldvarsym = class(tfieldvarsym)
+ end;
+ tcpufieldvarsymclass = class of tcpufieldvarsym;
+
+ tcpulocalvarsym = class(tlocalvarsym)
+ end;
+ tcpulocalvarsymclass = class of tcpulocalvarsym;
+
+ tcpuparavarsym = class(tparavarsym)
+ end;
+ tcpuparavarsymclass = class of tcpuparavarsym;
+
+ tcpustaticvarsym = class(tstaticvarsym)
+ end;
+ tcpustaticvarsymclass = class of tcpustaticvarsym;
+
+ tcpuabsolutevarsym = class(tabsolutevarsym)
+ end;
+ tcpuabsolutevarsymclass = class of tcpuabsolutevarsym;
+
+ tcpupropertysym = class(tpropertysym)
+ end;
+ tcpupropertysymclass = class of tcpupropertysym;
+
+ tcpuconstsym = class(tconstsym)
+ end;
+ tcpuconstsymclass = class of tcpuconstsym;
+
+ tcpuenumsym = class(tenumsym)
+ end;
+ tcpuenumsymclass = class of tcpuenumsym;
+
+ tcpusyssym = class(tsyssym)
+ end;
+ tcpusyssymclass = class of tcpusyssym;
+
+
+const
+ pbestrealtype : ^tdef = @s64floattype;
+
+
+implementation
+
+begin
+ { used tdef classes }
+ cfiledef:=tcpufiledef;
+ cvariantdef:=tcpuvariantdef;
+ cformaldef:=tcpuformaldef;
+ cforwarddef:=tcpuforwarddef;
+ cundefineddef:=tcpuundefineddef;
+ cerrordef:=tcpuerrordef;
+ cpointerdef:=tcpupointerdef;
+ crecorddef:=tcpurecorddef;
+ cimplementedinterface:=tcpuimplementedinterface;
+ cobjectdef:=tcpuobjectdef;
+ cclassrefdef:=tcpuclassrefdef;
+ carraydef:=tcpuarraydef;
+ corddef:=tcpuorddef;
+ cfloatdef:=tcpufloatdef;
+ cprocvardef:=tcpuprocvardef;
+ cprocdef:=tcpuprocdef;
+ cstringdef:=tcpustringdef;
+ cenumdef:=tcpuenumdef;
+ csetdef:=tcpusetdef;
+
+ { used tsym classes }
+ clabelsym:=tcpulabelsym;
+ cunitsym:=tcpuunitsym;
+ cprogramparasym:=tcpuprogramparasym;
+ cnamespacesym:=tcpunamespacesym;
+ cprocsym:=tcpuprocsym;
+ ctypesym:=tcputypesym;
+ cfieldvarsym:=tcpufieldvarsym;
+ clocalvarsym:=tcpulocalvarsym;
+ cparavarsym:=tcpuparavarsym;
+ cstaticvarsym:=tcpustaticvarsym;
+ cabsolutevarsym:=tcpuabsolutevarsym;
+ cpropertysym:=tcpupropertysym;
+ cconstsym:=tcpuconstsym;
+ cenumsym:=tcpuenumsym;
+ csyssym:=tcpusyssym;
+end.
+
diff --git a/riscv_new/compiler/riscv64/aoptcpu.pas b/riscv_new/compiler/riscv64/aoptcpu.pas
new file mode 100644
index 0000000000..cebdc53420
--- /dev/null
+++ b/riscv_new/compiler/riscv64/aoptcpu.pas
@@ -0,0 +1,178 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the RiscV64 optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit aoptcpu;
+
+interface
+
+{$I fpcdefs.inc}
+
+{$define DEBUG_AOPTCPU}
+
+uses
+ cpubase,
+ globals, globtype,
+ cgbase,
+ aoptobj, aoptcpub, aopt,
+ aasmtai, aasmcpu;
+
+type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ function RegLoadedWithNewValue(reg: tregister; hp: tai): boolean; override;
+ Function GetNextInstructionUsingReg(Current: tai; Out Next: tai; reg: TRegister): Boolean;
+ { outputs a debug message into the assembler file }
+ procedure DebugMsg(const s: string; p: tai);
+
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+ end;
+
+implementation
+
+ uses
+ cutils;
+
+{$ifdef DEBUG_AOPTCPU}
+ procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
+ begin
+ asml.insertbefore(tai_comment.Create(strpnew(s)), p);
+ end;
+{$else DEBUG_AOPTCPU}
+ procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
+ begin
+ end;
+{$endif DEBUG_AOPTCPU}
+
+
+ function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
+ begin
+ result:=
+ (hp.typ=ait_instruction) and
+ (taicpu(hp).ops>1) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ (taicpu(hp).oper[0]^.reg=reg) and
+ (taicpu(hp).spilling_get_operation_type(0)=operand_write);
+ end;
+
+
+ function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai; out Next: tai; reg: TRegister): Boolean;
+ begin
+ Next:=Current;
+ repeat
+ Result:=GetNextInstruction(Next,Next);
+ until not (Result) or
+ not(cs_opt_level3 in current_settings.optimizerswitches) or
+ (Next.typ<>ait_instruction) or
+ RegInInstruction(reg,Next) or
+ is_calljmp(taicpu(Next).opcode);
+ end;
+
+
+ function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ var
+ hp1: tai;
+ begin
+ result:=false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_ADDI:
+ begin
+ {
+ Changes
+ addi x, y, #
+ addi z, x, #
+ dealloc x
+ To
+ addi z, y, #+#
+ }
+ if (taicpu(p).ops=3) and
+ (taicpu(p).oper[2]^.typ=top_const) and
+ GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+ (hp1.typ=ait_instruction) and
+ (taicpu(hp1).opcode=A_ADDI) and
+ (taicpu(hp1).ops=3) and
+ (taicpu(p).oper[2]^.typ=top_const) and
+ is_imm12(taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val) and
+ (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
+ RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
+ begin
+ taicpu(hp1).loadreg(1,taicpu(p).oper[1]^.reg);
+ taicpu(hp1).loadconst(2, taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val);
+
+ DebugMsg('Peephole AddiAddi2Addi performed', hp1);
+
+ GetNextInstruction(p,hp1);
+ AsmL.Remove(p);
+ p.Free;
+ p:=hp1;
+
+ result:=true;
+ end
+ {
+ Changes
+ addi x, x, (ref)
+ ld/sd y, 0(x)
+ dealloc x
+ To
+ ld/sd y, 0(ref)(x)
+ }
+ else if (taicpu(p).ops=3) and
+ (taicpu(p).oper[2]^.typ=top_ref) and
+ (taicpu(p).oper[0]^.reg=taicpu(p).oper[1]^.reg) and
+ GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+ (hp1.typ=ait_instruction) and
+ (taicpu(hp1).opcode in [A_LB,A_LBU,A_LH,A_LHU,A_LW,A_LWU,A_LD,
+ A_SB,A_SH,A_SW,A_SD]) and
+ (taicpu(hp1).ops=2) and
+ (taicpu(hp1).oper[1]^.typ=top_ref) and
+ (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
+ (taicpu(hp1).oper[1]^.ref^.offset=0) and
+ (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
+ RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
+ begin
+ taicpu(hp1).loadref(1,taicpu(p).oper[2]^.ref^);
+ taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[0]^.reg;
+
+ DebugMsg('Peephole AddiMem2Mem performed', hp1);
+
+ GetNextInstruction(p,hp1);
+ AsmL.Remove(p);
+ p.Free;
+ p:=hp1;
+
+ result:=true;
+ end;
+ end;
+ A_ANDI:
+ begin
+
+ end;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ casmoptimizer := TCpuAsmOptimizer;
+end.
diff --git a/riscv_new/compiler/riscv64/aoptcpub.pas b/riscv_new/compiler/riscv64/aoptcpub.pas
new file mode 100644
index 0000000000..da6587c061
--- /dev/null
+++ b/riscv_new/compiler/riscv64/aoptcpub.pas
@@ -0,0 +1,116 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the RiscV64 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+****************************************************************************
+}
+unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$I fpcdefs.inc}
+
+{ enable the following define if memory references can have a scaled index }
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+{ define RefsHaveSegment}
+
+interface
+
+uses
+ aasmcpu, AOptBase, cpubase;
+
+type
+
+ { type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+ { ************************************************************************* }
+ { **************************** TCondRegs ********************************** }
+ { ************************************************************************* }
+ { Info about the conditional registers }
+ TCondRegs = object
+ constructor Init;
+ destructor Done;
+ end;
+
+ { ************************************************************************* }
+ { **************************** TAoptBaseCpu ******************************* }
+ { ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ end;
+
+ { ************************************************************************* }
+ { ******************************* Constants ******************************* }
+ { ************************************************************************* }
+const
+
+ { the maximum number of things (registers, memory, ...) a single instruction }
+ { changes }
+
+ MaxCh = 3;
+
+ { the maximum number of operands an instruction has }
+
+ MaxOps = 5;
+
+ {Oper index of operand that contains the source (reference) with a load }
+ {instruction }
+
+ LoadSrc = 1;
+
+ {Oper index of operand that contains the destination (register) with a load }
+ {instruction }
+
+ LoadDst = 0;
+
+ {Oper index of operand that contains the source (register) with a store }
+ {instruction }
+
+ StoreSrc = 0;
+
+ {Oper index of operand that contains the destination (reference) with a load }
+ {instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_JAL;
+ aopt_condjmp = A_Bxx;
+
+implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+
+constructor TCondRegs.init;
+begin
+end;
+
+destructor TCondRegs.Done;
+{$IFDEF inl}inline;
+{$ENDIF inl}
+begin
+end;
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/aoptcpuc.pas b/riscv_new/compiler/riscv64/aoptcpuc.pas
new file mode 100644
index 0000000000..e002fedb21
--- /dev/null
+++ b/riscv_new/compiler/riscv64/aoptcpuc.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+****************************************************************************
+}
+unit aoptcpuc;
+
+interface
+
+{$I fpcdefs.inc}
+
+uses
+ AOptCs;
+
+type
+ TRegInfoCpu = object(TRegInfo)
+ end;
+
+implementation
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/aoptcpud.pas b/riscv_new/compiler/riscv64/aoptcpud.pas
new file mode 100644
index 0000000000..5e6e7fc308
--- /dev/null
+++ b/riscv_new/compiler/riscv64/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcpud;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ AOptDA;
+
+type
+ TAOptDFACpu = class(TAOptDFA)
+ end;
+
+implementation
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/cgcpu.pas b/riscv_new/compiler/riscv64/cgcpu.pas
new file mode 100644
index 0000000000..88b4dd10ee
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cgcpu.pas
@@ -0,0 +1,477 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the RiscV64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype, symtype, symdef, symsym,
+ cgbase, cgobj,cgrv,
+ aasmbase, aasmcpu, aasmtai,aasmdata,
+ cpubase, cpuinfo, cgutils, rgcpu,
+ parabase;
+
+ type
+ tcgrv64 = class(tcgrv)
+ procedure init_register_allocators; override;
+ procedure done_register_allocators; override;
+
+ { move instructions }
+ procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister); override;
+
+ procedure g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef); override;
+
+ procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean); override;
+ procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean); override;
+
+ procedure g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
+ procedure g_concatcopy(list: TAsmList; const source, dest: treference; len: aint); override;
+ end;
+
+ procedure create_codegen;
+
+implementation
+
+ uses
+ sysutils, cclasses,
+ globals, verbose, systems, cutils,
+ symconst, fmodule, symtable,
+ rgobj, tgobj, cpupi, procinfo, paramgr, cpupara;
+
+
+ procedure tcgrv64.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_X10,RS_X11,RS_X12,RS_X13,RS_X14,RS_X15,RS_X16,RS_X17,
+ RS_X31,RS_X30,RS_X29,RS_X28,
+ RS_X5,RS_X6,RS_X7,
+ RS_X3,RS_X4,
+ RS_X9,RS_X27,RS_X26,RS_X25,RS_X24,RS_X23,RS_X22,
+ RS_X21,RS_X20,RS_X19,RS_X18],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,RS_F16,RS_F17,
+ RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
+ RS_F28,RS_F29,RS_F30,RS_F31,
+ RS_F8,RS_F9,
+ RS_F27,
+ RS_F26,RS_F25,RS_F24,RS_F23,RS_F22,RS_F21,RS_F20,RS_F19,RS_F18],first_fpu_imreg,[]);
+ end;
+
+
+ procedure tcgrv64.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure tcgrv64.a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+ var
+ ai: taicpu;
+ begin
+ if (fromsize=tosize) or
+ ((tcgsize2unsigned[fromsize]=tcgsize2unsigned[tosize]) and
+ (tcgsize2unsigned[fromsize]=OS_64)) then
+ begin
+ ai:=taicpu.op_reg_reg_const(A_ADDI,reg2,reg1,0);
+ list.concat(ai);
+ rg[R_INTREGISTER].add_move_instruction(ai);
+ end
+ else if (fromsize=OS_S32) then
+ list.Concat(taicpu.op_reg_reg_const(A_ADDIW,reg2,reg1,0))
+ else if (fromsize=OS_8) then
+ list.Concat(taicpu.op_reg_reg_const(A_ANDI,reg2,reg1,$FF))
+ else
+ begin
+ if tcgsize2size[tosize]<tcgsize2size[fromsize] then
+ fromsize:=tosize;
+
+ if tcgsize2unsigned[fromsize]<>OS_64 then
+ list.Concat(taicpu.op_reg_reg_const(A_SLLI,reg2,reg1,8*(8-tcgsize2size[fromsize])))
+ else
+ a_load_reg_reg(list,fromsize,fromsize,reg1,reg2);
+
+ if tcgsize2unsigned[fromsize]=fromsize then
+ list.Concat(taicpu.op_reg_reg_const(A_SRLI,reg2,reg2,8*(8-tcgsize2size[fromsize])))
+ else
+ list.Concat(taicpu.op_reg_reg_const(A_SRAI,reg2,reg2,8*(8-tcgsize2size[fromsize])));
+ end;
+ end;
+
+ procedure tcgrv64.a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; register: tregister);
+ var
+ l: TAsmLabel;
+ hr: treference;
+ begin
+ if a=0 then
+ a_load_reg_reg(list,size,size,NR_X0,register)
+ else
+ begin
+ if is_imm12(a) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,register,NR_X0,a))
+ else if is_lui_imm(a) then
+ list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF))
+ else if sarlongint(a shl 32,32)=a then
+ begin
+ if (a and $800)<>0 then
+ list.concat(taicpu.op_reg_const(A_LUI,register,((a shr 12)+1) and $FFFFF))
+ else
+ list.concat(taicpu.op_reg_const(A_LUI,register,(a shr 12) and $FFFFF));
+
+ list.concat(taicpu.op_reg_reg_const(A_ADDIW,register,register,SarSmallint(a shl 4,4)));
+ end
+ else
+ begin
+ reference_reset(hr,4,[]);
+
+ current_asmdata.getjumplabel(l);
+ current_procinfo.aktlocaldata.Concat(cai_align.Create(8));
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ hr.symboldata:=current_procinfo.aktlocaldata.last;
+ current_procinfo.aktlocaldata.concat(tai_const.Create_64bit(a));
+
+ hr.symbol:=l;
+ hr.refaddr:=addr_pcrel_hi20;
+
+ current_asmdata.getjumplabel(l);
+ a_label(list,l);
+
+ list.concat(taicpu.op_reg_ref(A_AUIPC,register,hr));
+
+ reference_reset_symbol(hr,l,0,0,[]);
+ hr.refaddr:=addr_pcrel_lo12;
+ hr.base:=register;
+ list.concat(taicpu.op_reg_ref(A_LD,register,hr));
+ end;
+ end;
+ end;
+
+
+ procedure tcgrv64.g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef);
+ begin
+ end;
+
+
+ procedure tcgrv64.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
+ var
+ regs, fregs: tcpuregisterset;
+ r: TSuperRegister;
+ href: treference;
+ stackcount: longint;
+ begin
+ if not(nostackframe) then
+ begin
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ a_reg_alloc(list,NR_FRAME_POINTER_REG);
+
+ reference_reset_base(href,NR_STACK_POINTER_REG,-8,ctempposinvalid,0,[]);
+
+ { Int registers }
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
+
+ if (pi_do_call in current_procinfo.flags) then
+ regs:=regs+[RS_RETURN_ADDRESS_REG];
+
+ stackcount:=0;
+ for r:=RS_X0 to RS_X31 do
+ if r in regs then
+ inc(stackcount,8);
+
+ { Float registers }
+ fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F31 do
+ if r in fregs then
+ inc(stackcount,8);
+
+ inc(localsize,stackcount);
+ if not is_imm12(-localsize) then
+ begin
+ if not (RS_RETURN_ADDRESS_REG in regs) then
+ begin
+ include(regs,RS_RETURN_ADDRESS_REG);
+ inc(localsize,8);
+ end;
+ end;
+
+ stackcount:=0;
+ for r:=RS_X0 to RS_X31 do
+ if r in regs then
+ begin
+ list.concat(taicpu.op_reg_ref(A_SD,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
+ dec(href.offset,8);
+ end;
+
+ { Float registers }
+ for r:=RS_F0 to RS_F31 do
+ if r in fregs then
+ begin
+ list.concat(taicpu.op_reg_ref(A_FSD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
+ dec(href.offset,8);
+ end;
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,0));
+
+ if localsize>0 then
+ begin
+ localsize:=align(localsize,8);
+
+ if is_imm12(-localsize) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize))
+ else
+ begin
+ a_load_const_reg(list,OS_INT,localsize,NR_RETURN_ADDRESS_REG);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_RETURN_ADDRESS_REG));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcgrv64.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
+ var
+ r: tsuperregister;
+ regs, fregs: tcpuregisterset;
+ stackcount, localsize: longint;
+ href: treference;
+ begin
+ if not(nostackframe) then
+ begin
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_RETURN_ADDRESS_REG];
+
+ if (pi_do_call in current_procinfo.flags) then
+ regs:=regs+[RS_RETURN_ADDRESS_REG];
+
+ stackcount:=0;
+ reference_reset_base(href,NR_STACK_POINTER_REG,-8,ctempposinvalid,0,[]);
+ for r:=RS_X31 downto RS_X0 do
+ if r in regs then
+ dec(href.offset,8);
+
+ { Float registers }
+ fregs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F31 do
+ if r in fregs then
+ dec(stackcount,8);
+
+ localsize:=current_procinfo.calc_stackframe_size+(-href.offset-8);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG,0))
+ else if localsize>0 then
+ begin
+ localsize:=align(localsize,8);
+
+ if is_imm12(localsize) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize))
+ else
+ begin
+ if not (RS_RETURN_ADDRESS_REG in regs) then
+ begin
+ include(regs,RS_RETURN_ADDRESS_REG);
+ dec(href.offset,8);
+ inc(localsize,8);
+ end;
+
+ a_load_const_reg(list,OS_INT,localsize,NR_RETURN_ADDRESS_REG);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_RETURN_ADDRESS_REG));
+ end;
+ end;
+
+ { Float registers }
+ for r:=RS_F31 downto RS_F0 do
+ if r in fregs then
+ begin
+ inc(href.offset,8);
+ list.concat(taicpu.op_reg_ref(A_FLD,newreg(R_FPUREGISTER,r,R_SUBWHOLE),href));
+ end;
+
+ for r:=RS_X31 downto RS_X0 do
+ if r in regs then
+ begin
+ inc(href.offset,8);
+ list.concat(taicpu.op_reg_ref(A_LD,newreg(R_INTREGISTER,r,R_SUBWHOLE),href));
+ inc(stackcount);
+ end;
+ end;
+
+ list.concat(taicpu.op_reg_reg(A_JALR,NR_X0,NR_RETURN_ADDRESS_REG));
+ end;
+
+
+ procedure tcgrv64.g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
+ var
+ paraloc1, paraloc2, paraloc3: TCGPara;
+ pd: tprocdef;
+ begin
+ pd:=search_system_proc('MOVE');
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(list, pd, 1, paraloc1);
+ paramanager.getintparaloc(list, pd, 2, paraloc2);
+ paramanager.getintparaloc(list, pd, 3, paraloc3);
+ a_load_const_cgpara(list, OS_SINT, len, paraloc3);
+ a_loadaddr_ref_cgpara(list, dest, paraloc2);
+ a_loadaddr_ref_cgpara(list, Source, paraloc1);
+ paramanager.freecgpara(list, paraloc3);
+ paramanager.freecgpara(list, paraloc2);
+ paramanager.freecgpara(list, paraloc1);
+ alloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
+ alloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
+ a_call_name(list, 'FPC_MOVE', false);
+ dealloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+ procedure tcgrv64.g_concatcopy(list: TAsmList; const source, dest: treference; len: aint);
+ var
+ tmpreg1, hreg, countreg: TRegister;
+ src, dst, src2, dst2: TReference;
+ lab: tasmlabel;
+ Count, count2: aint;
+
+ function reference_is_reusable(const ref: treference): boolean;
+ begin
+ result:=(ref.base<>NR_NO) and (ref.index=NR_NO) and
+ (ref.symbol=nil) and
+ is_imm12(ref.offset);
+ end;
+
+ begin
+ src2:=source;
+ fixref(list,src2);
+
+ dst2:=dest;
+ fixref(list,dst2);
+
+ if len > high(longint) then
+ internalerror(2002072704);
+ { A call (to FPC_MOVE) requires the outgoing parameter area to be properly
+ allocated on stack. This can only be done before tmipsprocinfo.set_first_temp_offset,
+ i.e. before secondpass. Other internal procedures request correct stack frame
+ by setting pi_do_call during firstpass, but for this particular one it is impossible.
+ Therefore, if the current procedure is a leaf one, we have to leave it that way. }
+
+ { anybody wants to determine a good value here :)? }
+ if (len > 100) and
+ assigned(current_procinfo) and
+ (pi_do_call in current_procinfo.flags) then
+ g_concatcopy_move(list, src2, dst2, len)
+ else
+ begin
+ Count := len div 4;
+ if (count<=4) and reference_is_reusable(src2) then
+ src:=src2
+ else
+ begin
+ reference_reset(src,sizeof(aint),[]);
+ { load the address of src2 into src.base }
+ src.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, src2, src.base);
+ end;
+ if (count<=4) and reference_is_reusable(dst2) then
+ dst:=dst2
+ else
+ begin
+ reference_reset(dst,sizeof(aint),[]);
+ { load the address of dst2 into dst.base }
+ dst.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, dst2, dst.base);
+ end;
+ { generate a loop }
+ if Count > 4 then
+ begin
+ countreg := GetIntRegister(list, OS_INT);
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, Count, countreg);
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, src.base, src.base, 4));
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, dst.base, dst.base, 4));
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, countreg, countreg, -1));
+ a_cmp_reg_reg_label(list,OS_INT,OC_GT,NR_X0,countreg,lab);
+ len := len mod 4;
+ end;
+ { unrolled loop }
+ Count := len div 4;
+ if Count > 0 then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ for count2 := 1 to Count do
+ begin
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
+ Inc(src.offset, 4);
+ Inc(dst.offset, 4);
+ end;
+ len := len mod 4;
+ end;
+ if (len and 4) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_32, OS_32, src, hreg);
+ a_load_reg_ref(list, OS_32, OS_32, hreg, dst);
+ Inc(src.offset, 4);
+ Inc(dst.offset, 4);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_16, OS_16, src, hreg);
+ a_load_reg_ref(list, OS_16, OS_16, hreg, dst);
+ Inc(src.offset, 2);
+ Inc(dst.offset, 2);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_8, OS_8, src, hreg);
+ a_load_reg_ref(list, OS_8, OS_8, hreg, dst);
+ end;
+ end;
+ end;
+
+procedure create_codegen;
+begin
+ cg := tcgrv64.create;
+ cg128:=tcg128.create;
+end;
+
+end.
diff --git a/riscv_new/compiler/riscv64/cpubase.pas b/riscv_new/compiler/riscv64/cpubase.pas
new file mode 100644
index 0000000000..6bc19044de
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cpubase.pas
@@ -0,0 +1,436 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the RiscV64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This Unit contains the base types for the RiscV64
+}
+unit cpubase;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ strings, globtype,
+ cutils, cclasses, aasmbase, cpuinfo, cgbase;
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+type
+ TAsmOp=(A_None,
+ A_NOP,
+ { normal opcodes }
+ A_LUI,A_AUIPC,A_JAL,A_JALR,
+ A_Bxx,A_LB,A_LH,A_LW,A_LBU,A_LHU,
+ A_SB,A_SH,A_SW,
+ A_ADDI,A_SLTI,A_SLTIU,
+ A_XORI,A_ORI,A_ANDI,
+ A_SLLI,A_SRLI,A_SRAI,
+ A_ADD,A_SUB,A_SLL,A_SLT,A_SLTU,
+ A_XOR,A_SRL,A_SRA,A_OR,A_AND,
+ A_FENCE,A_FENCE_I,
+ A_ECALL,A_EBREAK,
+ A_CSRRW,A_CSRRS,A_CSRRC,A_CSRRWI,A_CSRRSI,A_CSRRCI,
+ { 64-bit }
+ A_ADDIW,A_SLLIW,A_SRLIW,A_SRAIW,
+ A_ADDW,A_SLLW,A_SRLW,A_SUBW,A_SRAW,
+ A_LD,A_SD,A_LWU,
+
+ { M-extension }
+ A_MUL,A_MULH,A_MULHSU,A_MULHU,
+ A_DIV,A_DIVU,A_REM,A_REMU,
+ { 64-bit }
+ A_MULW,
+ A_DIVW,A_DIVUW,A_REMW,A_REMUW,
+
+ { A-extension }
+ A_LR_W,A_SC_W,A_AMOSWAP_W,A_AMOADD_W,A_AMOXOR_W,A_AMOAND_W,
+ A_AMOOR_W,A_AMOMIN_W,A_AMOMAX_W,A_AMOMINU_W,A_AMOMAXU_W,
+ { 64-bit }
+ A_LR_D,A_SC_D,A_AMOSWAP_D,A_AMOADD_D,A_AMOXOR_D,A_AMOAND_D,
+ A_AMOOR_D,A_AMOMIN_D,A_AMOMAX_D,A_AMOMINU_D,A_AMOMAXU_D,
+
+ { F-extension }
+ A_FLW,A_FSW,
+ A_FMADD_S,A_FMSUB_S,A_FNMSUB_S,A_FNMADD_S,
+ A_FADD_S,A_FSUB_S,A_FMUL_S,A_FDIV_S,
+ A_FSQRT_S,A_FSGNJ_S,A_FSGNJN_S,A_FSGNJX_S,
+ A_FMIN_S,A_FMAX_S,
+ A_FMV_X_S,A_FEQ_S,A_FLT_S,A_FLE_S,A_FCLASS_S,
+ A_FCVT_W_S,A_FCVT_WU_S,A_FCVT_S_W,A_FCVT_S_WU,
+ A_FMV_S_X,
+ A_FRCSR,A_FRRM,A_FRFLAGS,A_FSCSR,A_FSRM,
+ A_FSFLAGS,A_FSRMI,A_FSFLAGSI,
+ { 64-bit }
+ A_FCVT_L_S,A_FCVT_LU_S,
+ A_FCVT_S_L,A_FCVT_S_LU,
+
+ { D-extension }
+ A_FLD,A_FSD,
+ A_FMADD_D,A_FMSUB_D,A_FNMSUB_D,A_FNMADD_D,
+ A_FADD_D,A_FSUB_D,A_FMUL_D,A_FDIV_D,
+ A_FSQRT_D,A_FSGNJ_D,A_FSGNJN_D,A_FSGNJX_D,
+ A_FMIN_D,A_FMAX_D,
+ A_FEQ_D,A_FLT_D,A_FLE_D,A_FCLASS_D,
+ A_FCVT_D_S,A_FCVT_S_D,
+ A_FCVT_W_D,A_FCVT_WU_D,A_FCVT_D_W,A_FCVT_D_WU,
+ { 64-bit }
+ A_FCVT_L_D,A_FCVT_LU_D,A_FMV_X_D,
+ A_FCVT_D_L,A_FCVT_D_LU,A_FMV_D_X,
+
+ { Machine mode }
+ A_MRET,A_HRET,A_SRET,A_URET,
+ A_WFI,
+
+ { Supervisor }
+ A_SFENCE_VM
+ );
+
+ {# This should define the array of instructions as string }
+ op2strtable = array[tasmop] of string[8];
+
+const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+ {*****************************************************************************
+ Registers
+ *****************************************************************************}
+
+type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rrv32nor.inc}-1;
+ totherregisterset = set of tregisterindex;
+
+ const
+ maxvarregs = 32-6; { 32 int registers - r0 - stackpointer - r2 - 3 scratch registers }
+ maxfpuvarregs = 28; { 32 fpuregisters - some scratch registers (minimally 2) }
+ { Available Superregisters }
+ {$i rrv32sup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE=R_SUBNONE;
+
+ { Available Registers }
+ {$i rrv32con.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_imreg = $20;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rrv32num.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rrv32sta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rrv32dwa.inc}
+ );
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond = (C_None { unconditional jumps },
+ C_LT,C_LTU,C_GE,C_GEU,C_NE,C_EQ);
+
+ const
+ cond2str: Array[TAsmCond] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'lt','ltu','ge','geu','ne','eq');
+
+ uppercond2str: Array[TAsmCond] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'LT','LTU','GE','GEU','NE','EQ');
+
+ {*****************************************************************************
+ Flags
+ *****************************************************************************}
+
+type
+ TResFlagsEnum = (F_EQ,F_NE,F_LT,F_LTU,F_GE,F_GEU);
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ {*****************************************************************************
+ Operand Sizes
+ *****************************************************************************}
+
+ {*****************************************************************************
+ Constants
+ *****************************************************************************}
+
+const
+ max_operands = 5;
+
+ {*****************************************************************************
+ Default generic sizes
+ *****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ {# the natural int size for a processor,
+ has to match osuinttype/ossinttype as initialized in psystem }
+ OS_INT = OS_64;
+ OS_SINT = OS_S64;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+ {*****************************************************************************
+ GDB Information
+ *****************************************************************************}
+
+ stab_regindex: array[tregisterindex] of shortint = (
+{$I rrv32sta.inc}
+ );
+
+ {*****************************************************************************
+ Generic Register names
+ *****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_X2;
+ RS_STACK_POINTER_REG = RS_X2;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_X8;
+ RS_FRAME_POINTER_REG = RS_X8;
+
+ NR_PIC_OFFSET_REG = NR_X3;
+ { Return address of a function }
+ NR_RETURN_ADDRESS_REG = NR_X1;
+ RS_RETURN_ADDRESS_REG = RS_X1;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_X10;
+ RS_FUNCTION_RETURN_REG = RS_X10;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_X10;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_X10;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_X11;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_X11;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_F10;
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_DEFAULTFLAGS = NR_NO;
+ RS_DEFAULTFLAGS = RS_NO;
+
+ {*****************************************************************************
+ GCC /ABI linking information
+ *****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers: array[0..12] of tsuperregister = (
+ RS_X2,
+ RS_X8,RS_X9,
+ RS_X18,RS_X19,
+ RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27
+ );
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ maxfpuregs = 8;
+
+ {*****************************************************************************
+ Helpers
+ *****************************************************************************}
+
+ function is_imm12(value: aint): boolean;
+ function is_lui_imm(value: aint): boolean;
+
+ function is_calljmp(o:tasmop):boolean;
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function dwarf_reg(r:tregister):shortint;
+
+ function conditions_equal(const c1,c2: TAsmCond): boolean;
+
+implementation
+
+ uses
+ rgbase,verbose;
+
+ const
+ std_regname_table : TRegNameTable = (
+ {$i rrv32std.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rrv32rni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rrv32sri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_imm12(value: aint): boolean;
+ begin
+ result:=(value >= -2048) and (value <= 2047);
+ end;
+
+
+ function is_lui_imm(value: aint): boolean;
+ begin
+ result:=SarInt64((value and $FFFFF000) shl 32, 32) = value;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp:=false;
+ case o of
+ A_JAL,A_JALR,A_Bxx:
+ is_calljmp:=true;
+ end;
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inv_condflags:array[TAsmCond] of TAsmCond=(C_None,
+ C_GE,C_GEU,C_LT,C_LTU,C_EQ,C_NE);
+ begin
+ result := inv_condflags[c];
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ result:=OS_32;
+ R_MMREGISTER:
+ result:=OS_M128;
+ R_FPUREGISTER:
+ result:=OS_F64;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean;
+ begin
+ result:=c1=c2;
+ end;
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/cpuinfo.pas b/riscv_new/compiler/riscv64/cpuinfo.pas
new file mode 100644
index 0000000000..0c3f2b1124
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cpuinfo.pas
@@ -0,0 +1,136 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the Risc-V64
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit CPUInfo;
+
+interface
+
+uses
+ globtype;
+
+type
+ bestreal = double;
+{$if FPC_FULLVERSION>20700}
+ bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = extended;
+ ts64comp = comp;
+
+ pbestreal = ^bestreal;
+
+ { possible supported processors for this target }
+ tcputype = (cpu_none,
+ cpu_rv64imafd,
+ cpu_rv64ima,
+ cpu_rv64im,
+ cpu_rv64i
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_libgcc,
+ fpu_soft,
+ fpu_fd
+ );
+
+ tcontrollertype =
+ (ct_none
+ );
+
+ tcontrollerdatatype = record
+ controllertypestr, controllerunitstr: string[20];
+ cputype: tcputype; fputype: tfputype;
+ flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize, bootbase, bootsize: dword;
+ end;
+
+
+Const
+ { Is there support for dealing with multiple microcontrollers available }
+ { for this platform? }
+ ControllerSupport = false;
+
+ { We know that there are fields after sramsize
+ but we don't care about this warning }
+ {$PUSH}
+ {$WARN 3177 OFF}
+ embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
+ (
+ (controllertypestr:''; controllerunitstr:''; cputype:cpu_none; fputype:fpu_none; flashbase:0; flashsize:0; srambase:0; sramsize:0));
+ {$POP}
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions: tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { the difference with stdcall is that all const record
+ parameters are passed by reference }
+ pocall_mwpascal
+ ];
+
+ cputypestr: array[tcputype] of string[10] = ('',
+ 'RV64IMAFD',
+ 'RV64IMA',
+ 'RV64IM',
+ 'RV64I'
+ );
+
+ fputypestr: array[tfputype] of string[8] = ('',
+ 'LIBGCC',
+ 'SOFT',
+ 'FD'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,
+ cs_opt_tailrecursion,cs_opt_reorder_fields,cs_opt_fastmath,
+ cs_opt_stackframe];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse,cs_opt_tailrecursion];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+ level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [cs_opt_stackframe];
+
+ type
+ tcpuflags =
+ (CPURV_HAS_MUL,
+ CPURV_HAS_ATOMIC,
+ CPURV_HAS_COMPACT
+ );
+
+ const
+ cpu_capabilities : array[tcputype] of set of tcpuflags =
+ ( { cpu_none } [],
+ { cpu_rv64imafd } [CPURV_HAS_MUL,CPURV_HAS_ATOMIC],
+ { cpu_rv64ima } [CPURV_HAS_MUL,CPURV_HAS_ATOMIC],
+ { cpu_rv64im } [CPURV_HAS_MUL],
+ { cpu_rv64i } []
+ );
+
+implementation
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/cpunode.pas b/riscv_new/compiler/riscv64/cpunode.pas
new file mode 100644
index 0000000000..f9f680bf91
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cpunode.pas
@@ -0,0 +1,54 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the RiscV64 code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$I fpcdefs.inc}
+
+interface
+
+implementation
+
+uses
+ { generic nodes }
+ ncgbas, ncgld, ncgflw, ncgcnv, ncgmem, ncgcon, ncgcal, ncgset, ncginl, ncgopt,
+ ncgobjc,
+ { symtable }
+ symcpu,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+{$ifndef llvm}
+ nrv64add,
+ nrv64cal,
+ nrvset,
+ nrvinl,
+ nrv64mat,
+ nrv64cnv,
+ nrv64ld
+{$else not llvm}
+ llvmnode
+{$endif not llvm}
+ ;
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/cpupara.pas b/riscv_new/compiler/riscv64/cpupara.pas
new file mode 100644
index 0000000000..4c85ae9861
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cpupara.pas
@@ -0,0 +1,593 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ RiscV64 specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit cpupara;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,aasmdata,
+ cpubase,
+ symconst, symtype, symdef, symsym,
+ paramgr, parabase, cgbase, cgutils;
+
+ type
+ tcpuparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
+ function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
+ function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
+ function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
+
+ procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
+ function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
+ function create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist): longint; override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
+
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;
+ function parseparaloc(p: tparavarsym; const s: string): boolean; override;
+ procedure create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
+ end;
+
+implementation
+
+ uses
+ verbose, systems,
+ globals, cpuinfo,
+ defutil,symtable,symcpu,
+ procinfo, cpupi;
+
+ function tcpuparamanager.get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset;
+ begin
+ result:=[RS_X0..RS_X31]-[RS_X2,RS_X8..RS_X9,RS_X18..RS_X27];
+ end;
+
+ function tcpuparamanager.get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset;
+ begin
+ result:=[RS_F0..RS_F31]-[RS_F8..RS_F9,RS_F18..RS_F27];
+ end;
+
+ procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
+ var
+ paraloc: pcgparalocation;
+ psym: tparavarsym;
+ pdef: tdef;
+ begin
+ psym:=tparavarsym(pd.paras[nr-1]);
+ pdef:=psym.vardef;
+ if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+ pdef:=cpointerdef.getreusable_no_free(pdef);
+ cgpara.reset;
+ cgpara.size := def_cgsize(pdef);
+ cgpara.intsize := tcgsize2size[cgpara.size];
+ cgpara.alignment := get_para_align(pd.proccalloption);
+ cgpara.def:=pdef;
+ paraloc := cgpara.add_location;
+ with paraloc^ do begin
+ size := def_cgsize(pdef);
+ def := pdef;
+ if (nr <= 8) then begin
+ if (nr = 0) then
+ internalerror(200309271);
+ loc := LOC_REGISTER;
+ register := newreg(R_INTREGISTER, RS_X10 + nr-1, R_SUBWHOLE);
+ end else begin
+ loc := LOC_REFERENCE;
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ reference.offset := sizeof(aint) * (nr - 9);
+ end;
+ end;
+ end;
+
+ function getparaloc(p: tdef): tcgloc;
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ result := LOC_REGISTER;
+ floatdef:
+ if (cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_soft]) then
+ result := LOC_REGISTER
+ else
+ result := LOC_FPUREGISTER;
+ enumdef:
+ result := LOC_REGISTER;
+ pointerdef:
+ result := LOC_REGISTER;
+ formaldef:
+ result := LOC_REGISTER;
+ classrefdef:
+ result := LOC_REGISTER;
+ procvardef,
+ recorddef:
+ result := LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ filedef:
+ result := LOC_REGISTER;
+ arraydef:
+ if is_dynamic_array(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ result := LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result := LOC_REGISTER
+ else
+ result := LOC_REFERENCE;
+ variantdef:
+ result := LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result := LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+ function tcpuparamanager.push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
+ begin
+ result := false;
+ { var,out,constref always require address }
+ if varspez in [vs_var, vs_out, vs_constref] then
+ begin
+ result := true;
+ exit;
+ end;
+ case def.typ of
+ variantdef,
+ formaldef:
+ result := true;
+ procvardef,
+ recorddef:
+ result :=
+ (varspez = vs_const) and
+ (
+ (
+ (not (calloption in [pocall_cdecl, pocall_cppdecl]) and
+ (def.size > 8))
+ ) or
+ (calloption = pocall_mwpascal)
+ );
+ arraydef:
+ result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef:
+ result := is_object(def);
+ setdef:
+ result := not is_smallset(def);
+ stringdef:
+ result := tstringdef(def).stringtype in [st_shortstring, st_longstring];
+ end;
+ end;
+
+ function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
+ var
+ tmpdef: tdef;
+ begin
+ if handle_common_ret_in_param(def,pd,result) then
+ exit;
+
+ { general rule: passed in registers -> returned in registers }
+ result:=push_addr_param(vs_value,def,pd.proccalloption);
+
+ case def.typ of
+ procvardef:
+ result:=def.size>8;
+ recorddef:
+ result:=true;
+ end;
+ end;
+
+ procedure tcpuparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ { register parameter save area begins at 48(r2) }
+ cur_stack_offset := 0;
+ curintreg := RS_X10;
+ curfloatreg := RS_F10;
+ curmmreg := RS_NO;
+ end;
+
+ function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+ var
+ paraloc: pcgparalocation;
+ retcgsize: tcgsize;
+ nextfloatreg, nextintreg, nextmmreg: tsuperregister;
+ stack_offset: aword;
+ begin
+ if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
+ exit;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if result.def.typ=floatdef then
+ begin
+ if (p.proccalloption in [pocall_softfloat]) or
+ (cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_soft]) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ paraloc^.size:=retcgsize;
+ paraloc^.def:=result.def;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ paraloc^.def:=result.def;
+ end;
+ end
+ else
+ { Return in register }
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ paraloc^.size:=retcgsize;
+ paraloc^.def:=result.def;
+ end;
+ end;
+
+ function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg : tsuperregister;
+ begin
+ init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
+
+ result := create_paraloc_info_intern(p, side, p.paras, curintreg, curfloatreg, curmmreg, cur_stack_offset, false);
+
+ create_funcretloc_info(p, side);
+ end;
+
+ function tcpuparamanager.create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;
+ var
+ nextintreg, nextfloatreg, nextmmreg : tsuperregister;
+ i: integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+ delphi_nestedfp: boolean;
+
+ begin
+{$IFDEF extdebug}
+ if po_explicitparaloc in p.procoptions then
+ internalerror(200411141);
+{$ENDIF extdebug}
+
+ result := 0;
+ nextintreg := curintreg;
+ nextfloatreg := curfloatreg;
+ nextmmreg := curmmreg;
+
+ for i := 0 to paras.count - 1 do begin
+ hp := tparavarsym(paras[i]);
+
+ if (vo_has_explicit_paraloc in hp.varoptions) then begin
+ internalerror(200412153);
+ end;
+
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) and
+ is_array_of_const(hp.vardef) then begin
+ paraloc := hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc := LOC_REGISTER;
+ paraloc^.register := NR_X0;
+ paraloc^.size := OS_ADDR;
+ paraloc^.def := voidpointertype;
+ break;
+ end;
+ delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
+ create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
+ nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
+ end;
+
+ curintreg := nextintreg;
+ curfloatreg := nextfloatreg;
+ curmmreg := nextmmreg;
+ result := cur_stack_offset;
+ end;
+
+ procedure tcpuparamanager.create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
+ var
+ paracgsize: tcgsize;
+ loc: tcgloc;
+ paraloc: pcgparalocation;
+ { def to use for all paralocs if <> nil }
+ alllocdef,
+ { def to use for the current paraloc }
+ locdef,
+ tmpdef: tdef;
+ paralen: aint;
+ parashift: byte;
+ tailpadding,
+ firstparaloc,
+ paraaligned: boolean;
+ begin
+ alllocdef:=nil;
+ locdef:=nil;
+ parashift := 0;
+ para.reset;
+ { should the tail be shifted into the most significant bits? }
+ tailpadding:=false;
+ { have we ensured that the next parameter location will be aligned to the
+ next 8 byte boundary? }
+ paraaligned:=false;
+ if push_addr_param(varspez, paradef, p.proccalloption) then begin
+ paradef := cpointerdef.getreusable_no_free(paradef);
+ loc := LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end else begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+
+ if (paradef.typ=recorddef) and
+ tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
+ (tmpdef.typ=floatdef) then
+ begin
+ paradef:=tmpdef;
+ loc:=getparaloc(paradef);
+ paracgsize:=def_cgsize(paradef)
+ end
+ else if (((paradef.typ=arraydef) and not
+ is_special_array(paradef)) or
+ (paradef.typ=recorddef)) then
+ begin
+ { general fallback rule: pass aggregate types in integer registers
+ without special adjustments (incl. Darwin h) }
+ loc:=LOC_REGISTER;
+ paracgsize:=int_cgsize(paralen);
+ end
+ else
+ begin
+ loc:=getparaloc(paradef);
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen:=tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+
+ { patch FPU values into integer registers if we are processing varargs }
+ if (isVararg) and (paradef.typ = floatdef) then begin
+ loc := LOC_REGISTER;
+ if paracgsize = OS_F64 then
+ paracgsize := OS_64
+ else
+ paracgsize := OS_32;
+ end;
+
+
+ para.alignment := std_param_align;
+ para.size := paracgsize;
+ para.intsize := paralen;
+ para.def := paradef;
+ if (paralen = 0) then
+ if (paradef.typ = recorddef) then begin
+ paraloc := para.add_location;
+ paraloc^.loc := LOC_VOID;
+ end else
+ internalerror(2005011310);
+ if not assigned(alllocdef) then
+ locdef:=paradef
+ else
+ begin
+ locdef:=alllocdef;
+ paracgsize:=def_cgsize(locdef);
+ end;
+ firstparaloc:=true;
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do begin
+ paraloc := para.add_location;
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_X17) and
+ not forceintmem then begin
+ paraloc^.loc := loc;
+ paraloc^.shiftval := parashift;
+
+ { make sure we don't lose whether or not the type is signed }
+ if (paracgsize <> OS_NO) and
+ (paradef.typ <> orddef) and
+ not assigned(alllocdef) then
+ begin
+ paracgsize := int_cgsize(paralen);
+ locdef:=get_paraloc_def(paradef, paralen, firstparaloc);
+ end;
+
+ { Partial aggregate data may have to be left-aligned. If so, add tail
+ padding }
+ if tailpadding and
+ (paralen < sizeof(aint)) then
+ begin
+ paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
+ paraloc^.size := OS_INT;
+ paraloc^.def := u64inttype;
+ end
+ else if (paracgsize in [OS_NO, OS_128, OS_S128]) then
+ begin
+ if (paralen>4) or
+ (parashift<>0) then
+ begin
+ paraloc^.size := OS_INT;
+ paraloc^.def := osuinttype;
+ end
+ else
+ begin
+ { for 3-byte records aligned in the lower bits of register }
+ paraloc^.size := OS_32;
+ paraloc^.def := u32inttype;
+ end;
+ end
+ else
+ begin
+ paraloc^.size := paracgsize;
+ paraloc^.def := locdef;
+ end;
+
+ paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
+ inc(nextintreg);
+ inc(nextfloatreg);
+ dec(paralen, tcgsize2size[paraloc^.size]);
+ end else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= RS_F17) then begin
+ paraloc^.loc := loc;
+ paraloc^.size := paracgsize;
+ paraloc^.def := locdef;
+ paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
+ { the RiscV ABI says that the GPR index is increased for every parameter, no matter
+ which type it is stored in }
+ inc(nextintreg);
+ inc(nextfloatreg);
+ dec(paralen, tcgsize2size[paraloc^.size]);
+ end else if (loc = LOC_MMREGISTER) then begin
+ { Altivec not supported }
+ internalerror(200510192);
+ end else begin
+ { either LOC_REFERENCE, or one of the above which must be passed on the
+ stack because of insufficient registers }
+ paraloc^.loc := LOC_REFERENCE;
+ case loc of
+ LOC_FPUREGISTER:
+ begin
+ paraloc^.size:=int_float_cgsize(paralen);
+ case paraloc^.size of
+ OS_F32: paraloc^.def:=s32floattype;
+ OS_F64: paraloc^.def:=s64floattype;
+ else
+ internalerror(2013060122);
+ end;
+ end;
+ LOC_REGISTER,
+ LOC_REFERENCE:
+ begin
+ paraloc^.size:=int_cgsize(paralen);
+ paraloc^.def:=get_paraloc_def(paradef, paralen, firstparaloc);
+ end;
+ else
+ internalerror(2006011101);
+ end;
+ if (side = callerside) then
+ paraloc^.reference.index := NR_STACK_POINTER_REG
+ else begin
+ { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
+ paraloc^.reference.index := NR_FRAME_POINTER_REG;
+ { create_paraloc_info_intern might be also called when being outside of
+ code generation so current_procinfo might be not set }
+ if assigned(current_procinfo) then
+ trv64procinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+ paraloc^.reference.offset := stack_offset;
+
+ { align temp contents to next register size }
+ if not paraaligned then
+ inc(stack_offset, align(paralen, 8))
+ else
+ inc(stack_offset, paralen);
+ paralen := 0;
+ end;
+ firstparaloc:=false;
+ end;
+ end;
+
+function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
+ varargspara: tvarargsparalist): longint;
+var
+ cur_stack_offset: aword;
+ parasize, l: longint;
+ curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+ i: integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+begin
+ init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
+ firstfloatreg := curfloatreg;
+
+ result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
+ curfloatreg, curmmreg, cur_stack_offset, false);
+ if (p.proccalloption in [pocall_cdecl, pocall_cppdecl, pocall_mwpascal]) then begin
+ { just continue loading the parameters in the registers }
+ result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
+ curfloatreg, curmmreg, cur_stack_offset, true);
+ { varargs routines have to reserve at least 64 bytes for the RiscV ABI }
+ if (result < 64) then
+ result := 64;
+ end else begin
+ parasize := cur_stack_offset;
+ for i := 0 to varargspara.count - 1 do begin
+ hp := tparavarsym(varargspara[i]);
+ hp.paraloc[callerside].alignment := 8;
+ paraloc := hp.paraloc[callerside].add_location;
+ paraloc^.loc := LOC_REFERENCE;
+ paraloc^.size := def_cgsize(hp.vardef);
+ paraloc^.def := hp.vardef;
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ l := push_size(hp.varspez, hp.vardef, p.proccalloption);
+ paraloc^.reference.offset := parasize;
+ parasize := parasize + l;
+ end;
+ result := parasize;
+ end;
+ if curfloatreg <> firstfloatreg then
+ include(varargspara.varargsinfo, va_uses_float_reg);
+end;
+
+function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
+begin
+ internalerror(200404182);
+ result := true;
+end;
+
+
+begin
+ paramanager := tcpuparamanager.create;
+end.
+
diff --git a/riscv_new/compiler/riscv64/cpupi.pas b/riscv_new/compiler/riscv64/cpupi.pas
new file mode 100644
index 0000000000..a0b3c129fb
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cpupi.pas
@@ -0,0 +1,116 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,aasmdata,
+ globtype, cgutils, cgbase,
+ procinfo, cpuinfo, psub;
+
+ type
+ trv64procinfo = class(tcgprocinfo)
+ stackframesize,
+ floatregstart : aint;
+ stackpaddingreg: TSuperRegister;
+
+ needs_frame_pointer: boolean;
+
+ constructor create(aparent: tprocinfo); override;
+ procedure set_first_temp_offset; override;
+ function calc_stackframe_size: longint; override;
+ end;
+
+implementation
+
+ uses
+ globals, systems,
+ cpubase,
+ aasmtai,
+ tgobj,cgobj,
+ symconst, symsym, paramgr, symutil, symtable,
+ verbose,
+ aasmcpu;
+
+
+ constructor trv64procinfo.create(aparent: tprocinfo);
+ begin
+ inherited create(aparent);
+ maxpushedparasize := 0;
+ end;
+
+
+ procedure trv64procinfo.set_first_temp_offset;
+ begin
+ if (po_nostackframe in procdef.procoptions) then
+ begin
+ { maxpushedparasize sghould be zero,
+ if not we will get an error later. }
+ tg.setfirsttemp(maxpushedparasize);
+ exit;
+ end;
+
+ if tg.direction = -1 then
+ tg.setfirsttemp(-(1+12)*8)
+ else
+ tg.setfirsttemp(maxpushedparasize);
+ end;
+
+
+ function trv64procinfo.calc_stackframe_size: longint;
+ var
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ floatsavesize : aword;
+ regs: tcpuregisterset;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,8));
+ floatsavesize:=0;
+ case current_settings.fputype of
+ fpu_fd:
+ begin
+ floatsavesize:=0;
+ regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F31 do
+ if r in regs then
+ inc(floatsavesize,8);
+ end;
+ end;
+ floatsavesize:=system.align(floatsavesize,max(current_settings.alignment.localalignmin,8));
+ result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,8))+maxpushedparasize+aint(floatsavesize);
+
+ if tg.direction=1 then
+ floatregstart:=result-aint(floatsavesize)
+ else
+ floatregstart:=-result+maxpushedparasize;
+ end;
+
+
+begin
+ cprocinfo := trv64procinfo;
+end.
+
diff --git a/riscv_new/compiler/riscv64/cputarg.pas b/riscv_new/compiler/riscv64/cputarg.pas
new file mode 100644
index 0000000000..6986b1f2b6
--- /dev/null
+++ b/riscv_new/compiler/riscv64/cputarg.pas
@@ -0,0 +1,85 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the RiscV64 dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETEMBEDDED}
+ ,t_embed
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGRVGAS}
+ ,agrvgas
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaRVGas}
+ ,rarv64gas
+ {$endif NoRaRVGas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgStabx}
+ ,dbgstabx
+ {$endif NoDbgStabx}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+
+{**************************************
+ Optimizer
+**************************************}
+
+ {$ifndef NOOPT}
+ , aoptcpu
+ {$endif NOOPT}
+ ;
+
+end.
diff --git a/riscv_new/compiler/riscv64/hlcgcpu.pas b/riscv_new/compiler/riscv64/hlcgcpu.pas
new file mode 100644
index 0000000000..3c0f4968f7
--- /dev/null
+++ b/riscv_new/compiler/riscv64/hlcgcpu.pas
@@ -0,0 +1,78 @@
+{
+ Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
+ Member of the Free Pascal development team
+
+ This unit contains high-level code generator support for riscv64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit hlcgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ aasmdata,
+ symtype,
+ cgbase,cgutils,hlcgobj,hlcgrv;
+
+type
+ thlcgcpu = class(thlcgriscv)
+ procedure a_load_const_subsetreg(list: TAsmlist; tosubsetsize: tdef; a: tcgint; const sreg: tsubsetregister); override;
+ end;
+
+ procedure create_hlcodegen;
+
+implementation
+
+ uses
+ cpubase,aasmcpu,
+ defutil,
+ cgobj,cgcpu;
+
+ { thlcgcpu }
+
+
+ procedure thlcgcpu.a_load_const_subsetreg(list: TAsmlist; tosubsetsize: tdef; a: tcgint; const sreg: tsubsetregister);
+ var
+ tmpreg : TRegister;
+ begin
+{$ifdef extdebug}
+ list.concat(tai_comment.create(strpnew('a_load_const_subsetreg subsetregsize = ' + cgsize2string(sreg.subsetregsize) + ' subsetsize = ' + cgsize2string(def_cgsize(subsetsize)) + ' startbit = ' + intToStr(sreg.startbit) + ' a = ' + intToStr(a))));
+{$endif}
+ { loading the constant into the lowest bits of a temp register and then inserting is
+ better than loading some usually large constants and do some masking and shifting on riscv64 }
+ tmpreg:=getintregister(list,tosubsetsize);
+ a_load_const_reg(list,tosubsetsize,a,tmpreg);
+ a_load_reg_subsetreg(list,tosubsetsize,tosubsetsize,tmpreg,sreg);
+ end;
+
+
+ procedure create_hlcodegen;
+ begin
+ hlcg:=thlcgcpu.create;
+ create_codegen;
+ end;
+
+
+
+begin
+ chlcgobj:=thlcgcpu;
+end.
diff --git a/riscv_new/compiler/riscv64/itcpugas.pas b/riscv_new/compiler/riscv64/itcpugas.pas
new file mode 100644
index 0000000000..4fabace6e8
--- /dev/null
+++ b/riscv_new/compiler/riscv64/itcpugas.pas
@@ -0,0 +1,157 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the RiscV64 GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase, cgbase;
+
+ const
+ gas_op2str: array[tasmop] of string[14] = ('<none>',
+ 'nop',
+ 'lui','auipc','jal','jalr',
+ 'b','lb','lh','lw','lbu','lhu',
+ 'sb','sh','sw',
+ 'addi','slti','sltiu',
+ 'xori','ori','andi',
+ 'slli','srli','srai',
+ 'add','sub','sll','slt','sltu',
+ 'xor','srl','sra','or','and',
+ 'fence','fence.i',
+ 'ecall','ebreak',
+ 'csrrw','csrrs','csrrc','csrrwi','csrrsi','csrrci',
+ { 64-bit }
+ 'addiw','slliw','srliw','sraiw',
+ 'addw','sllw','srlw','subw','sraw',
+ 'ld','sd','lwu',
+
+ { m-extension }
+ 'mul','mulh','mulhsu','mulhu',
+ 'div','divu','rem','remu',
+ { 64-bit }
+ 'mulw',
+ 'divw','divuw','remw','remuw',
+
+ { a-extension }
+ 'lr.w','sc.w','amoswap.w','amoadd.w','amoxor.w','amoand.w',
+ 'amoor.w','amomin.w','amomax.w','amominu.w','amomaxu.w',
+ { 64-bit }
+ 'lr.d','sc.d','amoswap.d','amoadd.d','amoxor.d','amoand.d',
+ 'amoor.d','amomin.d','amomax.d','amominu.d','amomaxu.d',
+
+ { f-extension }
+ 'flw','fsw',
+ 'fmadd.s','fmsub.s','fnmsub.s','fnmadd.s',
+ 'fadd.s','fsub.s','fmul.s','fdiv.s',
+ 'fsqrt.s','fsgnj.s','fsgnjn.s','fsgnjx.s',
+ 'fmin.s','fmax.s',
+ 'fmv.x.s','feq.s','flt.s','fle.s','fclass.s',
+ 'fcvt.w.s','fcvt.wu.s','fcvt.s.w','fcvt.s.wu',
+ 'fmv.s.x',
+ 'frcsr','frrm','frflags','fscsr','fsrm',
+ 'fsflags','fsrmi','fsflagsi',
+ { 64-bit }
+ 'fcvt.l.s','fcvt.lu.s',
+ 'fcvt.s.l','fcvt.s.lu',
+
+ { d-extension }
+ 'fld','fsd',
+ 'fmadd.d','fmsub.d','fnmsub.d','fnmadd.d',
+ 'fadd.d','fsub.d','fmul.d','fdiv.d',
+ 'fsqrt.d','fsgnj.d','fsgnjn.d','fsgnjx.d',
+ 'fmin.d','fmax.d',
+ 'feq.d','flt.d','fle.d','fclass.d',
+ 'fcvt.d.s','fcvt.s.d',
+ 'fcvt.w.d','fcvt.wu.d','fcvt.d.w','fcvt.d.wu',
+ { 64-bit }
+ 'fcvt.l.d','fcvt.lu.d','fmv.x.d',
+ 'fcvt.d.l','fcvt.d.lu','fmv.d.x',
+
+ { Machine mode }
+ 'mret','hret','sret','uret',
+ 'wfi',
+
+ { Supervisor mode }
+ 'sfence.vm'
+ );
+
+ function gas_regnum_search(const s: string): Tregister;
+ function gas_regname(r: Tregister): string;
+
+ implementation
+
+ uses
+ globtype,globals,aasmbase,
+ cutils,verbose, systems,
+ rgbase;
+
+ const
+ gas_regname_table : TRegNameTable = (
+ {$i rrv32std.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rrv32sri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/nrv64add.pas b/riscv_new/compiler/riscv64/nrv64add.pas
new file mode 100644
index 0000000000..37356772ff
--- /dev/null
+++ b/riscv_new/compiler/riscv64/nrv64add.pas
@@ -0,0 +1,98 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the Risc-V64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv64add;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ node, ncgadd, aasmbase, nrvadd, cpubase;
+
+ type
+ trv64addnode = class(trvaddnode)
+ protected
+ function pass_1: tnode; override;
+
+ procedure second_add64bit; override;
+
+ function use_generic_mul32to64: boolean; override;
+ end;
+
+ implementation
+
+ uses
+ systems,
+ cutils,verbose,
+ paramgr,procinfo,
+ aasmtai,aasmdata,aasmcpu,defutil,
+ cgbase,cgcpu,cgutils,
+ globals,
+ pass_1,
+ CPUInfo,cpupara,
+ ncon,nset,nadd,
+ symconst,
+ hlcgobj, ncgutil,cgobj;
+
+ function trv64addnode.pass_1: tnode;
+ begin
+ if (nodetype=muln) and
+ (left.resultdef.typ=orddef) and (left.resultdef.typ=orddef) and
+ (CPURV_HAS_MUL in cpu_capabilities[current_settings.cputype]) then
+ begin
+ result:=nil;
+
+ firstpass(left);
+ firstpass(right);
+
+ expectloc:=LOC_REGISTER;
+ end
+ else if (nodetype=muln) and
+ (not (CPURV_HAS_MUL in cpu_capabilities[current_settings.cputype])) and
+ (is_64bit(left.resultdef) or
+ is_64bit(right.resultdef)) then
+ begin
+ result:=first_add64bitint;
+ end
+ else
+ Result:=inherited pass_1;
+
+ if expectloc=LOC_FLAGS then
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ procedure trv64addnode.second_add64bit;
+ begin
+ second_addordinal;
+ end;
+
+
+ function trv64addnode.use_generic_mul32to64: boolean;
+ begin
+ result:=false;
+ end;
+
+begin
+ caddnode := trv64addnode;
+end.
+
diff --git a/riscv_new/compiler/riscv64/nrv64cal.pas b/riscv_new/compiler/riscv64/nrv64cal.pas
new file mode 100644
index 0000000000..7781434673
--- /dev/null
+++ b/riscv_new/compiler/riscv64/nrv64cal.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the RiscV64 specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv64cal;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ aasmdata, cgbase,
+ symdef, node, ncal, ncgcal;
+
+type
+
+ trv64callparanode = class(tcgcallparanode)
+ end;
+
+ trv64ccallnode = class(tcgcallnode)
+ end;
+
+implementation
+
+uses
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst, symbase, symsym, symtable, defutil, paramgr, parabase,
+ pass_2,
+ cpuinfo, cpubase, aasmbase, aasmtai, aasmcpu,
+ nmem, nld, ncnv,
+ ncgutil, cgutils, cgobj, tgobj, rgobj, rgcpu,
+ cgcpu, cpupi, procinfo;
+
+begin
+ ccallparanode:=trv64callparanode;
+ ccallnode := trv64ccallnode;
+end.
+
diff --git a/riscv_new/compiler/riscv64/nrv64cnv.pas b/riscv_new/compiler/riscv64/nrv64cnv.pas
new file mode 100644
index 0000000000..531b6d49f1
--- /dev/null
+++ b/riscv_new/compiler/riscv64/nrv64cnv.pas
@@ -0,0 +1,136 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate RiscV64 assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv64cnv;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ node, ncnv, ncgcnv, nrvcnv;
+
+ type
+ trv64typeconvnode = class(trvtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real; override;
+ { procedure second_real_to_real; override;}
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool; override; }
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+ implementation
+
+ uses
+ verbose, globtype, globals, systems,
+ symconst, symdef, aasmbase, aasmtai,aasmdata,
+ defutil, symcpu,
+ cgbase, cgutils, pass_1, pass_2,
+ ncon, ncal,procinfo,
+ ncgutil,
+ cpubase, aasmcpu,
+ rgobj, tgobj, cgobj, hlcgobj;
+
+ {*****************************************************************************
+ FirstTypeConv
+ *****************************************************************************}
+
+ function trv64typeconvnode.first_int_to_real: tnode;
+ begin
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ result:=inherited first_int_to_real
+ { converting a 64bit integer to a float requires a helper }
+ else
+ begin
+ if (is_currency(left.resultdef)) then begin
+ // hack to avoid double division by 10000, as it's
+ // already done by typecheckpass.resultdef_int_to_real
+ left.resultdef := s64inttype;
+ end else begin
+ // everything that is less than 64 bits is converted to a 64 bit signed
+ // integer - because the int_to_real conversion is faster for 64 bit
+ // signed ints compared to 64 bit unsigned ints.
+ if (not (torddef(left.resultdef).ordtype in [s64bit, u64bit, scurrency])) then begin
+ inserttypeconv(left, s64inttype);
+ end;
+ end;
+ firstpass(left);
+ result := nil;
+ expectloc := LOC_FPUREGISTER;
+ end;
+ end;
+
+ {*****************************************************************************
+ SecondTypeConv
+ *****************************************************************************}
+
+ procedure trv64typeconvnode.second_int_to_real;
+ const
+ ops: array[boolean,boolean,s32real..s64real] of TAsmOp = (
+ ((A_FCVT_S_WU,A_FCVT_D_WU),
+ (A_FCVT_S_W,A_FCVT_D_W)),
+ ((A_FCVT_S_LU,A_FCVT_D_LU),
+ (A_FCVT_S_L,A_FCVT_D_L)));
+ var
+ restype: tfloattype;
+ begin
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+
+ restype:=tfloatdef(resultdef).floattype;
+
+ location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, tfloat2tcgsize[restype]);
+ if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(ops[is_64bit(left.resultdef),is_signed(left.resultdef),restype], location.register, left.location.register));
+ end
+ else
+ begin
+ { Load memory in fpu register }
+ hlcg.location_force_mem(current_asmdata.CurrAsmList, left.location, left.resultdef);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F32, OS_F32, left.location.reference, location.Register);
+ tg.ungetiftemp(current_asmdata.CurrAsmList, left.location.reference);
+
+ case restype of
+ s64real: cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList, OS_F32, OS_F64, location.register, location.Register);
+ end;
+ end;
+ end;
+
+begin
+ ctypeconvnode := trv64typeconvnode;
+end.
+
diff --git a/riscv_new/compiler/riscv64/nrv64ld.pas b/riscv_new/compiler/riscv64/nrv64ld.pas
new file mode 100644
index 0000000000..c2a6963a5b
--- /dev/null
+++ b/riscv_new/compiler/riscv64/nrv64ld.pas
@@ -0,0 +1,57 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate riscv64 assembler for nodes that handle loads and assignments
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv64ld;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ncgld;
+
+type
+ trv64loadnode = class(tcgloadnode)
+ procedure pass_generate_code override;
+ end;
+
+implementation
+
+uses
+ verbose,
+ systems,
+ cpubase,
+ cgutils, cgobj,
+ aasmbase, aasmtai,aasmdata,
+ symconst, symsym,
+ procinfo,
+ nld;
+
+procedure trv64loadnode.pass_generate_code;
+begin
+ inherited pass_generate_code;
+end;
+
+
+begin
+ cloadnode := trv64loadnode;
+end.
+
diff --git a/riscv_new/compiler/riscv64/nrv64mat.pas b/riscv_new/compiler/riscv64/nrv64mat.pas
new file mode 100644
index 0000000000..abcdfdb124
--- /dev/null
+++ b/riscv_new/compiler/riscv64/nrv64mat.pas
@@ -0,0 +1,163 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate RiscV64 assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nrv64mat;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ node,nmat, ncgmat,
+ cgbase;
+
+ type
+ trv64moddivnode = class(tcgmoddivnode)
+ function use_moddiv64bitint_helper: boolean; override;
+ procedure emit_div_reg_reg(signed: boolean; denum, num: tregister); override;
+ procedure emit_mod_reg_reg(signed: boolean; denum, num: tregister); override;
+ function first_moddiv64bitint: tnode; override;
+ end;
+
+ trv64shlshrnode = class(tcgshlshrnode)
+ end;
+
+ trv64unaryminusnode = class(tcgunaryminusnode)
+ end;
+
+ trv64notnode = class(tcgnotnode)
+ procedure second_boolean; override;
+ end;
+
+implementation
+
+ uses
+ nadd,ninl,ncal,ncnv,
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ cpuinfo,
+ symconst,symdef,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ defutil,
+ cgutils,cgobj,hlcgobj,
+ pass_1,pass_2,htypechk,
+ ncon,procinfo,
+ cpubase,
+ ncgutil,cgcpu;
+
+ procedure trv64notnode.second_boolean;
+ var
+ tlabel, flabel: tasmlabel;
+ begin
+ if not handle_locjump then
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ Internalerror(2016060601);
+ //location_copy(location,left.location);
+ //inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER,
+ LOC_REFERENCE, LOC_CREFERENCE,
+ LOC_SUBSETREG, LOC_CSUBSETREG,
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+
+ location_reset(location,LOC_REGISTER,OS_INT);
+ location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,s64inttype);
+
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_const(A_SLTIU,location.register,left.location.register,1));
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+
+ function trv64moddivnode.use_moddiv64bitint_helper: boolean;
+ begin
+ Result:=true;
+ end;
+
+
+ procedure trv64moddivnode.emit_div_reg_reg(signed: boolean; denum, num: tregister);
+ var
+ op: TAsmOp;
+ begin
+ if signed then
+ op:=A_DIV
+ else
+ op:=A_DIVU;
+
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,num,num,denum));
+ end;
+
+
+ procedure trv64moddivnode.emit_mod_reg_reg(signed: boolean; denum, num: tregister);
+ var
+ op: TAsmOp;
+ begin
+ if signed then
+ op:=A_REM
+ else
+ op:=A_REMU;
+
+ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(op,num,num,denum));
+ end;
+
+
+ function trv64moddivnode.first_moddiv64bitint: tnode;
+ var
+ power: longint;
+ begin
+ {We can handle all cases of constant division}
+ if not(cs_check_overflow in current_settings.localswitches) and
+ (right.nodetype=ordconstn) and
+ (nodetype=divn) and
+ ((CPURV_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
+ (ispowerof2(tordconstnode(right).value,power) or
+ (tordconstnode(right).value=1) or
+ (tordconstnode(right).value=int64(-1))
+ )
+ ) then
+ result:=nil
+ else if (CPURV_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
+ (nodetype in [divn,modn]) then
+ result:=nil
+ else
+ result:=inherited;
+
+ { we may not change the result type here }
+ if assigned(result) and (torddef(result.resultdef).ordtype<>torddef(resultdef).ordtype) then
+ inserttypeconv(result,resultdef);
+ end;
+
+begin
+ cmoddivnode := trv64moddivnode;
+ cshlshrnode := trv64shlshrnode;
+ cunaryminusnode := trv64unaryminusnode;
+ cnotnode := trv64notnode;
+end.
+
diff --git a/riscv_new/compiler/riscv64/rarv.pas b/riscv_new/compiler/riscv64/rarv.pas
new file mode 100644
index 0000000000..a735913b92
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rarv.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common riscv assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rarv;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ aasmbase, aasmtai,aasmdata, aasmcpu,
+ cpubase, rautils, cclasses;
+
+type
+ TRVOperand = class(TOperand)
+ end;
+
+ TRVInstruction = class(TInstruction)
+ end;
+
+implementation
+
+end.
+
diff --git a/riscv_new/compiler/riscv64/rarv64gas.pas b/riscv_new/compiler/riscv64/rarv64gas.pas
new file mode 100644
index 0000000000..9cf15fe457
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rarv64gas.pas
@@ -0,0 +1,770 @@
+{
+ Copyright (c) 2016 by Jeppe Johansen
+
+ Does the parsing for the RiscV64 GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rarv64gas;
+
+{$I fpcdefs.inc}
+
+ interface
+
+ uses
+ raatt, rarv;
+
+ type
+ trv64attreader = class(tattreader)
+ function is_register(const s: string): boolean; override;
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : trvoperand);
+ procedure BuildOperand(oper : trvoperand);
+ procedure BuildOpCode(instr : trvinstruction);
+ procedure ReadAt(oper : trvoperand);
+ procedure ReadSym(oper : trvoperand);
+ end;
+
+ implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symsym,symdef,
+ { parser }
+ procinfo,
+ rabase,rautils,
+ cgbase,cgobj,cgrv
+ ;
+
+ procedure trv64attreader.ReadSym(oper : trvoperand);
+ var
+ tempstr, mangledname : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ procedure trv64attreader.ReadAt(oper : trvoperand);
+ begin
+ { check for ...@ }
+ if actasmtoken=AS_AT then
+ begin
+ if (oper.opr.ref.symbol=nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ {if upper(actasmpattern)='L' then
+ oper.opr.ref.refaddr:=addr_low
+ else if upper(actasmpattern)='HI' then
+ oper.opr.ref.refaddr:=addr_high
+ else if upper(actasmpattern)='HA' then
+ oper.opr.ref.refaddr:=addr_higha
+ else}
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+
+
+ procedure trv64attreader.BuildReference(oper: trvoperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+ var
+ l : aint;
+ relsym: string;
+ asmsymtyp: tasmsymtype;
+ isflags: tindsymflags;
+
+ begin
+ Consume(AS_LPAREN);
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { offset(offset) is invalid }
+ If oper.opr.Ref.Offset <> 0 Then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ End
+ Else
+ Begin
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ end;
+ exit;
+ End;
+ AS_REGISTER: { (reg ... }
+ Begin
+ if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+ ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ Consume_RParen;
+ end; {end case }
+ AS_ID:
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_PLUS:
+ begin
+ { add a constant expression? }
+ l:=BuildConstExpression(true,true);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ AS_MINUS:
+ begin
+ Consume(AS_MINUS);
+ BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
+ if (relsym<>'') then
+ begin
+ if (oper.opr.typ = OPR_REFERENCE) then
+ oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym,AT_DATA)
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end
+ end
+ else
+ begin
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ dec(oper.opr.val,l);
+ OPR_LOCAL :
+ dec(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ dec(oper.opr.ref.offset,l);
+ else
+ internalerror(2007092601);
+ end;
+ end;
+ end;
+ end;
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ End;
+ AS_COMMA: { (, ... can either be scaling, or index }
+ Begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken=AS_REGISTER) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end;
+
+
+ procedure trv64attreader.BuildOperand(oper: trvoperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.DefineAsmSymbol(mangledname,AB_EXTERNAL,AT_FUNCTION,voidcodepointertype);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ var
+ tempreg : tregister;
+ hl : tasmlabel;
+ ofs : aint;
+ refaddr: trefaddr;
+ Begin
+ expr:='';
+
+ refaddr:=addr_full;
+ if actasmtoken=AS_MOD then
+ begin
+ consume(AS_MOD);
+
+ if actasmtoken<>AS_ID then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end
+ else
+ begin
+ if lower(actasmpattern)='pcrel_hi' then
+ refaddr:=addr_pcrel_hi20
+ else if lower(actasmpattern)='pcrel_lo' then
+ refaddr:=addr_pcrel_lo12
+ else if lower(actasmpattern)='hi' then
+ refaddr:=addr_hi20
+ else if lower(actasmpattern)='lo' then
+ refaddr:=addr_lo12
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+
+ consume(AS_ID);
+ consume(AS_LPAREN);
+ end;
+ end;
+
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ ReadAt(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+
+ if refaddr<>addr_full then
+ begin
+ if oper.opr.typ<>OPR_REFERENCE then
+ oper.InitRef;
+
+ oper.opr.ref.refaddr:=refaddr;
+ Consume(AS_RPAREN);
+ end;
+ end;
+
+
+{*****************************************************************************
+ trv64attreader
+*****************************************************************************}
+
+ procedure trv64attreader.BuildOpCode(instr : trvinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ<>OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as trvoperand);
+ end; { end case }
+ until false;
+ if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
+ dec(operandnum);
+ instr.Ops:=operandnum;
+ end;
+
+ function trv64attreader.is_register(const s: string): boolean;
+ type
+ treg2str = record
+ name : string[3];
+ reg : tregister;
+ end;
+
+ const
+ extraregs : array[0..31] of treg2str = (
+ (name: 'A0'; reg : NR_X10),
+ (name: 'A1'; reg : NR_X11),
+ (name: 'A2'; reg : NR_X12),
+ (name: 'A3'; reg : NR_X13),
+ (name: 'A5'; reg : NR_X14),
+ (name: 'A6'; reg : NR_X15),
+ (name: 'A7'; reg : NR_X16),
+ (name: 'A8'; reg : NR_X17),
+ (name: 'RA'; reg : NR_X1),
+ (name: 'SP'; reg : NR_X2),
+ (name: 'GP'; reg : NR_X3),
+ (name: 'TP'; reg : NR_X4),
+ (name: 'T0'; reg : NR_X5),
+ (name: 'T1'; reg : NR_X6),
+ (name: 'T2'; reg : NR_X7),
+ (name: 'S0'; reg : NR_X8),
+ (name: 'FP'; reg : NR_X8),
+ (name: 'S1'; reg : NR_X9),
+ (name: 'S2'; reg : NR_X18),
+ (name: 'S3'; reg : NR_X19),
+ (name: 'S4'; reg : NR_X20),
+ (name: 'S5'; reg : NR_X21),
+ (name: 'S6'; reg : NR_X22),
+ (name: 'S7'; reg : NR_X23),
+ (name: 'S8'; reg : NR_X24),
+ (name: 'S9'; reg : NR_X25),
+ (name: 'S10';reg : NR_X26),
+ (name: 'S11';reg : NR_X27),
+ (name: 'T3'; reg : NR_X28),
+ (name: 'T4'; reg : NR_X29),
+ (name: 'T5'; reg : NR_X30),
+ (name: 'T6'; reg : NR_X31)
+ );
+
+ var
+ i : longint;
+
+ begin
+ result:=inherited is_register(s);
+ { reg found?
+ possible aliases are always 2 char
+ }
+ if result or (not (length(s) in [2,3])) then
+ exit;
+ for i:=low(extraregs) to high(extraregs) do
+ begin
+ if s=extraregs[i].name then
+ begin
+ actasmregister:=extraregs[i].reg;
+ result:=true;
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function trv64attreader.is_asmopcode(const s: string):boolean;
+ var
+ cond : tasmcond;
+ hs : string;
+
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+ { clear condition }
+ fillchar(actcondition,sizeof(actcondition),0);
+
+ { check for direction hint }
+ actopcode := tasmop(ptruint(iasmops.find(hs)));
+ if actopcode <> A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ { not found, check branch instructions }
+ if hs[1]='B' then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ actopcode := A_Bxx;
+ for cond:=low(TAsmCond) to high(TAsmCond) do
+ if copy(hs,2,length(s)-1)=uppercond2str[cond] then
+ begin
+ actcondition:=cond;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure trv64attreader.handleopcode;
+ var
+ instr : trvinstruction;
+ begin
+ instr:=trvinstruction.Create(trvoperand);
+ BuildOpcode(instr);
+ instr.condition := actcondition;
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ asmmode_rv64_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : trv64attreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_rv64_standard_info);
+end.
+
diff --git a/riscv_new/compiler/riscv64/rrv32con.inc b/riscv_new/compiler/riscv64/rrv32con.inc
new file mode 100644
index 0000000000..94c5f42533
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32con.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+NR_NO = tregister($00000000);
+NR_X0 = tregister($01000000);
+NR_X1 = tregister($01000001);
+NR_X2 = tregister($01000002);
+NR_X3 = tregister($01000003);
+NR_X4 = tregister($01000004);
+NR_X5 = tregister($01000005);
+NR_X6 = tregister($01000006);
+NR_X7 = tregister($01000007);
+NR_X8 = tregister($01000008);
+NR_X9 = tregister($01000009);
+NR_X10 = tregister($0100000a);
+NR_X11 = tregister($0100000b);
+NR_X12 = tregister($0100000c);
+NR_X13 = tregister($0100000d);
+NR_X14 = tregister($0100000e);
+NR_X15 = tregister($0100000f);
+NR_X16 = tregister($01000010);
+NR_X17 = tregister($01000011);
+NR_X18 = tregister($01000012);
+NR_X19 = tregister($01000013);
+NR_X20 = tregister($01000014);
+NR_X21 = tregister($01000015);
+NR_X22 = tregister($01000016);
+NR_X23 = tregister($01000017);
+NR_X24 = tregister($01000018);
+NR_X25 = tregister($01000019);
+NR_X26 = tregister($0100001a);
+NR_X27 = tregister($0100001b);
+NR_X28 = tregister($0100001c);
+NR_X29 = tregister($0100001d);
+NR_X30 = tregister($0100001e);
+NR_X31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_FCSR = tregister($05000001);
diff --git a/riscv_new/compiler/riscv64/rrv32dwa.inc b/riscv_new/compiler/riscv64/rrv32dwa.inc
new file mode 100644
index 0000000000..6755ebb4c5
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32dwa.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0
diff --git a/riscv_new/compiler/riscv64/rrv32nor.inc b/riscv_new/compiler/riscv64/rrv32nor.inc
new file mode 100644
index 0000000000..a3c3b517a4
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32nor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from rv32reg.dat }
+66
diff --git a/riscv_new/compiler/riscv64/rrv32num.inc b/riscv_new/compiler/riscv64/rrv32num.inc
new file mode 100644
index 0000000000..f9553bf4fb
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32num.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($05000001)
diff --git a/riscv_new/compiler/riscv64/rrv32rni.inc b/riscv_new/compiler/riscv64/rrv32rni.inc
new file mode 100644
index 0000000000..de9f6b796b
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32rni.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65
diff --git a/riscv_new/compiler/riscv64/rrv32sri.inc b/riscv_new/compiler/riscv64/rrv32sri.inc
new file mode 100644
index 0000000000..a39dc1faa3
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32sri.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+0,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/riscv_new/compiler/riscv64/rrv32sta.inc b/riscv_new/compiler/riscv64/rrv32sta.inc
new file mode 100644
index 0000000000..6755ebb4c5
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32sta.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+0
diff --git a/riscv_new/compiler/riscv64/rrv32std.inc b/riscv_new/compiler/riscv64/rrv32std.inc
new file mode 100644
index 0000000000..468a711616
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32std.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+'INVALID',
+'x0',
+'x1',
+'x2',
+'x3',
+'x4',
+'x5',
+'x6',
+'x7',
+'x8',
+'x9',
+'x10',
+'x11',
+'x12',
+'x13',
+'x14',
+'x15',
+'x16',
+'x17',
+'x18',
+'x19',
+'x20',
+'x21',
+'x22',
+'x23',
+'x24',
+'x25',
+'x26',
+'x27',
+'x28',
+'x29',
+'x30',
+'x31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'fcsr'
diff --git a/riscv_new/compiler/riscv64/rrv32sup.inc b/riscv_new/compiler/riscv64/rrv32sup.inc
new file mode 100644
index 0000000000..cb12862e9d
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rrv32sup.inc
@@ -0,0 +1,67 @@
+{ don't edit, this file is generated from rv32reg.dat }
+RS_NO = $00;
+RS_X0 = $00;
+RS_X1 = $01;
+RS_X2 = $02;
+RS_X3 = $03;
+RS_X4 = $04;
+RS_X5 = $05;
+RS_X6 = $06;
+RS_X7 = $07;
+RS_X8 = $08;
+RS_X9 = $09;
+RS_X10 = $0a;
+RS_X11 = $0b;
+RS_X12 = $0c;
+RS_X13 = $0d;
+RS_X14 = $0e;
+RS_X15 = $0f;
+RS_X16 = $10;
+RS_X17 = $11;
+RS_X18 = $12;
+RS_X19 = $13;
+RS_X20 = $14;
+RS_X21 = $15;
+RS_X22 = $16;
+RS_X23 = $17;
+RS_X24 = $18;
+RS_X25 = $19;
+RS_X26 = $1a;
+RS_X27 = $1b;
+RS_X28 = $1c;
+RS_X29 = $1d;
+RS_X30 = $1e;
+RS_X31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_FCSR = $01;
diff --git a/riscv_new/compiler/riscv64/rv32reg.dat b/riscv_new/compiler/riscv64/rv32reg.dat
new file mode 100644
index 0000000000..0be9f17f99
--- /dev/null
+++ b/riscv_new/compiler/riscv64/rv32reg.dat
@@ -0,0 +1,77 @@
+;
+; RiscV registers
+;
+; layout
+; <name>,<type>,<subtype>,<value>,<stdname>,<stab idx>,<dwarf idx>
+;
+NO,$00,$00,$00,INVALID,-1,-1
+; Integer registers
+X0,$01,$00,$00,x0,0,0
+X1,$01,$00,$01,x1,1,1
+X2,$01,$00,$02,x2,2,2
+X3,$01,$00,$03,x3,3,3
+X4,$01,$00,$04,x4,4,4
+X5,$01,$00,$05,x5,5,5
+X6,$01,$00,$06,x6,6,6
+X7,$01,$00,$07,x7,7,7
+X8,$01,$00,$08,x8,8,8
+X9,$01,$00,$09,x9,9,9
+X10,$01,$00,$0a,x10,10,10
+X11,$01,$00,$0b,x11,11,11
+X12,$01,$00,$0c,x12,12,12
+X13,$01,$00,$0d,x13,13,13
+X14,$01,$00,$0e,x14,14,14
+X15,$01,$00,$0f,x15,15,15
+X16,$01,$00,$10,x16,16,16
+X17,$01,$00,$11,x17,17,17
+X18,$01,$00,$12,x18,18,18
+X19,$01,$00,$13,x19,19,19
+X20,$01,$00,$14,x20,20,20
+X21,$01,$00,$15,x21,21,21
+X22,$01,$00,$16,x22,22,22
+X23,$01,$00,$17,x23,23,23
+X24,$01,$00,$18,x24,24,24
+X25,$01,$00,$19,x25,25,25
+X26,$01,$00,$1a,x26,26,26
+X27,$01,$00,$1b,x27,27,27
+X28,$01,$00,$1c,x28,28,28
+X29,$01,$00,$1d,x29,29,29
+X30,$01,$00,$1e,x30,30,30
+X31,$01,$00,$1f,x31,31,31
+
+; Float registers
+F0,$02,$00,$00,f0,0,0
+F1,$02,$00,$01,f1,1,1
+F2,$02,$00,$02,f2,2,2
+F3,$02,$00,$03,f3,3,3
+F4,$02,$00,$04,f4,4,4
+F5,$02,$00,$05,f5,5,5
+F6,$02,$00,$06,f6,6,6
+F7,$02,$00,$07,f7,7,7
+F8,$02,$00,$08,f8,8,8
+F9,$02,$00,$09,f9,9,9
+F10,$02,$00,$0a,f10,10,10
+F11,$02,$00,$0b,f11,11,11
+F12,$02,$00,$0c,f12,12,12
+F13,$02,$00,$0d,f13,13,13
+F14,$02,$00,$0e,f14,14,14
+F15,$02,$00,$0f,f15,15,15
+F16,$02,$00,$10,f16,16,16
+F17,$02,$00,$11,f17,17,17
+F18,$02,$00,$12,f18,18,18
+F19,$02,$00,$13,f19,19,19
+F20,$02,$00,$14,f20,20,20
+F21,$02,$00,$15,f21,21,21
+F22,$02,$00,$16,f22,22,22
+F23,$02,$00,$17,f23,23,23
+F24,$02,$00,$18,f24,24,24
+F25,$02,$00,$19,f25,25,25
+F26,$02,$00,$1a,f26,26,26
+F27,$02,$00,$1b,f27,27,27
+F28,$02,$00,$1c,f28,28,28
+F29,$02,$00,$1d,f29,29,29
+F30,$02,$00,$1e,f30,30,30
+F31,$02,$00,$1f,f31,31,31
+
+; Special registers
+FCSR,$05,$00,$01,fcsr,0,0
diff --git a/riscv_new/compiler/riscv64/symcpu.pas b/riscv_new/compiler/riscv64/symcpu.pas
new file mode 100644
index 0000000000..e1b5f3b08e
--- /dev/null
+++ b/riscv_new/compiler/riscv64/symcpu.pas
@@ -0,0 +1,220 @@
+{
+ Copyright (c) 2014 by Florian Klaempfl
+
+ Symbol table overrides for RiscV64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit symcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ symtype,symdef,symsym;
+
+type
+ { defs }
+ tcpufiledef = class(tfiledef)
+ end;
+ tcpufiledefclass = class of tcpufiledef;
+
+ tcpuvariantdef = class(tvariantdef)
+ end;
+ tcpuvariantdefclass = class of tcpuvariantdef;
+
+ tcpuformaldef = class(tformaldef)
+ end;
+ tcpuformaldefclass = class of tcpuformaldef;
+
+ tcpuforwarddef = class(tforwarddef)
+ end;
+ tcpuforwarddefclass = class of tcpuforwarddef;
+
+ tcpuundefineddef = class(tundefineddef)
+ end;
+ tcpuundefineddefclass = class of tcpuundefineddef;
+
+ tcpuerrordef = class(terrordef)
+ end;
+ tcpuerrordefclass = class of tcpuerrordef;
+
+ tcpupointerdef = class(tpointerdef)
+ end;
+ tcpupointerdefclass = class of tcpupointerdef;
+
+ tcpurecorddef = class(trecorddef)
+ end;
+ tcpurecorddefclass = class of tcpurecorddef;
+
+ tcpuimplementedinterface = class(timplementedinterface)
+ end;
+ tcpuimplementedinterfaceclass = class of tcpuimplementedinterface;
+
+ tcpuobjectdef = class(tobjectdef)
+ end;
+ tcpuobjectdefclass = class of tcpuobjectdef;
+
+ tcpuclassrefdef = class(tclassrefdef)
+ end;
+ tcpuclassrefdefclass = class of tcpuclassrefdef;
+
+ tcpuarraydef = class(tarraydef)
+ end;
+ tcpuarraydefclass = class of tcpuarraydef;
+
+ tcpuorddef = class(torddef)
+ end;
+ tcpuorddefclass = class of tcpuorddef;
+
+ tcpufloatdef = class(tfloatdef)
+ end;
+ tcpufloatdefclass = class of tcpufloatdef;
+
+ tcpuprocvardef = class(tprocvardef)
+ end;
+ tcpuprocvardefclass = class of tcpuprocvardef;
+
+ tcpuprocdef = class(tprocdef)
+ end;
+ tcpuprocdefclass = class of tcpuprocdef;
+
+ tcpustringdef = class(tstringdef)
+ end;
+ tcpustringdefclass = class of tcpustringdef;
+
+ tcpuenumdef = class(tenumdef)
+ end;
+ tcpuenumdefclass = class of tcpuenumdef;
+
+ tcpusetdef = class(tsetdef)
+ end;
+ tcpusetdefclass = class of tcpusetdef;
+
+ { syms }
+ tcpulabelsym = class(tlabelsym)
+ end;
+ tcpulabelsymclass = class of tcpulabelsym;
+
+ tcpuunitsym = class(tunitsym)
+ end;
+ tcpuunitsymclass = class of tcpuunitsym;
+
+ tcpuprogramparasym = class(tprogramparasym)
+ end;
+ tcpuprogramparasymclass = class(tprogramparasym);
+
+ tcpunamespacesym = class(tnamespacesym)
+ end;
+ tcpunamespacesymclass = class of tcpunamespacesym;
+
+ tcpuprocsym = class(tprocsym)
+ end;
+ tcpuprocsymclass = class of tcpuprocsym;
+
+ tcputypesym = class(ttypesym)
+ end;
+ tcpuypesymclass = class of tcputypesym;
+
+ tcpufieldvarsym = class(tfieldvarsym)
+ end;
+ tcpufieldvarsymclass = class of tcpufieldvarsym;
+
+ tcpulocalvarsym = class(tlocalvarsym)
+ end;
+ tcpulocalvarsymclass = class of tcpulocalvarsym;
+
+ tcpuparavarsym = class(tparavarsym)
+ end;
+ tcpuparavarsymclass = class of tcpuparavarsym;
+
+ tcpustaticvarsym = class(tstaticvarsym)
+ end;
+ tcpustaticvarsymclass = class of tcpustaticvarsym;
+
+ tcpuabsolutevarsym = class(tabsolutevarsym)
+ end;
+ tcpuabsolutevarsymclass = class of tcpuabsolutevarsym;
+
+ tcpupropertysym = class(tpropertysym)
+ end;
+ tcpupropertysymclass = class of tcpupropertysym;
+
+ tcpuconstsym = class(tconstsym)
+ end;
+ tcpuconstsymclass = class of tcpuconstsym;
+
+ tcpuenumsym = class(tenumsym)
+ end;
+ tcpuenumsymclass = class of tcpuenumsym;
+
+ tcpusyssym = class(tsyssym)
+ end;
+ tcpusyssymclass = class of tcpusyssym;
+
+
+const
+ pbestrealtype : ^tdef = @s64floattype;
+
+
+implementation
+
+ uses
+ symconst, defutil, defcmp;
+
+
+begin
+ { used tdef classes }
+ cfiledef:=tcpufiledef;
+ cvariantdef:=tcpuvariantdef;
+ cformaldef:=tcpuformaldef;
+ cforwarddef:=tcpuforwarddef;
+ cundefineddef:=tcpuundefineddef;
+ cerrordef:=tcpuerrordef;
+ cpointerdef:=tcpupointerdef;
+ crecorddef:=tcpurecorddef;
+ cimplementedinterface:=tcpuimplementedinterface;
+ cobjectdef:=tcpuobjectdef;
+ cclassrefdef:=tcpuclassrefdef;
+ carraydef:=tcpuarraydef;
+ corddef:=tcpuorddef;
+ cfloatdef:=tcpufloatdef;
+ cprocvardef:=tcpuprocvardef;
+ cprocdef:=tcpuprocdef;
+ cstringdef:=tcpustringdef;
+ cenumdef:=tcpuenumdef;
+ csetdef:=tcpusetdef;
+
+ { used tsym classes }
+ clabelsym:=tcpulabelsym;
+ cunitsym:=tcpuunitsym;
+ cprogramparasym:=tcpuprogramparasym;
+ cnamespacesym:=tcpunamespacesym;
+ cprocsym:=tcpuprocsym;
+ ctypesym:=tcputypesym;
+ cfieldvarsym:=tcpufieldvarsym;
+ clocalvarsym:=tcpulocalvarsym;
+ cparavarsym:=tcpuparavarsym;
+ cstaticvarsym:=tcpustaticvarsym;
+ cabsolutevarsym:=tcpuabsolutevarsym;
+ cpropertysym:=tcpupropertysym;
+ cconstsym:=tcpuconstsym;
+ cenumsym:=tcpuenumsym;
+ csyssym:=tcpusyssym;
+end.
+
diff --git a/riscv_new/compiler/systems.inc b/riscv_new/compiler/systems.inc
index 9da234156e..997fb22199 100644
--- a/riscv_new/compiler/systems.inc
+++ b/riscv_new/compiler/systems.inc
@@ -52,7 +52,9 @@
cpu_i8086, { 15 }
cpu_aarch64, { 16 }
cpu_wasm, { 17 }
- cpu_sparc64 { 18 }
+ cpu_sparc64, { 18 }
+ cpu_riscv32, { 19 }
+ cpu_riscv64 { 20 }
);
tasmmode= (asmmode_none
@@ -179,7 +181,11 @@
system_wasm_wasm32, { 92 }
system_sparc64_linux, { 93 }
system_sparc64_solaris, { 94 }
- system_arm_netbsd { 95 }
+ system_arm_netbsd, { 95 }
+ system_riscv32_linux, { 96 }
+ system_riscv64_linux, { 97 }
+ system_riscv64_embedded, { 98 }
+ system_riscv32_embedded { 99 }
);
type
diff --git a/riscv_new/compiler/systems.pas b/riscv_new/compiler/systems.pas
index b0201c7576..7366b8de1b 100644
--- a/riscv_new/compiler/systems.pas
+++ b/riscv_new/compiler/systems.pas
@@ -232,7 +232,8 @@ interface
systems_android = [system_arm_android, system_i386_android, system_mipsel_android];
systems_linux = [system_i386_linux,system_x86_64_linux,system_powerpc_linux,system_powerpc64_linux,
system_arm_linux,system_sparc_linux,system_sparc64_linux,system_m68k_linux,
- system_x86_6432_linux,system_mipseb_linux,system_mipsel_linux,system_aarch64_linux];
+ system_x86_6432_linux,system_mipseb_linux,system_mipsel_linux,system_aarch64_linux,
+ system_riscv32_linux,system_riscv64_linux];
systems_dragonfly = [system_x86_64_dragonfly];
systems_freebsd = [system_i386_freebsd,
system_x86_64_freebsd];
@@ -274,7 +275,7 @@ interface
system_mips_embedded,system_arm_embedded,
system_powerpc64_embedded,system_avr_embedded,
system_jvm_java32,system_mipseb_embedded,system_mipsel_embedded,
- system_i8086_embedded];
+ system_i8086_embedded,system_riscv32_embedded,system_riscv64_embedded];
{ all systems that allow section directive }
systems_allow_section = systems_embedded;
@@ -397,7 +398,7 @@ interface
cpu2str : array[TSystemCpu] of string[10] =
('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
'mips','arm', 'powerpc64', 'avr', 'mipsel','jvm', 'i8086',
- 'aarch64', 'wasm', 'sparc64');
+ 'aarch64', 'wasm', 'sparc64','riscv32','riscv64');
abiinfo : array[tabi] of tabiinfo = (
(name: 'DEFAULT'; supported: true),
@@ -1036,6 +1037,14 @@ begin
{$ifdef wasm}
default_target(system_wasm_wasm32);
{$endif}
+
+{$ifdef riscv32}
+ default_target(system_riscv32_linux);
+{$endif riscv32}
+
+{$ifdef riscv64}
+ default_target(system_riscv64_linux);
+{$endif riscv64}
end;
diff --git a/riscv_new/compiler/systems/i_linux.pas b/riscv_new/compiler/systems/i_linux.pas
index 701dca158f..5ccdb25e90 100644
--- a/riscv_new/compiler/systems/i_linux.pas
+++ b/riscv_new/compiler/systems/i_linux.pas
@@ -1029,6 +1029,138 @@ unit i_linux;
llvmdatalayout : 'e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64';
);
+ system_riscv32_linux_info : tsysteminfo =
+ (
+ system : system_riscv32_linux;
+ name : 'Linux for RISC-V 32';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_smartlink_sections,
+ tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_has_winlike_resources];
+ cpu : cpu_riscv32;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+// p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : ld_none;
+ linkextern : ld_linux;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 0;
+ stacksize : 32*1024*1024;
+ stackalign : 8;
+ abi : abi_default;
+ llvmdatalayout : 'e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64';
+ );
+
+ system_riscv64_linux_info : tsysteminfo =
+ (
+ system : system_riscv64_linux;
+ name : 'Linux for RISC-V 64';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_smartlink_sections,
+ tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_has_winlike_resources];
+ cpu : cpu_riscv64;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+// p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : ld_none;
+ linkextern : ld_linux;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 4;
+ constalignmax : 16;
+ varalignmin : 4;
+ varalignmax : 16;
+ localalignmin : 8;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 10*1024*1024;
+ stackalign : 16;
+ abi : abi_default;
+ llvmdatalayout : 'E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:64:64-v128:128:128-n32:64';
+ );
+
implementation
initialization
@@ -1095,4 +1227,14 @@ initialization
set_source_info(system_mipsel_linux_info);
{$endif linux}
{$endif CPUMIPSEL}
+{$ifdef CPURISCV32}
+ {$ifdef linux}
+ set_source_info(system_riscv32_linux_info);
+ {$endif linux}
+{$endif CPURISCV32}
+{$ifdef CPURISCV64}
+ {$ifdef linux}
+ set_source_info(system_riscv64_linux_info);
+ {$endif linux}
+{$endif CPURISCV64}
end.
diff --git a/riscv_new/compiler/systems/t_linux.pas b/riscv_new/compiler/systems/t_linux.pas
index 0a4af94074..013667b8a8 100644
--- a/riscv_new/compiler/systems/t_linux.pas
+++ b/riscv_new/compiler/systems/t_linux.pas
@@ -234,6 +234,13 @@ const defdynlinker='/lib/ld-linux-aarch64.so.1';
const defdynlinker='/lib64/ld-linux.so.2';
{$endif sparc64}
+{$ifdef riscv32}
+ const defdynlinker='/lib32/ld.so.1';
+{$endif riscv32}
+{$ifdef riscv64}
+ const defdynlinker='/lib/ld.so.1';
+{$endif riscv64}
+
procedure SetupDynlinker(out DynamicLinker:string;out libctype:TLibcType);
begin
@@ -338,6 +345,8 @@ const
platform_select='-EB';
{$endif}
{$endif}
+{$ifdef riscv32} platform_select='';{$endif} {unknown :( }
+{$ifdef riscv64} platform_select='';{$endif} {unknown :( }
var
platformopt: string;
@@ -1892,5 +1901,15 @@ initialization
RegisterTarget(system_mipseb_linux_info);
{$endif MIPSEL}
{$endif MIPS}
+{$ifdef riscv32}
+ RegisterImport(system_riscv32_linux,timportliblinux);
+ RegisterExport(system_riscv32_linux,texportliblinux);
+ RegisterTarget(system_riscv32_linux_info);
+{$endif riscv32}
+{$ifdef riscv64}
+ RegisterImport(system_riscv64_linux,timportliblinux);
+ RegisterExport(system_riscv64_linux,texportliblinux);
+ RegisterTarget(system_riscv64_linux_info);
+{$endif riscv64}
RegisterRes(res_elf_info,TWinLikeResourceFile);
end.
diff --git a/riscv_new/compiler/utils/fpc.pp b/riscv_new/compiler/utils/fpc.pp
index e2152aaf69..b531da3f9a 100644
--- a/riscv_new/compiler/utils/fpc.pp
+++ b/riscv_new/compiler/utils/fpc.pp
@@ -168,6 +168,14 @@ program fpc;
processorname:='mips';
{$endif mips}
{$endif not mipsel}
+{$ifdef riscv32}
+ ppcbin:='ppcrv32';
+ processorname:='riscv32';
+{$endif riscv32}
+{$ifdef riscv64}
+ ppcbin:='ppcrv64';
+ processorname:='riscv64';
+{$endif riscv64}
versionstr:=''; { Default is just the name }
if ParamCount = 0 then
begin
diff --git a/riscv_new/compiler/utils/ppuutils/ppudump.pp b/riscv_new/compiler/utils/ppuutils/ppudump.pp
index 74fde5c6c2..e94c4df219 100644
--- a/riscv_new/compiler/utils/ppuutils/ppudump.pp
+++ b/riscv_new/compiler/utils/ppuutils/ppudump.pp
@@ -80,7 +80,9 @@ const
{ 15 } 'i8086',
{ 16 } 'aarch64',
{ 17 } 'wasm',
- { 18 } 'sparc64'
+ { 18 } 'sparc64',
+ { 19 } 'riscv32',
+ { 20 } 'riscv64'
);
{ List of all supported system-cpu couples }
@@ -181,7 +183,11 @@ const
{ 92 } 'WebAssembly-wasm',
{ 93 } 'Linux-sparc64',
{ 94 } 'Solaris-sparc64',
- { 95 } 'NetBSD-arm'
+ { 95 } 'NetBSD-arm',
+ { 96 } 'Linux-RiscV32',
+ { 97 } 'Linux-RiscV64',
+ { 98 } 'Embedded-RiscV32',
+ { 99 } 'Embedded-RiscV64'
);
const
diff --git a/riscv_new/compiler/version.pas b/riscv_new/compiler/version.pas
index f217547df9..d5ad996f9b 100644
--- a/riscv_new/compiler/version.pas
+++ b/riscv_new/compiler/version.pas
@@ -74,6 +74,12 @@ interface
{$ifdef cpuaarch64}
source_cpu_string = 'aarch64';
{$endif cpuaarch64}
+{$ifdef cpuriscv64}
+ source_cpu_string = 'riscv64';
+{$endif cpuriscv64}
+{$ifdef cpuriscv32}
+ source_cpu_string = 'riscv32';
+{$endif cpuriscv32}
function version_string:string;
function full_version_string:string;
diff --git a/riscv_new/rtl/inc/system.inc b/riscv_new/rtl/inc/system.inc
index 3aa5f656f0..3dea5fa444 100644
--- a/riscv_new/rtl/inc/system.inc
+++ b/riscv_new/rtl/inc/system.inc
@@ -277,6 +277,22 @@ function do_isdevice(handle:thandle):boolean;forward;
{$define SYSPROCDEFINED}
{$endif cpuaarch64}
+{$ifdef cpuriscv32}
+ {$ifdef SYSPROCDEFINED}
+ {$Error Can't determine processor type !}
+ {$endif}
+ {$i riscv32.inc} { Case dependent, don't change }
+ {$define SYSPROCDEFINED}
+{$endif cpuriscv32}
+
+{$ifdef cpuriscv64}
+ {$ifdef SYSPROCDEFINED}
+ {$Error Can't determine processor type !}
+ {$endif}
+ {$i riscv64.inc} { Case dependent, don't change }
+ {$define SYSPROCDEFINED}
+{$endif cpuriscv64}
+
{$ifndef SYSPROCDEFINED}
{$Error Can't determine processor type !}
{$endif}
diff --git a/riscv_new/rtl/inc/systemh.inc b/riscv_new/rtl/inc/systemh.inc
index 08df955d8b..4d9f991023 100644
--- a/riscv_new/rtl/inc/systemh.inc
+++ b/riscv_new/rtl/inc/systemh.inc
@@ -367,6 +367,51 @@ Type
FarPointer = Pointer;
{$endif CPUAARCH64}
+{$ifdef CPURISCV32}
+ {$define DEFAULT_DOUBLE}
+
+ {$define SUPPORT_SINGLE}
+ {$define SUPPORT_DOUBLE}
+
+ {$define FPC_INCLUDE_SOFTWARE_MOD_DIV}
+ {$define FPC_INCLUDE_SOFTWARE_MUL}
+ {$define FPC_INCLUDE_SOFTWARE_SHIFT_INT64}
+ {$define FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
+
+ {$ifndef FPUNONE}
+ {$define FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
+ ValReal = Double;
+ {$endif}
+
+ { map comp to int64, but this doesn't mean we compile the comp support in! }
+ Comp = Int64;
+ PComp = ^Comp;
+
+ FarPointer = Pointer;
+{$endif CPURISCV32}
+
+{$ifdef CPURISCV64}
+ {$define DEFAULT_DOUBLE}
+
+ {$define SUPPORT_SINGLE}
+ {$define SUPPORT_DOUBLE}
+
+ {$define FPC_INCLUDE_SOFTWARE_MOD_DIV}
+ {$define FPC_INCLUDE_SOFTWARE_MUL}
+ {$define FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
+
+ {$ifndef FPUNONE}
+ {$define FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
+ ValReal = Double;
+ {$endif}
+
+ { map comp to int64, but this doesn't mean we compile the comp support in! }
+ Comp = Int64;
+ PComp = ^Comp;
+
+ FarPointer = Pointer;
+{$endif CPURISCV64}
+
{$ifdef CPU64}
SizeInt = Int64;
diff --git a/riscv_new/rtl/linux/osdefs.inc b/riscv_new/rtl/linux/osdefs.inc
index 67f7324a36..7e7a91e227 100644
--- a/riscv_new/rtl/linux/osdefs.inc
+++ b/riscv_new/rtl/linux/osdefs.inc
@@ -94,6 +94,16 @@
{$define FPC_USEGETTIMEOFDAY}
{$endif cpusparc64}
+{$ifdef cpuriscv32}
+ {$define generic_linux_syscalls}
+ {$undef usestime}
+{$endif cpuriscv32}
+
+{$ifdef cpuriscv64}
+ {$define generic_linux_syscalls}
+ {$undef usestime}
+{$endif cpuriscv64}
+
{$ifdef android}
{$undef usestime}
{$undef OLDMMAP}
diff --git a/riscv_new/rtl/linux/riscv32/bsyscall.inc b/riscv_new/rtl/linux/riscv32/bsyscall.inc
new file mode 100644
index 0000000000..c690ebeb2c
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/bsyscall.inc
@@ -0,0 +1 @@
+{ nothing }
diff --git a/riscv_new/rtl/linux/riscv32/cprt0.as b/riscv_new/rtl/linux/riscv32/cprt0.as
new file mode 100644
index 0000000000..5b9474e9c3
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/cprt0.as
@@ -0,0 +1,139 @@
+/* Startup code for ARM & ELF
+ Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment.
+
+ Note that the code in the .init section has already been run.
+ This includes _init and _libc_init
+
+
+ At this entry point, most registers' values are unspecified, except:
+
+ a1 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ sp The stack contains the arguments and environment:
+ 0(sp) argc
+ 4(sp) argv[0]
+ ...
+ (4*argc)(sp) NULL
+ (4*(argc+1))(sp) envp[0]
+ ...
+ NULL
+*/
+
+ .text
+ .globl _start
+ .type _start,function
+_start:
+ /* Clear the frame pointer since this is the outermost frame. */
+ mov fp, #0
+ ldmia sp!, {a2}
+
+ /* Pop argc off the stack and save a pointer to argv */
+ ldr ip,=operatingsystem_parameter_argc
+ ldr a3,=operatingsystem_parameter_argv
+ str a2,[ip]
+
+ /* calc envp */
+ add a4,a2,#1
+ add a4,sp,a4,LSL #2
+ ldr ip,=operatingsystem_parameter_envp
+
+ str sp,[a3]
+ str a4,[ip]
+
+ /* Save initial stackpointer */
+ ldr ip,=__stkptr
+ str sp,[ip]
+
+ /* Fetch address of fini */
+ ldr ip, =_fini
+
+ /* argc already loaded to a2*/
+
+ /* load argv */
+ mov a3, sp
+
+ /* Push stack limit */
+ str a3, [sp, #-4]!
+
+ /* Push rtld_fini */
+ str a1, [sp, #-4]!
+
+ /* Set up the other arguments in registers */
+ ldr a1, =PASCALMAIN
+ ldr a4, =_init
+
+ /* Push fini */
+ str ip, [sp, #-4]!
+
+ /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+
+ /* Let the libc call main and exit with its return code. */
+ bl __libc_start_main
+
+ /* should never get here....*/
+ bl abort
+
+ .globl _haltproc
+ .type _haltproc,function
+_haltproc:
+ ldr r0,=operatingsystem_result
+ ldrb r0,[r0]
+ swi 0x900001
+ b _haltproc
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
+
+.bss
+ .comm __stkptr,4
+
+ .comm operatingsystem_parameter_envp,4
+ .comm operatingsystem_parameter_argc,4
+ .comm operatingsystem_parameter_argv,4
+
+ .section ".comment"
+ .byte 0
+ .ascii "generated by FPC http://www.freepascal.org\0"
+
+/* We need this stuff to make gdb behave itself, otherwise
+ gdb will chokes with SIGILL when trying to debug apps.
+*/
+ .section ".note.ABI-tag", "a"
+ .align 4
+ .long 1f - 0f
+ .long 3f - 2f
+ .long 1
+0: .asciz "GNU"
+1: .align 4
+2: .long 0
+ .long 2,0,0
+3: .align 4
+
+.section .note.GNU-stack,"",%progbits
diff --git a/riscv_new/rtl/linux/riscv32/dllprt0.as b/riscv_new/rtl/linux/riscv32/dllprt0.as
new file mode 100644
index 0000000000..a7b7ee585d
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/dllprt0.as
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the Free Pascal run time library.
+ * Copyright (c) 2011 by Thomas Schatzl,
+ * member of the Free Pascal development team.
+ *
+ * Startup code for shared libraries, ARM version.
+ *
+ * See the file COPYING.FPC, included in this distribution,
+ * for details about the copyright.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+.file "dllprt0.as"
+.text
+ .globl _startlib
+ .type _startlib,function
+_startlib:
+ .globl FPC_SHARED_LIB_START
+ .type FPC_SHARED_LIB_START,function
+FPC_SHARED_LIB_START:
+ sw x1, -4(x2)
+ sw x8, -8(x2)
+ addi x8, x2, 0
+ addi x2, x2, -8
+
+ /* a1 contains argc, a2 contains argv and a3 contains envp */
+ lui x15, %hi(operatingsystem_parameter_argc)
+ addi x15,x15,%lo(operatingsystem_parameter_argc)
+ sw a1, (x15)
+
+ lui x15, %hi(operatingsystem_parameter_argv)
+ addi x15,x15,%lo(operatingsystem_parameter_argv)
+ sw a2, (x15)
+
+ lui x15, %hi(operatingsystem_parameter_envp)
+ addi x15,x15,%lo(operatingsystem_parameter_envp)
+ sw a3, (x15)
+
+ /* save initial stackpointer */
+ lui x15, %hi(__stklen)
+ addi x15,x15,%lo(__stklen)
+ sw x2, (x15)
+
+ /* call main and exit normally */
+ jal x1, PASCALMAIN
+ lw x8, -8(x8)
+ lw x1, -4(x8)
+
+ jalr x0, x1
+
+ .globl _haltproc
+ .type _haltproc,function
+_haltproc:
+ /* reload exitcode */
+ lui x10, %hi(operatingsystem_result)
+ addi x10,x10,%lo(operatingsystem_result)
+ addi x17, x0, 248
+ scall
+ jal x0, _haltproc
+
+.data
+
+ .type operatingsystem_parameters,object
+ .size operatingsystem_parameters,12
+operatingsystem_parameters:
+ .skip 3*4
+ .global operatingsystem_parameter_envp
+ .global operatingsystem_parameter_argc
+ .global operatingsystem_parameter_argv
+ .set operatingsystem_parameter_envp,operatingsystem_parameters+0
+ .set operatingsystem_parameter_argc,operatingsystem_parameters+4
+ .set operatingsystem_parameter_argv,operatingsystem_parameters+8
+
+.bss
+
+ .comm __stkptr,4
+
diff --git a/riscv_new/rtl/linux/riscv32/gprt0.as b/riscv_new/rtl/linux/riscv32/gprt0.as
new file mode 100644
index 0000000000..d7d6337e55
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/gprt0.as
@@ -0,0 +1,118 @@
+/*
+ Start-up code for Free Pascal Compiler when linking with C library
+ with profiling support.
+
+ Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+ .text
+ .align 2
+
+ .globl _start
+ .type _start,#function
+_start:
+ /* Initialise FP to zero */
+ mov x29,#0
+
+ /* This is rtld_fini */
+ mov x5,x0
+
+ /* Get argc, argv, envp */
+ ldr x1,[sp]
+ add x2,sp,#8
+ add x11,x1,#1
+ add x11,x2,x11,lsl #3
+
+ /* Save argc, argv, envp, and initial stack pointer */
+ adrp x10,:got:operatingsystem_parameter_argc
+ ldr x10,[x10,#:got_lo12:operatingsystem_parameter_argc]
+ str x1,[x10]
+ adrp x10,:got:operatingsystem_parameter_argv
+ ldr x10,[x10,#:got_lo12:operatingsystem_parameter_argv]
+ str x2,[x10]
+ adrp x10,:got:operatingsystem_parameter_envp
+ ldr x10,[x10,#:got_lo12:operatingsystem_parameter_envp]
+ str x11,[x10]
+ adrp x10,:got:__stkptr
+ ldr x10,[x10,#:got_lo12:__stkptr]
+ mov x6,sp
+ str x6,[x10]
+
+ /* __libc_start_main(main, argc, argv,
+ init, fini, rtld_fini, stack_end) */
+ adrp x0,:got:main_stub
+ ldr x0,[x0,#:got_lo12:main_stub]
+ adrp x3,:got:_init_dummy
+ ldr x3,[x3,#:got_lo12:_init_dummy]
+ adrp x4,:got:_fini_dummy
+ ldr x4,[x4,#:got_lo12:_fini_dummy]
+ bl __libc_start_main
+
+ /* This should never happen */
+ b abort
+
+ .globl _init_dummy
+ .type _init_dummy,#function
+_init_dummy:
+ ret
+
+ .globl _fini_dummy
+ .type _fini_dummy,#function
+_fini_dummy:
+ ret
+
+ .globl main_stub
+ .type main_stub,#function
+main_stub:
+ stp x29,x30,[sp,#-16]!
+
+ /* Save initial stackpointer */
+ mov x0,sp
+ adrp x1,:got:__stkptr
+ ldr x1,[x1,#:got_lo12:__stkptr]
+ str x0,[x1]
+
+ /* Initialize gmon */
+ adrp x0,:got:_start
+ ldr x0,[x0,#:got_lo12:_start]
+ adrp x1,:got:_etext
+ ldr x1,[x1,#:got_lo12:_etext]
+ bl __monstartup
+ adrp x0,:got:_mcleanup
+ ldr x0,[x0,#:got_lo12:_mcleanup]
+ bl atexit
+
+ /* Start the program */
+ bl PASCALMAIN
+ b abort
+
+ .globl _haltproc
+ .type _haltproc,#function
+_haltproc:
+ /* Return to libc */
+ adrp x1,:got:__stkptr
+ ldr x1,[x1,#:got_lo12:__stkptr]
+ ldr x1,[x1]
+ mov sp,x1
+ ldp x29,x30,[sp],#16
+ ret
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .align 3
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
+
+ .bss
+ .align 3
+
+ .comm __stkptr,8
+
+ .comm operatingsystem_parameter_envp,8
+ .comm operatingsystem_parameter_argc,8
+ .comm operatingsystem_parameter_argv,8
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/riscv_new/rtl/linux/riscv32/prt0.as b/riscv_new/rtl/linux/riscv32/prt0.as
new file mode 100644
index 0000000000..18f568521f
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/prt0.as
@@ -0,0 +1,85 @@
+/*
+ Start-up code for Free Pascal Compiler, not in a shared library,
+ not linking with C library.
+
+ Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+ .text
+ .align 2
+
+ .globl _dynamic_start
+ .type _dynamic_start, function
+_dynamic_start:
+ lui x5,%hi(__dl_fini)
+ addi x5,x5,%lo(__dl_fini)
+ sw x10, (x5)
+ jal x0, _start
+
+ .globl _start
+ .type _start, function
+_start:
+ /* Initialise FP to zero */
+ addi x2,x0,0
+
+ /* Get argc, argv, envp */
+ lw x5,(x2)
+ addi x6,x2,8
+ addi x7,x5,1
+ slli x7,x7,3
+ add x7,x6,x7
+
+ /* Save argc, argv, envp, and initial stack pointer */
+ lui x8,%hi(operatingsystem_parameter_argc)
+ addi x8,x8,%lo(operatingsystem_parameter_argc)
+ sw x5,(x8)
+ lui x8,%hi(operatingsystem_parameter_argv)
+ addi x8,x8,%lo(operatingsystem_parameter_argv)
+ sw x6,(x8)
+ lui x8,%hi(operatingsystem_parameter_envp)
+ addi x8,x8,%lo(operatingsystem_parameter_envp)
+ sw x7,(x8)
+ lui x5,%hi(__stkptr)
+ addi x5,x8,%lo(__stkptr)
+ addi x6, x2, 0
+ sw x6,(x5)
+
+ /* Call main */
+ jal x1, PASCALMAIN
+
+ .globl _haltproc
+ .type _haltproc,function
+_haltproc:
+ lui x10,%hi(__dl_fini)
+ addi x10,x10,%lo(__dl_fini)
+ lw x10,(x10)
+ beq x10,x0,.Lexit
+ jalr x1,x10
+.Lexit:
+ lui x10,%hi(operatingsystem_result)
+ addi x10,x10,%lo(operatingsystem_result)
+ lw x10,(x10)
+ addi x17, x0, 94
+ scall
+ jal x0, _haltproc
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .align 3
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
+
+ .bss
+ .align 3
+
+ .comm __dl_fini,8
+ .comm __stkptr,8
+
+ .comm operatingsystem_parameter_envp,8
+ .comm operatingsystem_parameter_argc,8
+ .comm operatingsystem_parameter_argv,8
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/riscv_new/rtl/linux/riscv32/sighnd.inc b/riscv_new/rtl/linux/riscv32/sighnd.inc
new file mode 100644
index 0000000000..011b63a960
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/sighnd.inc
@@ -0,0 +1,44 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt,
+ member of the Free Pascal development team.
+
+ Signal handler is arch dependant due to processor to language
+ exception conversion.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+procedure SignalToRunerror(Sig: longint; SigInfo: PSigInfo; UContext: PUContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
+
+var
+ res : word;
+begin
+ res:=0;
+ case sig of
+ SIGFPE:
+ res:=207;
+ SIGILL:
+ res:=216;
+ SIGSEGV :
+ res:=216;
+ SIGBUS:
+ res:=214;
+ SIGINT:
+ res:=217;
+ SIGQUIT:
+ res:=233;
+ end;
+ reenable_signal(sig);
+ { give runtime error at the position where the signal was raised }
+ if res<>0 then
+ HandleErrorAddrFrame(res,
+ pointer(uContext^.uc_mcontext.pc),
+ pointer(uContext^.uc_mcontext.regs[29]));
+end;
diff --git a/riscv_new/rtl/linux/riscv32/sighndh.inc b/riscv_new/rtl/linux/riscv32/sighndh.inc
new file mode 100644
index 0000000000..8fa6a35ebd
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/sighndh.inc
@@ -0,0 +1,47 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Jonas Maebe,
+ member of the Free Pascal development team.
+
+ TSigContext and associated structures.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$packrecords C}
+
+type
+ PSigContext = ^TSigContext;
+ TSigContext = record
+ fault_address : cULong;
+ regs : array[0..30] of cULong;
+ sp : cULong;
+ pc : cULong;
+ pstate : cULong;
+ __pad : cULong;
+ { The following field should be 16-byte-aligned. Currently the
+ directive for specifying alignment is buggy, so the preceding
+ field was added so that the record has the right size. }
+ __reserved : array[0..4095] of cUChar;
+ end;
+
+ stack_t = record
+ ss_sp : pointer;
+ ss_flags : cInt;
+ ss_size : size_t;
+ end;
+
+ PUContext = ^TUContext;
+ TUContext = record
+ uc_flags : cULong;
+ uc_link : PUContext;
+ uc_stack : stack_t;
+ uc_mcontext : TSigContext;
+ uc_sigmask : sigset_t;
+ end;
diff --git a/riscv_new/rtl/linux/riscv32/stat.inc b/riscv_new/rtl/linux/riscv32/stat.inc
new file mode 100644
index 0000000000..6d69441361
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/stat.inc
@@ -0,0 +1,72 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Jonas Maebe, (c) 2005 Thomas Schatzl,
+ members of the Free Pascal development team.
+
+ Contains the definition of the stat type for the PowerPC64 platform.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ This structure was adapted from
+
+ include/uapi/asm-generic/stat.h
+
+ in Linux 4.0. Note that the stat record is the same for direct
+ syscalls as for when linking to libc.
+}
+
+{$PACKRECORDS C}
+ stat = record
+ case integer of
+ 0 : (
+ st_dev : cULong;
+ st_ino : cULong;
+ st_mode : cUInt;
+ st_nlink : cUInt;
+ st_uid : cUInt;
+ st_gid : cUInt;
+ st_rdev : cULong;
+ __pad1a : cULong;
+ st_size : cLong;
+ st_blksize : cInt;
+ __pad2a : cInt;
+ st_blocks : cLong;
+ st_atime : cLong;
+ st_atime_nsec : cULong;
+ st_mtime : cLong;
+ st_mtime_nsec : cULong;
+ st_ctime : cLong;
+ st_ctime_nsec : cULong;
+ __unused4a : cUInt;
+ __unused5a : cUInt;
+ );
+ 1 : (
+ dev : cULong deprecated;
+ ino : cULong deprecated;
+ mode : cUInt deprecated;
+ nlink : cUInt deprecated;
+ uid : cUInt deprecated;
+ gid : cUInt deprecated;
+ rdev : cULong deprecated;
+ __pad1b : cULong deprecated;
+ size : cLong deprecated;
+ blksize : cInt deprecated;
+ __pad2b : cInt deprecated;
+ blocks : cLong deprecated;
+ atime : cLong deprecated;
+ atime_nsec : cULong deprecated;
+ mtime : cLong deprecated;
+ mtime_nsec : cULong deprecated;
+ ctime : cLong deprecated;
+ ctime_nsec : cULong deprecated;
+ __unused4b : cUInt deprecated;
+ __unused5b : cUInt deprecated;
+ );
+ end;
diff --git a/riscv_new/rtl/linux/riscv32/syscall.inc b/riscv_new/rtl/linux/riscv32/syscall.inc
new file mode 100644
index 0000000000..a7ecca5d8c
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/syscall.inc
@@ -0,0 +1,141 @@
+{
+ This file is part of the Free Pascal run time library.
+
+ Perform syscall with 0..6 arguments.
+ If syscall return value is negative, negate it, set errno, and return -1.
+
+ Written by Edmund Grimley Evans in 2015 and released into the public domain.
+}
+
+function FpSysCall(sysnr:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
+asm
+ addi x17, sysnr, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL1'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL2'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL3'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL4'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ addi x13, x14, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL5'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ addi x13, x14, 0
+ addi x14, x15, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL6'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ addi x13, x14, 0
+ addi x14, x15, 0
+ addi x15, x16, 0
+ scall
+ bge x10,x0,.Ldone
+ sw x1, -4(x2)
+ addi x2, x2, -4
+ sub x10, x0, x10
+ jal x1, seterrno
+ addi x2, x2, 4
+ lw x1, -4(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
diff --git a/riscv_new/rtl/linux/riscv32/syscallh.inc b/riscv_new/rtl/linux/riscv32/syscallh.inc
new file mode 100644
index 0000000000..ea0768dd7f
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/syscallh.inc
@@ -0,0 +1,35 @@
+{
+ Copyright (c) 2002 by Marco van de Voort
+
+ Header for syscalls in system unit.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA.
+
+ ****************************************************************************
+
+}
+
+Type
+ TSysResult = longint;
+ TSysParam = longint;
+
+function Do_SysCall(sysnr:TSysParam):TSysResult; external name 'FPC_SYSCALL0';
+function Do_SysCall(sysnr,param1:TSysParam):TSysResult; external name 'FPC_SYSCALL1';
+function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult; external name 'FPC_SYSCALL2';
+function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; external name 'FPC_SYSCALL3';
+function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; external name 'FPC_SYSCALL4';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult; external name 'FPC_SYSCALL5';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult; external name 'FPC_SYSCALL6';
diff --git a/riscv_new/rtl/linux/riscv32/sysnr.inc b/riscv_new/rtl/linux/riscv32/sysnr.inc
new file mode 100644
index 0000000000..4d654232bf
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv32/sysnr.inc
@@ -0,0 +1,413 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2003-2004 by Florian Klaempfl,
+ member of the Free Pascal development team.
+
+ Syscall nrs for arm-linux
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
+{
+* This file contains the system call numbers.
+ Last update from 2.4.22 kernel sources according to the sources it contains already the 2.5 extensions
+}
+
+Const
+{$ifdef FPC_ABI_EABI}
+ syscall_nr_base = $0;
+{$else FPC_ABI_EABI}
+ syscall_nr_base = $900000;
+{$endif FPC_ABI_EABI}
+
+ syscall_nr_exit = syscall_nr_base+ 1;
+ syscall_nr_fork = syscall_nr_base+ 2;
+ syscall_nr_read = syscall_nr_base+ 3;
+ syscall_nr_write = syscall_nr_base+ 4;
+ syscall_nr_open = syscall_nr_base+ 5;
+ syscall_nr_close = syscall_nr_base+ 6;
+ // not supported: syscall_nr_waitpid = syscall_nr_base+ 7;
+ syscall_nr_creat = syscall_nr_base+ 8;
+ syscall_nr_link = syscall_nr_base+ 9;
+ syscall_nr_unlink = syscall_nr_base+10;
+ syscall_nr_execve = syscall_nr_base+11;
+ syscall_nr_chdir = syscall_nr_base+12;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_time = syscall_nr_base+13;
+{$endif}
+ syscall_nr_mknod = syscall_nr_base+14;
+ syscall_nr_chmod = syscall_nr_base+15;
+ syscall_nr_lchown = syscall_nr_base+16;
+ syscall_nr_break = syscall_nr_base+17;
+
+ syscall_nr_lseek = syscall_nr_base+19;
+ syscall_nr_getpid = syscall_nr_base+20;
+ syscall_nr_mount = syscall_nr_base+21;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_umount = syscall_nr_base+22;
+{$endif}
+ syscall_nr_setuid = syscall_nr_base+23;
+ syscall_nr_getuid = syscall_nr_base+24;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_stime = syscall_nr_base+25;
+{$endif}
+ syscall_nr_ptrace = syscall_nr_base+26;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_alarm = syscall_nr_base+27;
+{$endif}
+
+ syscall_nr_pause = syscall_nr_base+29;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_utime = syscall_nr_base+30;
+{$endif}
+ syscall_nr_stty = syscall_nr_base+31;
+ syscall_nr_gtty = syscall_nr_base+32;
+ syscall_nr_access = syscall_nr_base+33;
+ syscall_nr_nice = syscall_nr_base+34;
+ syscall_nr_ftime = syscall_nr_base+35;
+ syscall_nr_sync = syscall_nr_base+36;
+ syscall_nr_kill = syscall_nr_base+37;
+ syscall_nr_rename = syscall_nr_base+38;
+ syscall_nr_mkdir = syscall_nr_base+39;
+ syscall_nr_rmdir = syscall_nr_base+40;
+ syscall_nr_dup = syscall_nr_base+41;
+ syscall_nr_pipe = syscall_nr_base+42;
+ syscall_nr_times = syscall_nr_base+43;
+ syscall_nr_prof = syscall_nr_base+44;
+ syscall_nr_brk = syscall_nr_base+45;
+ syscall_nr_setgid = syscall_nr_base+46;
+ syscall_nr_getgid = syscall_nr_base+47;
+ syscall_nr_signal = syscall_nr_base+48;
+ syscall_nr_geteuid = syscall_nr_base+49;
+ syscall_nr_getegid = syscall_nr_base+50;
+ syscall_nr_acct = syscall_nr_base+51;
+ syscall_nr_umount2 = syscall_nr_base+52;
+ syscall_nr_lock = syscall_nr_base+53;
+ syscall_nr_ioctl = syscall_nr_base+54;
+ syscall_nr_fcntl = syscall_nr_base+55;
+ syscall_nr_mpx = syscall_nr_base+56;
+ syscall_nr_setpgid = syscall_nr_base+57;
+ syscall_nr_ulimit = syscall_nr_base+58;
+
+ syscall_nr_umask = syscall_nr_base+60;
+ syscall_nr_chroot = syscall_nr_base+61;
+ syscall_nr_ustat = syscall_nr_base+62;
+ syscall_nr_dup2 = syscall_nr_base+63;
+ syscall_nr_getppid = syscall_nr_base+64;
+ syscall_nr_getpgrp = syscall_nr_base+65;
+ syscall_nr_setsid = syscall_nr_base+66;
+ syscall_nr_sigaction = syscall_nr_base+67;
+ syscall_nr_sgetmask = syscall_nr_base+68;
+ syscall_nr_ssetmask = syscall_nr_base+69;
+ syscall_nr_setreuid = syscall_nr_base+70;
+ syscall_nr_setregid = syscall_nr_base+71;
+ syscall_nr_sigsuspend = syscall_nr_base+72;
+ syscall_nr_sigpending = syscall_nr_base+73;
+ syscall_nr_sethostname = syscall_nr_base+74;
+ syscall_nr_setrlimit = syscall_nr_base+75;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_getrlimit = syscall_nr_base+76;
+{$endif}
+ syscall_nr_getrusage = syscall_nr_base+77;
+ syscall_nr_gettimeofday = syscall_nr_base+78;
+ syscall_nr_settimeofday = syscall_nr_base+79;
+ syscall_nr_getgroups = syscall_nr_base+80;
+ syscall_nr_setgroups = syscall_nr_base+81;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_select = syscall_nr_base+82;
+{$endif}
+ syscall_nr_symlink = syscall_nr_base+83;
+
+ syscall_nr_readlink = syscall_nr_base+85;
+ syscall_nr_uselib = syscall_nr_base+86;
+ syscall_nr_swapon = syscall_nr_base+87;
+ syscall_nr_reboot = syscall_nr_base+88;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_readdir = syscall_nr_base+89;
+ syscall_nr_mmap = syscall_nr_base+90;
+{$endif}
+ syscall_nr_munmap = syscall_nr_base+91;
+ syscall_nr_truncate = syscall_nr_base+92;
+ syscall_nr_ftruncate = syscall_nr_base+93;
+ syscall_nr_fchmod = syscall_nr_base+94;
+ syscall_nr_fchown = syscall_nr_base+95;
+ syscall_nr_getpriority = syscall_nr_base+96;
+ syscall_nr_setpriority = syscall_nr_base+97;
+ syscall_nr_profil = syscall_nr_base+98;
+ syscall_nr_statfs = syscall_nr_base+99;
+ syscall_nr_fstatfs = syscall_nr_base+100;
+ syscall_nr_ioperm = syscall_nr_base+101;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_socketcall = syscall_nr_base+102;
+{$endif}
+ syscall_nr_syslog = syscall_nr_base+103;
+ syscall_nr_setitimer = syscall_nr_base+104;
+ syscall_nr_getitimer = syscall_nr_base+105;
+ syscall_nr_stat = syscall_nr_base+106;
+ syscall_nr_lstat = syscall_nr_base+107;
+ syscall_nr_fstat = syscall_nr_base+108;
+ syscall_nr_vhangup = syscall_nr_base+111;
+ syscall_nr_idle = syscall_nr_base+112;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_syscall = syscall_nr_base+113;
+{$endif}
+ syscall_nr_wait4 = syscall_nr_base+114;
+ syscall_nr_swapoff = syscall_nr_base+115;
+ syscall_nr_sysinfo = syscall_nr_base+116;
+{$ifndef FPC_ABI_EABI}
+ syscall_nr_ipc = syscall_nr_base+117;
+{$endif}
+ syscall_nr_fsync = syscall_nr_base+118;
+ syscall_nr_sigreturn = syscall_nr_base+119;
+ syscall_nr_clone = syscall_nr_base+120;
+ syscall_nr_setdomainname = syscall_nr_base+121;
+ syscall_nr_uname = syscall_nr_base+122;
+ syscall_nr_modify_ldt = syscall_nr_base+123;
+ syscall_nr_adjtimex = syscall_nr_base+124;
+ syscall_nr_mprotect = syscall_nr_base+125;
+ syscall_nr_sigprocmask = syscall_nr_base+126;
+ syscall_nr_create_module = syscall_nr_base+127;
+ syscall_nr_init_module = syscall_nr_base+128;
+ syscall_nr_delete_module = syscall_nr_base+129;
+ syscall_nr_get_kernel_syms = syscall_nr_base+130;
+ syscall_nr_quotactl = syscall_nr_base+131;
+ syscall_nr_getpgid = syscall_nr_base+132;
+ syscall_nr_fchdir = syscall_nr_base+133;
+ syscall_nr_bdflush = syscall_nr_base+134;
+ syscall_nr_sysfs = syscall_nr_base+135;
+ syscall_nr_personality = syscall_nr_base+136;
+ syscall_nr_afs_syscall = syscall_nr_base+137;
+ syscall_nr_setfsuid = syscall_nr_base+138;
+ syscall_nr_setfsgid = syscall_nr_base+139;
+ syscall_nr__llseek = syscall_nr_base+140;
+ syscall_nr_getdents = syscall_nr_base+141;
+ syscall_nr__newselect = syscall_nr_base+142;
+ syscall_nr_flock = syscall_nr_base+143;
+ syscall_nr_msync = syscall_nr_base+144;
+ syscall_nr_readv = syscall_nr_base+145;
+ syscall_nr_writev = syscall_nr_base+146;
+ syscall_nr_getsid = syscall_nr_base+147;
+ syscall_nr_fdatasync = syscall_nr_base+148;
+ syscall_nr__sysctl = syscall_nr_base+149;
+ syscall_nr_mlock = syscall_nr_base+150;
+ syscall_nr_munlock = syscall_nr_base+151;
+ syscall_nr_mlockall = syscall_nr_base+152;
+ syscall_nr_munlockall = syscall_nr_base+153;
+ syscall_nr_sched_setparam = syscall_nr_base+154;
+ syscall_nr_sched_getparam = syscall_nr_base+155;
+ syscall_nr_sched_setscheduler = syscall_nr_base+156;
+ syscall_nr_sched_getscheduler = syscall_nr_base+157;
+ syscall_nr_sched_yield = syscall_nr_base+158;
+ syscall_nr_sched_get_priority_max = syscall_nr_base+159;
+ syscall_nr_sched_get_priority_min = syscall_nr_base+160;
+ syscall_nr_sched_rr_get_interval = syscall_nr_base+161;
+ syscall_nr_nanosleep = syscall_nr_base+162;
+ syscall_nr_mremap = syscall_nr_base+163;
+ syscall_nr_setresuid = syscall_nr_base+164;
+ syscall_nr_getresuid = syscall_nr_base+165;
+ syscall_nr_vm86 = syscall_nr_base+166;
+ syscall_nr_query_module = syscall_nr_base+167;
+ syscall_nr_poll = syscall_nr_base+168;
+ syscall_nr_nfsservctl = syscall_nr_base+169;
+ syscall_nr_setresgid = syscall_nr_base+170;
+ syscall_nr_getresgid = syscall_nr_base+171;
+ syscall_nr_prctl = syscall_nr_base+172;
+ syscall_nr_rt_sigreturn = syscall_nr_base+173;
+ syscall_nr_rt_sigaction = syscall_nr_base+174;
+ syscall_nr_rt_sigprocmask = syscall_nr_base+175;
+ syscall_nr_rt_sigpending = syscall_nr_base+176;
+ syscall_nr_rt_sigtimedwait = syscall_nr_base+177;
+ syscall_nr_rt_sigqueueinfo = syscall_nr_base+178;
+ syscall_nr_rt_sigsuspend = syscall_nr_base+179;
+ syscall_nr_pread = syscall_nr_base+180;
+ syscall_nr_pwrite = syscall_nr_base+181;
+ syscall_nr_chown = syscall_nr_base+182;
+ syscall_nr_getcwd = syscall_nr_base+183;
+ syscall_nr_capget = syscall_nr_base+184;
+ syscall_nr_capset = syscall_nr_base+185;
+ syscall_nr_sigaltstack = syscall_nr_base+186;
+ syscall_nr_sendfile = syscall_nr_base+187;
+ syscall_nr_vfork = syscall_nr_base+190;
+ syscall_nr_ugetrlimit = syscall_nr_base+191;
+ syscall_nr_mmap2 = syscall_nr_base+192;
+ syscall_nr_truncate64 = syscall_nr_base+193;
+ syscall_nr_ftruncate64 = syscall_nr_base+194;
+ syscall_nr_stat64 = syscall_nr_base+195;
+ syscall_nr_lstat64 = syscall_nr_base+196;
+ syscall_nr_fstat64 = syscall_nr_base+197;
+ syscall_nr_lchown32 = syscall_nr_base+198;
+ syscall_nr_getuid32 = syscall_nr_base+199;
+ syscall_nr_getgid32 = syscall_nr_base+200;
+ syscall_nr_geteuid32 = syscall_nr_base+201;
+ syscall_nr_getegid32 = syscall_nr_base+202;
+ syscall_nr_setreuid32 = syscall_nr_base+203;
+ syscall_nr_setregid32 = syscall_nr_base+204;
+ syscall_nr_getgroups32 = syscall_nr_base+205;
+ syscall_nr_setgroups32 = syscall_nr_base+206;
+ syscall_nr_fchown32 = syscall_nr_base+207;
+ syscall_nr_setresuid32 = syscall_nr_base+208;
+ syscall_nr_getresuid32 = syscall_nr_base+209;
+ syscall_nr_setresgid32 = syscall_nr_base+210;
+ syscall_nr_getresgid32 = syscall_nr_base+211;
+ syscall_nr_chown32 = syscall_nr_base+212;
+ syscall_nr_setuid32 = syscall_nr_base+213;
+ syscall_nr_setgid32 = syscall_nr_base+214;
+ syscall_nr_setfsuid32 = syscall_nr_base+215;
+ syscall_nr_setfsgid32 = syscall_nr_base+216;
+ syscall_nr_getdents64 = syscall_nr_base+217;
+ syscall_nr_pivot_root = syscall_nr_base+218;
+ syscall_nr_mincore = syscall_nr_base+219;
+ syscall_nr_madvise = syscall_nr_base+220;
+ syscall_nr_fcntl64 = syscall_nr_base+221;
+ syscall_nr_security = syscall_nr_base+223;
+ syscall_nr_gettid = syscall_nr_base+224;
+ syscall_nr_readahead = syscall_nr_base+225;
+ syscall_nr_setxattr = syscall_nr_base+226;
+ syscall_nr_lsetxattr = syscall_nr_base+227;
+ syscall_nr_fsetxattr = syscall_nr_base+228;
+ syscall_nr_getxattr = syscall_nr_base+229;
+ syscall_nr_lgetxattr = syscall_nr_base+230;
+ syscall_nr_fgetxattr = syscall_nr_base+231;
+ syscall_nr_listxattr = syscall_nr_base+232;
+ syscall_nr_llistxattr = syscall_nr_base+233;
+ syscall_nr_flistxattr = syscall_nr_base+234;
+ syscall_nr_removexattr = syscall_nr_base+235;
+ syscall_nr_lremovexattr = syscall_nr_base+236;
+ syscall_nr_fremovexattr = syscall_nr_base+237;
+ syscall_nr_tkill = syscall_nr_base+238;
+ syscall_nr_sendfile64 = syscall_nr_base+239;
+ syscall_nr_futex = syscall_nr_base+240;
+ syscall_nr_sched_setaffinity = syscall_nr_base+241;
+ syscall_nr_sched_getaffinity = syscall_nr_base+242;
+ syscall_nr_io_setup = syscall_nr_base+243;
+ syscall_nr_io_destroy = syscall_nr_base+244;
+ syscall_nr_io_getevents = syscall_nr_base+245;
+ syscall_nr_io_submit = syscall_nr_base+246;
+ syscall_nr_io_cancel = syscall_nr_base+247;
+ syscall_nr_exit_group = syscall_nr_base+248;
+ syscall_nr_lookup_dcookie = syscall_nr_base+249;
+ syscall_nr_epoll_create = syscall_nr_base+250;
+ syscall_nr_epoll_ctl = syscall_nr_base+251;
+ syscall_nr_epoll_wait = syscall_nr_base+252;
+ syscall_nr_remap_file_pages = syscall_nr_base+253;
+ syscall_nr_set_tid_address = syscall_nr_base+256;
+ { 254 for set_thread_area }
+ { 255 for get_thread_area }
+ syscall_nr_timer_create = syscall_nr_base+257;
+ syscall_nr_timer_settime = syscall_nr_base+258;
+ syscall_nr_timer_gettime = syscall_nr_base+259;
+ syscall_nr_timer_getoverrun = syscall_nr_base+260;
+ syscall_nr_timer_delete = syscall_nr_base+261;
+ syscall_nr_clock_settime = syscall_nr_base+262;
+ syscall_nr_clock_gettime = syscall_nr_base+263;
+ syscall_nr_clock_getres = syscall_nr_base+264;
+ syscall_nr_clock_nanosleep = syscall_nr_base+265;
+ syscall_nr_statfs64 = syscall_nr_base+266;
+ syscall_nr_fstatfs64 = syscall_nr_base+267;
+ syscall_nr_tgkill = syscall_nr_base+268;
+ syscall_nr_utimes = syscall_nr_base+269;
+ syscall_nr_fadvise64_64 = syscall_nr_base+270;
+ syscall_nr_pciconfig_iobase = syscall_nr_base+271;
+ syscall_nr_pciconfig_read = syscall_nr_base+272;
+ syscall_nr_pciconfig_write = syscall_nr_base+273;
+ syscall_nr_mq_open = syscall_nr_base+274;
+ syscall_nr_mq_unlink = syscall_nr_base+275;
+ syscall_nr_mq_timedsend = syscall_nr_base+276;
+ syscall_nr_mq_timedreceive = syscall_nr_base+277;
+ syscall_nr_mq_notify = syscall_nr_base+278;
+ syscall_nr_mq_getsetattr = syscall_nr_base+279;
+ syscall_nr_waitid = syscall_nr_base+280;
+ syscall_nr_socket = syscall_nr_base+281;
+ syscall_nr_bind = syscall_nr_base+282;
+ syscall_nr_connect = syscall_nr_base+283;
+ syscall_nr_listen = syscall_nr_base+284;
+ syscall_nr_accept = syscall_nr_base+285;
+ syscall_nr_getsockname = syscall_nr_base+286;
+ syscall_nr_getpeername = syscall_nr_base+287;
+ syscall_nr_socketpair = syscall_nr_base+288;
+ syscall_nr_send = syscall_nr_base+289;
+ syscall_nr_sendto = syscall_nr_base+290;
+ syscall_nr_recv = syscall_nr_base+291;
+ syscall_nr_recvfrom = syscall_nr_base+292;
+ syscall_nr_shutdown = syscall_nr_base+293;
+ syscall_nr_setsockopt = syscall_nr_base+294;
+ syscall_nr_getsockopt = syscall_nr_base+295;
+ syscall_nr_sendmsg = syscall_nr_base+296;
+ syscall_nr_recvmsg = syscall_nr_base+297;
+ syscall_nr_semop = syscall_nr_base+298;
+ syscall_nr_semget = syscall_nr_base+299;
+ syscall_nr_semctl = syscall_nr_base+300;
+ syscall_nr_msgsnd = syscall_nr_base+301;
+ syscall_nr_msgrcv = syscall_nr_base+302;
+ syscall_nr_msgget = syscall_nr_base+303;
+ syscall_nr_msgctl = syscall_nr_base+304;
+ syscall_nr_shmat = syscall_nr_base+305;
+ syscall_nr_shmdt = syscall_nr_base+306;
+ syscall_nr_shmget = syscall_nr_base+307;
+ syscall_nr_shmctl = syscall_nr_base+308;
+ syscall_nr_add_key = syscall_nr_base+309;
+ syscall_nr_request_key = syscall_nr_base+310;
+ syscall_nr_keyctl = syscall_nr_base+311;
+ syscall_nr_semtimedop = syscall_nr_base+312;
+ syscall_nr_vserver = syscall_nr_base+313;
+ syscall_nr_ioprio_set = syscall_nr_base+314;
+ syscall_nr_ioprio_get = syscall_nr_base+315;
+ syscall_nr_inotify_init = syscall_nr_base+316;
+ syscall_nr_inotify_add_watch = syscall_nr_base+317;
+ syscall_nr_inotify_rm_watch = syscall_nr_base+318;
+ syscall_nr_mbind = syscall_nr_base+319;
+ syscall_nr_get_mempolicy = syscall_nr_base+320;
+ syscall_nr_set_mempolicy = syscall_nr_base+321;
+ syscall_nr_openat = syscall_nr_base+322;
+ syscall_nr_mkdirat = syscall_nr_base+323;
+ syscall_nr_mknodat = syscall_nr_base+324;
+ syscall_nr_fchownat = syscall_nr_base+325;
+ syscall_nr_futimesat = syscall_nr_base+326;
+ syscall_nr_fstatat64 = syscall_nr_base+327;
+ syscall_nr_unlinkat = syscall_nr_base+328;
+ syscall_nr_renameat = syscall_nr_base+329;
+ syscall_nr_linkat = syscall_nr_base+330;
+ syscall_nr_symlinkat = syscall_nr_base+331;
+ syscall_nr_readlinkat = syscall_nr_base+332;
+ syscall_nr_fchmodat = syscall_nr_base+333;
+ syscall_nr_faccessat = syscall_nr_base+334;
+ {* 335 for pselect6 *}
+ {* 336 for ppoll *}
+ syscall_nr_unshare = syscall_nr_base+337;
+ syscall_nr_set_robust_list = syscall_nr_base+338;
+ syscall_nr_get_robust_list = syscall_nr_base+339;
+ syscall_nr_splice = syscall_nr_base+340;
+ syscall_nr_arm_sync_file_range = syscall_nr_base+341;
+ syscall_nr_sync_file_range2 = syscall_nr_arm_sync_file_range;
+ syscall_nr_tee = syscall_nr_base+342;
+ syscall_nr_vmsplice = syscall_nr_base+343;
+ syscall_nr_move_pages = syscall_nr_base+344;
+ syscall_nr_getcpu = syscall_nr_base+345;
+ {* 346 for epoll_pwait *}
+ syscall_nr_kexec_load = syscall_nr_base+347;
+ syscall_nr_utimensat = syscall_nr_base+348;
+ syscall_nr_signalfd = syscall_nr_base+349;
+ syscall_nr_timerfd_create = syscall_nr_base+350;
+ syscall_nr_eventfd = syscall_nr_base+351;
+ syscall_nr_fallocate = syscall_nr_base+352;
+ syscall_nr_timerfd_settime = syscall_nr_base+353;
+ syscall_nr_timerfd_gettime = syscall_nr_base+354;
+ syscall_nr_signalfd4 = syscall_nr_base+355;
+ syscall_nr_eventfd2 = syscall_nr_base+356;
+ syscall_nr_epoll_create1 = syscall_nr_base+357;
+ syscall_nr_dup3 = syscall_nr_base+358;
+ syscall_nr_pipe2 = syscall_nr_base+359;
+ syscall_nr_inotify_init1 = syscall_nr_base+360;
+ syscall_nr_preadv = syscall_nr_base+361;
+ syscall_nr_pwritev = syscall_nr_base+362;
+ syscall_nr_rt_tgsigqueueinfo = syscall_nr_base+363;
+ syscall_nr_perf_event_open = syscall_nr_base+364;
+ syscall_nr_recvmmsg = syscall_nr_base+365;
+
diff --git a/riscv_new/rtl/linux/riscv64/bsyscall.inc b/riscv_new/rtl/linux/riscv64/bsyscall.inc
new file mode 100644
index 0000000000..c690ebeb2c
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/bsyscall.inc
@@ -0,0 +1 @@
+{ nothing }
diff --git a/riscv_new/rtl/linux/riscv64/cprt0.as b/riscv_new/rtl/linux/riscv64/cprt0.as
new file mode 100644
index 0000000000..5b9474e9c3
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/cprt0.as
@@ -0,0 +1,139 @@
+/* Startup code for ARM & ELF
+ Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment.
+
+ Note that the code in the .init section has already been run.
+ This includes _init and _libc_init
+
+
+ At this entry point, most registers' values are unspecified, except:
+
+ a1 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ sp The stack contains the arguments and environment:
+ 0(sp) argc
+ 4(sp) argv[0]
+ ...
+ (4*argc)(sp) NULL
+ (4*(argc+1))(sp) envp[0]
+ ...
+ NULL
+*/
+
+ .text
+ .globl _start
+ .type _start,function
+_start:
+ /* Clear the frame pointer since this is the outermost frame. */
+ mov fp, #0
+ ldmia sp!, {a2}
+
+ /* Pop argc off the stack and save a pointer to argv */
+ ldr ip,=operatingsystem_parameter_argc
+ ldr a3,=operatingsystem_parameter_argv
+ str a2,[ip]
+
+ /* calc envp */
+ add a4,a2,#1
+ add a4,sp,a4,LSL #2
+ ldr ip,=operatingsystem_parameter_envp
+
+ str sp,[a3]
+ str a4,[ip]
+
+ /* Save initial stackpointer */
+ ldr ip,=__stkptr
+ str sp,[ip]
+
+ /* Fetch address of fini */
+ ldr ip, =_fini
+
+ /* argc already loaded to a2*/
+
+ /* load argv */
+ mov a3, sp
+
+ /* Push stack limit */
+ str a3, [sp, #-4]!
+
+ /* Push rtld_fini */
+ str a1, [sp, #-4]!
+
+ /* Set up the other arguments in registers */
+ ldr a1, =PASCALMAIN
+ ldr a4, =_init
+
+ /* Push fini */
+ str ip, [sp, #-4]!
+
+ /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+
+ /* Let the libc call main and exit with its return code. */
+ bl __libc_start_main
+
+ /* should never get here....*/
+ bl abort
+
+ .globl _haltproc
+ .type _haltproc,function
+_haltproc:
+ ldr r0,=operatingsystem_result
+ ldrb r0,[r0]
+ swi 0x900001
+ b _haltproc
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
+
+.bss
+ .comm __stkptr,4
+
+ .comm operatingsystem_parameter_envp,4
+ .comm operatingsystem_parameter_argc,4
+ .comm operatingsystem_parameter_argv,4
+
+ .section ".comment"
+ .byte 0
+ .ascii "generated by FPC http://www.freepascal.org\0"
+
+/* We need this stuff to make gdb behave itself, otherwise
+ gdb will chokes with SIGILL when trying to debug apps.
+*/
+ .section ".note.ABI-tag", "a"
+ .align 4
+ .long 1f - 0f
+ .long 3f - 2f
+ .long 1
+0: .asciz "GNU"
+1: .align 4
+2: .long 0
+ .long 2,0,0
+3: .align 4
+
+.section .note.GNU-stack,"",%progbits
diff --git a/riscv_new/rtl/linux/riscv64/dllprt0.as b/riscv_new/rtl/linux/riscv64/dllprt0.as
new file mode 100644
index 0000000000..a7b7ee585d
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/dllprt0.as
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the Free Pascal run time library.
+ * Copyright (c) 2011 by Thomas Schatzl,
+ * member of the Free Pascal development team.
+ *
+ * Startup code for shared libraries, ARM version.
+ *
+ * See the file COPYING.FPC, included in this distribution,
+ * for details about the copyright.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+.file "dllprt0.as"
+.text
+ .globl _startlib
+ .type _startlib,function
+_startlib:
+ .globl FPC_SHARED_LIB_START
+ .type FPC_SHARED_LIB_START,function
+FPC_SHARED_LIB_START:
+ sw x1, -4(x2)
+ sw x8, -8(x2)
+ addi x8, x2, 0
+ addi x2, x2, -8
+
+ /* a1 contains argc, a2 contains argv and a3 contains envp */
+ lui x15, %hi(operatingsystem_parameter_argc)
+ addi x15,x15,%lo(operatingsystem_parameter_argc)
+ sw a1, (x15)
+
+ lui x15, %hi(operatingsystem_parameter_argv)
+ addi x15,x15,%lo(operatingsystem_parameter_argv)
+ sw a2, (x15)
+
+ lui x15, %hi(operatingsystem_parameter_envp)
+ addi x15,x15,%lo(operatingsystem_parameter_envp)
+ sw a3, (x15)
+
+ /* save initial stackpointer */
+ lui x15, %hi(__stklen)
+ addi x15,x15,%lo(__stklen)
+ sw x2, (x15)
+
+ /* call main and exit normally */
+ jal x1, PASCALMAIN
+ lw x8, -8(x8)
+ lw x1, -4(x8)
+
+ jalr x0, x1
+
+ .globl _haltproc
+ .type _haltproc,function
+_haltproc:
+ /* reload exitcode */
+ lui x10, %hi(operatingsystem_result)
+ addi x10,x10,%lo(operatingsystem_result)
+ addi x17, x0, 248
+ scall
+ jal x0, _haltproc
+
+.data
+
+ .type operatingsystem_parameters,object
+ .size operatingsystem_parameters,12
+operatingsystem_parameters:
+ .skip 3*4
+ .global operatingsystem_parameter_envp
+ .global operatingsystem_parameter_argc
+ .global operatingsystem_parameter_argv
+ .set operatingsystem_parameter_envp,operatingsystem_parameters+0
+ .set operatingsystem_parameter_argc,operatingsystem_parameters+4
+ .set operatingsystem_parameter_argv,operatingsystem_parameters+8
+
+.bss
+
+ .comm __stkptr,4
+
diff --git a/riscv_new/rtl/linux/riscv64/gprt0.as b/riscv_new/rtl/linux/riscv64/gprt0.as
new file mode 100644
index 0000000000..592c9c9b96
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/gprt0.as
@@ -0,0 +1,162 @@
+/* Startup code for ARM & ELF
+ Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment.
+
+ Note that the code in the .init section has already been run.
+ This includes _init and _libc_init
+
+
+ At this entry point, most registers' values are unspecified, except:
+
+ a1 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ sp The stack contains the arguments and environment:
+ 0(sp) argc
+ 4(sp) argv[0]
+ ...
+ (4*argc)(sp) NULL
+ (4*(argc+1))(sp) envp[0]
+ ...
+ NULL
+*/
+
+ .text
+ .globl _start
+ .type _start,#function
+_start:
+ /* Clear the frame pointer since this is the outermost frame. */
+ addi x8, x0, 0
+ ld a2, (sp)
+ addi sp, sp, 4
+
+ /* Pop argc off the stack and save a pointer to argv */
+ la x5, operatingsystem_parameter_argc
+ la x6,operatingsystem_parameter_argv
+ sd a2, (x5)
+
+ /* calc envp */
+ addi a4,a2,1
+ slli a4,a4,3
+ add a4,sp,a4
+ la x5, operatingsystem_parameter_envp
+
+ sd sp,(a3)
+ sd a4,(x5)
+
+ /* Save initial stackpointer */
+ la x5,__stkptr
+ sd sp, (x5)
+
+ /* Initialize gmon */
+ mov r2,#1
+ ldr r1,=_etext
+ ldr r0,=_start
+ bl __monstartup
+ ldr r0,=_mcleanup
+ bl atexit
+
+ /* argc already loaded to a2*/
+ ldr ip, =operatingsystem_parameter_argc
+ ldr a2,[ip]
+
+ /* Fetch address of fini */
+ ldr ip, =_fini
+
+ /* load argv */
+ mov a3, sp
+
+ /* Push stack limit */
+ str a3, [sp, #-4]!
+
+ /* Push rtld_fini */
+ str a1, [sp, #-4]!
+
+ /* Set up the other arguments in registers */
+ ldr a1, =PASCALMAIN
+ ldr a4, =_init
+
+ /* Push fini */
+ str ip, [sp, #-4]!
+
+ /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+
+ /* Let the libc call main and exit with its return code. */
+ bl __libc_start_main
+
+ /* should never get here....*/
+ bl abort
+
+ .globl _haltproc
+ .type _haltproc,#function
+_haltproc:
+ ldr r0,=operatingsystem_result
+ ldrb r0,[r0]
+ swi 0x900001
+ b _haltproc
+
+ .globl _haltproc_eabi
+ .type _haltproc_eabi,#function
+_haltproc_eabi:
+ bl exit /* libc exit */
+
+ ldr r0,=operatingsystem_result
+ ldrb r0,[r0]
+ mov r7,#248
+ swi 0x0
+ b _haltproc_eabi
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
+
+.bss
+ .comm __stkptr,4
+
+ .comm operatingsystem_parameter_envp,4
+ .comm operatingsystem_parameter_argc,4
+ .comm operatingsystem_parameter_argv,4
+
+ .section ".comment"
+ .byte 0
+ .ascii "generated by FPC http://www.freepascal.org\0"
+
+/* We need this stuff to make gdb behave itself, otherwise
+ gdb will chokes with SIGILL when trying to debug apps.
+*/
+ .section ".note.ABI-tag", "a"
+ .align 4
+ .long 1f - 0f
+ .long 3f - 2f
+ .long 1
+0: .asciz "GNU"
+1: .align 4
+2: .long 0
+ .long 2,0,0
+3: .align 4
+
+.section .note.GNU-stack,"",%progbits
diff --git a/riscv_new/rtl/linux/riscv64/prt0.as b/riscv_new/rtl/linux/riscv64/prt0.as
new file mode 100644
index 0000000000..d489b5dcad
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/prt0.as
@@ -0,0 +1,83 @@
+/*
+ Start-up code for Free Pascal Compiler, not in a shared library,
+ not linking with C library.
+
+ Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+ .text
+ .align 2
+
+ .globl _dynamic_start
+ .type _dynamic_start, function
+_dynamic_start:
+1:
+ auipc x5,%pcrel_hi(__dl_fini)
+ sd x10, %pcrel_lo(1b)(x5)
+ jal x0, _start
+
+ .globl _start
+ .type _start, function
+_start:
+1:
+ auipc gp, %pcrel_hi(__bss_start+0x800)
+ addi gp, gp, %pcrel_lo(1b)
+
+ /* Get argc, argv, envp */
+ ld x5,(x2)
+ addi x6,x2,8
+ addi x7,x5,1
+ slli x7,x7,3
+ add x7,x6,x7
+
+ /* Save argc, argv, envp, and initial stack pointer */
+1:auipc x8,%pcrel_hi(operatingsystem_parameter_argc)
+ sd x5,%pcrel_lo(1b)(x8)
+1:auipc x8,%pcrel_hi(operatingsystem_parameter_argv)
+ sd x6,%pcrel_lo(1b)(x8)
+1:auipc x8,%pcrel_hi(operatingsystem_parameter_envp)
+ sd x7,%pcrel_lo(1b)(x8)
+1:auipc x5,%pcrel_hi(__stkptr)
+ addi x6, x2, 0
+ sd x6,%pcrel_lo(1b)(x5)
+
+ /* Initialise FP to zero */
+ addi x8,x0,0
+
+ /* Call main */
+ jal x1, PASCALMAIN
+
+ .globl _haltproc
+ .type _haltproc,function
+_haltproc:
+1:auipc x10,%pcrel_hi(__dl_fini)
+ ld x10,%pcrel_lo(1b)(x10)
+ beq x10,x0,.Lexit
+ jalr x1,x10
+.Lexit:
+1:auipc x10,%pcrel_hi(operatingsystem_result)
+ ld x10,%pcrel_lo(1b)(x10)
+ addi x17, x0, 94
+ ecall
+ jal x0, _haltproc
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .align 4
+ .globl __data_start
+__data_start:
+ .quad 0
+ .weak data_start
+ data_start = __data_start
+
+ .bss
+ .align 4
+
+ .comm __dl_fini,8
+ .comm __stkptr,8
+
+ .comm operatingsystem_parameter_envp,8
+ .comm operatingsystem_parameter_argc,8
+ .comm operatingsystem_parameter_argv,8
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/riscv_new/rtl/linux/riscv64/sighnd.inc b/riscv_new/rtl/linux/riscv64/sighnd.inc
new file mode 100644
index 0000000000..011b63a960
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/sighnd.inc
@@ -0,0 +1,44 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt,
+ member of the Free Pascal development team.
+
+ Signal handler is arch dependant due to processor to language
+ exception conversion.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+procedure SignalToRunerror(Sig: longint; SigInfo: PSigInfo; UContext: PUContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
+
+var
+ res : word;
+begin
+ res:=0;
+ case sig of
+ SIGFPE:
+ res:=207;
+ SIGILL:
+ res:=216;
+ SIGSEGV :
+ res:=216;
+ SIGBUS:
+ res:=214;
+ SIGINT:
+ res:=217;
+ SIGQUIT:
+ res:=233;
+ end;
+ reenable_signal(sig);
+ { give runtime error at the position where the signal was raised }
+ if res<>0 then
+ HandleErrorAddrFrame(res,
+ pointer(uContext^.uc_mcontext.pc),
+ pointer(uContext^.uc_mcontext.regs[29]));
+end;
diff --git a/riscv_new/rtl/linux/riscv64/sighndh.inc b/riscv_new/rtl/linux/riscv64/sighndh.inc
new file mode 100644
index 0000000000..8fa6a35ebd
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/sighndh.inc
@@ -0,0 +1,47 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Jonas Maebe,
+ member of the Free Pascal development team.
+
+ TSigContext and associated structures.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$packrecords C}
+
+type
+ PSigContext = ^TSigContext;
+ TSigContext = record
+ fault_address : cULong;
+ regs : array[0..30] of cULong;
+ sp : cULong;
+ pc : cULong;
+ pstate : cULong;
+ __pad : cULong;
+ { The following field should be 16-byte-aligned. Currently the
+ directive for specifying alignment is buggy, so the preceding
+ field was added so that the record has the right size. }
+ __reserved : array[0..4095] of cUChar;
+ end;
+
+ stack_t = record
+ ss_sp : pointer;
+ ss_flags : cInt;
+ ss_size : size_t;
+ end;
+
+ PUContext = ^TUContext;
+ TUContext = record
+ uc_flags : cULong;
+ uc_link : PUContext;
+ uc_stack : stack_t;
+ uc_mcontext : TSigContext;
+ uc_sigmask : sigset_t;
+ end;
diff --git a/riscv_new/rtl/linux/riscv64/stat.inc b/riscv_new/rtl/linux/riscv64/stat.inc
new file mode 100644
index 0000000000..6d69441361
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/stat.inc
@@ -0,0 +1,72 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Jonas Maebe, (c) 2005 Thomas Schatzl,
+ members of the Free Pascal development team.
+
+ Contains the definition of the stat type for the PowerPC64 platform.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ This structure was adapted from
+
+ include/uapi/asm-generic/stat.h
+
+ in Linux 4.0. Note that the stat record is the same for direct
+ syscalls as for when linking to libc.
+}
+
+{$PACKRECORDS C}
+ stat = record
+ case integer of
+ 0 : (
+ st_dev : cULong;
+ st_ino : cULong;
+ st_mode : cUInt;
+ st_nlink : cUInt;
+ st_uid : cUInt;
+ st_gid : cUInt;
+ st_rdev : cULong;
+ __pad1a : cULong;
+ st_size : cLong;
+ st_blksize : cInt;
+ __pad2a : cInt;
+ st_blocks : cLong;
+ st_atime : cLong;
+ st_atime_nsec : cULong;
+ st_mtime : cLong;
+ st_mtime_nsec : cULong;
+ st_ctime : cLong;
+ st_ctime_nsec : cULong;
+ __unused4a : cUInt;
+ __unused5a : cUInt;
+ );
+ 1 : (
+ dev : cULong deprecated;
+ ino : cULong deprecated;
+ mode : cUInt deprecated;
+ nlink : cUInt deprecated;
+ uid : cUInt deprecated;
+ gid : cUInt deprecated;
+ rdev : cULong deprecated;
+ __pad1b : cULong deprecated;
+ size : cLong deprecated;
+ blksize : cInt deprecated;
+ __pad2b : cInt deprecated;
+ blocks : cLong deprecated;
+ atime : cLong deprecated;
+ atime_nsec : cULong deprecated;
+ mtime : cLong deprecated;
+ mtime_nsec : cULong deprecated;
+ ctime : cLong deprecated;
+ ctime_nsec : cULong deprecated;
+ __unused4b : cUInt deprecated;
+ __unused5b : cUInt deprecated;
+ );
+ end;
diff --git a/riscv_new/rtl/linux/riscv64/syscall.inc b/riscv_new/rtl/linux/riscv64/syscall.inc
new file mode 100644
index 0000000000..6abf3ac807
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/syscall.inc
@@ -0,0 +1,155 @@
+{
+ This file is part of the Free Pascal run time library.
+
+ Perform syscall with 0..6 arguments.
+ If syscall return value is negative, negate it, set errno, and return -1.
+
+ Written by Edmund Grimley Evans in 2015 and released into the public domain.
+}
+
+function FpSysCall(sysnr:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
+asm
+ addi x17, sysnr, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL1'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL2'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL3'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL4'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ addi x13, x14, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL5'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ addi x13, x14, 0
+ addi x14, x15, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL6'];
+asm
+ addi x17, sysnr, 0
+ addi x10, x11, 0
+ addi x11, x12, 0
+ addi x12, x13, 0
+ addi x13, x14, 0
+ addi x14, x15, 0
+ addi x15, x16, 0
+ ecall
+ bge x10,x0,.Ldone
+ sd x1, -8(x2)
+ addi x2, x2, -8
+ sub x10, x0, x10
+.Ll1:
+ auipc x1, %pcrel_hi(seterrno)
+ jalr x1, x1, %pcrel_lo(.Ll1)
+ addi x2, x2, 8
+ ld x1, -8(x2)
+ addi x10,x0, -1
+.Ldone:
+end;
diff --git a/riscv_new/rtl/linux/riscv64/syscallh.inc b/riscv_new/rtl/linux/riscv64/syscallh.inc
new file mode 100644
index 0000000000..6961a190ca
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/syscallh.inc
@@ -0,0 +1,35 @@
+{
+ Copyright (c) 2002 by Marco van de Voort
+
+ Header for syscalls in system unit.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA.
+
+ ****************************************************************************
+
+}
+
+Type
+ TSysResult = Int64;
+ TSysParam = Int64;
+
+function Do_SysCall(sysnr:TSysParam):TSysResult; external name 'FPC_SYSCALL0';
+function Do_SysCall(sysnr,param1:TSysParam):TSysResult; external name 'FPC_SYSCALL1';
+function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult; external name 'FPC_SYSCALL2';
+function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; external name 'FPC_SYSCALL3';
+function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; external name 'FPC_SYSCALL4';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult; external name 'FPC_SYSCALL5';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult; external name 'FPC_SYSCALL6';
diff --git a/riscv_new/rtl/linux/riscv64/sysnr.inc b/riscv_new/rtl/linux/riscv64/sysnr.inc
new file mode 100644
index 0000000000..3763caa818
--- /dev/null
+++ b/riscv_new/rtl/linux/riscv64/sysnr.inc
@@ -0,0 +1 @@
+{$i ../sysnr-gen.inc}
diff --git a/riscv_new/rtl/linux/system.pp b/riscv_new/rtl/linux/system.pp
index 332a7fb54b..398bf6471d 100644
--- a/riscv_new/rtl/linux/system.pp
+++ b/riscv_new/rtl/linux/system.pp
@@ -45,13 +45,13 @@ const
function get_cmdline:Pchar; deprecated 'use paramstr' ;
property cmdline:Pchar read get_cmdline;
-{$if defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
+{$if defined(CPURISCV32) or defined(CPURISCV64) or defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
{$define fpc_softfpu_interface}
{$i softfpu.pp}
{$undef fpc_softfpu_interface}
-{$endif defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
+{$endif defined(CPURISCV32) or defined(CPURISCV64) or defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
{$ifdef android}
{$I sysandroidh.inc}
@@ -73,7 +73,7 @@ const
procedure OsSetupEntryInformation(constref info: TEntryInformation); forward;
{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
-{$if defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
+{$if defined(CPURISCV32) or defined(CPURISCV64) or defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
{$define fpc_softfpu_implementation}
{$if defined(CPUM68K)}
@@ -95,7 +95,7 @@ procedure OsSetupEntryInformation(constref info: TEntryInformation); forward;
{$define FPC_SYSTEM_HAS_extractFloat32Exp}
{$define FPC_SYSTEM_HAS_extractFloat32Sign}
-{$endif defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
+{$endif defined(CPURISCV32) or defined(CPURISCV64) or defined(CPUARM) or defined(CPUM68K) or (defined(CPUSPARC) and defined(VER2_6))}
{$I system.inc}
diff --git a/riscv_new/rtl/linux/termios.inc b/riscv_new/rtl/linux/termios.inc
index 8bc408362e..0e0d5abbc4 100644
--- a/riscv_new/rtl/linux/termios.inc
+++ b/riscv_new/rtl/linux/termios.inc
@@ -556,6 +556,536 @@ Const
{$endif cpupowerpc}
+{$ifdef cpuriscv32}
+
+{ from Linux 4.0, include/uapi/asm-generic/ioctls.h }
+
+ { For Terminal handling }
+ TCGETS = $5401;
+ TCSETS = $5402;
+ TCSETSW = $5403;
+ TCSETSF = $5404;
+ TCGETA = $5405;
+ TCSETA = $5406;
+ TCSETAW = $5407;
+ TCSETAF = $5408;
+ TCSBRK = $5409;
+ TCXONC = $540A;
+ TCFLSH = $540B;
+ TIOCEXCL = $540C;
+ TIOCNXCL = $540D;
+ TIOCSCTTY = $540E;
+ TIOCGPGRP = $540F;
+ TIOCSPGRP = $5410;
+ TIOCOUTQ = $5411;
+ TIOCSTI = $5412;
+ TIOCGWINSZ = $5413;
+ TIOCSWINSZ = $5414;
+ TIOCMGET = $5415;
+ TIOCMBIS = $5416;
+ TIOCMBIC = $5417;
+ TIOCMSET = $5418;
+ TIOCGSOFTCAR = $5419;
+ TIOCSSOFTCAR = $541A;
+ FIONREAD = $541B;
+ TIOCINQ = FIONREAD;
+ TIOCLINUX = $541C;
+ TIOCCONS = $541D;
+ TIOCGSERIAL = $541E;
+ TIOCSSERIAL = $541F;
+ TIOCPKT = $5420;
+ FIONBIO = $5421;
+ TIOCNOTTY = $5422;
+ TIOCSETD = $5423;
+ TIOCGETD = $5424;
+ TCSBRKP = $5425;
+
+ TIOCSBRK = $5427;
+ TIOCCBRK = $5428;
+ TIOCGSID = $5429;
+
+ TIOCGRS485 = $542E;
+ TIOCSRS485 = $542F;
+
+ TCGETX = $5432;
+ TCSETX = $5433;
+ TCSETXF = $5434;
+ TCSETXW = $5435;
+ TIOCVHANGUP = $5437;
+
+ FIONCLEX = $5450;
+ FIOCLEX = $5451;
+ FIOASYNC = $5452;
+ TIOCSERCONFIG = $5453;
+ TIOCSERGWILD = $5454;
+ TIOCSERSWILD = $5455;
+ TIOCGLCKTRMIOS = $5456;
+ TIOCSLCKTRMIOS = $5457;
+ TIOCSERGSTRUCT = $5458;
+ TIOCSERGETLSR = $5459;
+ TIOCSERGETMULTI = $545A;
+ TIOCSERSETMULTI = $545B;
+ TIOCMIWAIT = $545C;
+ TIOCGICOUNT = $545D;
+
+ FIOQSIZE = $5460;
+
+ TIOCPKT_DATA = 0;
+ TIOCPKT_FLUSHREAD = 1;
+ TIOCPKT_FLUSHWRITE = 2;
+ TIOCPKT_STOP = 4;
+ TIOCPKT_START = 8;
+ TIOCPKT_NOSTOP = 16;
+ TIOCPKT_DOSTOP = 32;
+ TIOCPKT_IOCTL = 64;
+
+ TIOCSER_TEMT = $01;
+
+{ from Linux 4.0, include/uapi/asm-generic/termbits.h }
+
+ { c_cc characters }
+ VINTR = 0;
+ VQUIT = 1;
+ VERASE = 2;
+ VKILL = 3;
+ VEOF = 4;
+ VTIME = 5;
+ VMIN = 6;
+ VSWTC = 7;
+ VSTART = 8;
+ VSTOP = 9;
+ VSUSP = 10;
+ VEOL = 11;
+ VREPRINT = 12;
+ VDISCARD = 13;
+ VWERASE = 14;
+ VLNEXT = 15;
+ VEOL2 = 16;
+
+ { c_iflag bits }
+ IGNBRK = &0000001;
+ BRKINT = &0000002;
+ IGNPAR = &0000004;
+ PARMRK = &0000010;
+ INPCK = &0000020;
+ ISTRIP = &0000040;
+ INLCR = &0000100;
+ IGNCR = &0000200;
+ ICRNL = &0000400;
+ IUCLC = &0001000;
+ IXON = &0002000;
+ IXANY = &0004000;
+ IXOFF = &0010000;
+ IMAXBEL = &0020000;
+ IUTF8 = &0040000;
+
+ { c_oflag bits }
+ OPOST = &0000001;
+ OLCUC = &0000002;
+ ONLCR = &0000004;
+ OCRNL = &0000010;
+ ONOCR = &0000020;
+ ONLRET = &0000040;
+ OFILL = &0000100;
+ OFDEL = &0000200;
+ NLDLY = &0000400;
+ NL0 = &0000000;
+ NL1 = &0000400;
+ CRDLY = &0003000;
+ CR0 = &0000000;
+ CR1 = &0001000;
+ CR2 = &0002000;
+ CR3 = &0003000;
+ TABDLY = &0014000;
+ TAB0 = &0000000;
+ TAB1 = &0004000;
+ TAB2 = &0010000;
+ TAB3 = &0014000;
+ XTABS = &0014000;
+ BSDLY = &0020000;
+ BS0 = &0000000;
+ BS1 = &0020000;
+ VTDLY = &0040000;
+ VT0 = &0000000;
+ VT1 = &0040000;
+ FFDLY = &0100000;
+ FF0 = &0000000;
+ FF1 = &0100000;
+
+ { c_cflag bits }
+ CBAUD = &0010017;
+ B0 = &0000000;
+ B50 = &0000001;
+ B75 = &0000002;
+ B110 = &0000003;
+ B134 = &0000004;
+ B150 = &0000005;
+ B200 = &0000006;
+ B300 = &0000007;
+ B600 = &0000010;
+ B1200 = &0000011;
+ B1800 = &0000012;
+ B2400 = &0000013;
+ B4800 = &0000014;
+ B9600 = &0000015;
+ B19200 = &0000016;
+ B38400 = &0000017;
+ EXTA = B19200;
+ EXTB = B38400;
+ CSIZE = &0000060;
+ CS5 = &0000000;
+ CS6 = &0000020;
+ CS7 = &0000040;
+ CS8 = &0000060;
+ CSTOPB = &0000100;
+ CREAD = &0000200;
+ PARENB = &0000400;
+ PARODD = &0001000;
+ HUPCL = &0002000;
+ CLOCAL = &0004000;
+ CBAUDEX = &0010000;
+ BOTHER = &0010000;
+ B57600 = &0010001;
+ B115200 = &0010002;
+ B230400 = &0010003;
+ B460800 = &0010004;
+ B500000 = &0010005;
+ B576000 = &0010006;
+ B921600 = &0010007;
+ B1000000 = &0010010;
+ B1152000 = &0010011;
+ B1500000 = &0010012;
+ B2000000 = &0010013;
+ B2500000 = &0010014;
+ B3000000 = &0010015;
+ B3500000 = &0010016;
+ B4000000 = &0010017;
+
+ CIBAUD = &002003600000;
+ CMSPAR = &010000000000;
+ CRTSCTS = &020000000000;
+
+ IBSHIFT = 16;
+
+ { c_lflag bits }
+ ISIG = &0000001;
+ ICANON = &0000002;
+ XCASE = &0000004;
+ ECHO = &0000010;
+ ECHOE = &0000020;
+ ECHOK = &0000040;
+ ECHONL = &0000100;
+ NOFLSH = &0000200;
+ TOSTOP = &0000400;
+ ECHOCTL = &0001000;
+ ECHOPRT = &0002000;
+ ECHOKE = &0004000;
+ FLUSHO = &0010000;
+ PENDIN = &0040000;
+ IEXTEN = &0100000;
+ EXTPROC = &0200000;
+
+ { TCFlow }
+ TCOOFF = 0;
+ TCOON = 1;
+ TCIOFF = 2;
+ TCION = 3;
+
+ { TCFlush }
+ TCIFLUSH = 0;
+ TCOFLUSH = 1;
+ TCIOFLUSH = 2;
+
+ { TCSetAttr }
+ TCSANOW = 0;
+ TCSADRAIN = 1;
+ TCSAFLUSH = 2;
+
+{ from Linux 4.0, include/uapi/asm-generic/termios.h }
+
+ { c_line bits }
+ TIOCM_LE = $001;
+ TIOCM_DTR = $002;
+ TIOCM_RTS = $004;
+ TIOCM_ST = $008;
+ TIOCM_SR = $010;
+ TIOCM_CTS = $020;
+ TIOCM_CAR = $040;
+ TIOCM_RNG = $080;
+ TIOCM_DSR = $100;
+ TIOCM_CD = TIOCM_CAR;
+ TIOCM_RI = TIOCM_RNG;
+ TIOCM_OUT1 = $2000;
+ TIOCM_OUT2 = $4000;
+ TIOCM_LOOP = $8000;
+
+{$endif cpuriscv32}
+
+{$ifdef cpuriscv64}
+
+{ from Linux 4.0, include/uapi/asm-generic/ioctls.h }
+
+ { For Terminal handling }
+ TCGETS = $5401;
+ TCSETS = $5402;
+ TCSETSW = $5403;
+ TCSETSF = $5404;
+ TCGETA = $5405;
+ TCSETA = $5406;
+ TCSETAW = $5407;
+ TCSETAF = $5408;
+ TCSBRK = $5409;
+ TCXONC = $540A;
+ TCFLSH = $540B;
+ TIOCEXCL = $540C;
+ TIOCNXCL = $540D;
+ TIOCSCTTY = $540E;
+ TIOCGPGRP = $540F;
+ TIOCSPGRP = $5410;
+ TIOCOUTQ = $5411;
+ TIOCSTI = $5412;
+ TIOCGWINSZ = $5413;
+ TIOCSWINSZ = $5414;
+ TIOCMGET = $5415;
+ TIOCMBIS = $5416;
+ TIOCMBIC = $5417;
+ TIOCMSET = $5418;
+ TIOCGSOFTCAR = $5419;
+ TIOCSSOFTCAR = $541A;
+ FIONREAD = $541B;
+ TIOCINQ = FIONREAD;
+ TIOCLINUX = $541C;
+ TIOCCONS = $541D;
+ TIOCGSERIAL = $541E;
+ TIOCSSERIAL = $541F;
+ TIOCPKT = $5420;
+ FIONBIO = $5421;
+ TIOCNOTTY = $5422;
+ TIOCSETD = $5423;
+ TIOCGETD = $5424;
+ TCSBRKP = $5425;
+
+ TIOCSBRK = $5427;
+ TIOCCBRK = $5428;
+ TIOCGSID = $5429;
+
+ TIOCGRS485 = $542E;
+ TIOCSRS485 = $542F;
+
+ TCGETX = $5432;
+ TCSETX = $5433;
+ TCSETXF = $5434;
+ TCSETXW = $5435;
+ TIOCVHANGUP = $5437;
+
+ FIONCLEX = $5450;
+ FIOCLEX = $5451;
+ FIOASYNC = $5452;
+ TIOCSERCONFIG = $5453;
+ TIOCSERGWILD = $5454;
+ TIOCSERSWILD = $5455;
+ TIOCGLCKTRMIOS = $5456;
+ TIOCSLCKTRMIOS = $5457;
+ TIOCSERGSTRUCT = $5458;
+ TIOCSERGETLSR = $5459;
+ TIOCSERGETMULTI = $545A;
+ TIOCSERSETMULTI = $545B;
+ TIOCMIWAIT = $545C;
+ TIOCGICOUNT = $545D;
+
+ FIOQSIZE = $5460;
+
+ TIOCPKT_DATA = 0;
+ TIOCPKT_FLUSHREAD = 1;
+ TIOCPKT_FLUSHWRITE = 2;
+ TIOCPKT_STOP = 4;
+ TIOCPKT_START = 8;
+ TIOCPKT_NOSTOP = 16;
+ TIOCPKT_DOSTOP = 32;
+ TIOCPKT_IOCTL = 64;
+
+ TIOCSER_TEMT = $01;
+
+{ from Linux 4.0, include/uapi/asm-generic/termbits.h }
+
+ { c_cc characters }
+ VINTR = 0;
+ VQUIT = 1;
+ VERASE = 2;
+ VKILL = 3;
+ VEOF = 4;
+ VTIME = 5;
+ VMIN = 6;
+ VSWTC = 7;
+ VSTART = 8;
+ VSTOP = 9;
+ VSUSP = 10;
+ VEOL = 11;
+ VREPRINT = 12;
+ VDISCARD = 13;
+ VWERASE = 14;
+ VLNEXT = 15;
+ VEOL2 = 16;
+
+ { c_iflag bits }
+ IGNBRK = &0000001;
+ BRKINT = &0000002;
+ IGNPAR = &0000004;
+ PARMRK = &0000010;
+ INPCK = &0000020;
+ ISTRIP = &0000040;
+ INLCR = &0000100;
+ IGNCR = &0000200;
+ ICRNL = &0000400;
+ IUCLC = &0001000;
+ IXON = &0002000;
+ IXANY = &0004000;
+ IXOFF = &0010000;
+ IMAXBEL = &0020000;
+ IUTF8 = &0040000;
+
+ { c_oflag bits }
+ OPOST = &0000001;
+ OLCUC = &0000002;
+ ONLCR = &0000004;
+ OCRNL = &0000010;
+ ONOCR = &0000020;
+ ONLRET = &0000040;
+ OFILL = &0000100;
+ OFDEL = &0000200;
+ NLDLY = &0000400;
+ NL0 = &0000000;
+ NL1 = &0000400;
+ CRDLY = &0003000;
+ CR0 = &0000000;
+ CR1 = &0001000;
+ CR2 = &0002000;
+ CR3 = &0003000;
+ TABDLY = &0014000;
+ TAB0 = &0000000;
+ TAB1 = &0004000;
+ TAB2 = &0010000;
+ TAB3 = &0014000;
+ XTABS = &0014000;
+ BSDLY = &0020000;
+ BS0 = &0000000;
+ BS1 = &0020000;
+ VTDLY = &0040000;
+ VT0 = &0000000;
+ VT1 = &0040000;
+ FFDLY = &0100000;
+ FF0 = &0000000;
+ FF1 = &0100000;
+
+ { c_cflag bits }
+ CBAUD = &0010017;
+ B0 = &0000000;
+ B50 = &0000001;
+ B75 = &0000002;
+ B110 = &0000003;
+ B134 = &0000004;
+ B150 = &0000005;
+ B200 = &0000006;
+ B300 = &0000007;
+ B600 = &0000010;
+ B1200 = &0000011;
+ B1800 = &0000012;
+ B2400 = &0000013;
+ B4800 = &0000014;
+ B9600 = &0000015;
+ B19200 = &0000016;
+ B38400 = &0000017;
+ EXTA = B19200;
+ EXTB = B38400;
+ CSIZE = &0000060;
+ CS5 = &0000000;
+ CS6 = &0000020;
+ CS7 = &0000040;
+ CS8 = &0000060;
+ CSTOPB = &0000100;
+ CREAD = &0000200;
+ PARENB = &0000400;
+ PARODD = &0001000;
+ HUPCL = &0002000;
+ CLOCAL = &0004000;
+ CBAUDEX = &0010000;
+ BOTHER = &0010000;
+ B57600 = &0010001;
+ B115200 = &0010002;
+ B230400 = &0010003;
+ B460800 = &0010004;
+ B500000 = &0010005;
+ B576000 = &0010006;
+ B921600 = &0010007;
+ B1000000 = &0010010;
+ B1152000 = &0010011;
+ B1500000 = &0010012;
+ B2000000 = &0010013;
+ B2500000 = &0010014;
+ B3000000 = &0010015;
+ B3500000 = &0010016;
+ B4000000 = &0010017;
+
+ CIBAUD = &002003600000;
+ CMSPAR = &010000000000;
+ CRTSCTS = &020000000000;
+
+ IBSHIFT = 16;
+
+ { c_lflag bits }
+ ISIG = &0000001;
+ ICANON = &0000002;
+ XCASE = &0000004;
+ ECHO = &0000010;
+ ECHOE = &0000020;
+ ECHOK = &0000040;
+ ECHONL = &0000100;
+ NOFLSH = &0000200;
+ TOSTOP = &0000400;
+ ECHOCTL = &0001000;
+ ECHOPRT = &0002000;
+ ECHOKE = &0004000;
+ FLUSHO = &0010000;
+ PENDIN = &0040000;
+ IEXTEN = &0100000;
+ EXTPROC = &0200000;
+
+ { TCFlow }
+ TCOOFF = 0;
+ TCOON = 1;
+ TCIOFF = 2;
+ TCION = 3;
+
+ { TCFlush }
+ TCIFLUSH = 0;
+ TCOFLUSH = 1;
+ TCIOFLUSH = 2;
+
+ { TCSetAttr }
+ TCSANOW = 0;
+ TCSADRAIN = 1;
+ TCSAFLUSH = 2;
+
+{ from Linux 4.0, include/uapi/asm-generic/termios.h }
+
+ { c_line bits }
+ TIOCM_LE = $001;
+ TIOCM_DTR = $002;
+ TIOCM_RTS = $004;
+ TIOCM_ST = $008;
+ TIOCM_SR = $010;
+ TIOCM_CTS = $020;
+ TIOCM_CAR = $040;
+ TIOCM_RNG = $080;
+ TIOCM_DSR = $100;
+ TIOCM_CD = TIOCM_CAR;
+ TIOCM_RI = TIOCM_RNG;
+ TIOCM_OUT1 = $2000;
+ TIOCM_OUT2 = $4000;
+ TIOCM_LOOP = $8000;
+
+{$endif cpuriscv64}
+
{$ifdef cpui386}
{ For Terminal handling }
TCGETS = $5401;
diff --git a/riscv_new/rtl/riscv32/int64p.inc b/riscv_new/rtl/riscv32/int64p.inc
new file mode 100644
index 0000000000..1cb045808f
--- /dev/null
+++ b/riscv_new/rtl/riscv32/int64p.inc
@@ -0,0 +1,14 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team
+
+ This file contains some helper routines for int64 and qword
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
diff --git a/riscv_new/rtl/riscv32/makefile.cpu b/riscv_new/rtl/riscv32/makefile.cpu
new file mode 100644
index 0000000000..48d8c2101f
--- /dev/null
+++ b/riscv_new/rtl/riscv32/makefile.cpu
@@ -0,0 +1,6 @@
+#
+# Here we set processor dependent include file names.
+#
+
+CPUNAMES=riscv32 int64p math set setjump setjumph strings stringss
+CPUINCNAMES=$(addsuffix .inc,$(CPUNAMES))
diff --git a/riscv_new/rtl/riscv32/math.inc b/riscv_new/rtl/riscv32/math.inc
new file mode 100644
index 0000000000..472337688e
--- /dev/null
+++ b/riscv_new/rtl/riscv32/math.inc
@@ -0,0 +1,15 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ Implementation of mathematical Routines (only for real)
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
diff --git a/riscv_new/rtl/riscv32/riscv32.inc b/riscv_new/rtl/riscv32/riscv32.inc
new file mode 100644
index 0000000000..597e395c75
--- /dev/null
+++ b/riscv_new/rtl/riscv32/riscv32.inc
@@ -0,0 +1,83 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ Processor dependent implementation for the system unit for
+ AVR
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+procedure fpc_cpuinit;{$ifdef SYSTEMINLINE}inline;{$endif}
+ begin
+ end;
+
+
+{$IFNDEF INTERNAL_BACKTRACE}
+{$define FPC_SYSTEM_HAS_GET_FRAME}
+function get_frame:pointer;assembler;nostackframe;
+ asm
+ end;
+{$ENDIF not INTERNAL_BACKTRACE}
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;
+ asm
+ end;
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;
+ asm
+ end;
+
+
+{$define FPC_SYSTEM_HAS_SPTR}
+Function Sptr : pointer;assembler;
+ asm
+ end;
+
+
+function InterLockedDecrement (var Target: longint) : longint;
+ begin
+ dec(Target);
+ Result:=Target;
+ end;
+
+
+function InterLockedIncrement (var Target: longint) : longint;
+ begin
+ inc(Target);
+ Result:=Target;
+ end;
+
+
+function InterLockedExchange (var Target: longint;Source : longint) : longint;
+ begin
+ Result:=Target;
+ Target:=Source;
+ end;
+
+
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;
+ begin
+ Result:=Target;
+ if Target=Comperand then
+ Target:=NewValue;
+ end;
+
+
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
+ begin
+ Result:=Target;
+ inc(Target,Source);
+ end;
+
diff --git a/riscv_new/rtl/riscv32/set.inc b/riscv_new/rtl/riscv32/set.inc
new file mode 100644
index 0000000000..681a4b7cbb
--- /dev/null
+++ b/riscv_new/rtl/riscv32/set.inc
@@ -0,0 +1,15 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ Include file with set operations called by the compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
diff --git a/riscv_new/rtl/riscv32/setjump.inc b/riscv_new/rtl/riscv32/setjump.inc
new file mode 100644
index 0000000000..be2a0c181c
--- /dev/null
+++ b/riscv_new/rtl/riscv32/setjump.inc
@@ -0,0 +1,26 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ SetJmp and LongJmp implementation for exception handling
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+function fpc_setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJMP'];nostackframe;compilerproc;
+ asm
+ end;
+
+
+procedure fpc_longjmp(var S : jmp_buf;value : longint);assembler;[Public, alias : 'FPC_LONGJMP'];compilerproc;
+ asm
+ end;
+
+
diff --git a/riscv_new/rtl/riscv32/setjumph.inc b/riscv_new/rtl/riscv32/setjumph.inc
new file mode 100644
index 0000000000..f27b3c9cbc
--- /dev/null
+++ b/riscv_new/rtl/riscv32/setjumph.inc
@@ -0,0 +1,25 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ SetJmp/Longjmp declarations
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+type
+ jmp_buf = packed record
+ end;
+ pjmp_buf = ^jmp_buf;
+
+function setjmp(var S : jmp_buf) : longint;[external name 'FPC_SETJMP'];
+procedure longjmp(var S : jmp_buf;value : longint);[external name 'FPC_LONGJMP'];
+
+
diff --git a/riscv_new/rtl/riscv32/strings.inc b/riscv_new/rtl/riscv32/strings.inc
new file mode 100644
index 0000000000..0d10cd5002
--- /dev/null
+++ b/riscv_new/rtl/riscv32/strings.inc
@@ -0,0 +1,18 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2000 by Jonas Maebe, member of the
+ Free Pascal development team
+
+ Processor dependent part of strings.pp, that can be shared with
+ sysutils unit.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
diff --git a/riscv_new/rtl/riscv32/stringss.inc b/riscv_new/rtl/riscv32/stringss.inc
new file mode 100644
index 0000000000..b30572827e
--- /dev/null
+++ b/riscv_new/rtl/riscv32/stringss.inc
@@ -0,0 +1,18 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Jonas Maebe, member of the
+ Free Pascal development team
+
+ Processor dependent part of strings.pp, not shared with
+ sysutils unit.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
diff --git a/riscv_new/rtl/riscv64/int64p.inc b/riscv_new/rtl/riscv64/int64p.inc
new file mode 100644
index 0000000000..1cb045808f
--- /dev/null
+++ b/riscv_new/rtl/riscv64/int64p.inc
@@ -0,0 +1,14 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team
+
+ This file contains some helper routines for int64 and qword
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
diff --git a/riscv_new/rtl/riscv64/makefile.cpu b/riscv_new/rtl/riscv64/makefile.cpu
new file mode 100644
index 0000000000..03bae91aca
--- /dev/null
+++ b/riscv_new/rtl/riscv64/makefile.cpu
@@ -0,0 +1,6 @@
+#
+# Here we set processor dependent include file names.
+#
+
+CPUNAMES=riscv64 int64p math set setjump setjumph strings stringss
+CPUINCNAMES=$(addsuffix .inc,$(CPUNAMES))
diff --git a/riscv_new/rtl/riscv64/math.inc b/riscv_new/rtl/riscv64/math.inc
new file mode 100644
index 0000000000..472337688e
--- /dev/null
+++ b/riscv_new/rtl/riscv64/math.inc
@@ -0,0 +1,15 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ Implementation of mathematical Routines (only for real)
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
diff --git a/riscv_new/rtl/riscv64/mathu.inc b/riscv_new/rtl/riscv64/mathu.inc
new file mode 100644
index 0000000000..74743e0a6e
--- /dev/null
+++ b/riscv_new/rtl/riscv64/mathu.inc
@@ -0,0 +1,151 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2014 by Jonas Maebe
+ member of the Free Pascal development team
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+**********************************************************************}
+
+function getfpcr: dword; nostackframe; assembler;
+ asm
+ end;
+
+
+procedure setfpcr(val: dword); nostackframe; assembler;
+ asm
+ end;
+
+
+function getfpsr: dword; nostackframe; assembler;
+ asm
+ end;
+
+
+procedure setfpsr(val: dword); nostackframe; assembler;
+ asm
+ end;
+
+
+function GetRoundMode: TFPURoundingMode;
+ const
+ bits2rm: array[0..3] of TFPURoundingMode = (rmNearest,rmUp,rmDown,rmTruncate);
+ begin
+ result:=TFPURoundingMode(bits2rm[(getfpcr shr 22) and 3])
+ end;
+
+
+function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
+ const
+ rm2bits: array[TFPURoundingMode] of byte = (0,2,1,3);
+ begin
+ softfloat_rounding_mode:=RoundMode;
+ SetRoundMode:=RoundMode;
+ setfpcr((getfpcr and $ff3fffff) or (rm2bits[RoundMode] shl 22));
+ end;
+
+
+function GetPrecisionMode: TFPUPrecisionMode;
+ begin
+ result:=pmDouble;
+ end;
+
+
+function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
+ begin
+ result:=pmDouble;
+ end;
+
+
+const
+ fpu_ioe = 1 shl 8;
+ fpu_dze = 1 shl 9;
+ fpu_ofe = 1 shl 10;
+ fpu_ufe = 1 shl 11;
+ fpu_ixe = 1 shl 12;
+ fpu_ide = 1 shl 15;
+ fpu_exception_mask = fpu_ioe or fpu_dze or fpu_ofe or fpu_ufe or fpu_ixe or fpu_ide;
+ fpu_exception_mask_to_status_mask_shift = 8;
+
+
+function GetExceptionMask: TFPUExceptionMask;
+ var
+ fpcr: dword;
+ begin
+ fpcr:=getfpcr;
+ result:=[];
+ if ((fpcr and fpu_ioe)=0) then
+ result := result+[exInvalidOp];
+ if ((fpcr and fpu_ofe)=0) then
+ result := result+[exOverflow];
+ if ((fpcr and fpu_ufe)=0) then
+ result := result+[exUnderflow];
+ if ((fpcr and fpu_dze)=0) then
+ result := result+[exZeroDivide];
+ if ((fpcr and fpu_ixe)=0) then
+ result := result+[exPrecision];
+ if ((fpcr and fpu_ide)=0) then
+ result := result+[exDenormalized];
+ end;
+
+
+function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
+ var
+ newfpcr: dword;
+ begin
+ softfloat_exception_mask:=mask;
+ newfpcr:=fpu_exception_mask;
+ if exInvalidOp in Mask then
+ newfpcr:=newfpcr and not(fpu_ioe);
+ if exOverflow in Mask then
+ newfpcr:=newfpcr and not(fpu_ofe);
+ if exUnderflow in Mask then
+ newfpcr:=newfpcr and not(fpu_ufe);
+ if exZeroDivide in Mask then
+ newfpcr:=newfpcr and not(fpu_dze);
+ if exPrecision in Mask then
+ newfpcr:=newfpcr and not(fpu_ixe);
+ if exDenormalized in Mask then
+ newfpcr:=newfpcr and not(fpu_ide);
+ { clear "exception happened" flags }
+ ClearExceptions(false);
+ { set new exception mask }
+ setfpcr((getfpcr and not(fpu_exception_mask)) or newfpcr);
+ { unsupported mask bits will remain 0 -> read exception mask again }
+ result:=GetExceptionMask;
+ softfloat_exception_mask:=result;
+ end;
+
+
+procedure ClearExceptions(RaisePending: Boolean);
+ var
+ fpsr: dword;
+ f: TFPUException;
+ begin
+ fpsr:=getfpsr;
+ if raisepending then
+ begin
+ if (fpsr and (fpu_dze shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+ float_raise(exZeroDivide);
+ if (fpsr and (fpu_ofe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+ float_raise(exOverflow);
+ if (fpsr and (fpu_ufe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+ float_raise(exUnderflow);
+ if (fpsr and (fpu_ioe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+ float_raise(exInvalidOp);
+ if (fpsr and (fpu_ixe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+ float_raise(exPrecision);
+ if (fpsr and (fpu_ide shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+ float_raise(exDenormalized);
+ { now the soft float exceptions }
+ for f in softfloat_exception_flags do
+ float_raise(f);
+ end;
+ softfloat_exception_flags:=[];
+ setfpsr(fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift));
+ end;
diff --git a/riscv_new/rtl/riscv64/riscv64.inc b/riscv_new/rtl/riscv64/riscv64.inc
new file mode 100644
index 0000000000..3b71640ca5
--- /dev/null
+++ b/riscv_new/rtl/riscv64/riscv64.inc
@@ -0,0 +1,124 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ Processor dependent implementation for the system unit for
+ AVR
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+procedure fpc_cpuinit;{$ifdef SYSTEMINLINE}inline;{$endif}
+ begin
+ end;
+
+
+{$IFNDEF INTERNAL_BACKTRACE}
+{$define FPC_SYSTEM_HAS_GET_FRAME}
+function get_frame:pointer;assembler;nostackframe;
+ asm
+ addi a0, fp, 0
+ end;
+{$ENDIF not INTERNAL_BACKTRACE}
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;
+ asm
+ ld a0, -8*2(a0)
+ end;
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;
+ asm
+ ld a0, -8*1(a0)
+ end;
+
+
+{$define FPC_SYSTEM_HAS_SPTR}
+Function Sptr : pointer;assembler;
+ asm
+ addi a0, sp, 0
+ end;
+
+
+function InterLockedDecrement (var Target: longint) : longint;
+ begin
+ dec(Target);
+ Result:=Target;
+ end;
+
+
+function InterLockedIncrement (var Target: longint) : longint;
+ begin
+ inc(Target);
+ Result:=Target;
+ end;
+
+
+function InterLockedExchange (var Target: longint;Source : longint) : longint;
+ begin
+ Result:=Target;
+ Target:=Source;
+ end;
+
+
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;
+ begin
+ Result:=Target;
+ if Target=Comperand then
+ Target:=NewValue;
+ end;
+
+
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
+ begin
+ Result:=Target;
+ inc(Target,Source);
+ end;
+
+
+
+function InterLockedDecrement64 (var Target: int64) : int64;
+ begin
+ dec(Target);
+ Result:=Target;
+ end;
+
+
+function InterLockedIncrement64 (var Target: int64) : int64;
+ begin
+ inc(Target);
+ Result:=Target;
+ end;
+
+
+function InterLockedExchange64 (var Target: int64;Source : int64) : int64;
+ begin
+ Result:=Target;
+ Target:=Source;
+ end;
+
+
+function InterlockedCompareExchange64(var Target: int64; NewValue: int64; Comperand: int64): int64;
+ begin
+ Result:=Target;
+ if Target=Comperand then
+ Target:=NewValue;
+ end;
+
+
+function InterLockedExchangeAdd64 (var Target: int64;Source : int64) : int64;
+ begin
+ Result:=Target;
+ inc(Target,Source);
+ end;
+
diff --git a/riscv_new/rtl/riscv64/set.inc b/riscv_new/rtl/riscv64/set.inc
new file mode 100644
index 0000000000..681a4b7cbb
--- /dev/null
+++ b/riscv_new/rtl/riscv64/set.inc
@@ -0,0 +1,15 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ Include file with set operations called by the compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
diff --git a/riscv_new/rtl/riscv64/setjump.inc b/riscv_new/rtl/riscv64/setjump.inc
new file mode 100644
index 0000000000..bb238b7aba
--- /dev/null
+++ b/riscv_new/rtl/riscv64/setjump.inc
@@ -0,0 +1,132 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ SetJmp and LongJmp implementation for exception handling
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+function fpc_setjmp(var S : jmp_buf) : longint;assembler;nostackframe;[Public, alias : 'FPC_SETJMP'];nostackframe;compilerproc;
+ asm
+ sd ra, 0*8(a0)
+ sd s0, 1*8(a0)
+ sd s1, 2*8(a0)
+ sd s2, 3*8(a0)
+ sd s3, 4*8(a0)
+ sd s4, 5*8(a0)
+ sd s5, 6*8(a0)
+ sd s6, 7*8(a0)
+ sd s7, 8*8(a0)
+ sd s8, 9*8(a0)
+ sd s9, 10*8(a0)
+ sd s10, 11*8(a0)
+ sd s11, 12*8(a0)
+ sd sp, 13*8(a0)
+
+{$if defined(FPUFD) or defined(FPUD)}
+ frcsr s0
+
+ sd s0, 14*8(a0)
+
+ fsd f8, 15*8(a0)
+ fsd f9, 16*8(a0)
+ fsd f18, 17*8(a0)
+ fsd f19, 18*8(a0)
+ fsd f20, 19*8(a0)
+ fsd f21, 20*8(a0)
+ fsd f22, 21*8(a0)
+ fsd f23, 22*8(a0)
+ fsd f24, 23*8(a0)
+ fsd f25, 24*8(a0)
+ fsd f26, 25*8(a0)
+ fsd f27, 26*8(a0)
+{$endif FPUFD or FPUD}
+{$if defined(FPUF)}
+ frcsr s0
+
+ sd s0, 14*8(a0)
+
+ fsw f8, 30*4(a0)
+ fsw f9, 31*4(a0)
+ fsw f18, 32*4(a0)
+ fsw f19, 33*4(a0)
+ fsw f20, 34*4(a0)
+ fsw f21, 35*4(a0)
+ fsw f22, 36*4(a0)
+ fsw f23, 37*4(a0)
+ fsw f24, 38*4(a0)
+ fsw f25, 39*4(a0)
+ fsw f26, 40*4(a0)
+ fsw f27, 41*4(a0)
+{$endif FPUF}
+
+ addi x10, x0, 0
+ end;
+
+
+procedure fpc_longjmp(var S : jmp_buf;value : longint);assembler;nostackframe;[Public, alias : 'FPC_LONGJMP'];compilerproc;
+ asm
+ ld ra, 0*8(a0)
+ ld s0, 1*8(a0)
+ ld s1, 2*8(a0)
+ ld s2, 3*8(a0)
+ ld s3, 4*8(a0)
+ ld s4, 5*8(a0)
+ ld s5, 6*8(a0)
+ ld s6, 7*8(a0)
+ ld s7, 8*8(a0)
+ ld s8, 9*8(a0)
+ ld s9, 10*8(a0)
+ ld s10,11*8(a0)
+ ld s11,12*8(a0)
+
+{$if defined(FPUFD) or defined(FPUD)}
+ ld sp, 14*8(a0)
+
+ fld f8, 15*8(a0)
+ fld f9, 16*8(a0)
+ fld f18, 17*8(a0)
+ fld f19, 18*8(a0)
+ fld f20, 19*8(a0)
+ fld f21, 20*8(a0)
+ fld f22, 21*8(a0)
+ fld f23, 22*8(a0)
+ fld f24, 23*8(a0)
+ fld f25, 24*8(a0)
+ fld f26, 25*8(a0)
+ fld f27, 26*8(a0)
+
+ fscsr sp
+{$endif FPUFD or FPUD}
+{$if defined(FPUF)}
+ ld sp, 14*8(a0)
+
+ flw f8, 30*4(a0)
+ flw f9, 31*4(a0)
+ flw f18, 32*4(a0)
+ flw f19, 33*4(a0)
+ flw f20, 34*4(a0)
+ flw f21, 35*4(a0)
+ flw f22, 36*4(a0)
+ flw f23, 37*4(a0)
+ flw f24, 38*4(a0)
+ flw f25, 39*4(a0)
+ flw f26, 40*4(a0)
+ flw f27, 41*4(a0)
+
+ fscsr sp
+{$endif FPUF}
+ ld sp, 13*8(a0)
+
+ sltiu a0, a1, 1
+ add a0, a0, a1
+ end;
+
diff --git a/riscv_new/rtl/riscv64/setjumph.inc b/riscv_new/rtl/riscv64/setjumph.inc
new file mode 100644
index 0000000000..fa0c4a14c6
--- /dev/null
+++ b/riscv_new/rtl/riscv64/setjumph.inc
@@ -0,0 +1,39 @@
+{
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2008 by the Free Pascal development team.
+
+ SetJmp/Longjmp declarations
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+type
+ jmp_buf = packed record
+ ra,
+ x8,x9,x18,x19,x20,x21,
+ x22,x23,x24,x25,x26,
+ x27,x2: qword;
+{$if defined(FPUFD) or defined(FPUD)}
+ fcsr,
+ f8,f9,f18,f19,f20,f21,
+ f22,f23,f24,f25,f26,f27: qword;
+{$endif FPUFD or FPUD}
+{$if defined(FPUF)}
+ fcsr: qword;
+ f8,f9,f18,f19,f20,f21,
+ f22,f23,f24,f25,f26,f27: longword;
+{$endif FPUF}
+ end;
+ pjmp_buf = ^jmp_buf;
+
+function setjmp(var S : jmp_buf) : longint;[external name 'FPC_SETJMP'];
+procedure longjmp(var S : jmp_buf;value : longint);[external name 'FPC_LONGJMP'];
+
+
diff --git a/riscv_new/rtl/riscv64/strings.inc b/riscv_new/rtl/riscv64/strings.inc
new file mode 100644
index 0000000000..0d10cd5002
--- /dev/null
+++ b/riscv_new/rtl/riscv64/strings.inc
@@ -0,0 +1,18 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2000 by Jonas Maebe, member of the
+ Free Pascal development team
+
+ Processor dependent part of strings.pp, that can be shared with
+ sysutils unit.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
diff --git a/riscv_new/rtl/riscv64/stringss.inc b/riscv_new/rtl/riscv64/stringss.inc
new file mode 100644
index 0000000000..b30572827e
--- /dev/null
+++ b/riscv_new/rtl/riscv64/stringss.inc
@@ -0,0 +1,18 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Jonas Maebe, member of the
+ Free Pascal development team
+
+ Processor dependent part of strings.pp, not shared with
+ sysutils unit.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
diff --git a/riscv_new/utils/fpcm/fpcmmain.pp b/riscv_new/utils/fpcm/fpcmmain.pp
index 925f3eb92d..174fc8ec3b 100644
--- a/riscv_new/utils/fpcm/fpcmmain.pp
+++ b/riscv_new/utils/fpcm/fpcmmain.pp
@@ -67,7 +67,7 @@ interface
type
TCpu=(
- c_i386,c_m68k,c_powerpc,c_sparc,c_x86_64,c_arm,c_powerpc64,c_avr,c_armeb,c_armel,c_mips,c_mipsel,c_mips64,c_mips64el,c_jvm,c_i8086,c_aarch64,c_wasm,c_sparc64
+ c_i386,c_m68k,c_powerpc,c_sparc,c_x86_64,c_arm,c_powerpc64,c_avr,c_armeb,c_armel,c_mips,c_mipsel,c_mips64,c_mips64el,c_jvm,c_i8086,c_aarch64,c_wasm,c_sparc64,c_riscv32,c_riscv64
);
TOS=(
@@ -82,15 +82,15 @@ interface
const
CpuStr : array[TCpu] of string=(
- 'i386','m68k','powerpc','sparc','x86_64','arm','powerpc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','i8086','aarch64','wasm','sparc64'
+ 'i386','m68k','powerpc','sparc','x86_64','arm','powerpc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','i8086','aarch64','wasm','sparc64','riscv32','riscv64'
);
CpuSuffix : array[TCpu] of string=(
- '_i386','_m68k','_powerpc','_sparc','_x86_64','_arm','_powerpc64','_avr','_armeb', '_armel', '_mips', '_mipsel', '_mips64', '_mips64el', '_jvm','_i8086','_aarch64','_wasm','_sparc64'
+ '_i386','_m68k','_powerpc','_sparc','_x86_64','_arm','_powerpc64','_avr','_armeb', '_armel', '_mips', '_mipsel', '_mips64', '_mips64el', '_jvm','_i8086','_aarch64','_wasm','_sparc64','_riscv32','_riscv64'
);
ppcSuffix : array[TCpu] of string=(
- '386','68k','ppc','sparc','x64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','8086','a64','wasm','sparc64'
+ '386','68k','ppc','sparc','x64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','8086','a64','wasm','sparc64','rv32','rv64'
);
OSStr : array[TOS] of string=(
@@ -113,46 +113,46 @@ interface
{ This table is kept OS,Cpu because it is easier to maintain (PFV) }
OSCpuPossible : array[TOS,TCpu] of boolean = (
- { os i386 m68k ppc sparc x86_64 arm ppc64 avr armeb armel mips mipsel mips64 misp64el jvm i8086 aarch64 wasm sparc64}
- { linux } ( true, true, true, true, true, true, true, false, true, false, true, true, false, false, false, false, true, false, true),
- { go32v2 } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { win32 } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { os2 } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { freebsd } ( true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { beos } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { haiku } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { netbsd } ( true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { amiga } ( false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { atari } ( false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { solaris } ( true, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { qnx } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { netware } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { openbsd } ( true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { wdosx } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { palmos } ( false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { macos } ( false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { darwin } ( true, false, true, false, true, true, true, false, false, false, false, false, false, false, false, false, true, false, false),
- { emx } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { watcom } ( true, false, false, false ,false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { morphos } ( false, false, true, false ,false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { netwlibc }( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { win64 } ( false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { wince }( true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { gba } ( false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { nds } ( false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { embedded }( true, true, true, true, true, true, true, true, true , false, false, true , false, false, false, true , false, false, false),
- { symbian } ( true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { nativent }( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { iphonesim }( true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { wii } ( false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { aix } ( false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false),
- { java } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false),
- { android } ( true, false, false, false, false, true, false, false, false, false, false, true, false, false, true, false, false, false, false),
- { msdos } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true , false, false, false),
- { aros } ( true, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false),
- {dragonfly} ( false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
- { win16 } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true , false, false, false),
- { wasm } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false)
+ { os i386 m68k ppc sparc x86_64 arm ppc64 avr armeb armel mips mipsel mips64 misp64el jvm i8086 aarch64 wasm sparc64 riscv32 riscv64}
+ { linux } ( true, true, true, true, true, true, true, false, true, false, true, true, false, false, false, false, true, false, true, true, true),
+ { go32v2 } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { win32 } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { os2 } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { freebsd } ( true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { beos } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { haiku } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { netbsd } ( true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { amiga } ( false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { atari } ( false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { solaris } ( true, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { qnx } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { netware } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { openbsd } ( true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { wdosx } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { palmos } ( false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { macos } ( false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { darwin } ( true, false, true, false, true, true, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false),
+ { emx } ( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { watcom } ( true, false, false, false ,false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { morphos } ( false, false, true, false ,false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { netwlibc }( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { win64 } ( false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { wince }( true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { gba } ( false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { nds } ( false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { embedded }( true, true, true, true, true, true, true, true, true , false, false, true , false, false, false, true , false, false, false, true, true ),
+ { symbian } ( true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { nativent }( true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { iphonesim }( true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { wii } ( false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { aix } ( false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { java } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false),
+ { android } ( true, false, false, false, false, true, false, false, false, false, false, true, false, false, true, false, false, false, false, false, false),
+ { msdos } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true , false, false, false, false, false),
+ { aros } ( true, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ {dragonfly} ( false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+ { win16 } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true , false, false, false, false, false),
+ { wasm } ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false)
);
type