1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-10 08:30:38 +00:00

Poisoning high/low byte of word poisons the word.

This commit is contained in:
Cat's Eye Technologies 2014-04-04 19:06:58 +01:00
parent 56f8407b55
commit 81526ec834
5 changed files with 78 additions and 45 deletions

View File

@ -122,4 +122,4 @@ TODO
* `outputs` on externals
* Routine is a kind of StorageLocation? (Location)?
* remove DELTA -> ADD/SUB (requires carry be notated on ADD and SUB though)
* Poisoning the highbyte or lowbyte of a word should poison the word
* explicit `with` syntax

View File

@ -16,7 +16,7 @@ routine.
| }
= main ([])
= A: UpdatedWith (Immediate 4)
= NamedLocation (Just Byte) "score": UpdatedWith A
= NamedLocation Nothing "score": UpdatedWith A
A routine cannot expect registers which a called routine does not
preserve, to be preserved.
@ -53,16 +53,15 @@ But if it does it can.
= main ([])
= A: UpdatedWith (Immediate 4)
= X: PoisonedWith (Immediate 1)
= NamedLocation (Just Byte) "border_colour": UpdatedWith A
= NamedLocation (Just Byte) "score": PoisonedWith X
= NamedLocation Nothing "border_colour": UpdatedWith A
= NamedLocation Nothing "score": PoisonedWith X
=
= update_score ([])
= X: UpdatedWith (Immediate 1)
= NamedLocation (Just Byte) "score": UpdatedWith X
= NamedLocation Nothing "score": UpdatedWith X
We can't expect to stay named variables to stay unmodified either.
| assign byte border_colour 4000
| reserve byte score
| routine update_score
| {
@ -71,9 +70,9 @@ We can't expect to stay named variables to stay unmodified either.
| }
| routine main {
| jsr update_score
| ldx score
| lda score
| }
? routine does not preserve 'NamedLocation (Just Byte) "score"'
? routine does not preserve 'NamedLocation Nothing "score"'
What the solution to the above is to notate `update_score` as intentionally
modifying score, as an "output" of the routine.
@ -92,12 +91,12 @@ modifying score, as an "output" of the routine.
| }
= main ([])
= A: PoisonedWith (Immediate 8)
= X: UpdatedWith (NamedLocation (Just Byte) "score")
= NamedLocation (Just Byte) "score": UpdatedWith A
= X: UpdatedWith (NamedLocation Nothing "score")
= NamedLocation Nothing "score": UpdatedWith A
=
= update_score ([NamedLocation Nothing "score"])
= A: UpdatedWith (Immediate 8)
= NamedLocation (Just Byte) "score": UpdatedWith A
= NamedLocation Nothing "score": UpdatedWith A
Routines can name registers as outputs.
@ -123,7 +122,7 @@ Routines can name registers as outputs.
| }
= main ([])
= A: UpdatedWith (Immediate 8)
= NamedLocation (Just Byte) "score": UpdatedWith A
= NamedLocation Nothing "score": UpdatedWith A
=
= update_score ([A])
= A: UpdatedWith (Immediate 8)
@ -196,3 +195,19 @@ after the `if`.
| sta score
| }
? routine does not preserve 'A'
Poisoning a high byte or low byte of a word poisons the whole word.
| reserve word score
| reserve byte temp
| routine update_score
| {
| ldx #4
| stx <score
| }
| routine main {
| jsr update_score
| lda >score
| sta temp
| }
? routine does not preserve 'NamedLocation Nothing "score"'

View File

