Skip to content

Commit

Permalink
Merge pull request #251 from tomhea/feature/push-pop-byte
Browse files Browse the repository at this point in the history
Feature/push pop byte
  • Loading branch information
tomhea authored Nov 18, 2023
2 parents 31ec349 + 7d6ed6d commit c130aa5
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 108 deletions.
108 changes: 61 additions & 47 deletions flipjump/stl/hex/pointers/stack.fj
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ ns hex {
.ptr_sub hex.pointers.sp, value
}

// Time Complexity: w(1.5@+5) + 9@+14
// Space Complexity: w(1.875@+20) + 5@+55
// Time Complexity: w(2.25@+10) + 9@+ 51
// Space Complexity: w(2.62@+49) + 20@+231
// Like: stack[++sp] = return_address
// Pushes the given return_address to the next cell in the stack (assumes it's zero). Increments sp.
// Pushes the given return_address to the next cell in the stack. Increments sp.
// Note: the pushed returned address must be popd out afterwards with pop_ret_address.
// return_address is a fj-op address, so we assume is dw-aligned.
def push_ret_address return_address < hex.pointers.sp {
.sp_inc
.zero_ptr hex.pointers.sp
.ptr_wflip_2nd_word hex.pointers.sp, return_address
}

// Time Complexity: w(1.5@+5) + 9@+23
// Time Complexity: w( 1.5@+ 5) + 9@+23
// Space Complexity: w(1.875@+20) + 5@+67
// Like: stack[sp--] = 0
// Pops the given return_address from the current cell in the stack (assumes it has the value of the return_address). Decrements sp.
Expand All @@ -51,64 +52,77 @@ ns hex {
.sp_dec
}


// Time Complexity: w(0.5@+2) + 14@+26
// Space Complexity: w(0.875@+5.25) + 10@+131
// Like: stack[++sp] = hex (assumes stack[++sp] == 0 beforehand, which the stack-macros guarantee).
// Pushes the given hex to the next cell in the stack (assumes it's zero). Increments sp.
// Time Complexity: w(0.75@+ 5) + 20@+ 39
// Space Complexity: w(1.13@+32) + 16@+167
// Like: stack[++sp] = hex
// Pushes the given hex to the next cell in the stack. Increments sp.
def push_hex hex < hex.pointers.sp {
.sp_inc
.write_hex hex.pointers.sp, hex
}

// Time Complexity: n(w(0.5@+2) + 14@+26)
// Space Complexity: n(w(0.875@+5.25) + 10@+131)
// Like: stack[sp+1:][:n] = hex[:n]; sp += n (assumes stack[sp:sp+n] == 0 beforehand, which the stack-macros guarantee).
// Pushes the given hex[:n] to the next n cells in the stack (assumes they're zero). Increments sp by n.
def push n, hex {
rep(n, i) .push_hex hex+i*dw
}


