Skip to content

Commit 9db9657

Browse files
committed
1st stage
1 parent f975b48 commit 9db9657

4 files changed

Lines changed: 395 additions & 0 deletions

File tree

src/ria/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ target_sources(${RIA_TARGET} PRIVATE
6262
api/atr.c
6363
api/clk.c
6464
api/dir.c
65+
api/mth.c
6566
api/oem.c
6667
api/pro.c
6768
api/std.c

src/ria/api/mth.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
* Copyright (c) 2025 Rumbledethumps
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include "api/api.h"
8+
#include "api/mth.h"
9+
#include <math.h>
10+
#include <string.h>
11+
12+
/* Type-punning helpers — safe via memcpy (no UB) */
13+
14+
static inline float bits_to_f32(uint32_t b)
15+
{
16+
float f;
17+
memcpy(&f, &b, 4);
18+
return f;
19+
}
20+
21+
static inline uint32_t f32_to_bits(float f)
22+
{
23+
uint32_t b;
24+
memcpy(&b, &f, 4);
25+
return b;
26+
}
27+
28+
static inline bool mth_pop_double(double *d)
29+
{
30+
return api_pop_n(d, sizeof(double));
31+
}
32+
33+
/* Pop exactly 8 bytes — fails if stack does not have exactly 8 bytes left.
34+
* Used for the last (first-pushed) double argument.
35+
*/
36+
static bool mth_pop_double_end(double *d)
37+
{
38+
if (xstack_ptr != XSTACK_SIZE - sizeof(double))
39+
return false;
40+
memcpy(d, &xstack[xstack_ptr], sizeof(double));
41+
xstack_ptr = XSTACK_SIZE;
42+
return true;
43+
}
44+
45+
static inline bool mth_push_double(double d)
46+
{
47+
return api_push_n(&d, sizeof(double));
48+
}
49+
50+
/**********************/
51+
/* Integer operations */
52+
/**********************/
53+
54+
/* $30: u8 * u8 -> u16
55+
* API_A = b (fastcall), xstack = a
56+
*/
57+
bool mth_api_mul8(void)
58+
{
59+
uint8_t b = API_A;
60+
uint8_t a;
61+
if (!api_pop_uint8_end(&a))
62+
return api_return_errno(API_EINVAL);
63+
return api_return_ax((uint16_t)a * b);
64+
}
65+
66+
/* $31: u16 * u16 -> u32
67+
* API_AX = b (fastcall), xstack = a
68+
*/
69+
bool mth_api_mul16(void)
70+
{
71+
uint16_t b = API_AX;
72+
uint16_t a;
73+
if (!api_pop_uint16_end(&a))
74+
return api_return_errno(API_EINVAL);
75+
return api_return_axsreg((uint32_t)a * b);
76+
}
77+
78+
/* $32: s16 * s16 -> s32
79+
* API_AX = b (fastcall), xstack = a
80+
*/
81+
bool mth_api_muls16(void)
82+
{
83+
int16_t b = (int16_t)API_AX;
84+
int16_t a;
85+
if (!api_pop_int16_end(&a))
86+
return api_return_errno(API_EINVAL);
87+
return api_return_axsreg((uint32_t)((int32_t)a * b));
88+
}
89+
90+
/* $33: u32 / u16 -> quot(u16) | rem(u16)<<16
91+
* API_AX = divisor (fastcall), xstack = dividend (u32)
92+
*/
93+
bool mth_api_div16(void)
94+
{
95+
uint16_t divisor = API_AX;
96+
if (divisor == 0)
97+
return api_return_errno(API_EDOM);
98+
uint32_t dividend;
99+
if (!api_pop_uint32_end(&dividend))
100+
return api_return_errno(API_EINVAL);
101+
uint16_t quotient = (uint16_t)(dividend / divisor);
102+
uint16_t remainder = (uint16_t)(dividend % divisor);
103+
return api_return_axsreg((uint32_t)quotient | ((uint32_t)remainder << 16));
104+
}
105+
106+
/* $34: sqrt(u32) -> u16
107+
* API_AXSREG = n (fastcall)
108+
*/
109+
bool mth_api_sqrt32(void)
110+
{
111+
return api_return_ax((uint16_t)sqrtf((float)API_AXSREG));
112+
}
113+
114+
/***********************/
115+
/* Float32 operations */
116+
/***********************/
117+
118+
/* $38: f32 + f32 -> f32
119+
* API_AXSREG = b bits (fastcall), xstack = a bits
120+
*/
121+
bool mth_api_fadd(void)
122+
{
123+
float b = bits_to_f32(API_AXSREG);
124+
uint32_t a_bits;
125+
if (!api_pop_uint32_end(&a_bits))
126+
return api_return_errno(API_EINVAL);
127+
return api_return_axsreg(f32_to_bits(bits_to_f32(a_bits) + b));
128+
}
129+
130+
/* $39: f32 - f32 -> f32
131+
* API_AXSREG = b bits (fastcall), xstack = a bits
132+
*/
133+
bool mth_api_fsub(void)
134+
{
135+
float b = bits_to_f32(API_AXSREG);
136+
uint32_t a_bits;
137+
if (!api_pop_uint32_end(&a_bits))
138+
return api_return_errno(API_EINVAL);
139+
return api_return_axsreg(f32_to_bits(bits_to_f32(a_bits) - b));
140+
}
141+
142+
/* $3A: f32 * f32 -> f32
143+
* API_AXSREG = b bits (fastcall), xstack = a bits
144+
*/
145+
bool mth_api_fmul(void)
146+
{
147+
float b = bits_to_f32(API_AXSREG);
148+
uint32_t a_bits;
149+
if (!api_pop_uint32_end(&a_bits))
150+
return api_return_errno(API_EINVAL);
151+
return api_return_axsreg(f32_to_bits(bits_to_f32(a_bits) * b));
152+
}
153+
154+
/* $3B: f32 / f32 -> f32
155+
* API_AXSREG = b bits (fastcall), xstack = a bits
156+
*/
157+
bool mth_api_fdiv(void)
158+
{
159+
float b = bits_to_f32(API_AXSREG);
160+
uint32_t a_bits;
161+
if (!api_pop_uint32_end(&a_bits))
162+
return api_return_errno(API_EINVAL);
163+
return api_return_axsreg(f32_to_bits(bits_to_f32(a_bits) / b));
164+
}
165+
166+
/* $3C: sqrt(f32) -> f32
167+
* API_AXSREG = a bits (fastcall)
168+
*/
169+
bool mth_api_fsqrt(void)
170+
{
171+
return api_return_axsreg(f32_to_bits(sqrtf(bits_to_f32(API_AXSREG))));
172+
}
173+
174+
/* $3D: sin(f32) -> f32
175+
* API_AXSREG = a bits (fastcall)
176+
*/
177+
bool mth_api_fsin(void)
178+
{
179+
return api_return_axsreg(f32_to_bits(sinf(bits_to_f32(API_AXSREG))));
180+
}
181+
182+
/* $3E: cos(f32) -> f32
183+
* API_AXSREG = a bits (fastcall)
184+
*/
185+
bool mth_api_fcos(void)
186+
{
187+
return api_return_axsreg(f32_to_bits(cosf(bits_to_f32(API_AXSREG))));
188+
}
189+
190+
/* $3F: atan2(a, b) -> f32
191+
* API_AXSREG = b bits (fastcall), xstack = a bits
192+
*/
193+
bool mth_api_fatan2(void)
194+
{
195+
float b = bits_to_f32(API_AXSREG);
196+
uint32_t a_bits;
197+
if (!api_pop_uint32_end(&a_bits))
198+
return api_return_errno(API_EINVAL);
199+
return api_return_axsreg(f32_to_bits(atan2f(bits_to_f32(a_bits), b)));
200+
}
201+
202+
/* $40: pow(a, b) -> f32
203+
* API_AXSREG = b bits (fastcall), xstack = a bits
204+
*/
205+
bool mth_api_fpow(void)
206+
{
207+
float b = bits_to_f32(API_AXSREG);
208+
uint32_t a_bits;
209+
if (!api_pop_uint32_end(&a_bits))
210+
return api_return_errno(API_EINVAL);
211+
return api_return_axsreg(f32_to_bits(powf(bits_to_f32(a_bits), b)));
212+
}
213+
214+
/* $41: log(f32) -> f32 (natural logarithm)
215+
* API_AXSREG = a bits (fastcall)
216+
*/
217+
bool mth_api_flog(void)
218+
{
219+
return api_return_axsreg(f32_to_bits(logf(bits_to_f32(API_AXSREG))));
220+
}
221+
222+
/* $42: exp(f32) -> f32
223+
* API_AXSREG = a bits (fastcall)
224+
*/
225+
bool mth_api_fexp(void)
226+
{
227+
return api_return_axsreg(f32_to_bits(expf(bits_to_f32(API_AXSREG))));
228+
}
229+
230+
/* $43: (s32)f32 — truncate float to signed integer
231+
* API_AXSREG = a bits (fastcall)
232+
*/
233+
bool mth_api_ftoi(void)
234+
{
235+
return api_return_axsreg((uint32_t)(int32_t)bits_to_f32(API_AXSREG));
236+
}
237+
238+
/* $44: (f32)s32 — convert signed integer to float
239+
* API_AXSREG = a (s32, fastcall)
240+
*/
241+
bool mth_api_itof(void)
242+
{
243+
return api_return_axsreg(f32_to_bits((float)(int32_t)API_AXSREG));
244+
}
245+
246+
/***********************/
247+
/* Double64 operations */
248+
/***********************/
249+
250+
/* $48: f64 + f64 -> f64
251+
* xstack (top): b (8 bytes), below: a (8 bytes)
252+
* Result pushed to xstack; api_return_ax(0) signals success.
253+
*/
254+
bool mth_api_dadd(void)
255+
{
256+
double b, a;
257+
if (!mth_pop_double(&b))
258+
return api_return_errno(API_EINVAL);
259+
if (!mth_pop_double_end(&a))
260+
return api_return_errno(API_EINVAL);
261+
if (!mth_push_double(a + b))
262+
return api_return_errno(API_ENOMEM);
263+
return api_return_ax(0);
264+
}
265+
266+
/* $49: f64 * f64 -> f64
267+
* xstack (top): b (8 bytes), below: a (8 bytes)
268+
* Result pushed to xstack; api_return_ax(0) signals success.
269+
*/
270+
bool mth_api_dmul(void)
271+
{
272+
double b, a;
273+
if (!mth_pop_double(&b))
274+
return api_return_errno(API_EINVAL);
275+
if (!mth_pop_double_end(&a))
276+
return api_return_errno(API_EINVAL);
277+
if (!mth_push_double(a * b))
278+
return api_return_errno(API_ENOMEM);
279+
return api_return_ax(0);
280+
}
281+
282+
/* $4A: f64 / f64 -> f64
283+
* xstack (top): b (8 bytes), below: a (8 bytes)
284+
* Result pushed to xstack; api_return_ax(0) signals success.
285+
*/
286+
bool mth_api_ddiv(void)
287+
{
288+
double b, a;
289+
if (!mth_pop_double(&b))
290+
return api_return_errno(API_EINVAL);
291+
if (!mth_pop_double_end(&a))
292+
return api_return_errno(API_EINVAL);
293+
if (!mth_push_double(a / b))
294+
return api_return_errno(API_ENOMEM);
295+
return api_return_ax(0);
296+
}

src/ria/api/mth.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2025 Rumbledethumps
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#ifndef _RIA_API_MTH_H_
8+
#define _RIA_API_MTH_H_
9+
10+
/* Math coprocessor — exposes RP2350 Cortex-M33 FPU to the 6502.
11+
*
12+
* Opcodes $30-$34: Integer arithmetic
13+
* Opcodes $38-$44: Float32 (IEEE 754 single precision)
14+
* Opcodes $48-$4A: Double64 (IEEE 754 double precision)
15+
*
16+
* Calling convention follows the RIA API standard:
17+
* - Last argument is fastcall (API_A / API_AX / API_AXSREG)
18+
* - Earlier arguments are on xstack (pushed in order, popped in reverse)
19+
* - 32-bit results returned via api_return_axsreg()
20+
* - Double results pushed to xstack, api_return_ax(0) signals success
21+
*/
22+
23+
#include <stdbool.h>
24+
25+
/* Integer operations */
26+
27+
bool mth_api_mul8(void); /* $30: u8 * u8 -> u16 */
28+
bool mth_api_mul16(void); /* $31: u16 * u16 -> u32 */
29+
bool mth_api_muls16(void); /* $32: s16 * s16 -> s32 */
30+
bool mth_api_div16(void); /* $33: u32 / u16 -> quot(u16) | rem(u16)<<16 */
31+
bool mth_api_sqrt32(void); /* $34: sqrt(u32) -> u16 */
32+
33+
/* Float32 operations */
34+
35+
bool mth_api_fadd(void); /* $38: f32 + f32 -> f32 */
36+
bool mth_api_fsub(void); /* $39: f32 - f32 -> f32 */
37+
bool mth_api_fmul(void); /* $3A: f32 * f32 -> f32 */
38+
bool mth_api_fdiv(void); /* $3B: f32 / f32 -> f32 */
39+
bool mth_api_fsqrt(void); /* $3C: sqrt(f32) -> f32 */
40+
bool mth_api_fsin(void); /* $3D: sin(f32) -> f32 */
41+
bool mth_api_fcos(void); /* $3E: cos(f32) -> f32 */
42+
bool mth_api_fatan2(void); /* $3F: atan2(f32,f32) -> f32 */
43+
bool mth_api_fpow(void); /* $40: pow(f32,f32) -> f32 */
44+
bool mth_api_flog(void); /* $41: log(f32) -> f32 */
45+
bool mth_api_fexp(void); /* $42: exp(f32) -> f32 */
46+
bool mth_api_ftoi(void); /* $43: (s32)f32 */
47+
bool mth_api_itof(void); /* $44: (f32)s32 */
48+
49+
/* Double64 operations */
50+
51+
bool mth_api_dadd(void); /* $48: f64 + f64 -> f64 (via xstack) */
52+
bool mth_api_dmul(void); /* $49: f64 * f64 -> f64 (via xstack) */
53+
bool mth_api_ddiv(void); /* $4A: f64 / f64 -> f64 (via xstack) */
54+
55+
#endif /* _RIA_API_MTH_H_ */

0 commit comments

Comments
 (0)