@ -34,31 +34,27 @@ analyzeProgram program@(Program decls routines) =
-- -- -- -- -- -- -- -- -- -- -- --
checkInstr (COPY src dst) progCtx routCtx =
case Map.lookup src routCtx of
Just (PoisonedWith _) ->
error ("routine does not preserve '" ++ (show src) ++ "'")
_ ->
Map.insert dst (UpdatedWith src) routCtx
updateRoutCtx dst (UpdatedWith src) routCtx
checkInstr (DELTA dst val) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith (Immediate val)) routCtx
updateRoutCtx dst (UpdatedWith (Immediate val)) routCtx
checkInstr (ADD dst src) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith src) routCtx
updateRoutCtx dst (UpdatedWith src) routCtx
checkInstr (SUB dst src) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith src) routCtx
updateRoutCtx dst (UpdatedWith src) routCtx
checkInstr (AND dst src) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith src) routCtx
updateRoutCtx dst (UpdatedWith src) routCtx
checkInstr (OR dst src) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith src) routCtx
updateRoutCtx dst (UpdatedWith src) routCtx
checkInstr (XOR dst src) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith src) routCtx
updateRoutCtx dst (UpdatedWith src) routCtx
checkInstr (JSR name) progCtx routCtx =
let
@ -91,18 +87,18 @@ analyzeProgram program@(Program decls routines) =
checkInstr (BIT dst) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith (Immediate 0)) routCtx
updateRoutCtx dst (UpdatedWith (Immediate 0)) routCtx
checkInstr (SHR dst flg) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith flg) routCtx
updateRoutCtx dst (UpdatedWith flg) routCtx
checkInstr (SHL dst flg) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith flg) routCtx
updateRoutCtx dst (UpdatedWith flg) routCtx
checkInstr (COPYROUTINE name dst) progCtx routCtx =
-- TODO check that dst is not poisoned
Map.insert dst (UpdatedWith (Immediate 7)) routCtx
updateRoutCtx dst (UpdatedWith (Immediate 7)) routCtx
checkInstr (JMPVECTOR dst) progCtx routCtx =
routCtx
@ -127,20 +123,16 @@ mergeRoutCtxs routCtx calledRoutCtx calledRout@(Routine name outputs _) =
poison location usage routCtxAccum =
case usage of
UpdatedWith ulocation ->
case (untypedLocation location) `elem` outputs of
case location `elem` outputs of
True ->
Map.insert location usage routCtxAccum
updateRoutCtx location usage routCtxAccum
False ->
Map.insert location (PoisonedWith ulocation) routCtxAccum
updateRoutCtx location (PoisonedWith ulocation) routCtxAccum
PoisonedWith ulocation ->
Map.insert location usage routCtxAccum
updateRoutCtx location usage routCtxAccum
in
Map.foldrWithKey (poison) routCtx calledRoutCtx
untypedLocation (NamedLocation (Just _) name) =
NamedLocation Nothing name
untypedLocation x = x
--
-- Utility function:
-- Take 2 routine contexts -- one from each branch of an `if` -- and merge
@ -153,7 +145,7 @@ mergeAlternateRoutCtxs routCtx1 routCtx2 =
poison location usage2 routCtxAccum =
case Map.lookup location routCtx1 of
Nothing ->
Map.insert location usage2 routCtxAccum
updateRoutCtx location usage2 routCtxAccum
Just usage1 ->
-- it exists in both routCtxs.
-- if it is poisoned in either, it's poisoned here.
@ -164,6 +156,6 @@ mergeAlternateRoutCtxs routCtx1 routCtx2 =
(_, PoisonedWith _) -> usage2
_ -> usage1 -- or 2. doesn't matter.
in
Map.insert location newUsage routCtxAccum
updateRoutCtx location newUsage routCtxAccum
in
Map.foldrWithKey (poison) routCtx1 routCtx2

View File

@ -26,6 +26,30 @@ type RoutineContext = Map.Map StorageLocation Usage
type ProgramContext = Map.Map RoutineName RoutineContext
untypedLocation (HighByteOf (NamedLocation _ name)) =
NamedLocation Nothing name
untypedLocation (LowByteOf (NamedLocation _ name)) =
NamedLocation Nothing name
untypedLocation (NamedLocation _ name) =
NamedLocation Nothing name
untypedLocation x = x
updateRoutCtx :: StorageLocation -> Usage -> RoutineContext -> RoutineContext
updateRoutCtx dst (UpdatedWith src) routCtx =
let
s = untypedLocation src
d = untypedLocation dst
in
case Map.lookup s routCtx of
Just (PoisonedWith _) ->
error ("routine does not preserve '" ++ (show s) ++ "'")
_ ->
Map.insert d (UpdatedWith s) routCtx
updateRoutCtx dst (PoisonedWith src) routCtx =
Map.insert (untypedLocation dst) (PoisonedWith $ untypedLocation src) routCtx
-- pretty printing
ppAnalysis :: Program -> ProgramContext -> IO ()
ppAnalysis program progCtx =
let

View File

@ -440,17 +440,19 @@ sta = do
stx :: Parser Instruction
stx = do
string "stx"
spaces
l <- named_location
return (COPY X l)
addressing_mode "stx" gen
where
gen (Directly l) [] = COPY X (NamedLocation Nothing l)
gen (LowBytely l) [] = COPY X (LowByteOf (NamedLocation Nothing l))
gen (HighBytely l) [] = COPY X (HighByteOf (NamedLocation Nothing l))
sty :: Parser Instruction
sty = do
string "sty"
spaces
l <- named_location
return (COPY Y l)
addressing_mode "sty" gen
where
gen (Directly l) [] = COPY Y (NamedLocation Nothing l)
gen (LowBytely l) [] = COPY Y (LowByteOf (NamedLocation Nothing l))
gen (HighBytely l) [] = COPY Y (HighByteOf (NamedLocation Nothing l))
txa :: Parser Instruction
txa = do