Skip to content

Commit 6a71981

Browse files
authored
Merge pull request #116 from cmsc430/immediate-range
Immediate range
2 parents 42cd453 + a520c45 commit 6a71981

3 files changed

Lines changed: 78 additions & 10 deletions

File tree

langs/a86/ast.rkt

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
(error n "expects register; given ~v" a1))
3636
(unless (or (exact-integer? a2) (register? a2) (offset? a2))
3737
(error n "expects exact integer, register, or offset; given ~v" a2))
38+
(when (and (exact-integer? a2) (> (integer-length a2) 32))
39+
(error n "literal must not exceed 32-bits; given ~v (~v bits); go through a register instead" a2 (integer-length a2)))
3840
(values a1 a2)))
3941

4042
(define check:register
@@ -51,6 +53,22 @@
5153
(error n "expects register, offset, exact integer, or defined constant; given ~v" a2))
5254
(when (and (offset? a1) (offset? a2))
5355
(error n "cannot use two memory locations; given ~v, ~v" a1 a2))
56+
(when (and (exact-integer? a2) (> (integer-length a2) 32))
57+
(error n "literal must not exceed 32-bits; given ~v (~v bits); go through a register instead" a2 (integer-length a2)))
58+
(when (and (offset? a1) (exact-integer? a2))
59+
(error n "cannot use a memory locations and literal; given ~v, ~v; go through a register instead" a1 a2))
60+
(values a1 a2)))
61+
62+
(define check:mov
63+
(λ (a1 a2 n)
64+
(unless (or (register? a1) (offset? a1))
65+
(error n "expects register or offset; given ~v" a1))
66+
(unless (or (register? a2) (offset? a2) (exact-integer? a2) (Const? a2))
67+
(error n "expects register, offset, exact integer, or defined constant; given ~v" a2))
68+
(when (and (offset? a1) (offset? a2))
69+
(error n "cannot use two memory locations; given ~v, ~v" a1 a2))
70+
(when (and (exact-integer? a2) (> (integer-length a2) 64))
71+
(error n "literal must not exceed 64-bits; given ~v (~v bits)" a2 (integer-length a2)))
5472
(when (and (offset? a1) (exact-integer? a2))
5573
(error n "cannot use a memory locations and literal; given ~v, ~v; go through a register instead" a1 a2))
5674
(values a1 a2)))
@@ -76,6 +94,8 @@
7694
(λ (a1 n)
7795
(unless (or (exact-integer? a1) (register? a1))
7896
(error n "expects exact integer or register; given ~v" a1))
97+
(when (and (exact-integer? a1) (> (integer-length a1) 32))
98+
(error n "literal must not exceed 32-bits; given ~v (~v bits); go through a register instead" a1 (integer-length a1)))
7999
a1))
80100

81101
(define check:lea
@@ -126,7 +146,7 @@
126146
(instruct Label (x) check:label-symbol)
127147
(instruct Call (x) check:target)
128148
(instruct Ret () check:none)
129-
(instruct Mov (dst src) check:src-dest)
149+
(instruct Mov (dst src) check:mov)
130150
(instruct Add (dst src) check:arith)
131151
(instruct Sub (dst src) check:arith)
132152
(instruct Cmp (a1 a2) check:src-dest)
@@ -169,14 +189,22 @@
169189
(symbol? x)
170190
(integer? x)))
171191

172-
(provide offset? register? instruction? label?)
192+
(provide offset? register? instruction? label? 64-bit-integer? 32-bit-integer?)
173193

174194
(define offset? Offset?)
175195

