1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the GNU General Public License v3+, or later.
7 // See license.mkd for licensing and copyright information.
8 // --------------------------------------------------------------------------*/
11 * Virtual memory functions.
18 /** Base of virtual memory. */
19 #define SJME_VIRTUAL_MEM_BASE SJME_JINT_C(1048576)
21 /** Rounding of virtual memory. */
22 #define SJME_VIRTUAL_MEM_MASK SJME_JINT_C(1023)
24 /** Virtual memory information. */
27 /** The number of mappings. */
30 /** The next address for allocations. */
37 /** Creates a new virtual memory manager. */
38 sjme_vmem
* sjme_vmmnew(sjme_error
* error
)
42 /* Try to allocate space. */
43 rv
= sjme_malloc(sizeof(*rv
));
46 sjme_seterror(error
, SJME_ERROR_NOMEMORY
, sizeof(*rv
));
52 rv
->nextaddr
= SJME_VIRTUAL_MEM_BASE
;
57 /** Virtually maps the given region of memory. */
58 sjme_vmemmap
* sjme_vmmmap(sjme_vmem
* vmem
, sjme_jint at
, void* ptr
,
59 sjme_jint size
, sjme_error
* error
)
62 sjme_vmemmap
** newmaps
;
67 /* Invalid argument. */
68 if (vmem
== NULL
|| ptr
== NULL
|| size
<= 0)
70 sjme_seterror(error
, SJME_ERROR_INVALIDARG
, 0);
75 /* Allocate return value. */
76 rv
= sjme_malloc(sizeof(*rv
));
77 newmaps
= sjme_malloc(sizeof(*newmaps
) * (vmem
->count
+ 1));
80 sjme_seterror(error
, SJME_ERROR_NOMEMORY
, sizeof(*rv
));
88 /* Copy and set new mappings. */
89 for (i
= 0; i
< vmem
->count
; i
++)
90 newmaps
[i
] = vmem
->maps
[i
];
91 newmaps
[vmem
->count
] = rv
;
94 rv
->realptr
= (uintptr_t)ptr
;
95 rv
->fakeptr
= vmem
->nextaddr
;
98 /* Store the mappings (remember to free the old ones!). */
99 vmem
->nextaddr
= (vmem
->nextaddr
+ size
+ SJME_VIRTUAL_MEM_MASK
) &
100 (~SJME_VIRTUAL_MEM_MASK
);
101 vmem
->count
= vmem
->count
+ 1;
102 sjme_free(vmem
->maps
);
103 vmem
->maps
= newmaps
;
108 /** Resolves the given true memory address. */
109 void* sjme_vmmresolve(sjme_vmem
* vmem
, sjme_vmemptr ptr
, sjme_jint off
,
112 sjme_jint i
, n
, moff
;
117 /* Invalid argument. */
120 sjme_seterror(error
, SJME_ERROR_INVALIDARG
, 0);
125 /* Get true pointer position. */
128 /* Search for the mapping. */
129 for (i
= 0, n
= vmem
->count
; i
< n
; i
++)
134 /* Calculate the mapping offset. */
135 moff
= optr
- map
->fakeptr
;
138 if (moff
>= 0 && moff
< map
->size
)
140 /* If this mapping is banked, make sure it is mapped. */
141 if (map
->bank
!= NULL
)
143 /* Load the bank into memory. */
144 mp
= map
->bank(&moff
);
146 /* Return from the base mapping using the returned offset. */
147 return (void*)(mp
+ moff
);
150 /* Otherwise, use direct memory access. */
151 return (void*)(map
->realptr
+ moff
);
155 /* Address is not valid. */
156 sjme_seterror(error
, SJME_ERROR_BADADDRESS
, optr
);
160 /** Convert size to Java type. */
161 sjme_jint
sjme_vmmsizetojavatype(sjme_jint size
, sjme_error
* error
)
167 return SJME_VMMTYPE_BYTE
;
170 return SJME_VMMTYPE_JAVASHORT
;
173 return SJME_VMMTYPE_JAVAINTEGER
;
177 sjme_seterror(error
, SJME_ERROR_INVALIDSIZE
, size
);
181 /** Convert size to type. */
182 sjme_jint
sjme_vmmsizetotype(sjme_jint size
, sjme_error
* error
)
188 return SJME_VMMTYPE_BYTE
;
191 return SJME_VMMTYPE_SHORT
;
194 return SJME_VMMTYPE_INTEGER
;
198 sjme_seterror(error
, SJME_ERROR_INVALIDSIZE
, size
);
202 /** Reads from virtual memory. */
203 sjme_jint
sjme_vmmread(sjme_vmem
* vmem
, sjme_jint type
, sjme_vmemptr ptr
,
204 sjme_jint off
, sjme_error
* error
)
209 /* Invalid argument? */
212 sjme_seterror(error
, SJME_ERROR_INVALIDARG
, 0);
220 memset(&xerror
, 0, sizeof(xerror
));
224 /* Resolve address. */
225 realptr
= sjme_vmmresolve(vmem
, ptr
, off
, error
);
228 if (error
->code
== SJME_ERROR_NONE
)
229 sjme_seterror(error
, SJME_ERROR_ADDRRESFAIL
, ptr
+ off
);
234 /* Depends on the type. */
237 case SJME_VMMTYPE_BYTE
:
238 return *((sjme_jbyte
*)realptr
);
240 #if defined(SJME_BIG_ENDIAN)
241 case SJME_VMMTYPE_SHORT
:
242 case SJME_VMMTYPE_JAVASHORT
:
243 return *((sjme_jshort
*)realptr
);
245 case SJME_VMMTYPE_SHORT
:
246 return *((sjme_jshort
*)realptr
);
248 case SJME_VMMTYPE_JAVASHORT
:
249 type
= *((sjme_jshort
*)realptr
);
250 type
= (type
& SJME_JINT_C(0xFFFF0000)) |
251 (((type
<< SJME_JINT_C(8)) & SJME_JINT_C(0xFF00)) |
252 ((type
>> SJME_JINT_C(8)) & SJME_JINT_C(0x00FF)));
256 #if defined(SJME_BIG_ENDIAN)
257 case SJME_VMMTYPE_INTEGER
:
258 case SJME_VMMTYPE_JAVAINTEGER
:
259 return *((sjme_jint
*)realptr
);
261 case SJME_VMMTYPE_INTEGER
:
262 return *((sjme_jint
*)realptr
);
264 case SJME_VMMTYPE_JAVAINTEGER
:
265 type
= *((sjme_jint
*)realptr
);
266 type
= (((type
>> SJME_JINT_C(24)) & SJME_JINT_C(0x000000FF)) |
267 ((type
>> SJME_JINT_C(8)) & SJME_JINT_C(0x0000FF00)) |
268 ((type
<< SJME_JINT_C(8)) & SJME_JINT_C(0x00FF0000)) |
269 ((type
<< SJME_JINT_C(24)) & SJME_JINT_C(0xFF000000)));
274 sjme_seterror(error
, SJME_ERROR_INVALIDMEMTYPE
, type
);
279 /** Reads from virtual memory. */
280 sjme_jint
sjme_vmmreadp(sjme_vmem
* vmem
, sjme_jint type
, sjme_vmemptr
* ptr
,
286 rv
= sjme_vmmread(vmem
, type
, *ptr
, 0, error
);
288 /* Increment pointer. */
291 case SJME_VMMTYPE_BYTE
:
295 case SJME_VMMTYPE_SHORT
:
296 case SJME_VMMTYPE_JAVASHORT
:
300 case SJME_VMMTYPE_INTEGER
:
301 case SJME_VMMTYPE_JAVAINTEGER
:
310 /** Write to virtual memory. */
311 void sjme_vmmwrite(sjme_vmem
* vmem
, sjme_jint type
, sjme_vmemptr ptr
,
312 sjme_jint off
, sjme_jint val
, sjme_error
* error
)
317 /* Invalid argument? */
320 sjme_seterror(error
, SJME_ERROR_INVALIDARG
, 0);
328 memset(&xerror
, 0, sizeof(xerror
));
332 /* Resolve address. */
333 realptr
= sjme_vmmresolve(vmem
, ptr
, off
, error
);
336 if (error
->code
== SJME_ERROR_NONE
)
337 sjme_seterror(error
, SJME_ERROR_ADDRRESFAIL
, ptr
+ off
);
342 /* Depends on the type. */
345 case SJME_VMMTYPE_BYTE
:
346 *((sjme_jbyte
*)realptr
) = (sjme_jbyte
)val
;
349 case SJME_VMMTYPE_JAVASHORT
:
350 #if defined(SJME_LITTLE_ENDIAN)
351 val
= (val
& SJME_JINT_C(0xFFFF0000)) |
352 (((val
<< SJME_JINT_C(8)) & SJME_JINT_C(0xFF00)) |
353 ((val
>> SJME_JINT_C(8)) & SJME_JINT_C(0x00FF)));
355 case SJME_VMMTYPE_SHORT
:
356 *((sjme_jshort
*)realptr
) = (sjme_jshort
)val
;
359 case SJME_VMMTYPE_JAVAINTEGER
:
360 #if defined(SJME_LITTLE_ENDIAN)
361 val
= (((val
>> SJME_JINT_C(24)) & SJME_JINT_C(0x000000FF)) |
362 ((val
>> SJME_JINT_C(8)) & SJME_JINT_C(0x0000FF00)) |
363 ((val
<< SJME_JINT_C(8)) & SJME_JINT_C(0x00FF0000)) |
364 ((val
<< SJME_JINT_C(24)) & SJME_JINT_C(0xFF000000)));
366 case SJME_VMMTYPE_INTEGER
:
367 *((sjme_jint
*)realptr
) = (sjme_jint
)val
;
371 sjme_seterror(error
, SJME_ERROR_INVALIDMEMTYPE
, type
);
376 /** Write to virtual memory. */
377 void sjme_vmmwritep(sjme_vmem
* vmem
, sjme_jint type
, sjme_vmemptr
* ptr
,
378 sjme_jint val
, sjme_error
* error
)
383 sjme_vmmwrite(vmem
, type
, *ptr
, 0, val
, error
);
385 /* Increment pointer. */
388 case SJME_VMMTYPE_BYTE
:
392 case SJME_VMMTYPE_SHORT
:
393 case SJME_VMMTYPE_JAVASHORT
:
397 case SJME_VMMTYPE_INTEGER
:
398 case SJME_VMMTYPE_JAVAINTEGER
:
404 /** Atomically reads, checks, and then sets the value. */
405 sjme_jint
sjme_vmmatomicintcheckgetandset(sjme_vmem
* vmem
, sjme_jint check
,
406 sjme_jint set
, sjme_vmemptr ptr
, sjme_jint off
, sjme_error
* error
)
410 /* Invalid argument? */
413 sjme_seterror(error
, SJME_ERROR_INVALIDARG
, 0);
418 /* Read current value. */
419 rv
= sjme_vmmread(vmem
, SJME_VMMTYPE_INTEGER
, ptr
, off
, error
);
421 /* If value is the same, set it. */
423 sjme_vmmwrite(vmem
, SJME_VMMTYPE_INTEGER
, ptr
, off
, set
, error
);
425 /* Return the value. */
429 /** Atomically increments and integer and then gets its value. */
430 sjme_jint
sjme_vmmatomicintaddandget(sjme_vmem
* vmem
,
431 sjme_vmemptr ptr
, sjme_jint off
, sjme_jint add
, sjme_error
* error
)
435 /* Invalid argument? */
438 sjme_seterror(error
, SJME_ERROR_INVALIDARG
, 0);
443 /* Read current value. */
444 rv
= sjme_vmmread(vmem
, SJME_VMMTYPE_INTEGER
, ptr
, off
, error
);
449 /* Store new value. */
450 sjme_vmmwrite(vmem
, SJME_VMMTYPE_INTEGER
, ptr
, off
, rv
, error
);
452 /* Return new value. */