1
0
mirror of https://gitlab.os-k.eu/os-k-team/kvisc.git synced 2023-08-25 14:05:46 +02:00

more RISC-ifications

This commit is contained in:
julianb0 2019-07-18 22:49:31 +02:00
parent 5b315ad46a
commit 40653a8047
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
32 changed files with 436 additions and 601 deletions

View File

@ -11,7 +11,7 @@ kpc: vm/Makefile
@cd vm && make --no-print-directory -s verbose=yes
kas: kpc as/regs.lst as/k-as.py
@cp vm/in/instrs.lst as
@cp vm/ob/instrs.lst as
dos: kas dosclean
@cd ka && make --no-print-directory -s
@ -24,7 +24,7 @@ dosclean:
@rm -f $(KODIR)/*.com $(KODIR)/*.sym
inclean:
@rm -f vm/in/arch_i.h vm/in/instrs.lst vm/ob/in/*.o
@rm -f vm/ob/arch_i.h vm/ob/instrs.lst vm/ob/in/*.o
clean: dosclean
@cd vm && make clean --no-print-directory -s verbose=no

View File

@ -13,7 +13,6 @@ start:
mov rbp, zero
cls
cld
call main
mov rax, Sys.EnterHaltMode

View File

@ -10,4 +10,5 @@ include "crt/err/errno.k"
include "crt/fmt/format.k"
include "crt/str/string.k"
include "crt/lib/time.k"
include "crt/lib/arith128.k"

View File

@ -34,7 +34,7 @@ doprnt:
mov ax0, b[rbx]
call .doput
inc rbx
add rbx, rbx, 1
jmp .print_regular
.check_modf:
@ -71,7 +71,7 @@ doprnt:
cmp ax0, zero
jmp.z .main_loop
inc rdi
add rdi, rdi, 1
call .doput
jmp .print_string
@ -82,10 +82,8 @@ doprnt:
jmp .main_loop
.modf_p:
mov ax0, '0'
call .doput
mov ax0, 'x'
call .doput
call .doput, '0'
call .doput, 'x'
; Fallthrough
.modf_x:
@ -122,44 +120,29 @@ doprnt:
add.z rsp, rsp, 80
jmp.z .main_loop
inc rdi
add rdi, rdi, 1
call .doput
jmp .print_itoa_buf
.modf_percent:
mov ax0, '%'
call .doput
call .doput, '%'
jmp .main_loop
.bad_modifier:
; print "%?" to clearly indicate that something is wrong
mov ax0, '%'
call .doput
mov ax0, '?'
call .doput
call .doput, '%'
call .doput, '?'
jmp .main_loop
.nullstring:
; %s was passed a NULL
mov ax0, '('
call .doput
mov ax0, 'n'
call .doput
mov ax0, 'u'
call .doput
mov ax0, 'l'
call .doput
mov ax0, 'l'
call .doput
mov ax0, ')'
call .doput
call .doput, '('
call .doput, 'n'
call .doput, 'u'
call .doput, 'l'
call .doput, 'l'
call .doput, ')'
jmp .main_loop
@ -178,7 +161,7 @@ doprnt:
;
.doput:
; update print count
inc nx1
add nx1, nx1, 1
; if n==0, don't print
; we follow the C convention that sprintf()-like functions
@ -188,7 +171,7 @@ doprnt:
ret.z
; if n>0, decrement n and print
dec nx0
sub nx0, nx0, 1
call nx3
; did putc fail?

View File

@ -34,10 +34,9 @@ ltostr:
b.z ax3, zero, .conv
b.nz ax2, 10, .conv ; base 10
sgn r11, ax1 ; extract ax1 sign
cmp r11, -1 ; negative?
neg.z ax1, ax1
shr r11, ax1, 63 ; extract ax1 sign
cmp r11, zero ; negative?
sub.nz ax1, zero, ax1 ; yes
; main loop
.conv:
@ -55,7 +54,7 @@ ltostr:
.next:
mov b[ax0], r10
inc ax0
add ax0, ax0, 1
div ax1, ax1, ax2
jmp .conv
@ -64,12 +63,11 @@ ltostr:
.fini:
cmp r11, -1
mov.z b[ax0], '-'
inc.z ax0
add.z ax0, ax0, 1
mov b[ax0], zero
mov ax0, rax
call strrev2
call strrev2, rax
ret

View File

@ -39,12 +39,12 @@ strtoq:
.skip_spc:
cmp b[rdx], ' '
inc.z rdx
add.z rdx, rdx, 1
jmp.z .skip_spc
; skip +
cmp b[rdx], '+'
inc.z rdx
add.z rdx, rdx, 1
; signed?
cmp ax2, zero
@ -53,7 +53,7 @@ strtoq:
; parse '-'
cmp b[rdx], '-'
inc.z rdx
add.z rdx, rdx, 1
mov.z r10, 1
mov.nz r10, zero
@ -64,7 +64,7 @@ strtoq:
; base prefix?
b.nz b[rdx], '0', .main_loop
inc rdx
add rdx, rdx, 1
movzx rcx, b[rdx]
; "0x"/"0b" prefix
@ -81,7 +81,7 @@ strtoq:
; if not, leave rax = 0 and *rdx = 'x'
b.nz ax1, 16, .done
; else
inc rdx
add rdx, rdx, 1
jmp .main_loop
.parsed_0b:
@ -89,7 +89,7 @@ strtoq:
; if not, leave rax = 0 and *rdx = 'b'
b.nz ax1, 2, .done
; else
inc rdx
add rdx, rdx, 1
jmp .main_loop
.base_0:
@ -98,15 +98,15 @@ strtoq:
cmp b[rdx], '0'
mov.nz ax1, 10
jmp.nz .main_loop
inc rdx
add rdx, rdx, 1
cmp b[rdx], 'x'
inc.z rdx
add.z rdx, rdx, 1
mov.z ax1, 16
jmp.z .main_loop
cmp b[rdx], 'b'
inc.z rdx
add.z rdx, rdx, 1
mov.z ax1, 2
jmp.z .main_loop
@ -114,7 +114,7 @@ strtoq:
.main_loop:
movzx r12, b[rdx]
inc rdx
add rdx, rdx, 1
cmp r12, '0'
jmp.b .done
@ -147,7 +147,7 @@ strtoq:
ret.z
; yes
neg rax, rax
sub rax, zero, rax
ret
.bad:

59
ka/crt/lib/arith128.k Normal file
View File

@ -0,0 +1,59 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; int:int add_lq_q(int:int x, int y)
;
add_lq_q:
addf rax, ax0, ax2
adcx rdx, ax1, zero
ret
;
; int:int add_lq_lq(int:int x, int:int y)
;
add_lq_lq:
addf rax, ax0, ax2
adcx rdx, ax1, ax3
ret
;
; int:int sub_lq_q(int:int x, int y)
;
sub_lq_q:
subf rax, ax0, ax2
sbbx rdx, ax1, zero
ret
;
; int:int sub_q_lq(int x, int:int y)
;
sub_q_lq:
subf rax, ax0, ax1
sbbx rdx, zero, ax2
ret
;
; int:int sub_lq_lq(int:int x, int:int y)
;
sub_lq_lq:
subf rax, ax0, ax2
sbbx rdx, ax1, ax3
ret
;
; int:int mul_lq_q(int x, int y)
;
mul_q_q:
mov rax, ax0
mulhi rdx, rax, ax1
ret
;
; int:int imul_lq_q(int x, int y)
;
imul_q_q:
mov rax, ax0
imulhi rdx, rax, ax1
ret

View File

@ -36,7 +36,7 @@ DaysInYear:
b.nz rcx, zero, .end
.leap:
inc rax
add rax, rax, 1
.end:
ret

View File

@ -11,12 +11,27 @@
;
strcmp:
mov rcx, STRLEN_MAX
cmpzsb.rep.z ax0, ax1
mov rax, b[ax0-1]
mov rcx, b[ax1-1]
sub rax, rax, rcx
.1:
jmp.cxz .2
movzx rax, b[ax0]
movzx rdx, b[ax1]
cmp rax, rdx
jmp.nz .2
; both zero?
add r11, rax, rdx
b.z r11, zero, .2
add ax0, ax0, 1
add ax1, ax1, 1
sub rcx, rcx, 1
jmp .1
.2:
sub rax, rax, rdx
ret
;
@ -24,14 +39,22 @@ strcmp:
;
strncmp:
mov rcx, ax2
mov.cxz rax, zero
ret.cxz
cmpzsb.rep.z ax0, ax1
.1:
jmp.cxz .2
mov rax, b[ax0-1]
mov rcx, b[ax1-1]
sub rax, rax, rcx
mov rax, b[ax0]
mov rdx, b[ax1]
cmp rax, rdx
jmp.nz .2
add ax0, ax0, 1
add ax1, ax1, 1
sub rcx, rcx, 1
jmp .1
.2:
sub rax, rax, rdx
ret

View File

@ -5,8 +5,17 @@
; void strcpy(char *, const char *)
;
strcpy:
mov rcx, STRLEN_MAX
movsb.rep.nz ax0, ax1
mov rax, b[ax1]
mov b[ax0], rax
b.z rax, zero, .1
add ax0, ax0, 1
add ax1, ax1, 1
jmp strcpy
.1:
ret
;
@ -14,24 +23,42 @@ strcpy:
;
strncpy:
mov rcx, ax2
.1:
ret.cxz
movsb.rep.nz ax0, ax1
ret
mov rax, b[ax1]
mov b[ax0], rax
add ax0, ax0, 1
add ax1, ax1, 1
sub rcx, rcx, 1
jmp .1
;
; void strnzcpy(char *, const char *, int)
;
strnzcpy:
mov rcx, ax2
ret.cxz
dec rcx
jmp.cxz .1
movsb.rep.nz ax0, ax1
.1:
jmp.cxz .2
mov rax, b[ax1]
mov b[ax0], rax
b.z rax, zero, .3
add ax0, ax0, 1
add ax1, ax1, 1
sub rcx, rcx, 1
jmp .1
.2:
mov b[ax0], zero
.3:
ret

View File

@ -15,6 +15,10 @@ strnlen:
; int strlen(char *)
;
strlen:
mov ax1, STRLEN_MAX
jmp strnlen
mov rcx, STRLEN_MAX
mov rdx, rcx
scasb.rep.nz ax0, zero
sub rax, rdx, rcx
ret

View File

@ -18,7 +18,7 @@ strrev:
; the null terminator
mov rcx, STRLEN_MAX
scasb.rep.nz ax1, zero
dec ax1
sub ax1, ax1, 1
.2:
; copy, going backward though str
@ -30,8 +30,8 @@ strrev:
mov.z b[ax0+1], zero
ret.z
inc ax0
dec ax1
add ax0, ax0, 1
sub ax1, ax1, 1
jmp .2
@ -50,7 +50,7 @@ strrev2:
; the null terminator
mov rcx, STRLEN_MAX
scasb.rep.nz ax1, zero
dec ax1
sub ax1, ax1, 1
; increase ax0 while decreasing ax1, performing exchanges
.2:
@ -60,8 +60,8 @@ strrev2:
xchg rax, b[ax0]
mov b[ax1], rax
inc ax0
dec ax1
add ax0, ax0, 1
sub ax1, ax1, 1
jmp .2
.3:

View File

@ -28,17 +28,13 @@ TrapHandlers.epilog:
; TRAP return values: RAX-RDX
mov ax0, r12
mov ax1, $rax
mov ax2, rax
call RFS.StoreReg
call RFS.StoreReg, r12, $rax
mov ax1, $rdx
mov ax2, rdx
call RFS.StoreReg
call RFS.StoreReg, r12, $rdx
mov ax0, r11
call IDT.DoneHandling
call IDT.DoneHandling, r11
iret

View File

@ -37,18 +37,16 @@ trap0_handler:
.handle_Exit:
; Open COMMAND.COM
mov ax0, .cmdcom
call DISK.OpenFile
call DISK.OpenFile, .cmdcom
; Crash on failure
cmp rax, zero
crash.l
; Load at CMDCOM_LOADP
mov ax0, rax
mov ax1, CMDCOM_LOADP
mov ax2, CMDCOM_MAXSZ
call DISK.ReadFile
call DISK.ReadFile, rax
; Assume that COMMAND.COM being
; less then 4KB means something
@ -57,32 +55,26 @@ trap0_handler:
crash.b
; Close the handle
mov ax0, rax
call DISK.CloseFile
call DISK.CloseFile, rax
; Code address
mov ax0, zero
mov ax1, $rip
mov ax2, 0x100000
call RFS.StoreReg
call RFS.StoreReg, zero, $rip
; Usermode
mov ax1, $cr0
mov ax2, 3
call RFS.StoreReg
call RFS.StoreReg, zero, $cr0
mov rcx, CMDCOM_LOADP
sub rcx, rcx, 0x100000
; Code offset
mov ax1, $cr1
mov ax2, rcx
call RFS.StoreReg
call RFS.StoreReg, zero, $cr1
; Data offset
mov ax1, $cr2
mov ax2, rcx
call RFS.StoreReg
call RFS.StoreReg, zero, $cr2
; Return frame
mov q[rbp-16], zero
@ -128,7 +120,9 @@ trap0_handler:
.handle_HaltMode:
hlt
.HLT.loop:
xpause
pause
pause
pause
scan rax
b.z rax, zero, .HLT.loop

View File

@ -1,6 +1,61 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
arith128_test:
call .test_add
call .test_sub
ret
.print_lq:
push rax
push rdx
mov ax0, .fmt
call printf
add rsp, rsp, 16
prn 10
ret
.fmt = "0x%x:%x"
.test_add:
mov ax0, 0x99AABBCCDDEEFF00
mov ax1, 0x1122334455667788
mov ax2, 0xFF
call add_lq_q
call .print_lq
mov ax0, 0xFFFFFFFFFFFFFFFF
mov ax1, zero
mov ax2, 5
call add_lq_q
call .print_lq
mov ax0, 0x5500660077008800
mov ax1, 0x1100220033004400
mov ax2, 0x00AA00BB00CC00DD
mov ax3, 0x009900CE00DF00AB
call add_lq_lq
call .print_lq
ret
.test_sub:
mov ax0, 0x99AABBCCDDEEFFFF
mov ax1, 0x1122334455667788
mov ax2, 0xFF
call sub_lq_q
call .print_lq
mov ax0, zero
mov ax1, zero
mov ax2, 2
call sub_lq_q
call .print_lq
ret
file_test:
.bufsize := 256

View File

@ -32,7 +32,7 @@ builtins.dir:
b.z rax, 0, .end
; found something
inc nx0
add nx0, nx0, 1
; separate extension from file name
mov rcx, NAME_MAX
@ -46,13 +46,13 @@ builtins.dir:
; calculate where to put extension
sub r11, r10, .buf
dec r11
sub r11, r11, 1
.ext_pad:
; print at least 11 non-space characters before extension
b.ae r11, 11, .print_ext
prn ' '
inc r11
add r11, r11, 1
jmp .ext_pad
.print_ext:
@ -61,15 +61,16 @@ builtins.dir:
prn ' '
cmp b[r10], '.'
inc.z r10
add.z r10, r10, 1
.print_ext.1:
b.z b[r10], 0, .print_ext.2
; print and decrease rcx, unless it's already 0
prn b[r10]
inc r10
dec.cxnz rcx
mov r12, b[r10]
prn r12
add r10, r10, 1
sub.cxnz rcx, rcx, 1
jmp .print_ext.1
@ -88,10 +89,9 @@ builtins.dir:
shr rax, rdx, 10
and rdx, rdx, 1023
mov ax0, .bytesstr
push rdx
push rax
call printf
call printf, .bytesstr
add rsp, rsp, 16
.bytesstr = "%d kilobytes + %d bytes"
@ -102,14 +102,11 @@ builtins.dir:
jmp .next
.end:
mov ax0, .endstr1
push nx0
call printf
call printf, .endstr1
add rsp, rsp, 8
mov rcx, STRLEN_MAX
mov rdx, .endstr2
prns.rep.nz rdx
call print, .endstr2
pop nx0
ret

View File

@ -13,9 +13,7 @@ ps1 = "C:\\> "
main:
.print_prompt:
mov rcx, STRLEN_MAX
mov rdx, ps1
prns.rep.nz rdx
call print, ps1
; empty argbuf
mov rcx, argbuf.size
@ -43,7 +41,7 @@ main:
b.z rcx, zero, .input_loop
; delete it
dec rcx
sub rcx, rcx, 1
add rdx, rcx, argbuf
mov b[rdx], zero
@ -65,7 +63,7 @@ main:
; add character to buffer and increase iterator (rcx)
add rdx, rcx, argbuf
mov b[rdx], rax
inc rcx
add rcx, rcx, 1
; another one
jmp .input_loop
@ -83,7 +81,7 @@ main:
; argv1 exists? if so, save its position
mov r11, rdx
b.z b[r11], zero, .no_argv1
inc r11
add r11, r11, 1
.next_space:
mov r10, b[r11]
@ -91,7 +89,7 @@ main:
; skip spaces
cmp r10, ' '
inc.z r11
add.z r11, r11, 1
jmp.z .next_space
mov q[argv1pos], r11
@ -108,68 +106,59 @@ main:
sub rcx, rdx, argbuf
mov rdx, argbuf
mov rax, argv0
movsb.rep rax, rdx
.mmove:
jmp.cxz .detect_builtin
mov r11, b[rdx]
mov b[rax], r11
add rdx, rdx, 1
add rax, rax, 1
sub rcx, rcx, 1
jmp .mmove
.detect_builtin:
.builtin_cls = "cls"
mov ax0, argv0
mov ax1, .builtin_cls
call strcmp
call strcmp, argv0, .builtin_cls
b.z rax, 0, .handle_CLS
.builtin_date = "date"
mov ax0, argv0
mov ax1, .builtin_date
call strcmp
call strcmp, argv0, .builtin_date
b.z rax, 0, .handle_DATE
.builtin_dir = "dir"
mov ax0, argv0
mov ax1, .builtin_dir
call strcmp
call strcmp, argv0, .builtin_dir
b.z rax, 0, .handle_DIR
.builtin_dump = "dump"
mov ax0, argv0
mov ax1, .builtin_dump
call strcmp
call strcmp, argv0, .builtin_dump
b.z rax, 0, .handle_DUMP
.builtin_echo = "echo"
mov ax0, argv0
mov ax1, .builtin_echo
call strcmp
call strcmp, argv0, .builtin_echo
b.z rax, 0, .handle_ECHO
.builtin_exit = "exit"
mov ax0, argv0
mov ax1, .builtin_exit
call strcmp
call strcmp, argv0, .builtin_exit
b.z rax, 0, .handle_EXIT
.builtin_help = "help"
mov ax0, argv0
mov ax1, .builtin_help
call strcmp
call strcmp, argv0, .builtin_help
b.z rax, 0, .handle_HELP
.builtin_print = "print"
mov ax0, argv0
mov ax1, .builtin_print
call strcmp
call strcmp, argv0, .builtin_print
b.z rax, 0, .handle_PRINT
.builtin_time = "time"
mov ax0, argv0
mov ax1, .builtin_time
call strcmp
call strcmp, argv0, .builtin_time
b.z rax, 0, .handle_TIME
.builtin_ver = "ver"
mov ax0, argv0
mov ax1, .builtin_ver
call strcmp
call strcmp, argv0, .builtin_ver
b.z rax, 0, .handle_VER
jmp .command_not_found
@ -182,19 +171,17 @@ main:
jmp .print_prompt
.handle_DATE:
time ax0
call GetTimeUTC
push b[rax+3]
mov rcx, b[rax+4]
inc rcx
add rcx, rcx, 1
push rcx
push w[rax+6]
mov ax0, .datefmt
call printf
call printf, .datefmt
add rsp, rsp, 5*8
add rsp, rsp, 40
jmp .print_prompt
@ -252,53 +239,36 @@ main:
jmp .print_prompt
.handle_TIME:
time ax0
call GetTimeUTC
push b[rax]
push b[rax+1]
push b[rax+2]
mov ax0, .timefmt
call printf
add rsp, rsp, 3*8
call printf, .timefmt
add rsp, rsp, 24
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VER:
mov rcx, STRLEN_MAX
mov rdx, cmd.versionstr
prns.rep.nz rdx
call print, cmd.versionstr
prn 10
jmp .print_prompt
.handle_HELP:
mov rcx, STRLEN_MAX
mov rdx, .helpmsg
prns.rep.nz rdx
mov rdx, .helpmsg.cls
prns.rep.nz rdx
mov rdx, .helpmsg.date
prns.rep.nz rdx
mov rdx, .helpmsg.dir
prns.rep.nz rdx
mov rdx, .helpmsg.dump
prns.rep.nz rdx
mov rdx, .helpmsg.echo
prns.rep.nz rdx
mov rdx, .helpmsg.exit
prns.rep.nz rdx
mov rdx, .helpmsg.help
prns.rep.nz rdx
mov rdx, .helpmsg.print
prns.rep.nz rdx
mov rdx, .helpmsg.time
prns.rep.nz rdx
mov rdx, .helpmsg.ver
prns.rep.nz rdx
call print, .helpmsg
call print, .helpmsg.cls
call print, .helpmsg.date
call print, .helpmsg.dir
call print, .helpmsg.dump
call print, .helpmsg.echo
call print, .helpmsg.exit
call print, .helpmsg.help
call print, .helpmsg.print
call print, .helpmsg.time
call print, .helpmsg.ver
jmp .print_prompt
@ -315,22 +285,17 @@ main:
.helpmsg.ver = " VER Display current COMMAND.COM and DOS kernel versions\n"
.command_not_found:
mov rcx, STRLEN_MAX
mov rdx, argv0
prns.rep.nz rdx
mov rdx, .cnf_errmsg
prns.rep.nz rdx
call print, argv0
call print, .cnf_errmsg
jmp .print_prompt
.cnf_errmsg = ": command not found\n"
.file_not_found:
mov ax0, .fnf_errmsg
push q[argv1pos]
push argv0
call printf
call printf, .fnf_errmsg
add rsp, rsp, 16
jmp .print_prompt
@ -338,10 +303,9 @@ main:
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
mov ax0, .ef_errmsg
push q[argv1pos]
push argv0
call printf
call printf, .ef_errmsg
add rsp, rsp, 16
jmp .print_prompt
@ -349,10 +313,9 @@ main:
.ef_errmsg = "%s: %s: file is empty\n"
.couldnt_read:
mov ax0, .cno_errmsg
push q[argv1pos]
push argv0
call printf
call printf, .cno_errmsg
add rsp, rsp, 16
jmp .print_prompt
@ -360,12 +323,8 @@ main:
.cno_errmsg = "%s: %s: an error occured while reading file\n"
.need_params:
mov rcx, STRLEN_MAX
mov rdx, argv0
prns.rep.nz rdx
mov rdx, .np_errmsg
prns.rep.nz rdx
call print, argv0
call print, .np_errmsg
jmp .print_prompt

View File

@ -46,14 +46,14 @@ $(OBJDIR)/%.d: %.c
# echo ${CL2}[$@] ${CL}dependencies generated.${CL3};\
# fi
in/instrs.lst: in/INSTRS in/arch_i.py
ob/instrs.lst: in/arch_i.py
@cd in && python3 arch_i.py
clean:
@rm -f $(OBJDIR)/*/*.o in/arch_i.h in/instrs.lst
@rm -f $(OBJDIR)/*/*.o ob/arch_i.h ob/instrs.lst
@rm -f $(OBJDIR)/*/*.d
$(KEXE): in/instrs.lst $(obj)
$(KEXE): ob/instrs.lst $(obj)
@gcc -O2 -lSDL2 -lSDL2_ttf -Wall $(obj) -o $(KEXE)
@echo ${CL2}[$@] ${CL}made successfully.${CL3}

