1use crate::syscall::SyscallReturn;
13use crate::ErrorCode;
14
15#[inline]
20fn u64_to_be_u32s(src: u64) -> (u32, u32) {
21    let src_bytes = src.to_be_bytes();
22    let src_msb = u32::from_be_bytes([src_bytes[0], src_bytes[1], src_bytes[2], src_bytes[3]]);
23    let src_lsb = u32::from_be_bytes([src_bytes[4], src_bytes[5], src_bytes[6], src_bytes[7]]);
24
25    (src_msb, src_lsb)
26}
27
28#[repr(u32)]
34#[derive(Copy, Clone, Debug)]
35pub enum TRD104SyscallReturnVariant {
36    Failure = 0,
37    FailureU32 = 1,
38    FailureU32U32 = 2,
39    FailureU64 = 3,
40    Success = 128,
41    SuccessU32 = 129,
42    SuccessU32U32 = 130,
43    SuccessU64 = 131,
44    SuccessU32U32U32 = 132,
45    SuccessU32U64 = 133,
46}
47
48#[derive(Copy, Clone, Debug)]
54pub enum TRD104SyscallReturn {
55    Failure(ErrorCode),
56    FailureU32(ErrorCode, u32),
57    FailureU32U32(ErrorCode, u32, u32),
58    FailureU64(ErrorCode, u64),
59    Success,
60    SuccessU32(u32),
61    SuccessU32U32(u32, u32),
62    SuccessU32U32U32(u32, u32, u32),
63    SuccessU64(u64),
64    SuccessU32U64(u32, u64),
65    AllowReadWriteSuccess(*mut u8, usize),
66    AllowReadWriteFailure(ErrorCode, *mut u8, usize),
67    UserspaceReadableAllowSuccess(*mut u8, usize),
68    UserspaceReadableAllowFailure(ErrorCode, *mut u8, usize),
69    AllowReadOnlySuccess(*const u8, usize),
70    AllowReadOnlyFailure(ErrorCode, *const u8, usize),
71    SubscribeSuccess(*const (), usize),
72    SubscribeFailure(ErrorCode, *const (), usize),
73    YieldWaitFor(usize, usize, usize),
74}
75
76impl TRD104SyscallReturn {
77    pub fn from_syscall_return(syscall_return: SyscallReturn) -> Self {
81        match syscall_return {
82            SyscallReturn::Failure(a) => TRD104SyscallReturn::Failure(a),
84            SyscallReturn::FailureU32(a, b) => TRD104SyscallReturn::FailureU32(a, b),
85            SyscallReturn::FailureU32U32(a, b, c) => TRD104SyscallReturn::FailureU32U32(a, b, c),
86            SyscallReturn::FailureU64(a, b) => TRD104SyscallReturn::FailureU64(a, b),
87            SyscallReturn::Success => TRD104SyscallReturn::Success,
88            SyscallReturn::SuccessU32(a) => TRD104SyscallReturn::SuccessU32(a),
89            SyscallReturn::SuccessU32U32(a, b) => TRD104SyscallReturn::SuccessU32U32(a, b),
90            SyscallReturn::SuccessU32U32U32(a, b, c) => {
91                TRD104SyscallReturn::SuccessU32U32U32(a, b, c)
92            }
93            SyscallReturn::SuccessU64(a) => TRD104SyscallReturn::SuccessU64(a),
94            SyscallReturn::SuccessU32U64(a, b) => TRD104SyscallReturn::SuccessU32U64(a, b),
95            SyscallReturn::AllowReadWriteSuccess(a, b) => {
96                TRD104SyscallReturn::AllowReadWriteSuccess(a, b)
97            }
98            SyscallReturn::AllowReadWriteFailure(a, b, c) => {
99                TRD104SyscallReturn::AllowReadWriteFailure(a, b, c)
100            }
101            SyscallReturn::UserspaceReadableAllowSuccess(a, b) => {
102                TRD104SyscallReturn::UserspaceReadableAllowSuccess(a, b)
103            }
104            SyscallReturn::UserspaceReadableAllowFailure(a, b, c) => {
105                TRD104SyscallReturn::UserspaceReadableAllowFailure(a, b, c)
106            }
107            SyscallReturn::AllowReadOnlySuccess(a, b) => {
108                TRD104SyscallReturn::AllowReadOnlySuccess(a, b)
109            }
110            SyscallReturn::AllowReadOnlyFailure(a, b, c) => {
111                TRD104SyscallReturn::AllowReadOnlyFailure(a, b, c)
112            }
113            SyscallReturn::SubscribeSuccess(a, b) => TRD104SyscallReturn::SubscribeSuccess(a, b),
114            SyscallReturn::SubscribeFailure(a, b, c) => {
115                TRD104SyscallReturn::SubscribeFailure(a, b, c)
116            }
117            SyscallReturn::YieldWaitFor(a, b, c) => TRD104SyscallReturn::YieldWaitFor(a, b, c),
118
119            SyscallReturn::SuccessAddr(a) => TRD104SyscallReturn::SuccessU32(a as u32),
121            SyscallReturn::SuccessPtr(a) => {
122                TRD104SyscallReturn::SuccessU32(a.as_ptr::<()>() as u32)
123            }
124        }
125    }
126}
127
128pub fn encode_syscall_return_trd104(
132    syscall_return: &TRD104SyscallReturn,
133    a0: &mut u32,
134    a1: &mut u32,
135    a2: &mut u32,
136    a3: &mut u32,
137) {
138    match *syscall_return {
139        TRD104SyscallReturn::Failure(e) => {
140            *a0 = TRD104SyscallReturnVariant::Failure as u32;
141            *a1 = usize::from(e) as u32;
142        }
143        TRD104SyscallReturn::FailureU32(e, data0) => {
144            *a0 = TRD104SyscallReturnVariant::FailureU32 as u32;
145            *a1 = usize::from(e) as u32;
146            *a2 = data0;
147        }
148        TRD104SyscallReturn::FailureU32U32(e, data0, data1) => {
149            *a0 = TRD104SyscallReturnVariant::FailureU32U32 as u32;
150            *a1 = usize::from(e) as u32;
151            *a2 = data0;
152            *a3 = data1;
153        }
154        TRD104SyscallReturn::FailureU64(e, data0) => {
155            let (data0_msb, data0_lsb) = u64_to_be_u32s(data0);
156            *a0 = TRD104SyscallReturnVariant::FailureU64 as u32;
157            *a1 = usize::from(e) as u32;
158            *a2 = data0_lsb;
159            *a3 = data0_msb;
160        }
161        TRD104SyscallReturn::Success => {
162            *a0 = TRD104SyscallReturnVariant::Success as u32;
163        }
164        TRD104SyscallReturn::SuccessU32(data0) => {
165            *a0 = TRD104SyscallReturnVariant::SuccessU32 as u32;
166            *a1 = data0;
167        }
168        TRD104SyscallReturn::SuccessU32U32(data0, data1) => {
169            *a0 = TRD104SyscallReturnVariant::SuccessU32U32 as u32;
170            *a1 = data0;
171            *a2 = data1;
172        }
173        TRD104SyscallReturn::SuccessU32U32U32(data0, data1, data2) => {
174            *a0 = TRD104SyscallReturnVariant::SuccessU32U32U32 as u32;
175            *a1 = data0;
176            *a2 = data1;
177            *a3 = data2;
178        }
179        TRD104SyscallReturn::SuccessU64(data0) => {
180            let (data0_msb, data0_lsb) = u64_to_be_u32s(data0);
181
182            *a0 = TRD104SyscallReturnVariant::SuccessU64 as u32;
183            *a1 = data0_lsb;
184            *a2 = data0_msb;
185        }
186        TRD104SyscallReturn::SuccessU32U64(data0, data1) => {
187            let (data1_msb, data1_lsb) = u64_to_be_u32s(data1);
188
189            *a0 = TRD104SyscallReturnVariant::SuccessU32U64 as u32;
190            *a1 = data0;
191            *a2 = data1_lsb;
192            *a3 = data1_msb;
193        }
194        TRD104SyscallReturn::AllowReadWriteSuccess(ptr, len) => {
195            *a0 = TRD104SyscallReturnVariant::SuccessU32U32 as u32;
196            *a1 = ptr as u32;
197            *a2 = len as u32;
198        }
199        TRD104SyscallReturn::UserspaceReadableAllowSuccess(ptr, len) => {
200            *a0 = TRD104SyscallReturnVariant::SuccessU32U32 as u32;
201            *a1 = ptr as u32;
202            *a2 = len as u32;
203        }
204        TRD104SyscallReturn::AllowReadWriteFailure(err, ptr, len) => {
205            *a0 = TRD104SyscallReturnVariant::FailureU32U32 as u32;
206            *a1 = usize::from(err) as u32;
207            *a2 = ptr as u32;
208            *a3 = len as u32;
209        }
210        TRD104SyscallReturn::UserspaceReadableAllowFailure(err, ptr, len) => {
211            *a0 = TRD104SyscallReturnVariant::FailureU32U32 as u32;
212            *a1 = usize::from(err) as u32;
213            *a2 = ptr as u32;
214            *a3 = len as u32;
215        }
216        TRD104SyscallReturn::AllowReadOnlySuccess(ptr, len) => {
217            *a0 = TRD104SyscallReturnVariant::SuccessU32U32 as u32;
218            *a1 = ptr as u32;
219            *a2 = len as u32;
220        }
221        TRD104SyscallReturn::AllowReadOnlyFailure(err, ptr, len) => {
222            *a0 = TRD104SyscallReturnVariant::FailureU32U32 as u32;
223            *a1 = usize::from(err) as u32;
224            *a2 = ptr as u32;
225            *a3 = len as u32;
226        }
227        TRD104SyscallReturn::SubscribeSuccess(ptr, data) => {
228            *a0 = TRD104SyscallReturnVariant::SuccessU32U32 as u32;
229            *a1 = ptr as u32;
230            *a2 = data as u32;
231        }
232        TRD104SyscallReturn::SubscribeFailure(err, ptr, data) => {
233            *a0 = TRD104SyscallReturnVariant::FailureU32U32 as u32;
234            *a1 = usize::from(err) as u32;
235            *a2 = ptr as u32;
236            *a3 = data as u32;
237        }
238        TRD104SyscallReturn::YieldWaitFor(data0, data1, data2) => {
239            *a0 = data0 as u32;
240            *a1 = data1 as u32;
241            *a2 = data2 as u32;
242        }
243    }
244}