about summary refs log tree commit diff stats
path: root/subx/apps/dquotes
Commit message (Expand)AuthorAgeFilesLines
* another phase that supports the new segment syntaxKartik Agaram2019-05-171-0/+0
* 5181Kartik Agaram2019-05-171-0/+0
* 5180Kartik Agaram2019-05-161-0/+0
* complete the skeleton of dquotes.subxKartik Agaram2019-05-151-0/+0
* .Kartik Agaram2019-05-141-0/+0
* fix a stale register value in dquotes.subxKartik Agaram2019-05-141-0/+0
* Merge branch 'dquotes' into dquotes-1Kartik Agaram2019-05-131-0/+0
|\
| * Merge branch 'master' into dquotesKartik Agaram2019-05-101-0/+0
| |\
| | * 5151 - use mmap everywhere we need a heapKartik Agaram2019-05-101-0/+0
* | | dquotes - emit data segment - no escapesKartik Agaram2019-05-031-0/+0
* | | standardize function namesKartik Agaram2019-05-021-0/+0
|/ /
* / new failing test in dquotes phaseKartik Agaram2019-04-281-0/+0
|/
* 5118 - convert int to stringKartik Agaram2019-04-231-0/+0
* 5112Kartik Agaram2019-04-191-0/+0
* 5108Kartik Agaram2019-04-181-0/+0
* 5107Kartik Agaram2019-04-181-0/+0
* 5106Kartik Agaram2019-04-171-0/+0
* 5105Kartik Agaram2019-04-161-0/+0
* 5104Kartik Agaram2019-04-161-0/+0
* 5103Kartik Agaram2019-04-161-0/+0
* 5102 - tokenize string literalsKartik Agaram2019-04-161-0/+0
8 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
# Some unsafe methods not intended to be used directly in SubX, only through
# Mu after proper type-checking.

== code

stream-empty?:  # s: (addr stream _) -> result/eax: boolean
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    56/push-esi
    # result = false
    b8/copy-to-eax 0/imm32/false
    # esi = s
    8b/-> *(ebp+8) 6/r32/esi
    # return s->read >= s->write
    8b/-> *esi 1/r32/ecx
    39/compare-with *(esi+4) 1/r32/ecx
    0f 9d/set-if->= %al
$stream-empty?:end:
    # . restore registers
    5e/pop-to-esi
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

stream-full?:  # s: (addr stream _) -> result/eax: boolean
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    56/push-esi
    # result = false
    b8/copy-to-eax 0/imm32/false
    # esi = s
    8b/-> *(ebp+8) 6/r32/esi
    # return s->write >= s->size
    8b/-> *(esi+8) 1/r32/ecx
    39/compare-with *esi 1/r32/ecx
    0f 9d/set-if->= %al
$stream-full?:end:
    # . restore registers
    5e/pop-to-esi
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

write-to-stream:  # s: (addr stream _), in: (addr byte), n: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    50/push-eax
    51/push-ecx
    52/push-edx
    53/push-ebx
    57/push-edi
    # edi = s
    8b/-> *(ebp+8) 7/r32/edi
    # var swrite/edx: int = s->write
    8b/-> *edi 2/r32/edx
    # if (swrite + n > s->size) abort
    8b/-> *(ebp+0x10) 1/r32/ecx
    01/add-to %ecx 2/r32/edx
    3b/compare 1/r32/ecx *(edi+8)
    0f 8f/jump-if-> $write-to-stream:abort/disp32
    # var out/edx: (addr byte) = s->data + s->write
    8d/copy-address *(edi+edx+0xc) 2/r32/edx
    # var outend/ebx: (addr byte) = out + n
    8b/-> *(ebp+0x10) 3/r32/ebx
    8d/copy-address *(edx+ebx) 3/r32/ebx
    # eax = in
    8b/-> *(ebp+0xc) 0/r32/eax
    # var inend/ecx: (addr byte) = in + n
    8b/-> *(ebp+0x10) 1/r32/ecx
    8d/copy-address *(eax+ecx) 1/r32/ecx
    #
    (_append-4  %edx %ebx  %eax %ecx)  # => eax
    # s->write += n
    8b/-> *(ebp+0x10) 1/r32/ecx
    01/add-to *edi 1/r32/ecx
$write-to-stream:end:
    # . restore registers
    5f/pop-to-edi
    5b/pop-to-ebx
    5a/pop-to-edx
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

$write-to-stream:abort:
    (abort "write-to-stream: stream full")
    # never gets here

read-from-stream:  # s: (addr stream _), out: (addr byte), n: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    50/push-eax
    51/push-ecx
    52/push-edx
    53/push-ebx
    56/push-esi
    # esi = s
    8b/-> *(ebp+8) 6/r32/esi
    # var sread/edx: int = s->read
    8b/-> *(esi+4) 2/r32/edx
    # if (sread + n > s->write) abort
    8b/-> *(ebp+0x10) 1/r32/ecx
    01/add-to %ecx 2/r32/edx
    3b/compare 1/r32/ecx *esi
    0f 8f/jump-if-> $read-from-stream:abort/disp32
    # var in/edx: (addr byte) = s->data + s->read
    8d/copy-address *(esi+edx+0xc) 2/r32/edx
    # var inend/ebx: (addr byte) = in + n
    8b/-> *(ebp+0x10) 3/r32/ebx
    8d/copy-address *(edx+ebx) 3/r32/ebx
    # eax = out
    8b/-> *(ebp+0xc) 0/r32/eax
    # var outend/ecx: (addr byte) = out + n
    8b/-> *(ebp+0x10) 1/r32/ecx
    8d/copy-address *(eax+ecx) 1/r32/ecx
    #
    (_append-4  %eax %ecx  %edx %ebx)  # => eax
    # s->read += n
    8b/-> *(ebp+0x10) 1/r32/ecx
    01/add-to *(esi+4) 1/r32/ecx