106
vm/in/ALU
View File

@ -5,15 +5,6 @@
# Logical instructions #
#---------------------------------------------------------------------------#
#
# Bitwise NOT operation
#
# $1 = NOT($2)
#
# Preserves all flags
#
not r r
#
# Bitwise OR operation
#
@ -22,10 +13,6 @@ not r r
# Preserves all flags
#
or r r ri
# $dest = $src1 OR NOT($src2)
orn r r ri
# $dest = NOT($src1 OR $src2)
nor r r ri
#
# Bitwise AND operation
@ -35,10 +22,6 @@ nor r r ri
# Preserves all flags
#
and r r ri
# $dest = $src1 AND NOT($src2)
andn r r ri
# $dest = NOT($src1 AND $src2)
nand r r ri
#
# Bitwise XOR operation
@ -48,10 +31,6 @@ nand r r ri
# Preserves all flags
#
xor r r ri
# $dest = $src1 XOR NOT($src2)
xorn r r ri
# $dest = NOT($src1 XOR $src2)
xnor r r ri
#
# Logical left/right shift (SHL/SHR)
@ -91,50 +70,6 @@ sar r r ri
cmp r ri
cmp m ri
#
# Arithmetical SGN operation
#
# IF ($1 == 0) THEN
# $2 = 0
# ELIF ($1 GT 0) THEN
# $2 = 1
# ELSE
# $2 = LONG_MIN
# FI
#
# Treats $1 and $2 as signed values
#
# Preserves all flags
#
sgn r r
#
# Arithmetical NEG operation
#
# $1 = NOT($2) + 1
#
# Preserves all flags
#
neg r r
#
# Arithmetical INC operation
#
# $1 = $1 + 1
#
# Preserves all flags
#
inc r
#
# Arithmetical DEC operation
#
# $1 = $1 - 1
#
# Preserves all flags
#
dec r
#
# Arithmetical ADD operation
#
@ -146,7 +81,6 @@ dec r
#
add r r ri
addf r r ri
addo r r ri
#
# Arithmetical SUB operation
@ -159,26 +93,22 @@ addo r r ri
#
sub r r ri
subf r r ri
subo r r ri
#
# Arithmetical ADD/SUB operation, with carry/overflow
#
# $dest = $src1 + $src2 + CF (ADC)
# $dest = $src1 + $src2 + OF (ADO)
# $dest = $src1 - $src2 - CF (SBB)
# $dest = $src1 - $src2 - OF (SBO)
#
# Preserves ZF and SF
# Flags CF and OF are undefined for now
# Sets CF if unsigned integer overflow occur, clears it otherwise
# Sets OF is signed integer overflow occur, clears it otherwise
# Sets ZF and SF according to the result
#
adcx r r ri
adox r r ri
sbbx r r ri
sbox r r ri
#
# Arithmetical unsigned MUL operation
# Arithmetical MUL operation
#
# $dest = LO($src1 * $src2)
#
@ -187,31 +117,47 @@ sbox r r ri
#
mul r r ri
mulf r r ri
mulo r r ri
# Arithmetical unsigned MUL operation
#
# $dest1 = HI($dest2 * $src)
# $dest2 = LO($dest2 * $src)
#
# Sets CF and OF if HI($2 * $3) > 0, clears them otherwise
# Preserves ZF and SF
# Preserves all flags
#
mulhi r r ri
# Arithmetical signed MUL operation
#
# $dest1 = HI($dest2 ** $src)
# $dest2 = LO($dest2 ** $src)
#
# Preserves all flags
#
imulhi r r ri
#
# Arithmetical unsigned DIV operation
#
# $dest1 = $1 DIV $2
# $dest = $src1 DIV $src2
#
# Preserves all flags
#
div r r ri
#
# Arithmetical unsigned modulo operation (REM)
# Arithmetical signed DIV operation
#
# $1 = $1 MOD $2
# $dest = $src1 IDIV $src2
#
# Preserves all flags
#
idiv r r ri
#
# Arithmetical modulo operation (REM)
#
# $dest = $src1 MOD $src2
#
# Preserves all flags
#

