6742 - support for formatting in fake screens

We still need a few primitives, but we can implement these as needed. I'm
ready to call the fake screen done.
This commit is contained in:
Kartik Agaram 2020-09-07 13:51:54 -07:00
parent 9f293fef05
commit 5462619d96
8 changed files with 240 additions and 10 deletions

View File

@ -879,7 +879,7 @@ zero-out: # start: (addr byte), size: int
# curr/esi = start
# i/ecx = 0
# while true
# if (i >= len) break
# if (i >= size) break
# *curr = 0
# ++curr
# ++i
@ -896,10 +896,10 @@ zero-out: # start: (addr byte), size: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# var i/ecx: int = 0
31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx
# edx = len
# edx = size
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
$zero-out:loop:
# if (i >= len) break
# if (i >= size) break
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
7d/jump-if->= $zero-out:end/disp8
# *curr = 0
@ -929,7 +929,7 @@ test-zero-out:
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# zero-out(ecx, 3)
# . . push args
68/push 3/imm32/len
68/push 3/imm32/size
51/push-ecx
# . . call
e8/call zero-out/disp32

View File

@ -1,5 +1,7 @@
# 2-arg version of allocate-array.
== code
allocate-array2: # ad: (addr allocation-descriptor), array-len: int, elem-size: int, out: (addr handle array _)
# . prologue
55/push-ebp

View File

@ -1,6 +1,8 @@
# 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

57
310copy-bytes.subx Normal file
View File

@ -0,0 +1,57 @@
# Fill a region of memory with zeroes.
== code
copy-bytes: # src: (addr byte), dest: (addr byte), size: int
# pseudocode:
# curr-src/esi = src
# curr-dest/edi = dest
# i/ecx = 0
# while true
# if (i >= size) break
# *curr-dest = *curr-src
# ++curr-src
# ++curr-dest
# ++i
#
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
52/push-edx
56/push-esi
57/push-edi
# curr-src/esi = src
8b/-> *(ebp+8) 6/r32/esi
# curr-dest/edi = dest
8b/-> *(ebp+0xc) 7/r32/edi
# var i/ecx: int = 0
b9/copy-to-ecx 0/imm32
# edx = size
8b/-> *(ebp+0x10) 2/r32/edx
{
# if (i >= size) break
39/compare %ecx 2/r32/edx
7d/jump-if->= break/disp8
# *curr-dest = *curr-src
8a/byte-> *esi 0/r32/AL
88/byte<- *edi 0/r32/AL
# update
46/increment-esi
47/increment-edi
41/increment-ecx
eb/jump loop/disp8
}
$copy-bytes:end:
# . restore registers
5f/pop-to-edi
5e/pop-to-esi
5a/pop-to-edx
59/pop-to-ecx
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return

2
400.mu
View File

