@@ -68,6 +68,7 @@ function Chunk:checkRange(addr)
68
68
if addr < self .address or addr >= max then
69
69
error (fmt (" Address 0x%08X out of bounds %08X-%08X" , addr , self .address , max ), 2 )
70
70
end
71
+ return addr - self .address
71
72
end
72
73
73
74
local function word (self , idx )
236
237
function Chunk :alloc (len )
237
238
-- printf("alloc(%d) ", len)
238
239
-- printf("freeCellList before: %s ", self:freeCellListStr())
240
+ -- printf("\n")
239
241
240
242
len = (len + 3 ) & ~3
241
243
local freeCellPtrIdx = 0
@@ -305,7 +307,7 @@ function Chunk:freeCellListStr()
305
307
local list = self :freeCellList ()
306
308
local parts = {}
307
309
for i , idx in ipairs (self :freeCellList ()) do
308
- parts [i ] = string.format (" %d +%d" , idx * 4 , self :getCellLen (idx ))
310
+ parts [i ] = string.format (" %X +%d" , idx * 4 , self :getCellLen (idx ))
309
311
end
310
312
return table.concat (parts , " ," )
311
313
end
@@ -344,7 +346,7 @@ function Chunk:declareFreeCell(cellIdx, cellLen)
344
346
end
345
347
346
348
local nextCell = self [prev + 1 ]
347
- -- printf("free (%X): prev=%X next=%X\n", cellIdx << strideshift, prev << strideshift, nextCell << strideshift)
349
+ -- printf("declareFreeCell (%X): prev=%X next=%X\n", cellIdx << strideshift, prev << strideshift, nextCell << strideshift)
348
350
self [prev + 1 ] = cellIdx -- prev->next = cellIdx
349
351
self [cellIdx + 1 ] = nextCell -- cell->next = nextCell
350
352
@@ -365,6 +367,7 @@ function Chunk:declareFreeCell(cellIdx, cellLen)
365
367
end
366
368
367
369
function Chunk :realloc (offset , sz )
370
+ -- printf("realloc(0x%X, %d) freeCellList before: %s \n", offset, sz, self:freeCellListStr())
368
371
if sz == 0 then
369
372
self :free (offset )
370
373
return nil
@@ -384,17 +387,37 @@ function Chunk:realloc(offset, sz)
384
387
return offset
385
388
else
386
389
local newOffset = self :alloc (sz )
387
- local oldIdx = offset >> strideshift
388
- local newIdx = newOffset >> strideshift
389
- -- This is a little more optimised than doing a read() followed by a write()
390
- for i = 0 , (allocLen >> strideshift ) - 1 do
391
- self [newIdx + i ] = self [oldIdx + i ]
392
- end
390
+ self :aligned_memcpy (newOffset , offset , allocLen )
393
391
self :free (offset )
394
392
return newOffset
395
393
end
396
394
end
397
395
396
+ local function inrange (min , val , rangeLen )
397
+ return val >= min and val < min + rangeLen
398
+ end
399
+
400
+ -- must be non-overlapping, src, dest and len must all be a multiple of chunkstride
401
+ function Chunk :aligned_memcpy (dest , src , len )
402
+ local srcIdx = src >> strideshift
403
+ local destIdx = dest >> strideshift
404
+ for i = 0 , (len >> strideshift ) - 1 do
405
+ self [destIdx + i ] = self [srcIdx + i ]
406
+ end
407
+ end
408
+
409
+ function Chunk :memmove (dest , src , len )
410
+ if inrange (src , dest , src + len ) or inrange (src , dest + len , src + len ) then
411
+ -- overlapping just do it the dumb way
412
+ self :write (dest , self :read (src , len ))
413
+ elseif dest % chunkstride ~= 0 or src % chunkstride ~= 0 or len % chunkstride ~= 0 then
414
+ -- unaligned, ditto
415
+ self :write (dest , self :read (src , len ))
416
+ else
417
+ self :aligned_memcpy (dest , src , len )
418
+ end
419
+ end
420
+
398
421
Variable = class {
399
422
_type = nil ,
400
423
_chunk = nil ,
0 commit comments