View File

@ -24,36 +24,21 @@ dump
# Misc. instructions #
#---------------------------------------------------------------------------#
#
# Do nothing (NOOP)
#
# (nothing)
#
# Throws:
# (nothing)
#
# Preserves all flags
#
nop
#
# Pause the CPU for a very short amount of time (PAUSE)
# Used in spin-like loops
# Used in spin-type loops
#
pause
#
# Pause the CPU for a relatively long time (XPAUSE)
# Throw #OVF when RFX.OF=1 (INTO)
#
# Throws:
# #SYS if not in supervisor mode
#
xpause
into
#
# Get timestamp in seconds
# Get timestamp in µseconds
#
time r
utime r r
#
# $1 = seconds since start of month
@ -62,68 +47,11 @@ time r
#
ytime r r r
#
# Get timestamp in µseconds
#
utime r
#
# CPU Identification Number
#
# Does nothing (for now)
#
cpuid
#---------------------------------------------------------------------------#
# Clean-up misc. instructions #
#---------------------------------------------------------------------------#
#
# Clear all GPR registers except RBP/RSP
#
cls
#
# Clear base registers except RBP/RSP (CLR)
#
clr
#
# Clear argument registers (CLA)
#
cla
#
# Clear nonvolatile registers (CLN)
#
cln
#---------------------------------------------------------------------------#
# Flag manipulation instructions #
#---------------------------------------------------------------------------#
#
# Clear or set interrupt flag (CLI/STI)
#
# Throws:
# #SYS if not in supervisor mode
#
cli
sti
#
# Clear or set direction flag (CLD/STD)
#
cld
std
#
# Complement, clear or set carry flag (CMC/CLC/STC)
#
cmc
clc
stc
#---------------------------------------------------------------------------#
# Byte-wise / bit-wise manipulation instructions #
#---------------------------------------------------------------------------#
@ -144,7 +72,7 @@ dswap r r
#
# Send a character to standard output (PRN)
#
prn rim
prn ri
#
# Print a string to standard output (PRN)