@ -162,3 +162,5 @@ sig open filename: (addr array byte), write?: boolean, out: (addr handle buffere
sig stream-empty? s: (addr stream _) -> result/eax: boolean
sig stream-full? s: (addr stream _) -> result/eax: boolean
sig copy-bytes src: (addr byte), dest: (addr byte), n: int

View File

@ -258,8 +258,10 @@ $print-grapheme:body: {
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
var data/eax: (addr array screen-cell) <- lookup *data-ah
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
var cell/eax: (addr screen-cell) <- index data, offset
var dest/eax: (addr grapheme) <- get cell, data
var dest-cell/ecx: (addr screen-cell) <- index data, offset
var src-cell/eax: (addr screen-cell) <- get screen-addr, curr-attributes
copy-object src-cell, dest-cell
var dest/eax: (addr grapheme) <- get dest-cell, data
var c2/ecx: grapheme <- copy c
#? print-grapheme-to-real-screen c2
#? print-string-to-real-screen "\n"
@ -315,6 +317,23 @@ fn screen-grapheme-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> r
result <- copy *src
}
fn screen-color-at screen-on-stack: (addr screen), row: int, col: int -> result/eax: int {
var screen-addr/esi: (addr screen) <- copy screen-on-stack
var idx/ecx: int <- screen-cell-index screen-addr, row, col
result <- screen-color-at-idx screen-addr, idx
}
fn screen-color-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> result/eax: int {
var screen-addr/esi: (addr screen) <- copy screen-on-stack
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
var data/eax: (addr array screen-cell) <- lookup *data-ah
var idx/ecx: int <- copy idx-on-stack
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
var cell/eax: (addr screen-cell) <- index data, offset
var src/eax: (addr int) <- get cell, color
result <- copy *src
}
fn print-code-point screen: (addr screen), c: code-point {
var g/eax: grapheme <- to-grapheme c
print-grapheme screen, g
@ -346,6 +365,11 @@ $reset-formatting:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var dest/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
var empty-cell: screen-cell
var empty-cell-addr/eax: (addr screen-cell) <- address empty-cell
copy-object empty-cell-addr, dest
}
}
}
@ -361,6 +385,14 @@ $start-color:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
var dest/edx: (addr int) <- get attr, color
var src/eax: int <- copy fg
copy-to *dest, src
var dest/edx: (addr int) <- get attr, background-color
var src/eax: int <- copy bg
copy-to *dest, src
}
}
}
@ -376,6 +408,10 @@ $start-bold:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
var dest/edx: (addr boolean) <- get attr, bold?
copy-to *dest, 1
}
}
}
@ -391,6 +427,10 @@ $start-underline:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
var dest/edx: (addr boolean) <- get attr, underline?
copy-to *dest, 1
}
}
}
@ -406,6 +446,10 @@ $start-reverse-video:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
var dest/edx: (addr boolean) <- get attr, reverse?
copy-to *dest, 1
}
}
}
@ -421,6 +465,10 @@ $start-blinking:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
var dest/edx: (addr boolean) <- get attr, blink?
copy-to *dest, 1
}
}
}
@ -436,6 +484,9 @@ $hide-cursor:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var hide?/ecx: (addr boolean) <- get screen-addr, cursor-hide?
copy-to *hide?, 1
}
}
}
@ -451,6 +502,9 @@ $show-cursor:body: {
{
break-if-=
# fake screen
var screen-addr/esi: (addr screen) <- copy screen
var hide?/ecx: (addr boolean) <- get screen-addr, cursor-hide?
copy-to *hide?, 0
}
}
}
@ -479,14 +533,13 @@ fn check-screen-row-from screen-on-stack: (addr screen), row-idx: int, col-idx:
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
var expected-grapheme2/eax: int <- copy expected-grapheme
# compare graphemes
$check-screen-row:compare-graphemes: {
$check-screen-row-from:compare-graphemes: {
# if expected-grapheme is space, null grapheme is also ok
{
compare expected-grapheme2, 0x20
break-if-!=
compare g2, 0
break-if-!=
break $check-screen-row:compare-graphemes
break-if-= $check-screen-row-from:compare-graphemes
}
check-ints-equal g2, expected-grapheme2, msg
}
@ -497,10 +550,47 @@ fn check-screen-row-from screen-on-stack: (addr screen), row-idx: int, col-idx:
# various variants by screen-cell attribute; spaces in the 'expected' data should not match the attribute
fn check-screen-row-in-color screen-on-stack: (addr screen), fg: color, row-idx: int, expected: (addr array byte), msg: (addr array byte) {
fn check-screen-row-in-color screen: (addr screen), fg: color, row-idx: int, expected: (addr array byte), msg: (addr array byte) {
check-screen-row-in-color-from screen, fg, row-idx, 1, expected, msg
}
fn check-screen-row-in-color-from screen-on-stack: (addr screen), fg: color, row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
var screen/esi: (addr screen) <- copy screen-on-stack
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
var e: (stream byte 0x100)
var e-addr/edx: (addr stream byte) <- address e
write e-addr, expected
{
var done?/eax: boolean <- stream-empty? e-addr
compare done?, 0
break-if-!=
var g/eax: grapheme <- screen-grapheme-at-idx screen, idx
var g2/ebx: int <- copy g
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
var expected-grapheme2/edx: int <- copy expected-grapheme
# compare graphemes
$check-screen-row-in-color-from:compare-graphemes: {
# if expected-grapheme is space, null grapheme is also ok
{
compare expected-grapheme2, 0x20
break-if-!=
compare g2, 0
break-if-= $check-screen-row-in-color-from:compare-graphemes
}
# if expected-grapheme is space, a different color is ok
{
compare expected-grapheme2, 0x20
break-if-!=
var color/eax: int <- screen-color-at-idx screen, idx
compare color, fg
break-if-!= $check-screen-row-in-color-from:compare-graphemes
}
check-ints-equal g2, expected-grapheme2, msg
}
idx <- increment
loop
}
}
# background color is visible even for spaces, so 'expected' behaves as an array of booleans.
@ -704,7 +794,23 @@ fn test-check-screen-scrolls-on-overflow {
check-screen-row-from screen, 5, 1, "b", "F - test-check-screen-scrolls-on-overflow/2"
}
fn test-check-screen-color {
var screen-on-stack: screen
var screen/esi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5, 4
var c/eax: grapheme <- copy 0x61 # 'a'
print-grapheme screen, c
start-color screen, 1, 0 # foreground=1
c <- copy 0x62 # 'b'
print-grapheme screen, c
start-color screen, 0, 0 # back to default
c <- copy 0x63 # 'c'
print-grapheme screen, c
check-screen-row-in-color screen, 0, 1, "a c", "F - test-check-screen-color"
}
#? fn main -> exit-status/ebx: int {
#? #? test-check-screen-color
#? run-tests
#? exit-status <- copy 0
#? }

BIN
apps/mu

Binary file not shown.

View File

@ -12695,6 +12695,10 @@ has-primitive-name?: # stmt: (addr stmt) -> result/eax: boolean
(string-equal? %esi "compute-offset") # => eax
3d/compare-eax-and 0/imm32/false
0f 85/jump-if-!= $has-primitive-name?:end/disp32
# if (name == "copy-object") return true
(string-equal? %esi "copy-object") # => eax
3d/compare-eax-and 0/imm32/false
0f 85/jump-if-!= $has-primitive-name?:end/disp32
# if (name == "allocate") return true
(string-equal? %esi "allocate") # => eax
3d/compare-eax-and 0/imm32/false
@ -12820,6 +12824,14 @@ check-mu-primitive: # stmt: (addr stmt), fn: (addr function), err: (addr buffer
(check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
e9/jump $check-mu-primitive:end/disp32
}
# if (op == "copy-object") check-mu-copy-object-stmt
{
(string-equal? %ecx "copy-object") # => eax
3d/compare-eax-and 0/imm32/false
74/jump-if-= break/disp8
(check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
e9/jump $check-mu-primitive:end/disp32
}
# if (op == "allocate") check-mu-allocate-stmt
{
(string-equal? %ecx "allocate") # => eax
@ -13786,6 +13798,18 @@ $check-mu-compute-offset-stmt:end:
5d/pop-to-ebp
c3/return
check-mu-copy-object-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
$check-mu-copy-object-stmt:end:
# . restore registers
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
check-mu-allocate-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
# . prologue
55/push-ebp
@ -16039,6 +16063,15 @@ emit-subx-stmt: # out: (addr buffered-file), stmt: (addr stmt), primitives: (ad
(translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
e9/jump $emit-subx-stmt:end/disp32
}
# copy-object
{
# if (!string-equal?(stmt->operation, "copy-object")) break
(string-equal? %ecx "copy-object") # => eax
3d/compare-eax-and 0/imm32
0f 84/jump-if-= break/disp32
(translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
e9/jump $emit-subx-stmt:end/disp32
}
# allocate array
{
# if (!string-equal?(stmt->operation, "populate")) break
@ -16810,6 +16843,34 @@ $translate-mu-get-stmt:end:
5d/pop-to-ebp
c3/return
translate-mu-copy-object-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
#
(emit-indent *(ebp+8) *Curr-block-depth)
(write-buffered *(ebp+8) "(copy-bytes")
# eax = stmt
8b/-> *(ebp+0xc) 0/r32/eax
# var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
(lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax
(emit-subx-call-operand *(ebp+8) %eax)
(lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax
(emit-subx-call-operand *(ebp+8) %eax)
(write-buffered *(ebp+8) Space)
(addr-payload-size %eax *(ebp+0x10) *(ebp+0x14)) # => eax
(write-int32-hex-buffered *(ebp+8) %eax)
(write-buffered *(ebp+8) ")\n")
$translate-mu-copy-object-stmt:end:
# . restore registers
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
translate-mu-allocate-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
# . prologue
55/push-ebp