// Time Complexity: w(0.5@+2) + 14@+35
// Space Complexity: w(0.875@+17.25) + 10@+143
// Like: stack[sp--] = 0 (assumes stack[sp] == unchanged_hex beforehand)
// Pops the given unchanged_hex (a hex) from the current cell in the stack (assumes it has the exact value of hex). Decrements sp.
def pop_unchanged_parameter unchanged_hex < hex.pointers.sp {
.xor_hex_to_ptr hex.pointers.sp, unchanged_hex
.sp_dec
// Time Complexity: w(0.75@+ 5) + 26@+ 51
// Space Complexity: w(1.13@+32) + 22@+255
// Like: stack[++sp] = byte[:2]
// Pushes the given byte to the next cell in the stack. Increments sp.
// byte is a hex[:2].
def push_byte byte < hex.pointers.sp {
.sp_inc
.write_byte hex.pointers.sp, byte
}

// Time Complexity: n(w(0.5@+2) + 14@+35)
// Space Complexity: n(w(0.875@+17.25) + 10@+143)
// Like: sp -= n; stack[sp+1:][:n] = 0 (assumes stack[sp+1-n:][:n] == unchanged_hex[:n] beforehand)
// Pops the given unchanged_hex (a hex[:n]) from the current cell in the stack (assumes it has the exact value of hex). Decrements sp by n.
def pop_unchanged_parameter n, unchanged_hex {
rep(n, i) .pop_unchanged_parameter unchanged_hex+i*dw
// Time Complexity: n(w(0.38@+ 3) + 13@+ 25)
// Space Complexity: n(w(0.56@+16) + 11@+128)
// Like: stack[sp+1:][:M] = hex[:n]; sp += n.
// Pushes the given hex[:n] to the next M cells in the stack. Increments sp by M.
// M is (n+1)/2, which is because the function pushes the entire parameter as bytes.
//
// Note: This macro pushes bytes to the stack (2 hexs in one stack-cell).
//
// Note: The push/pop usage must be coordinated, and every push X must be untangled by a pop X (or a sp_sub (X+1)/2)
// For example: "push 3; push 3" can't be read with a "pop 6". That's because each "push 3" takes 2 stack cells,
// while the "pop 6" only pops out 3 stack cells (so there is another cell that needs to be popped.
def push n, hex {
rep(n/2, i) .push_byte hex+2*i*dw
rep(n%2, i) .push_hex hex+(n-1)*dw
}


// Time Complexity: w(1.25@+7) + 21@+48
// Space Complexity: w(1.625@+46) + 17@+191
// Like: hex = stack[sp]
// stack[sp--] = 0
// Time Complexity: w(0.75@+ 5) + 16@+ 36
// Space Complexity: w(1.13@+32) + 12@+115
// Like: hex = stack[sp--]
// Pops the current stack cell (only the least-significant-hex of it) into the the given hex. Decrements sp.
// hex is only an output parameter
// hex is only an output parameter.
def pop_hex hex < hex.pointers.sp {
hex.zero hex
.xor_hex_from_ptr hex, hex.pointers.sp
// .pop_unchanged_parameter hex
.read_hex hex, hex.pointers.sp
.sp_dec
}

// Time Complexity: w(0.75@+ 5) + 18@+ 36
// Space Complexity: w(1.13@+32) + 14@+139
// Like: byte[:2] = stack[sp--]
// Pops the current stack cell into the the given byte. Decrements sp.
// byte is hex[:2], and it's only an output parameter.
def pop_byte byte < hex.pointers.sp {
.read_byte byte, hex.pointers.sp
.sp_dec
}

// Time Complexity: n(w(1.25@+7) + 21@+48)
// Space Complexity: n(w(1.625@+46) + 17@+191)
// Like: sp -= n
// hex[:n] = stack[sp+1][:n]
// stack[sp+1:][:n] = 0
// Pops the current stack cell into the the given hex[:n]. Decrements sp by n.
// Time Complexity: n(w(0.38@+ 3) + 9@+18)
// Space Complexity: n(w(0.56@+16) + 7@+70)
// Like: sp -= M
// hex[:n] = stack[sp+1:][:M]
// Pops multiple stack cell into the the given hex[:n]. Decrements sp by M.
// M is (n+1)/2, which is because the function pops all the parameters as bytes.
//
// Note: The pops assume that they were pushed as bytes to the stack (2 hexs in one stack-cell).
// So this macro pops bytes.
//
// Note: The push/pop usage must be coordinated, and every push X must be untangled by a pop X (or a sp_sub (X+1)/2)
// For example: "push 3; push 3" can't be read with a "pop 6". That's because each "push 3" takes 2 stack cells,
// while the "pop 6" only pops out 3 stack cells (so there is another cell that needs to be popped.
// hex[:n] is only an output parameter.
def pop n, hex {
rep(n, i) .pop_hex hex+(n-1-i)*dw
rep(n%2, i) .pop_hex hex+(n-1)*dw
rep(n/2, i) .pop_byte hex+(n-n%2-2*(i+1))*dw
}
}
14 changes: 7 additions & 7 deletions flipjump/stl/ptrlib.fj
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ ns stl {

// @requires the stack_init.
ns stl {
// Time Complexity: ~1.5@ (exact: w(1.5@+5) + 9@+15)
// Space Complexity: <2@ (exact: w(1.875@+20) + 5@+55)
// Time Complexity: ~2.5w@ (exact: w(2.25@+10) + 24@+51)
// Space Complexity: <3w@ (exact: w(2.625@+49) + 20@+231)
// Saves the return address to the stack and jumps to the given "address".
// When returned, it removes the return-address from the stack.
//
Expand All @@ -40,21 +40,21 @@ ns stl {
hex.pop_ret_address return_label
}

// Time Complexity: <2@ (exact: w(1.5@+5) + 22@+20)
// Space Complexity: <2@ (exact: w(1.875@+20) + 28@+75)
// Time Complexity: <3w@ (exact: w(2.25@+10) + 37@+57)
// Space Complexity: <3w@ (exact: w(2.625@+49) + 43@+251)
// Saves the return address to the stack and jumps to the given "address".
// When returned, it removes the value from the stack, and pops "params_hex_length" variables from the stack.
// When returned, it removes the return-address from the stack, and pops "params_stack_length" cells from the stack.
//
// note: the pop_ret_address is for the future return (counts as space, but not time, complexity).
// @requires the stack_init.
def call address, params_hex_length @ return_label {
def call address, params_stack_length @ return_label {
hex.push_ret_address return_label
;address

pad 2
return_label:
hex.pop_ret_address return_label
hex.sp_sub params_hex_length
hex.sp_sub params_stack_length
}


Expand Down
4 changes: 2 additions & 2 deletions programs/func_tests/func3.fj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Tests push/pop_unchanged_parameter with an empty function call
// Tests push_hex/pop_hex (unchanged hex) with an empty function call


stl.startup_and_init_all 10
Expand All @@ -11,7 +11,7 @@ test3:
stl.output 'B'
stl.call func3
stl.output 'D'
hex.pop_unchanged_parameter x3
hex.pop_hex x3
stl.output 'E'

stl.output '\n'
Expand Down
4 changes: 2 additions & 2 deletions programs/func_tests/func5.fj
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ test5:
stl.output ' '

stl.output 'A'
hex.pop_unchanged_parameter y5
hex.pop_hex y5
stl.output 'B'
hex.pop_unchanged_parameter x5
hex.pop_hex x5
stl.output 'C'
hex.pop_hex res5
stl.output 'D'
Expand Down
5 changes: 3 additions & 2 deletions programs/func_tests/func6.fj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


N = 4
STACK_N = (N+1)/2
stl.startup_and_init_all 100

hex.set N, x, 7438
Expand All @@ -10,7 +11,7 @@ hex.set N, y, 2524

hex.push N, x
hex.push N, y
stl.call math.add, N
stl.call math.add, STACK_N
hex.pop N, res
hex.print_as_digit N, res, 1
stl.output '\n'
Expand All @@ -28,7 +29,7 @@ add:
hex.add N, .res, .temp

hex.push N, .res
hex.sp_add N+1
hex.sp_add STACK_N+1

stl.return

Expand Down
Loading

0 comments on commit c130aa5

Please sign in to comment.