View File

@ -52,6 +52,8 @@ b rm ri ri
# JMP(RIP)
#
call ri
call i ri
call i ri ri
#
# Return to caller (RET)
@ -103,9 +105,9 @@ pop r
# $1 = ADDR($2)
#
# For instance:
# LEA RAX, [RBX + RCX + 4]
# LEA RAX, [RBX + RCX * 2 + 4]
# will result in:
# RAX = RBX + RCX + 4
# RAX = RBX + RCX * 2 + 4
#
# Preserves all flags
#

View File

@ -20,24 +20,6 @@ stosw r ri
stosl r ri
stosq r ri
#
# Load value from string (LODSx)
#
# $1 = [%2]
# IF (DF == 0) THEN
# %str = %str + sizeof(x)
# ELSE
# %str = %str - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the loaded value
#
lodsb r r
lodsw r r
lodsl r r
lodsq r r
#
# Scan string for a particular value (SCASx)
#
@ -65,61 +47,5 @@ scasw r ri
scasl r ri
scasq r ri
#
# Compare bytes in strings (CMPSx)
#
# CMP([%1], [%2])
#
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# %2 = %2 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# %2 = %2 - sizeof(x)
# FI
#
# Sets CF, OF, ZF and SF according to the result of the comparison
#
# Moves past the compared values in any case!
#
cmpsb r r
cmpsw r r
cmpsl r r
cmpsq r r
#
# Safe compare bytes in strings (CMPZSx)
#
# Behaves precisely like CMPSx, except in the following case:
# - If both [%1] and [%2] are zero, clears ZF (indicating NOT EQUAL)
#
# This prevents 'CMPZSx.REP.Z' from ignoring null-terminators when both strings
# have the exact same content; this allows for short strcmp's
#
cmpzsb r r
cmpzsw r r
cmpzsl r r
cmpzsq r r
#
# Move value from string to string (MOVSx)
#
# [%1] = [%2]
# IF (DF == 0) THEN
# %1 = %1 + sizeof(x)
# %2 = %2 + sizeof(x)
# ELSE
# %1 = %1 - sizeof(x)
# %2 = %2 - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the moved value
#
movsb r r
movsw r r
movsl r r
movsq r r
#---------------------------------------------------------------------------#

