Skip to content

Commit 755d0eb

Browse files
committed
transpile: tests: snapshots: add ioq3 asm test
for aarch64 the asm is simply ifdeffed out
1 parent f90a602 commit 755d0eb

File tree

3 files changed

+250
-0
lines changed

3 files changed

+250
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// vm_x86.c -- load time compiler and execution environment for x86 (from ioq3)
2+
3+
/*
4+
eax scratch
5+
ebx/bl opStack offset
6+
ecx scratch (required for shifts)
7+
edx scratch (required for divisions)
8+
esi program stack
9+
edi opStack base
10+
x86_64:
11+
r8 vm->instructionPointers
12+
r9 vm->dataBase
13+
*/
14+
15+
typedef struct {
16+
int programStack;
17+
int entryOfs;
18+
void* dataBase;
19+
void* codeBase;
20+
unsigned long* instructionPointers;
21+
} vm_t;
22+
23+
typedef unsigned char byte;
24+
25+
#define OPSTACK_SIZE 256
26+
#define MAX_VMMAIN_ARGS 50
27+
28+
int VM_CallCompiled(vm_t *vm, int *args)
29+
{
30+
byte stack[OPSTACK_SIZE + 15];
31+
void *entryPoint;
32+
int programStack, stackOnEntry;
33+
byte *image;
34+
int *opStack;
35+
int opStackOfs;
36+
int arg;
37+
38+
vm_t* currentVM = vm;
39+
40+
// we might be called recursively, so this might not be the very top
41+
programStack = stackOnEntry = vm->programStack;
42+
43+
// set up the stack frame
44+
image = vm->dataBase;
45+
46+
programStack -= ( 8 + 4 * MAX_VMMAIN_ARGS );
47+
48+
for ( arg = 0; arg < MAX_VMMAIN_ARGS; arg++ )
49+
*(int *)&image[ programStack + 8 + arg * 4 ] = args[ arg ];
50+
51+
*(int *)&image[ programStack + 4 ] = 0; // return stack
52+
*(int *)&image[ programStack ] = -1; // will terminate the loop on return
53+
54+
// off we go into generated code...
55+
entryPoint = vm->codeBase + vm->entryOfs;
56+
opStack = (int*)stack + 16;
57+
*opStack = 0;
58+
opStackOfs = 0;
59+
60+
#if __x86_64__
61+
__asm__ volatile(
62+
"movq %5, %%rax\n"
63+
"movq %3, %%r8\n"
64+
"movq %4, %%r9\n"
65+
"push %%r15\n"
66+
"push %%r14\n"
67+
"push %%r13\n"
68+
"push %%r12\n"
69+
"callq *%%rax\n"
70+
"pop %%r12\n"
71+
"pop %%r13\n"
72+
"pop %%r14\n"
73+
"pop %%r15\n"
74+
: "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
75+
: "g" (vm->instructionPointers), "g" (vm->dataBase), "g" (entryPoint)
76+
: "cc", "memory", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11"
77+
);
78+
#elif __i386__
79+
__asm__ volatile(
80+
"calll *%3\n"
81+
: "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
82+
: "g" (entryPoint)
83+
: "cc", "memory", "%eax", "%ecx", "%edx"
84+
);
85+
#endif
86+
87+
if(opStackOfs != 1 || *opStack != 0xDEADBEEF)
88+
{
89+
return 0; // opStack corrupted in compiled code
90+
}
91+
if(programStack != stackOnEntry - (8 + 4 * MAX_VMMAIN_ARGS))
92+
return 0; // programStack corrupted in compiled code
93+
94+
vm->programStack = stackOnEntry;
95+
96+
return opStack[opStackOfs];
97+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
source: c2rust-transpile/tests/snapshots.rs
3+
expression: cat tests/snapshots/arch-specific/vm_x86.x86_64.rs
4+
input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c
5+
---
6+
#![allow(
7+
dead_code,
8+
mutable_transmutes,
9+
non_camel_case_types,
10+
non_snake_case,
11+
non_upper_case_globals,
12+
unused_assignments,
13+
unused_mut
14+
)]
15+
#[derive(Copy, Clone)]
16+
#[repr(C)]
17+
pub struct vm_t {
18+
pub programStack: std::ffi::c_int,
19+
pub entryOfs: std::ffi::c_int,
20+
pub dataBase: *mut std::ffi::c_void,
21+
pub codeBase: *mut std::ffi::c_void,
22+
pub instructionPointers: *mut std::ffi::c_ulong,
23+
}
24+
pub type byte = std::ffi::c_uchar;
25+
pub const MAX_VMMAIN_ARGS: std::ffi::c_int = unsafe { 50 as std::ffi::c_int };
26+
#[no_mangle]
27+
pub unsafe extern "C" fn VM_CallCompiled(
28+
mut vm: *mut vm_t,
29+
mut args: *mut std::ffi::c_int,
30+
) -> std::ffi::c_int {
31+
let mut stack: [byte; 271] = [0; 271];
32+
let mut entryPoint: *mut std::ffi::c_void = 0 as *mut std::ffi::c_void;
33+
let mut programStack: std::ffi::c_int = 0;
34+
let mut stackOnEntry: std::ffi::c_int = 0;
35+
let mut image: *mut byte = 0 as *mut byte;
36+
let mut opStack: *mut std::ffi::c_int = 0 as *mut std::ffi::c_int;
37+
let mut opStackOfs: std::ffi::c_int = 0;
38+
let mut arg: std::ffi::c_int = 0;
39+
let mut currentVM: *mut vm_t = vm;
40+
stackOnEntry = (*vm).programStack;
41+
programStack = stackOnEntry;
42+
image = (*vm).dataBase as *mut byte;
43+
programStack -= 8 as std::ffi::c_int + 4 as std::ffi::c_int * MAX_VMMAIN_ARGS;
44+
arg = 0 as std::ffi::c_int;
45+
while arg < MAX_VMMAIN_ARGS {
46+
*(&mut *image
47+
.offset((programStack + 8 as std::ffi::c_int + arg * 4 as std::ffi::c_int) as isize)
48+
as *mut byte as *mut std::ffi::c_int) = *args.offset(arg as isize);
49+
arg += 1;
50+
}
51+
*(&mut *image.offset((programStack + 4 as std::ffi::c_int) as isize) as *mut byte
52+
as *mut std::ffi::c_int) = 0 as std::ffi::c_int;
53+
*(&mut *image.offset(programStack as isize) as *mut byte as *mut std::ffi::c_int) =
54+
-(1 as std::ffi::c_int);
55+
entryPoint = ((*vm).codeBase).offset((*vm).entryOfs as isize);
56+
opStack = (stack.as_mut_ptr() as *mut std::ffi::c_int).offset(16 as std::ffi::c_int as isize);
57+
*opStack = 0 as std::ffi::c_int;
58+
opStackOfs = 0 as std::ffi::c_int;
59+
if opStackOfs != 1 as std::ffi::c_int
60+
|| *opStack as std::ffi::c_uint != 0xdeadbeef as std::ffi::c_uint
61+
{
62+
return 0 as std::ffi::c_int;
63+
}
64+
if programStack
65+
!= stackOnEntry - (8 as std::ffi::c_int + 4 as std::ffi::c_int * MAX_VMMAIN_ARGS)
66+
{
67+
return 0 as std::ffi::c_int;
68+
}
69+
(*vm).programStack = stackOnEntry;
70+
return *opStack.offset(opStackOfs as isize);
71+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
source: c2rust-transpile/tests/snapshots.rs
3+
expression: cat tests/snapshots/arch-specific/vm_x86.x86_64.rs
4+
input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c
5+
---
6+
#![allow(
7+
dead_code,
8+
mutable_transmutes,
9+
non_camel_case_types,
10+
non_snake_case,
11+
non_upper_case_globals,
12+
unused_assignments,
13+
unused_mut
14+
)]
15+
#![feature(asm)]
16+
use core::arch::asm;
17+
#[derive(Copy, Clone)]
18+
#[repr(C)]
19+
pub struct vm_t {
20+
pub programStack: std::ffi::c_int,
21+
pub entryOfs: std::ffi::c_int,
22+
pub dataBase: *mut std::ffi::c_void,
23+
pub codeBase: *mut std::ffi::c_void,
24+
pub instructionPointers: *mut std::ffi::c_ulong,
25+
}
26+
pub type byte = std::ffi::c_uchar;
27+
pub const MAX_VMMAIN_ARGS: std::ffi::c_int = unsafe { 50 as std::ffi::c_int };
28+
#[no_mangle]
29+
pub unsafe extern "C" fn VM_CallCompiled(
30+
mut vm: *mut vm_t,
31+
mut args: *mut std::ffi::c_int,
32+
) -> std::ffi::c_int {
33+
let mut stack: [byte; 271] = [0; 271];
34+
let mut entryPoint: *mut std::ffi::c_void = 0 as *mut std::ffi::c_void;
35+
let mut programStack: std::ffi::c_int = 0;
36+
let mut stackOnEntry: std::ffi::c_int = 0;
37+
let mut image: *mut byte = 0 as *mut byte;
38+
let mut opStack: *mut std::ffi::c_int = 0 as *mut std::ffi::c_int;
39+
let mut opStackOfs: std::ffi::c_int = 0;
40+
let mut arg: std::ffi::c_int = 0;
41+
let mut currentVM: *mut vm_t = vm;
42+
stackOnEntry = (*vm).programStack;
43+
programStack = stackOnEntry;
44+
image = (*vm).dataBase as *mut byte;
45+
programStack -= 8 as std::ffi::c_int + 4 as std::ffi::c_int * MAX_VMMAIN_ARGS;
46+
arg = 0 as std::ffi::c_int;
47+
while arg < MAX_VMMAIN_ARGS {
48+
*(&mut *image
49+
.offset((programStack + 8 as std::ffi::c_int + arg * 4 as std::ffi::c_int) as isize)
50+
as *mut byte as *mut std::ffi::c_int) = *args.offset(arg as isize);
51+
arg += 1;
52+
}
53+
*(&mut *image.offset((programStack + 4 as std::ffi::c_int) as isize) as *mut byte
54+
as *mut std::ffi::c_int) = 0 as std::ffi::c_int;
55+
*(&mut *image.offset(programStack as isize) as *mut byte as *mut std::ffi::c_int) =
56+
-(1 as std::ffi::c_int);
57+
entryPoint = ((*vm).codeBase).offset((*vm).entryOfs as isize);
58+
opStack = (stack.as_mut_ptr() as *mut std::ffi::c_int).offset(16 as std::ffi::c_int as isize);
59+
*opStack = 0 as std::ffi::c_int;
60+
opStackOfs = 0 as std::ffi::c_int;
61+
asm!(
62+
"movq [{2}], %rax\n", "movq [{0}], %r8\n", "movq [{1}], %r9\n", "push %r15\n",
63+
"push %r14\n", "push %r13\n", "push %r12\n", "callq *%rax\n", "pop %r12\n",
64+
"pop %r13\n", "pop %r14\n", "pop %r15\n", "\n", "mov {restmp0:x}, %bx\n", in
65+
(reg) & (* vm).instructionPointers, in (reg) & (* vm).dataBase, in (reg) &
66+
entryPoint, restmp0 = inlateout(reg) opStackOfs, inlateout("di") opStack,
67+
inlateout("si") programStack, out("rax") _, out("rcx") _, out("rdx") _, out("r8")
68+
_, out("r9") _, out("r10") _, out("r11") _, options(att_syntax)
69+
);
70+
if opStackOfs != 1 as std::ffi::c_int
71+
|| *opStack as std::ffi::c_uint != 0xdeadbeef as std::ffi::c_uint
72+
{
73+
return 0 as std::ffi::c_int;
74+
}
75+
if programStack
76+
!= stackOnEntry - (8 as std::ffi::c_int + 4 as std::ffi::c_int * MAX_VMMAIN_ARGS)
77+
{
78+
return 0 as std::ffi::c_int;
79+
}
80+
(*vm).programStack = stackOnEntry;
81+
return *opStack.offset(opStackOfs as isize);
82+
}

0 commit comments

Comments
 (0)