176196
(define (register? x)
177197
(and (memq x '(cl eax rax rbx rcx rdx rbp rsp rsi rdi r8 r9 r10 r11 r12 r13 r14 r15))
178198
#t))
179199

200+
(define (64-bit-integer? x)
201+
(and (exact-integer? x)
202+
(<= (integer-length x) 64)))
203+
204+
(define (32-bit-integer? x)
205+
(and (exact-integer? x)
206+
(<= (integer-length x) 32)))
207+
180208
(define (label? x)
181209
(and (symbol? x)
182210
(nasm-label? x)

langs/a86/test/errors.rkt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,21 @@
22
(require rackunit "../ast.rkt")
33
(check-exn exn:fail?
44
(thunk (Mov (Offset 'rax 0) 100)))
5+
6+
;; Checking literal widths
7+
(check-exn exn:fail? (thunk (Mov 'rax (expt 2 64))))
8+
(check-not-exn (thunk (Mov 'rax (sub1 (expt 2 64)))))
9+
(check-exn exn:fail? (thunk (Cmp 'rax (expt 2 32))))
10+
(check-not-exn (thunk (Cmp 'rax (sub1 (expt 2 32)))))
11+
(check-exn exn:fail? (thunk (And 'rax (expt 2 32))))
12+
(check-not-exn (thunk (And 'rax (sub1 (expt 2 32)))))
13+
(check-exn exn:fail? (thunk (Or 'rax (expt 2 32))))
14+
(check-not-exn (thunk (Or 'rax (sub1 (expt 2 32)))))
15+
(check-exn exn:fail? (thunk (Xor 'rax (expt 2 32))))
16+
(check-not-exn (thunk (Xor 'rax (sub1 (expt 2 32)))))
17+
(check-exn exn:fail? (thunk (Push (expt 2 32))))
18+
(check-not-exn (thunk (Push (sub1 (expt 2 32)))))
19+
(check-exn exn:fail? (thunk (Add 'rax (expt 2 32))))
20+
(check-not-exn (thunk (Add 'rax (sub1 (expt 2 32)))))
21+
(check-exn exn:fail? (thunk (Sub 'rax (expt 2 32))))
22+
(check-not-exn (thunk (Sub 'rax (sub1 (expt 2 32)))))

www/notes/a86.scrbl

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,28 @@ Each register plays the same role as in x86, so for example
720720
A predicate for offsets.
721721
}
722722

723+
@defproc[(64-bit-integer? [x any/c]) boolean?]{
724+
A predicate for determining if a value is an integer that fits in 64-bits.
725+
726+
@ex[
727+
(64-bit-integer? 0)
728+
(64-bit-integer? (sub1 (expt 2 64)))
729+
(64-bit-integer? (expt 2 64))
730+
(64-bit-integer? (- (expt 2 63)))
731+
(64-bit-integer? (sub1 (- (expt 2 63))))]
732+
}
733+
734+
@defproc[(32-bit-integer? [x any/c]) boolean?]{
735+
A predicate for determining if a value is an integer that fits in 64-bits.
736+
737+
@ex[
738+
(32-bit-integer? 0)
739+
(32-bit-integer? (sub1 (expt 2 32)))
740+
(32-bit-integer? (expt 2 32))
741+
(32-bit-integer? (- (expt 2 32)))
742+
(32-bit-integer? (sub1 (- (expt 2 32))))]
743+
}
744+
723745
@defproc[(seq [x (or/c instruction? (listof instruction?))] ...) (listof instruction?)]{
724746
A convenience function for splicing togeter instructions and lists of instructions.
725747

@@ -866,7 +888,7 @@ Each register plays the same role as in x86, so for example
866888

867889
}
868890

869-
@defstruct*[Mov ([dst (or/c register? offset?)] [src (or/c register? offset? exact-integer?)])]{
891+
@defstruct*[Mov ([dst (or/c register? offset?)] [src (or/c register? offset? 64-bit-integer?)])]{
870892

871893
A move instruction. Moves @racket[src] to @racket[dst].
872894

@@ -885,7 +907,7 @@ Each register plays the same role as in x86, so for example
885907

886908
}
887909

888-
@defstruct*[Add ([dst register?] [src (or/c register? offset? exact-integer?)])]{
910+
@defstruct*[Add ([dst register?] [src (or/c register? offset? 32-bit-integer?)])]{
889911

890912
An addition instruction. Adds @racket[src] to @racket[dst]
891913
and writes the result to @racket[dst].
@@ -901,7 +923,7 @@ Each register plays the same role as in x86, so for example
901923
]
902924
}
903925

904-
@defstruct*[Sub ([dst register?] [src (or/c register? offset? exact-integer?)])]{
926+
@defstruct*[Sub ([dst register?] [src (or/c register? offset? 32-bit-integer?)])]{
905927

906928
A subtraction instruction. Subtracts @racket[src] frrom
907929
@racket[dst] and writes the result to @racket[dst].
@@ -917,7 +939,7 @@ Each register plays the same role as in x86, so for example
917939
]
918940
}
919941

920-
@defstruct*[Cmp ([a1 (or/c register? offset?)] [a2 (or/c register? offset? exact-integer?)])]{
942+
@defstruct*[Cmp ([a1 (or/c register? offset?)] [a2 (or/c register? offset? 32-bit-integer?)])]{
921943
Compare @racket[a1] to @racket[a2]. Doing a comparison
922944
sets the status flags that affect the conditional instructions like @racket[Je], @racket[Jl], etc.
923945

@@ -1028,7 +1050,7 @@ Each register plays the same role as in x86, so for example
10281050
]
10291051
}
10301052

1031-
@defstruct*[And ([dst (or/c register? offset?)] [src (or/c register? offset? exact-integer?)])]{
1053+
@defstruct*[And ([dst (or/c register? offset?)] [src (or/c register? offset? 32-bit-integer?)])]{
10321054
Compute logical ``and'' of @racket[dst] and @racket[src] and put result in @racket[dst].
10331055

10341056
@#reader scribble/comment-reader
@@ -1043,7 +1065,7 @@ Each register plays the same role as in x86, so for example
10431065
)
10441066
}
10451067

1046-
@defstruct*[Or ([dst (or/c register? offset?)] [src (or/c register? offset? exact-integer?)])]{
1068+
@defstruct*[Or ([dst (or/c register? offset?)] [src (or/c register? offset? 32-bit-integer?)])]{
10471069
Compute logical ``or'' of @racket[dst] and @racket[src] and put result in @racket[dst].
10481070

10491071
@#reader scribble/comment-reader
@@ -1058,7 +1080,7 @@ Each register plays the same role as in x86, so for example
10581080
)
10591081
}
10601082

1061-
@defstruct*[Xor ([dst (or/c register? offset?)] [src (or/c register? offset? exact-integer?)])]{
1083+
@defstruct*[Xor ([dst (or/c register? offset?)] [src (or/c register? offset? 32-bit-integer?)])]{
10621084
Compute logical ``exclusive or'' of @racket[dst] and @racket[src] and put result in @racket[dst].
10631085

10641086
@#reader scribble/comment-reader
@@ -1113,7 +1135,7 @@ Each register plays the same role as in x86, so for example
11131135
)
11141136
}
11151137

1116-
@defstruct*[Push ([a1 (or/c exact-integer? register?)])]{
1138+
@defstruct*[Push ([a1 (or/c 32-bit-integer? register?)])]{
11171139

11181140
Decrements the stack pointer and then stores the source
11191141
operand on the top of the stack.

0 commit comments

Comments
 (0)