View File

@ -58,6 +58,15 @@ trap ri
#
iret
#
# Clear or set interrupt flag (CLI/STI)
#
# Throws:
# #SYS if not in supervisor mode
#
cli
sti
#---------------------------------------------------------------------------#
# Device control instructions #
#---------------------------------------------------------------------------#
@ -70,7 +79,7 @@ iret
# Throws:
# #SYS if not in supervisor mode
#
devctl ri ri
devctl r r
#
# Call a device-defined function slot of device (IOCALL)

View File

@ -4,26 +4,16 @@
#include <in/instrs.h>
#define _NEED_ARCH_I
#include <in/arch_i.h>
#include <ob/arch_i.h>
//----------------------------------------------------------------------------//
IMPL_START_2(not) { v1 = ~v2; } IMPL_OUT;
IMPL_START_3(or) { v1 = v2 | v3; } IMPL_OUT;
IMPL_START_3(and) { v1 = v2 & v3; } IMPL_OUT;
IMPL_START_3(xor) { v1 = v2 ^ v3; } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_3(orn) { v1 = v2 | ~v3; } IMPL_OUT;
IMPL_START_3(nor) { v1 = ~(v2 | v3); } IMPL_OUT;
IMPL_START_3(andn) { v1 = v2 & ~v3; } IMPL_OUT;
IMPL_START_3(nand) { v1 = ~(v2 & v3); } IMPL_OUT;
IMPL_START_3(xorn) { v1 = v2 ^ ~v3; } IMPL_OUT;
IMPL_START_3(xnor) { v1 = ~(v2 ^ v3); } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_3(shl) { v1 = v2 << v3; } IMPL_OUT;
IMPL_START_3(shr) { v1 = v2 >> v3; } IMPL_OUT;
IMPL_START_3(sal) { v1 = (ulong)((long)v2 << (long)v3); } IMPL_OUT;
@ -31,81 +21,64 @@ IMPL_START_3(sar) { v1 = (ulong)((long)v2 >> (long)v3); } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_2(sgn) { v1 = (!v2 ? 0: ((long)v2 < 0 ? (ulong)-1L : 1)); } IMPL_OUT;
IMPL_START_2(neg) { v1 = ~v2 + 1; } IMPL_OUT;
IMPL_START_1(inc) { v1++; } IMPL_OUT;
IMPL_START_1(dec) { v1--; } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_3(add) { v1 = v2 + v3; } IMPL_OUT;
IMPL_START_3(addf) { COMPARE(v2, ~v3+1); v1 = v2 + v3; } IMPL_OUT;
IMPL_START_3(addo) { COMPARE(v2, ~v3+1); v1 = v2 + v3; INTO(); } IMPL_OUT;
IMPL_START_3(addf) { COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_2(cmp) { COMPARE(v1, v2); } IMPL_END;
IMPL_START_2(cmp) { COMPARE_SUB(v1, v2); } IMPL_END;
IMPL_START_3(sub) { v1 = v2 - v3; } IMPL_OUT;
IMPL_START_3(subf){ COMPARE(v2, v3); v1 = v2 - v3; } IMPL_OUT;
IMPL_START_3(subo){ COMPARE(v2, v3); v1 = v2 - v3; INTO(); } IMPL_OUT;
IMPL_START_3(subf){ COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_3(adcx) { v1 = v2 + v3 + !!(R(RFX)&CF); } IMPL_OUT;
IMPL_START_3(adox) { v1 = v2 + v3 + !!(R(RFX)&OF); } IMPL_OUT;
IMPL_START_3(sbbx) { v1 = v2 - v3 - !!(R(RFX)&CF); } IMPL_OUT;
IMPL_START_3(sbox) { v1 = v2 - v3 - !!(R(RFX)&OF); } IMPL_OUT;
IMPL_START_3(adcx) { v3 += !!(R(RFX)&CF); COMPARE_ADD(v2, v3); v1 = v2 + v3; } IMPL_OUT;
IMPL_START_3(sbbx) { v3 += !!(R(RFX)&CF); COMPARE_SUB(v2, v3); v1 = v2 - v3; } IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_3(mul) { v1 = v2 * v3; } IMPL_OUT;
IMPL_START_3(rem) { v1 = v2 % v3; } IMPL_OUT;
IMPL_START_3(div) {
if (!v3)
_except(ctx, E_DIV, "DIV by 0");
v1 = v2 / v3;
} IMPL_OUT;
IMPL_START_3(idiv) {
if (!v3)
_except(ctx, E_DIV, "IDIV by 0");
v1 = (ulong)((long)v2/(long)v3);
} IMPL_OUT;
//----------------------------------------------------------------------------//
//
// www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
//
static void multiply(ulong u, ulong v, ulong *hi, ulong *lo)
static void __unsigned_multiply128(ulong u, ulong v, ulong *hi, ulong *lo)
{
ulong u1 = (u & 0xffffffff);
ulong v1 = (v & 0xffffffff);
ulong t = (u1 * v1);
ulong w3 = (t & 0xffffffff);
ulong k = (t >> 32);
u >>= 32;
t = (u * v1) + k;
k = (t & 0xffffffff);
ulong w1 = (t >> 32);
v >>= 32;
t = (u1 * v) + k;
k = (t >> 32);
if (hi) *hi = (u * v) + w1 + k;
if (lo) *lo = (t << 32) + w3;
__uint128_t r = (__uint128_t)u * (__uint128_t)v;
*hi = r >> 64;
*lo = r;
}
IMPL_START_3(mul) { v1 = v2 * v3; } IMPL_OUT;
IMPL_START_3(mulhi) { multiply(v2, v3, &v1, &v2); } IMPL_OUT_2;
IMPL_START_3(mulhi) { __unsigned_multiply128(v2, v3, &v1, &v2); } IMPL_OUT_2;
IMPL_START_3(mulf) {
ulong tmp;
multiply(v2, v3, &tmp, &v1);
__unsigned_multiply128(v2, v3, &tmp, &v1);
R(RFX) = v2 ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF);
} IMPL_OUT;
IMPL_START_3(mulo) {
ulong tmp;
multiply(v2, v3, &tmp, &v1);
R(RFX) = v2 ? (R(RFX)|CF|OF) : R(RFX)&~(CF|OF);
INTO();
} IMPL_OUT;
//----------------------------------------------------------------------------//
static void __signed_multiply128(ulong u, ulong v, ulong *hi, ulong *lo)
{
__int128_t r = (__int128_t)(long)u * (__int128_t)(long)v;
*hi = r >> 64;
*lo = r;
}
IMPL_START_3(imulhi) { __signed_multiply128(v2, v3, &v1, &v2); } IMPL_OUT_2;
//----------------------------------------------------------------------------//

View File

@ -131,8 +131,8 @@ def parse_2(fp):
count = count + 1
fi = open("INSTRS")
hd = open("arch_i.h", "w")
ls = open("instrs.lst", "w")
hd = open("../ob/arch_i.h", "w")
ls = open("../ob/instrs.lst", "w")
count = 0

View File

@ -2,7 +2,6 @@
// See the LICENSE file in the project root for more information.
#include <pc/arch.h>
#include <in/arch_i.h>
//----------------------------------------------------------------------------//
@ -108,18 +107,29 @@ IMPL_START_2(name) \
//----------------------------------------------------------------------------//
#define COMPARE(v1, v2) \
ulong _u1 = (ulong)v1, _u2 = (ulong)v2; \
long _s1 = (long)v1, _s2 = (long)v2; \
#define COMPARE_ADD(v1, v2) \
ulong _u1 = (ulong)v1, _u2 = (ulong)v2, _u3 = (_u1 + _u2); \
\
if (_u1 + _u2 < _u2) R(RFX) |= CF; \
else R(RFX) &= ~CF; \
\
if (((_u1 ^ _u3) & (_u2 ^ _u3)) >> 63) \
R(RFX) |= OF; \
else R(RFX) &= ~OF; \
\
SET_ZSF(_u3);
#define COMPARE_SUB(v1, v2) \
ulong _u1 = (ulong)v1, _u2 = (ulong)v2, _u3 = (_u1 - _u2); \
\
if (_u1 < _u2) R(RFX) |= CF; \
else R(RFX) &= ~CF; \
\
if ( ((_s1 < 0) && (_s1 > LONG_MAX + _s2)) \
|| ((_s2 > 0) && (_s1 < LONG_MIN + _s2)) ) \
if (((_u1 ^ _u3) & (_u1 ^ _u2)) >> 63) \
R(RFX) |= OF; \
else R(RFX) &= ~OF; \
SET_ZSF(_u1 - _u2);
\
SET_ZSF(_u3);
//----------------------------------------------------------------------------//

View File

@ -9,11 +9,8 @@
//----------------------------------------------------------------------------//
IMPL_START_0(nop) {} IMPL_END;
IMPL_START_0(cpuid) { rax = rdx = 0; } IMPL_END;
IMPL_START_0(into) { INTO(); } IMPL_END;
IMPL_START_0(pause) { usleep(5000); } IMPL_END;
IMPL_START_0(xpause) { CHK_SUPERV(); usleep(25000); } IMPL_END;
//----------------------------------------------------------------------------//
@ -46,8 +43,6 @@ IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_X_NOIN(time) { v1 = time(NULL); } IMPL_OUT;
IMPL_START_X_NOIN(ytime)
{
time_t t = time(NULL);
@ -77,24 +72,6 @@ IMPL_START_0(cls) {
for (int i = R10; i <= NX7; i++) R(i) = 0;
} IMPL_END;
IMPL_START_0(clr) {
R(RAX) = R(RBX) = R(RCX) = R(RDX) = R(RDI) = R(RSI) = R(RFX) = 0;
for (int i = R10; i <= R15; i++) R(i) = 0;
} IMPL_END;
IMPL_START_0(cla) { for (int i = AX0; i <= AX7; i++) R(i) = 0; } IMPL_END;
IMPL_START_0(cln) { for (int i = NX0; i <= NX7; i++) R(i) = 0; } IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(cli) { CHK_SUPERV(); R(CR0) &= ~IF; } IMPL_END;
IMPL_START_0(sti) { CHK_SUPERV(); R(CR0) |= IF; } IMPL_END;
IMPL_START_0(cld) { R(RFX) &= ~DF; } IMPL_END;
IMPL_START_0(clc) { R(RFX) &= ~CF; } IMPL_END;
IMPL_START_0(std) { R(RFX) |= DF; } IMPL_END;
IMPL_START_0(stc) { R(RFX) |= CF; } IMPL_END;
IMPL_START_0(cmc) { R(RFX) = (R(RFX)&CF ? R(RFX)&~CF : R(RFX)|CF); } IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_2(bswap)
@ -151,7 +128,7 @@ IMPL_START_0(prns)
{
uchar ch = readmemzx(ctx, R(p1->reg), 1);
COMPARE(ch, 0);
COMPARE_SUB(ch, 0);
if ((R(RFX) & ZF) == 0)
{

View File

@ -15,7 +15,7 @@ IMPL_START_1(loop) {
IMPL_END;
IMPL_START_3(b) {
COMPARE(v1, v2);
COMPARE_SUB(v1, v2);
if (eval_cond(ctx, ctx->cond))
R(RIP) = v3;
@ -51,11 +51,32 @@ IMPL_START_1(pop) {
R(RSP) += 8;
} IMPL_OUT;
/*
IMPL_START_1(call) {
R(RSP) -= 8;
writemem(ctx, R(RIP), R(RSP), 8);
R(RIP) = v1;
} IMPL_END;
*/
IMPL_START_1(call) {
R(RSP) -= 8;
writemem(ctx, R(RIP), R(RSP), 8);
R(RIP) = v1;
if (p2)
{
DECV(v2, p2);
ax0 = v2;
if (p3)
{
DECV(v3, p3);
ax1 = v3;
}
}
} IMPL_END;
IMPL_START_0(ret) {
R(RIP) = readmem(ctx, R(RSP), 8); R(RSP) += 8;

View File

@ -25,26 +25,12 @@ IMPL_START_0(stosq) { stos_impl(ctx, p1, p2, 8); } IMPL_END;
//----------------------------------------------------------------------------//
static void lods_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
R(p1->reg) = readmem(ctx, R(p2->reg), len);
R(RFX) = (R(p1->reg) == 0 ? R(RFX)|ZF : R(RFX)&~ZF);
STR_MOVE(p2->reg, len);
}
IMPL_START_0(lodsb) { lods_impl(ctx, p1, p2, 1); } IMPL_END;
IMPL_START_0(lodsw) { lods_impl(ctx, p1, p2, 2); } IMPL_END;
IMPL_START_0(lodsl) { lods_impl(ctx, p1, p2, 4); } IMPL_END;
IMPL_START_0(lodsq) { lods_impl(ctx, p1, p2, 8); } IMPL_END;
//----------------------------------------------------------------------------//
static void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
DECV(v2, p2);
ulong x = readmem(ctx, R(p1->reg), len);
COMPARE(x, v2);
COMPARE_SUB(x, v2);
if (x == 0) {
R(RFX) |= ZF;
@ -62,45 +48,6 @@ IMPL_START_0(scasq) { scas_impl(ctx, p1, p2, 8); } IMPL_END;
//----------------------------------------------------------------------------//
static void cmps_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong x1 = readmem(ctx, R(p1->reg), len);
ulong x2 = readmem(ctx, R(p2->reg), len);
COMPARE(x1, x2);
STR_MOVE(p1->reg, len);
STR_MOVE(p2->reg, len);
}
IMPL_START_0(cmpsb) { cmps_impl(ctx, p1, p2, 1); } IMPL_END;
IMPL_START_0(cmpsw) { cmps_impl(ctx, p1, p2, 2); } IMPL_END;
IMPL_START_0(cmpsl) { cmps_impl(ctx, p1, p2, 4); } IMPL_END;
IMPL_START_0(cmpsq) { cmps_impl(ctx, p1, p2, 8); } IMPL_END;
//----------------------------------------------------------------------------//
static void cmpzs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong x1 = readmem(ctx, R(p1->reg), len);
ulong x2 = readmem(ctx, R(p2->reg), len);
COMPARE(x1, x2);
if (!x1 && !x2)
R(RFX) &= ~ZF;
STR_MOVE(p1->reg, len);
STR_MOVE(p2->reg, len);
}
IMPL_START_0(cmpzsb) { cmpzs_impl(ctx, p1, p2, 1); } IMPL_END;
IMPL_START_0(cmpzsw) { cmpzs_impl(ctx, p1, p2, 2); } IMPL_END;
IMPL_START_0(cmpzsl) { cmpzs_impl(ctx, p1, p2, 4); } IMPL_END;
IMPL_START_0(cmpzsq) { cmpzs_impl(ctx, p1, p2, 8); } IMPL_END;
//----------------------------------------------------------------------------//
static void movs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong x = readmem(ctx, R(p2->reg), len);

View File

@ -42,7 +42,6 @@ IMPL_START_1(trap) {
_except(ctx, v1 + 256, "TRAP instruction");
} IMPL_END;
IMPL_START_0(into) { INTO(); } IMPL_END;
IMPL_START_0(iret) {
if (ctx->dumpsw)
@ -55,6 +54,9 @@ IMPL_START_0(iret) {
}
IMPL_END;
IMPL_START_0(cli) { CHK_SUPERV(); R(CR0) &= ~IF; } IMPL_END;
IMPL_START_0(sti) { CHK_SUPERV(); R(CR0) |= IF; } IMPL_END;
//----------------------------------------------------------------------------//
//

View File

@ -102,7 +102,7 @@ extern void do_hlt(ctx_t *ctx);
#include <pc/regs.h>
#include <pc/decode.h>
#include <pc/except.h>
#include <in/arch_i.h>
#include <ob/arch_i.h>
extern ctx_t main_ctx;
extern reg_t arch_r[NREGS];

View File

@ -2,7 +2,6 @@
// See the LICENSE file in the project root for more information.
#include <pc/arch.h>
#include <in/arch_i.h>
#define rfx R(RFX)