$read-from-stream:end:
    # . restore registers
    5e/pop-to-esi
    5b/pop-to-ebx
    5a/pop-to-edx
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

$read-from-stream:abort:
    (abort "read-from-stream: stream empty")
    # never gets here

stream-first:  # s: (addr stream byte) -> result/eax: byte
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    56/push-esi
    # result = false
    b8/copy-to-eax 0/imm32
    # esi = s
    8b/-> *(ebp+8) 6/r32/esi
    # var idx/ecx: int = s->read
    8b/-> *(esi+4) 1/r32/ecx
    # if idx >= s->write return 0
    3b/compare-with 1/r32/ecx *esi
    7d/jump-if->= $stream-first:end/disp8
    # result = s->data[idx]
    8a/byte-> *(esi+ecx+0xc) 0/r32/AL
$stream-first:end:
    # . restore registers
    5e/pop-to-esi
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

stream-final:  # s: (addr stream byte) -> result/eax: byte
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    56/push-esi
    # result = false
    b8/copy-to-eax 0/imm32
    # esi = s
    8b/-> *(ebp+8) 6/r32/esi
    # var max/ecx: int = s->write
    8b/-> *esi 1/r32/ecx
    # if s->read >= max return 0
    39/compare-with *(esi+4) 1/r32/ecx
    7d/jump-if->= $stream-final:end/disp8
    # var idx/ecx: int = max - 1
    49/decrement-ecx
    # result = s->data[idx]
    8a/byte-> *(esi+ecx+0xc) 0/r32/AL
$stream-final:end:
    # . restore registers
    5e/pop-to-esi
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

# compare all the data in two streams (ignoring the read pointer)
streams-data-equal?:  # a: (addr stream byte), b: (addr array byte) -> result/eax: boolean
    # pseudocode:
    #   awrite = a->write
    #   if (awrite != b->write) return false
    #   i = 0
    #   curra = a->data
    #   currb = b->data
    #   while i < awrite
    #     i1 = *curra
    #     i2 = *currb
    #     if (c1 != c2) return false
    #     i+=4, curra+=4, currb+=4
    #   return true
    #
    # registers:
    #   i: ecx
    #   awrite: edx
    #   curra: esi
    #   currb: edi
    #   i1: eax
    #   i2: ebx
    #
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    52/push-edx
    53/push-ebx
    56/push-esi
    57/push-edi
    # esi = a
    8b/-> *(ebp+8) 6/r32/esi
    # edi = b
    8b/-> *(ebp+0xc) 7/r32/edi
    # var awrite/edx: int = a->write
    8b/-> *esi 2/r32/edx
$streams-data-equal?:sizes:
    # if (awrite != b->write) return false
    39/compare *edi 2/r32/edx
    75/jump-if-!= $streams-data-equal?:false/disp8
    # var curra/esi: (addr byte) = a->data
    81 0/subop/add %esi 0xc/imm32
    # var currb/edi: (addr byte) = b->data
    81 0/subop/add %edi 0xc/imm32
    # var i/ecx: int = 0
    31/xor-with %ecx 1/r32/ecx
    # var vala/eax: int
    31/xor-with %eax 0/r32/eax
    # var valb/ebx: int
    31/xor-with %ebx 3/r32/ebx
$streams-data-equal?:loop:
    {
      # if (i >= awrite) return true
      39/compare %ecx 2/r32/edx
      7d/jump-if->= $streams-data-equal?:true/disp8
      # var vala/eax: int = *curra
      8a/byte-> *esi 0/r32/eax
      # var valb/ebx: int = *currb
      8a/byte-> *edi 3/r32/ebx
      # if (vala != valb) return false
      39/compare %eax 3/r32/ebx
      75/jump-if-!= $streams-data-equal?:false/disp8
      # i++
      41/increment-ecx
      # curra++
      46/increment-esi
      # currb++
      47/increment-edi
      eb/jump loop/disp8
    }
$streams-data-equal?:true:
    b8/copy-to-eax 1/imm32
    eb/jump $streams-data-equal?:end/disp8
$streams-data-equal?:false:
    b8/copy-to-eax 0/imm32
$streams-data-equal?:end:
    # . restore registers
    5f/pop-to-edi
    5e/pop-to-esi
    5b/pop-to-ebx
    5a/pop-to-edx
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

# helper for tests
check-streams-data-equal:  # s: (addr stream _), expected: (addr array _), msg: (addr array byte)
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    50/push-eax
    #
    (streams-data-equal? *(ebp+8) *(ebp+0xc))  # => eax
    (check-ints-equal %eax 1 *(ebp+0x10))
$check-streams-data-equal:end:
    # . restore registers
    58/pop-to-eax
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return